В связи с тестированием сетевых блокировок в РФ на стороне нашего хостинг-провайдера наблюдаются проблемы с сетью. Сайт может работать нестабильно. Проблема известна, ожидаем восстановления маршрутов.
Авторизация
или войдите через
Забыли пароль?Восстановить
Восстановить пароль
Помощь проекту
Укажите в комментарии свой ник, чтобы мы знали, кого благодарить
Проведена
масштабная модернизация runtime-среды, компилятора, ассемблера и
примеров проекта, направленная на расширение функционала
многопоточности, поддержку новых устройств и кардинальное улучшение
кодогенерации:
Плагин для IntelliJ IDEA — разработан многофункциональный и достаточно удобный плагин для vm5277
Расширение ядра RTOS — добавлены драйверы DHT11 и ANSI-дисплея, диспетчер задач, обработчик PCINT, программные таймеры
Существенное
улучшение компилятора и кодогенерации — переход на универсальные методы
кодогенерации, поддержка новых типов ячеек (CONST, FLAG), оптимизация
сравнений и присваиваний
Переработка модели DRAM — переход с 3-блочной на 1-блочную модель (1 ячейка = 8 байт)
Новые возможности стандартной библиотеки — CRC8, uptime в микросекундах, генератор случайных чисел, диагностика памяти
Расширение примеров — добавлено 11 новых примеров (многопоточность, таймеры, DHT11, RGB, ANSI-консоль)
Улучшение бутлоадеров — рабочая версия bldrtiny, оптимизация вывода символов
Также
сообщаю, что это мой последний пост на этой площадке. Причина —
администрация ресурса не выполняет свои обязанности, объявленные ею в
оферте.
Если
вам интересен проект (а я напомню — у него есть ряд ключевых преимуществ
по сравнению с текущими решениями для 8-битных микроконтроллеров), вот
несколько ссылок:
P.S.
В течение лета я начну ряд публикаций на Habr, где постараюсь полностью
рассказать о проекте и показать очевидные преимущества. К сожалению,
здесь моих публикаций не будет по уже указанной причине.
Q: Что такое VM5277? Это виртуальная машина?
A: Нет, несмотря на название. VM5277 — это компилятор
языка J8B (Java-подобный синтаксис) в нативный ассемблерный код для
8-битных микроконтроллеров. Никакой виртуальной машины на МК не
выполняется — только нативный код. Название историческое и отражает
архитектурную идею: для мощных устройств в будущем планируется
легковесная JVM, для слабых — трансляция в ассемблер.
Q: Проект бесплатный?
A: Да. Весь проект распространяется под лицензией
Apache 2.0. Исходный код открыт и всегда будет открыт. Использование в
коммерческих продуктах разрешено. Автор оставляет за собой право в
будущем предлагать платные расширения (эксклюзивные платформы,
специализированные драйверы, продвинутые оптимизации, улучшенное
качество кода), но открытая кодовая база навсегда остаётся доступной для
fork'а и самостоятельного развития сообществом.
Q: Проект разрабатывает один человек? Что будет, если вы забросите?
A: Да, проект разрабатывается одним человеком. На
текущий момент пройден путь от идеи до работающего компилятора,
ассемблера, RTOS и инструментария — это около 1 года активной
разработки. Объём проделанной работы и вложенного времени делают риск
прекращения разработки крайне низким. Код открыт под Apache 2.0 —
сообщество также сможет продолжить развитие.
Даже в случае прекращения активной разработки вы получаете работающий
компилятор и RTOS под открытой лицензией — это не облачный сервис,
который могут отключить.
Для пользователей (тех, кто пишет прошивки)
Q: На каких микроконтроллерах это работает прямо сейчас?
A: Сейчас поддерживается AVR: ATmega168p, ATmega328p
(Arduino Uno), Attiny2313a и другие. Добавление нового МК того же
семейства — это, как правило, формирование конфигурационного файла по
шаблону, а не переписывание кода. Поддержка PIC и STM8 архитектурно
проработана, реализация запланирована на ближайшее будущее. При этом код
на J8B пишется сразу с расчётом на кроссплатформенность — когда
появится поддержка новых архитектур, ваша бизнес-логика не потребует
переписывания.
Q: Чем J8B лучше Arduino C++?
A:
Читаемость: Java-подобный синтаксис без заголовочных файлов, дефайнов, указателей и ручного управления памятью.
Кросс-платформенность: бизнес-логика не привязана к
архитектуре МК. При смене платформы меняется только нижний слой,
разработка которого - наша задача.
RTOS из коробки: многозадачность через Thread API, а не через самодельные конечные автоматы.
Исключения: try-catch и stack trace прямо на МК.
Скорость сборки: компиляция в разы быстрее Arduino IDE.
Эффективность кода: компилятор и RTOS включают в
сборку только то, что реально задействовано в программе. Нет мёртвого
кода, нет раздутой стандартной библиотеки «на всякий случай».
ООП-конструкции частично разрешаются на этапе компиляции и не создают накладных
расходов в рантайме. По размеру прошивки и расходу ОЗУ результат
сопоставим с хорошо написанным кодом на Си — и заметно компактнее
типичного C++ с виртуальными методами и шаблонами.
Q: Чем J8B хуже Arduino C++?
Качество кода: проект в альфе — есть баги, не все фичи реализованы, тестирование пока не всестороннее.
Платформы: сейчас только AVR. Поддержка PIC и STM8 в разработке — если нужно прямо сегодня, придётся подождать.
Экосистема: готовых библиотек и драйверов крайне мало. На старте многое придётся писать самому или адаптировать.
Сообщество: его пока нет, а значит нет и готовых ответов на Stack Overflow, туториалов, примеров от других пользователей.
По сути, главный недостаток сегодня — проект мало кому
известен. С ростом сообщества эти проблемы уходят: больше тестирования —
меньше багов, больше пользователей — больше библиотек и примеров.
Q: Какой размер прошивки получается? Не раздует ли ООП мой код?
A: Компилятор генерирует оптимизированный ассемблерный
код, близкий по эффективности к ручному. ООП-конструкции (классы,
интерфейсы) разрешаются на этапе компиляции и не создают накладных
расходов в рантайме — там, где нужны служебные данные (например, таблицы
виртуальных методов для интерфейсов), они минимальны и включаются в
сборку только если вы реально используете полиморфизм. Конкретные цифры:
пример с enum и выводом — 1204 байта (3% памяти ATmega328p), пример с
исключениями и трассировкой стека — 2389 байт (7.5%).
Q: Могу ли я использовать существующие Arduino-библиотеки?
A: Нет — иначе это был бы клон или прослойка над Ардуино - это другой язык и другая экосистема. Но вы можете:
Обернуть нужный функционал в native-метод на ассемблере.
Переиспользовать логику, переписав её на J8B (обычно это проще, чем кажется).
В перспективе — использовать готовые библиотеки и драйверы из runtime библиотеки VM5277.
Q: Как отлаживать программу? Нужен ли дорогой программатор?
A: Нет, достаточно USB-UART адаптера. Сейчас реализовано:
Вывод в консоль (логи, значения переменных).
Трассировка исключений с именами методов и номерами строк.
Обновление прошивки без перетыкания проводов.
В разработке: полноценный отладчик верхнеуровневого языка.
Q: Какую IDE использовать?
A: На текущем этапе достаточно любого текстового
редактора — сборка запускается из командной строки одной командой. Также
поддерживается сборка через Maven. Для тех, кто предпочитает IDE:
доступен плагин для IntelliJ IDEA (приоритетное направление,
бета-версия) и NetBeans (слабый приоритет, черновая версия) — с
подсветкой синтаксиса, деревом проекта и запуском компиляции из IDE. В
планах — LSP-сервер для поддержки VS Code, Kate и других редакторов.
Q: Что нужно для старта?
A: Минимальный набор:
Плата Arduino Uno или любая с ATmega168p/328p. Также поддерживаются другие чипы ATmega и ATtiny.
Для плат без встроенного USB-UART — внешний USB-UART адаптер.
Компьютер с Windows, GNU/Linux или macOS — инструменты на Java
работают везде (в альфа-версии тестировались только на GNU/Linux).
5 минут на установку и первую прошивку.
Q: Где взять примеры кода?
A: В репозитории проекта в папке examples/j8b/:
helloworld, gpio, исключения, enum и другие. Каждый пример содержит
готовый pom.xml и собирается одной командой: mvn j8b:run -Parduino-uno
Или напрямую из IDE через плагин. После сборки — сразу готовая прошивка.
Для разработчиков и интересующихся архитектурой
Q: Почему вы написали свой компилятор, а не использовали LLVM/GCC?
A: Задача VM5277 — не только компиляция, но и глубокая
интеграция с собственной RTOS и системой исключений. Использование
готового бэкенда не дало бы нужного уровня контроля над кодогенерацией и
не позволило бы реализовать фичи вроде try-catch на устройствах с 2 КБ
ОЗУ. Кроме того, одна из целей проекта — максимальная скорость сборки
без тяжёлых зависимостей.
Q: На чём написан компилятор?
A: Полностью на Java, без сторонних зависимостей.
Собирается через Maven. Может работать как JAR (требуется JRE 8+) или
как нативный исполняемый файл через GraalVM Native Image (JRE не
требуется).
Q: Как устроен процесс компиляции?
A: Исходный код J8B → парсинг (AST) → семантический
анализ → промежуточное представление → генерация ассемблерного кода под
целевую платформу → встроенный ассемблер → HEX-прошивка. Весь процесс —
возможен одной командой, без внешних инструментов.
Q: Что такое J8B? Это подмножество Java?
A: J8B — самостоятельный язык с Java-подобным синтаксисом, спроектированный специально для 8-битных МК. От Java отличается:
Нет наследования классов (с наследованием интерфейсов) — архитектура строится на композиции.
Нет generics.
Примитивы адаптированы под 8-битное железо: bool, byte, char, short,
int, fixed (Q7.8 с фиксированной точкой), enum. Все целые, кроме fixed,
— беззнаковые.
Нет сборщика мусора — управление памятью через RTOS (подсчет ссылок).
Небольшие отличия в синтаксисе: например, оператор for с else.
Встроенная поддержка многозадачности и аппаратных абстракций — в активной разработке.
Q: Как устроена RTOS?
A: RTOS написана на ассемблере для каждой платформы
отдельно — это даёт полный контроль над размером кода и быстродействием
критичных участков. Включает: динамическое выделение памяти, вытесняющую
многозадачность, таймеры, блокировки, системные вызовы, драйверы
ввода-вывода. Предоставляет высокоуровневый API для J8B (Thread, System,
Math и т.д.).
Q: Как работают исключения при 2 КБ ОЗУ?
A: Механизм исключений реализован на уровне компилятора
и RTOS. Информация о типах исключений и обработчиках вычисляется на
этапе компиляции. Stack trace собирается средствами RTOS в компактном
бинарном виде, а в человекочитаемый формат (имена методов, номера строк)
разворачивается уже на хосте — утилитой прошивальщика с использованием
отладочной информации. Накладные расходы на МК минимальны: никакой
виртуальной машины, никакого хранения имён методов в прошивке.
Q: Что с поддержкой прерываний?
A: Низкоуровневые прерывания полностью под контролем
RTOS. Пользователю не нужно лезть в ассемблер для типовых задач — всё
уже обёрнуто в высокоуровневые конструкции языка и runtime-библиотеки:
классы Thread, GPIO, Timer и другие. Тот же мигающий светодиод по
таймеру — это несколько строк на J8B, без единой мысли о прерываниях.
Доступ к прерываниям опосредован — через API RTOS:
таймеры, блокировки, ожидание событий. J8B — язык для бизнес-логики,
весь hard realtime остаётся внутри RTOS. Единственный случай, когда
может понадобиться ассемблер — вы пишете что-то узкоспециализированное, и
тогда используете нативные методы.
Q: Как я могу помочь проекту?
A: На текущем этапе наиболее ценная помощь:
Распространять проект — рассказывать о нём, показывать коллегам. Чем больше пользователей, тем быстрее развитие.
Тестировать на реальном железе — запустить примеры на своих платах, проверить на разных ревизиях чипов.
Писать тесты — unit-тесты семантики компилятора и всего остального. Этого очень не хватает.
Давать обратную связь — особенно по работе frontend-компилятора: что удобно, что непонятно, что сломалось.
Сообщать об ошибках — в баг-трекер GitHub или напрямую на почту.
Помочь с плагинами для IDE — плагины для IntelliJ
IDEA и NetBeans сырые, документации по API NetBeans мало, поэтому
особенно ценен опытный разработчик плагинов, который поможет вывести их
на более качественный уровень.
Q: Когда будет поддержка PIC/STM8?
A: Я планировал в Q2 2026, но сильно засел на
багфиксинге и доработках проекта - скорее всего ближе к концу 2026 года.
Архитектура компилятора и RTOS изначально спроектированы под
мультиплатформенность, кодогенераторы для новых архитектур не требуют
переписывания фронтенда, но есть более приоритетные задачи.
Q: Планируется ли поддержка 32-битных МК?
A: Да, но не ранее STM8. Для слабых 32-битных устройств
— нативная компиляция, для мощных — легковесная JVM. Это стратегическое
направление развития, но приоритет сейчас — стабилизация и расширение
на 8-битном сегменте.
Tangatin совершил классическую ошибку поверхностного критика: сам придумал ограничение, сам приписал его чужому проекту и сам же на основе этого сделал ложные выводы.
Давайте разложим по полочкам, в чём именно заключается техническая неграмотность и логический провал Tangatin:
## 1. Подмена понятий: ООП без динамики — это не ООП
Tangatin заявляет: «Наследование вообще бесплатная штука... если не делать виртуальности».
Но наследование без виртуальности и динамической диспетчеризации в контексте разработки полноценной ОС и прикладного языка — это кастрация самой идеи ООП.
* Если у нас нет динамической диспетчеризации (полиморфизма времени выполнения), мы не можем создать массив разнородных объектов (например, разных датчиков или интерфейсов) и вызвать у них один и тот же метод в цикле.
* ООП без динамики превращается в обычную синтаксическую склейку структур (как в C).
Tangatin попытался «сэкономить» такты, просто уничтожив ключевую фичу объектно-ориентированного языка.
## 2. Создание «соломенного чучела» (Straw Man Fallacy)
Tangatin построил классическую демагогическую ловушку:
1. Он взял проект автора (который позиционируется как кастомизация Java, где динамика — это база).
2. Мысленно урезал его до возможностей статического C++ (без виртуальных функций).
3. Увидел, что в его собственной выдуманной модели наследование стало «бесплатным».
4. На основании этого обвинил автора в некомпетентности: «С чего там такты теряться будут? Ну так не делайте их [виртуальные функции]».
Это и есть «неумное приписывание негатива». Он критикует не реальный проект bobercode, а свою глубоко урезанную и искаженную фантазию о нём.
## 3. Тотальное непонимание расходов в 8-битном мире
Когда Tangatin пере переходит к исключениям, его логика окончательно ломается. Он заявляет: «Тактов не жалко!» (иронизируя над автором), полностью игнорируя реальность.
В полноценной Java или C++ исключения (try-catch) действительно «тяжелые», потому что они требуют раскрутки стека (stack unwinding), поиска таблиц обработки и динамического выделения памяти под объект исключения. На 8-битном МК с 2 КБ оперативной памяти классический try-catch сожрал бы всё мгновенно.
Но bobercode сразу поясняет: у него исключения — это «дешевый switch-case». То есть:
* Автор написал кастомную, легковесную систему переходов, которая не раскручивает «взрослый» стек, а работает как быстрый условный переход.
* Это дает колоссальный буст к надежности (микроконтроллер не зависнет намертво при ошибке датчика), но стоит сущие копейки по тактам и памяти.
## Итог
Tangatin проявил высокомерие, умноженное на невнимательность. Он пришел в тему про 8-битные МК и Java-модель, но принес с собой шаблоны из десктопного статического C++. В результате он:
1. Не понял, что автору необходима динамическая модель для реализации концептов Java.
2. Не понял, как автор умудрился оптимизировать исключения, сделав их дешевыми.
3. Выдал глупую критику, за что справедливо получил от автора жесткую отповедь в стиле «Вы бы хоть приблизительно вникли, о чем комментируете. Стыдоба».
Не поняли - спрашивайте, я с удовольствием расскажу как умею. А лучше смотреть проект или что проще - примеры. Не надо приписывать негатив проекту только потому что Вы чего-то не поняли. Это не умно.
Плохо, когда вот такие люди как Tangatin порочат чужие труды. И плохо они делают вам а не мне. Потому что из-за человека который не умеет думать и умеет строчить негатив вы можете пройти мимо чего-то стоящего.
Пример теста производительности основанный на подсчете CRC8 на языке J8B
А вот результат работы:
Результат работы теста производительности
Здесь мы видим, что было выполнено тысяча итераций подсчета CRC8 (SMBUS) для последовательности в 64 байта (байтовый массив). Общее время выполнения на ATmega328p на частоте 16МГц - 0.227 секунды, и 0.000227 секунды на одну итерацию.
Этот результат близок к максимально возможной скорости вычисления для ATmega328p на 16МГц для не табличных вычислений и сравним с ассемблерным аналогом. По сути, так и есть - потому что выполняется именно ассемблерный аналог. Однако для прикладного разработчика ничего не изменилось - его код как и ранее высокоуровневый, ему не нужно знать ничего об ассемблере или Си.
И да, ассемблерная функция вычисления CRC8 встроена в RTOS. На первый взгляд, это минус, ведь для каждой новой платформы нужно повторять набор всех ассемблерных функций. Но мой тулкит гибкий - можно реализовать вычисление CRC8 на J8B, а нативную реализацию из RTOS использовать там где она реализована. Таким образом к первым версиям RTOS других платформ не требуется реализация всего и вся - это просто доработка для повышения производительности.
Важно! Проект в состоянии альфа версии и я несколько месяцев не обновлял его на GitHub'е.
То, что вы там найдете - не будет соответствовать этому посту.
Прошу подождать, я планирую в течении недели выложить все свои доработки.
Сегодня я решил поделиться хорошей новостью - у меня успешно (без ошибок) отработал очередной пример написанный на моем языке J8B (близкий к синтаксису Java).
Я чуть более года создаю тулкит, который обойдет по многим важным аспектам существующие современные решения используемые для разработки программ (прошивок) на 8-битные микроконтроллеры (для начала). Ссылки на open source проект смотрите в конце поста.
Сейчас я акцентирую внимание на функционале и чаще всего для тестирования использую ATmega328p (он же используется в Arduino UNO), однако этот тулкит имеет все архитектурные возможности для мультиплатформенного кодинга (в том числе, в будущем, и для 32 битных микроконтроллеров)
Итак, я хочу рассказать о конкретном примере - опросе многим известного датчика температуры и влажности DHT11.
Картинка с просторов интернета модуля датчика DHT11 для Arduino
И здесь нет никаких сложностей. В интернете есть множество примеров и скетчей для Arduino с использованием этого датчика. И поэтому его опрос легко реализовать на Си и даже на Ассемблере.
Но что если я хочу писать не на Си и Ассемблере, а на высокоуровневом ООП языке схожим синтаксисом с Java? Что если я не хочу знать как работает серийный порт, что такое прерывания и как переносить мою программу с одного чипа на другой? А еще больше я не хочу погружаться в тяжелый синтаксис Си и тем более ассемблера.
Я хочу использовать язык похожий на Java, чтобы он был максимально безопасен: чтобы моя программа не падала из-за выхода за границы массивов, чтобы я мог отслеживать переполнения примитивов, чтобы у меня была нормальная работа с исключениями. И я не хочу постоянно заботиться о выделении и освобождении памяти - из-за этого постоянно куча трудно диагностируемых ошибок, особенно если добавить еще работу с указателями. А еще я хочу композицию, потому что полноценное наследование неоправданно дорого, особенно для 8-битных микроконтроллеров. Т.е. я хочу работать с объектами, хочу передавать их в методы не заботясь кто именно их реализует.
В J8B нет наследования классов - оно сильно
усложнило бы кодогенерацию, раздуло код и съело бы такты на анализ.
Вместо этого я оставил наследование только для интерфейсов. А вся
объектная модель строится через композицию. Это даёт предсказуемые
расходы памяти и времени - вы платите ровно за то, что реально
используете.
И поэтому мой пример выглядит вот так:
Пример опроса датчика DHT11 на языке j8b
Для сравнения приведу пример подобного опроса на Arduino (язык Си):
Один из многочисленных примеров на Си (лично я его не проверял)
Судить о том что лучше, функциональнее, надежнее и в том числе что привычней, предлагаю вам. Однако, это был бы не совсем честный взгляд, если не заглянуть в реализацию самой библиотеки датчика.
Вот моя мультиплатформенная реализация класса - маловероятно что она вообще потребует какие-либо изменений при смене одного чипа на другой, например при переходе с ATmega328p на STM8 или ESP32 - написано один раз - будет работать практически везде.
Это черновой код - он только-только прошел первое успешное тестирование
Как видите, этот код уже поддерживает мультиплатформенность, многопоточность, композицию, исключения, работу с безопасными массивами, легковесный примитив дробного типа fixed (Q7.8) и полностью отвязан от аппаратных особенностей МК.
И конечно обязательно нужно сказать о цене. Какова цена этим высокоуровневым фичам?
Килобайты ОЗУ, флеша? Компиляция в 5 минут? Сложные настройки компиляции и оптимизации?
Давайте посмотрим.
Размер занятого FLASH - 2947 байта (9.3%) - это не просто опрос датчика - здесь также множество универсальных библиотек RTOS которые будут использованы повторно в больших проектах. Можно снизить размер прошивки где-то еще на 100 байт указав опцию -Dj8b.bldrApiReuse=true для использования функций бутлоадера убрав их из основной прошивки.
Также мы видим весь процесс настройки проекта и его команды сборки: mvn j8b:run -Parduino-uno
Конечно настройки есть, и их много - их можно прописать в pom файле maven'а или использовать отдельные утилиты сборки, ассемблирования и прошивки. Но для обычной прошивки достаточно только одной команды Мейвена с параметром платформы (необходим установленный vm5277 бутлоадер - что делается тоже легко).
Чуть подробный вывод сборки, по которому можно судить о скорости сборки и прошивки проекта:
Первый скриншот процесса сборки и прошивки
Здесь мы видим, что компиляция прошла за 0.254 секунды, а ассемблирование за 0.202 секунды.
Второй скриншот сборки и прошивки
А здесь процесс прошивки, который длился 0.267 секунд.
В итоге, с учетом запуска Maven - сборка выполняется где-то за секунду. Этот процесс можно сильно сократить пользуясь утилитами напрямую (особенно если их собрать в нативный код с помощью GraalVM)
И последнее - расход памяти:
Здесь добавлен вывод System.showDRAMMap(); - показывает занятые биты карты динамической памяти: 011100... т.е. занято 3 блока по 8 байт каждый - 24 байта. Они ушли на заголовок и кучу экземпляра класса DHT11.
В данной конфигурации динамическая память занимает 1755 байт, общий стек - 192 байта, бит карта - 27 байт. Остальное (74 байта) ушло на служебные нужды RTOS.
Хочу также обратить внимание - сейчас у меня в приоритете функционал. Процесс оптимизации - это задача на будущее. Т.е. я планирую в будущем добиться еще лучше показателей.
Еще я хотел бы обратить ваше внимание на производительность. Понятно, что реализация высокоуровневого языка, и тем более ООП языка, требует дополнительных расходов - например процессорного времени.
Однако это не стоит дорого, потому что с таким архитектурным подходом можно смело разделить бизнес логику (которая не требует производительности железа) и низкоуровневую логику - которая создается прямо на ассемблере в RTOS.
Например - зачем писать подсчет CRC8 на уровне бизнес логики, когда ее можно оптимально и красиво написать на ассемблере и предоставить прикладнику в виде нативного метода. При этом никто не мешает, при необходимости, написать аналогичный код на j8b.
Таким образом - там где нужна бизнес логика - прикладник получает высокоуровневый, легко читаемый и надежный язык (защищающий от многих низкоуровневых ошибок), а продвинутый гуру - возможность дополнять низкий(нативный) уровень высокоэффективным ассемблерным кодом.
Я могу очень долго рассказывать о своем проекте. И уверен, что многие мои рассказы будут по началу вызывать скепсис. Но чем глубже Вы проникнитесь в мое решение тем интересней оно будет.
Но стоит сказать - это альфа версия. В ней много ошибок, много недоработок, плохая оптимизация и пока поддерживается только AVR. Однако, эта альфа уже доказывает корректно продуманную архитектуру и способность генерировать конечный рабочий результат.
И напоследок я хочу показать несколько скриншотов основного инструмента разработки на моем J8B языке и ассемблере:
Основная библиотека языка (Runtime)
RTOS для AVR
Сгенерированный ассемблерный файл примера с датчиком DHT11
Настройка параметров сборки/запуска
Прошивка бутлоадера
Создание нового проекта
И да, это IntelliJ IDEA 2025.2.6.2 (Community Edition) с моим плагином (пока не поддерживает семантику языка). Также есть плагин для NetBeans - но похоже я не будут его поддерживать дальше, по крайней мере в ближайшее время. Разработка плагина для IDEA гораздо менее трудозатратна.
В общем я просто хотел поделиться своим достижением, я очень рад что уровень проработки всех мои компонентов позволил мне собрать этот код в рабочую прошивку.
Важно! Я несколько месяцев не обновлял проект на GitHub'е.
То, что вы там найдете - не будет соответствовать этому посту.
Прошу подождать, я планирую в течении недели выложить все свои доработки.
VM5277 — это универсальный инструментарий для
embedded-разработки, который предоставляет мост между миром
высокоуровневой ООП-разработки (Java-подобный язык J8B) и нативной
компиляции под 8-битные микроконтроллеры (AVR, PIC, STM8).
Статус проекта: В общей картине проект находится в стадии активной альфа-разработки, но в фокусе AVR (ATmega328) реализовано ядро и полный цикл разработки:
Компилятор J8B с почти полной поддержкой синтаксиса
После месяцев разработки мои руки наконец-то дошли до пользовательской документации!
Представляю вашему вниманию проект vm5277 — это попытка сделать embedded-разработку доступнее, переносимее и привычнее для тех, кто любит ООП.
Проект находится на ранней стадии разработки.
Что это такое? По
сути, это компилятор, который превращает ваш Java-подобный код в
оптимизированный ассемблер для 8-битных микроконтроллеров (AVR, PIC,
STM8). Никаких виртуальных машин — только нативная производительность.
Кому это может быть интересно?
Если вы знакомы с Arduino и устали от digitalWrite(), раздутого кода и привязки к одной платформе.
Если вы Java-разработчик, который хочет заглянуть в embedded, но пугается мира повсеместных указателей и работы с памятью.
Если вы опытный embedded-инженер, который хочет ускорить написание бизнес-логики, не теряя контроля над критичными участками кода.
Проект в статусе "Альфа",
но уже есть работающее ядро для AVR, продуманная архитектура и планы на
будущее. Это не просто идея — уже можно компилировать и смотреть на
результат.
✅ Удобный современный синтаксис - Java-подобный ООП язык вместо низкоуровневого Си, что делает код более читаемым и поддерживаемым
✅ Лёгкость освоения и использования - Интуитивно понятная парадигма программирования без необходимости погружаться в аппаратные особенности каждого МК
✅ Кросс-платформенность - Единая кодовая база для разных 8-битных МК (AVR, PIC, STM8). Драйверы верхнего уровня (большинство датчиков, экранов, исполнителей и прочее) не требуют изменений при смене платформы — в отличие от Си, где необходима переработка макросов и низкоуровневых функций
✅ Кросс-платформенный тулкит - Инструменты разработки написаны на Java, а значит работают на любой ОС (Windows, Linux, macOS) без пересборки и зависимостей
✅ Максимальная производительность - Нативная компиляция в оптимизированный ассемблерный код с вызовами RTOS, полностью написанными и оптимизированными для каждой конкретной платформы (AVR/PIC/STM8), что обеспечивает эффективность близкую к ручной ассемблерной разработке
✅ Экспресс-компиляция - Сборка проектов в разы быстрее чем на Arduino благодаря специализированному инструментарию, заточенному исключительно под задачи embedded-разработки без сторонних зависимостей
✅ Готовая экосистема - Встроенные RTOS, драйверы и аппаратные абстракции из коробки, не требующие самостоятельной реализации
✅ Низкоуровневый доступ - Для экспертов: возможность оптимизации критичных участков на уровне ассемблера без ограничений и замена высокоуровневых методов на нативные вызовы
✅ Стратегическая масштабируемость - Архитектура позволяет расширение на 32-битные МК и компьютеры: для слабых устройств используется трансляция в нативный код, для мощных — легковесная JVM
📌 Проект находится на ранней, но активной стадии разработки
О проекте: Пишем один код - собираем на разные 8 бит МК!
https://vm5277.ru - это универсальное решение для embedded-разработки, которое позволяет сократить время создания прошивки для 8 бит микроконтроллеров в разы.
Как это работает?
Пишешь код на Java подобном языке (чистое ООП, без головной боли с указателями и не читабельным кодом)
Компилятор автоматически генерирует оптимизированный ассемблерный код под выбранную платформу
Код работает поверх легковесной RTOS, написанной на ассемблере для максимальной производительности
Ассемблер-сборщик финализирует проект в бинарный файл прошивки
Что входит в решение:
Высокоуровневый компилятор с Java подобным синтаксисом
Максимально оптимизированная RTOS, целиком на ассемблере для каждой платформы
Унифицированные драйвера - один API для UART, SPI, I2C, GPIO на всех МК
Стандартные библиотеки (Runtime): Базовые типы данных (Float, String), математические функции (Math), работа с памятью и другие абстракции, не зависящие от платформы.
Драйверы верхнего уровня (High-Level Drivers): Унифицированные API для работы с периферийными устройствами: датчиками (I2C/SPI), дисплеями, SD-картами, беспроводными модулями (ESP8266, Bluetooth).
Ключевые преимущества:
Скорость разработки: Создавайте функционал на высокоуровневом языке быстрее, чем на Си
Производительность: RTOS и драйверы оптимизированы до уровня чистого ассемблера, экономя каждый байт и такт
Переносимость: Переход с AVR на PIC или STM8 - дело нескольких правок, а не изучение и адаптация библиотек
Проект находится на ранней стадии, но я активно над ним работаю. Уже можно видеть, как высокоуровневый код на Java-подобном языке превращается в чистый и эффективный ассемблер! Это ещё не итоговый вариант, но прогресс уже есть.
Что уже работает в этом примере:
Наследование интерфейсов: Test implements Number
Динамическое выделение памяти: оператор new
Полиморфизм: вызов метода через переменную интерфейсного типа (Number.toByte())
Проверка типа во время выполнения: оператор is (аналог instanceof)
Полноценная работа с объектами: конструкторы, методы, поля.
Интеграция с RTOS: вызов системных функций (System.out).
Исходный код custom.j8b
Итоговый ассемблер код(стр. 1, черновой, могут быть ошибки)
Итоговый ассемблер код(стр. 2, черновой, могут быть ошибки)
Также приведу одну из функций RTOS(код сырой, может содержать ошибки)
1. Метаданные класса: Компилятор автоматически формирует структуру для поддержки RTTI (Run-Time Type Information), необходимую для instanceof.
2. Динамическое создание объекта в куче: Код конструктора new Byte(0x08) транслируется в вызов менеджера динамической памяти (os_dram_alloc) и инициализацию полей.
3. Проверка типа (is / instanceof):
Оператор if(b1 is Byte) компилируется в вызов процедуры j8bproc_instanceof_nr, которая проверяет метаданные объекта.
4. Полиморфный вызов метода:
Вызов b1.toByte() через интерфейс Number преобразуется в универсальный механизм поиска и диспетчеризации метода.
5. Интеграция с системными сервисами:
Вывод в "консоль" (System.out) — это вызов системного сервиса ОСРВ.
Что это значит?
Это доказывает, что подход vm5277 работоспособен. Мы можем писать на высокоуровневом ООП-языке, а под капотом получать код, который:
Эффективно использует память: объекты размещаются в куче, метаданные компактны.
Сохраняет производительность: ключевые операции (выделение памяти, проверка типов) вынесены в оптимизированные ассемблерные процедуры.
Является переносимым: этот же Java-код, после завершения работы над платформами, сможет работать на PIC и STM8 (ограничений почти нет).
Я продолжаю работать над проектом универсального тулкита разработки программ для 8-битных микроконтроллеров.
Моя цель — создать единый ООП-язык (в стиле Java) с унифицированным API и HAL для 8-битных МК (AVR, STM8, PIC).
Хорошо подходящий слоган: «Написано один раз — работает на большинстве МК» (конечно, если это вообще возможно).
Сейчас я разрабатываю методику выделения памяти для примитивов внутри метода и его блоков (условные операторы, циклы и т. п.).
Основные два подхода:
- Динамическое выделение памяти на основе битовой карты блоков памяти.
- Выделение памяти непосредственно в стеке.
Похоже,
в итоге я приду к выводу, что первый вариант нужен для хранения полей
класса, а второй — для локальных переменных метода.
Судя по всему (подсказка от DeepSeek), всем известный язык C статически выделяет блок в стеке при входе в функцию, при этом:
- выделяет полный объем для хранения всех примитивов (даже тех, которые объявлены в блоках и могут не использоваться);
- не умеет и не позволяет освобождать выделенную память до завершения функции;
- использует дополнительный код для выделения и освобождения блока в стеке.
Теперь я понимаю, почему разработчики на C для МК с малыми ресурсами используют глобальные переменные.
Представьте,
сколько памяти потребуется, если в программе будет огромное дерево
условий, внутри которого разная логика и разные переменные.
Это действительно огромная трата RAM.
Разрабатывая своё решение, я планирую использовать выделение памяти в стеке только для переменных метода (без учёта блоков), а для каждого блока — отдельную процедуру выделения памяти.
Это позволит существенно экономить RAM.
Но, к сожалению, увеличит размер прошивки, так как для каждого блока потребуется около 16 слов для 16-битного SP и около 5 слов для 8-битного SP (вероятно для 16 бит я вынесу данный код в процедуру, уменя есть подобное решение в core5277).
И это необходимо для высокоуровневого ООП-языка.
Я также планирую добавить опцию в компилятор, позволяющую выбрать, что экономить: RAM или FLASH+CPU.
При выборе FLASH+CPU память будет выделяться статически, как в C.
В
общем, проблема C ясна:
Для каждой функции выделяется блок в стеке под
все переменные (даже неиспользуемые), и освобождается он только при
завершении функции.
В ассемблере же: Программист сам решает, как использовать память при входе в функцию. Часто память вообще не выделяется — многие значения хранятся в регистрах. То, что не помещается в регистры, можно сохранить одной инструкцией PUSH и восстановить POP. Можно закрепить ячейку RAM за функцией и использовать её без дополнительных накладных расходов. Даже
если использовать аналогичные C-подобные макросы, программист, скорее
всего, будет выделять память для конкретных блоков, а не резервировать
максимальный объём для всей функции. При этом он будет эффективно использовать регистры.
Вот такая огромная разница в оптимизации между ассемблером и C.
К сожалению, я тоже не смогу добиться максимальной оптимизации (как в ассемблере) в своём компиляторе.
НО! В моём тулките это не так критично, как могло бы быть. Дело в том, что множество низкоуровневых алгоритмов будет реализовано и оптимизировано на ассемблере. Драйверы также будут на ассемблере и будут использовать эти алгоритмы. Язык высокого уровня будет их активно применять (часть — прозрачно через кодогенератор компилятора, часть — через явные вызовы).
P.S.
Прошло 3 недели, за две из них я набросал AVR-ассемблер (не полностью,
но его функционала и гибкости достаточно для текущих нужд тулкита).
Конечно, я был бы рад использовать avra, но он содержит ошибки, из-за которых не получается собирать мои проекты.
P.P.S. Я сменил лицензию с GPLv3-or-later на Apache-2.0. Судя по всему, это допустимо, так как на данный момент я являюсь автором всего кода в проекте.