В связи с тестированием сетевых блокировок в РФ на стороне нашего хостинг-провайдера наблюдаются проблемы с сетью. Сайт может работать нестабильно. Проблема известна, ожидаем восстановления маршрутов.
Авторизация
или войдите через
Забыли пароль?Восстановить
Восстановить пароль
Помощь проекту
Укажите в комментарии свой ник, чтобы мы знали, кого благодарить
Пример теста производительности основанный на подсчете 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, продуманная архитектура и планы на
будущее. Это не просто идея — уже можно компилировать и смотреть на
результат.
О проекте: Пишем один код - собираем на разные 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. Судя по всему, это допустимо, так как на данный момент я являюсь автором всего кода в проекте.
Всем, кто захочет покичиться своими знаниями лингвистики, рекомендуется ознакомится со словарями и комментариями к посту
Наверное невозможно найти человека, который бы никогда не встречал программ на Java. Сначала телефоны с J2ME, потом Android, который использует свои варианты реализации JVM и свой байткод. Даже многие сим-карты внутри используют свою оптимизированную разновидность Java.
Даже JavaScript обязан своим названием популярности Java, хотя и не имеет с ней прямого родства. (При этом некоторый промежуток времени существовали Java-апплеты)
3 миллиарда устройств уже 18 лет исполняют программы на Java
По официальной информации, 23 мая 1995 года, ровно 30 лет назад, Sun Microsystems выпустили первую бета-версию Java. Первая полноценная официальная версия JDK 1.0 выйдет только 23 января 1996.
Изначально язык должен был называться "Oak" (дуб, который рос рядом с офисом разработчиков), после чего был переименован "Green" (зеленый), а потом в честь кофе с острова Ява. А в качестве целей языка ставились:
Простота, объектно-ориентированность и знакомость.
Надежность и безопасность.
Независимость от архитектуры и переносимость.
Высокая производительность.
Интерпретируемость, многопоточность и поддержка динамического программирования.
Синтаксис был практически полностью позаимствован из C++, который уже был знаком многим программистам. Были выброшены процедурные артефакты C в виде "бродячих" глобальных переменных и функций, всё должно принадлежать классам. Также выбросили некоторые "неудачные" решения C++, к примеру дружественные классы, множественное наследование (его заменили интерфейсы), перегрузку операторов (зачем?!) и еще немного. Вместо ручного управления памятью было решено внедрить сборщик мусора, чтобы облегчить разработку и снизить количество ошибок и уязвимостей.
Главной особенностью языка стала концепция "напиши единожды, запускай везде" (хотя правильнее это будет назвать "напиши единожды, отлаживай везде" из-за различных реализаций и окружения), возможная благодаря тому, что код сначала компилируется в стандартизированный и независимый от процессора байткод для виртуальной машины (JVM), а в машинный код переводится только на машине потребителя, учитывая её архитектуру и особенности. Получается что-то среднее между интерпретируемым и компилируемым языком.
Вместо Swift там должен быть Rust
Язык получился... интересным.
То, что планировалось простым, в итоге превратилось в многословное нечто, а в сочетании со всякими архитектурными извращениями стало притчей во языцех о громоздкости корпоративного стиля. Потом появились совместимые с JVM альтернативы по типу Kotlin, ибо Java старательно игнорирует и не вводит ничего, что бы могло замазать многословность и неудобство. Android давно официально рекомендует использовать его вместо Java.
Добиться высокой скорости на интерпретируемом языке со сборкой мусора тоже проблемно. JIT замедляет запуск и жрет память, AOT поддерживается плохо и с ним невозможно реализовать некоторые вещи (кодогенерацию, к примеру), плюс остается сборщик мусора. Плюс некоторые не очень удачные решения и ограничения, тоже не способствующие высокой производительности (видно на контрасте с C#, в котором их исправили).
Тем не менее, Java на очень долгое время стала самым востребованным языком и отлично продолжает жить и сейчас, находясь на 4 месте популярности по версии TIOBE и дважды становясь языком года (в 2005 и 2015).
«Языки делятся на те, которые все ругают, и на которых никто не пишет» - Бьерн Страуструп
Недавно, и вполне заслуженно меня назвали по сути динозавром. Потому что я предпочитаю assembler вместо Си.
Но речь сейчас о другом.
Просто представьте, что уже много лет(лет 10 минимум) есть решение, позволяющее писать единый код практически на все платформы(linux, winodows, macos, android, ios и даже web).
Это решение зародилось давным давно, зовут его JavaFX, вроде как официальный выход - 2008 год.
Это очередной шедевр от Sun Microsystems, который до сих пор(без какого-либо развития данной библиотеки) прекрасно себя чуствует и имеет существенные достоинства по сравнению с соврменными решениями.
Для вас flutter весом? А с JavaFX сравнивали?
А еще есть компания GluonHQ, которая стала его поддерживать и развивать.
Просто подумайте - то что я говорю - является единственным решением позволяющим действительно писать один код для всех платформ. При этом организация UI просто на высшем уровне.
Почему эти наработки не в топе? А в топе флаттеры и веб фреймворки?
Давайте знакомиться) Меня зовут Макс Атыгаев. Я занимаюсь программированием всю сознательную жизнь) с юности и до сих пор)
Я пробовал Android разработку и даже выпустил пару приложений в Google Play, но потом понял что мир бекенда мне нравится больше.
Где-то в 2016 я открыл для себя Telegram и полюбил разработку ботов) Самый любимый проект - пересылка между групповым чатом в вк и групповым чатом в телеграм. То есть словно соединить два чата на разных сервисах в один)
Сейчас работаю в российской компании, в свободное от работы время веду канал на YouTube, RuTube, Telegram. В 2019 году начал консультировать и обучать людей программированию на Java.
Если у вас есть какие-нибудь вопросы к действующему разработчику то смело пишите) обсудим в комментах или сделаю отдельный пост)
Решил начать изучать java для себя. С нуля, прям вообще (школьный курс qbasic, думаю, можно не вспоминать). И сразу столкнулся с проблемой исполнения Hello World. Java Runtime поддерживает версии до 52.0, JDK от Oracle уже 55.0. Что нужно сделать, чтобы версии совместить. В интернете инфы не нашёл. Хотя бы ткните носом где искать.