О проекте: Пишем один код - собираем на разные 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:
import rtos.System;
import rtos.RTOSParam;
class Main {
interface Number {
byte toByte();
}
interface Test implements Number {
byte toByte();
void test();
}
public class Byte implements Test {
private byte value;
public Byte(byte value) {
this.value = value;
}
public byte toByte() {
return value;
}
public void test() {
}
}
public static void main() {
System.setParam(RTOSParam.STDOUT_PORT, 0x12);
Number b1 = new Byte(0x08);
if(b1 is Byte) {
System.out(b1.toByte());
}
}
}
Итоговый ассемблер код(черновой, могут быть ошибки)
.equ stdout_port = 18
.set OS_FT_DRAM = 1
.set OS_FT_STDOUT = 1
.include "devices/atmega328p.def"
.include "core/core.asm"
.include "dmem/dram.asm"
.include "j8b/inc_refcount.asm"
.include "j8b/dec_refcount.asm"
.include "j8b/instanceof.asm"
.include "j8b/clear_fields.asm"
.include "j8b/invoke_method.asm"
.include "stdio/out_num8.asm"
Main:
jmp j8bCMainMmain
;======== enter CLASS Main ========================
;======== enter CLASS Byte ========================
_j8b_meta10:
.db 15,2,13,1,14,2
.dw j8bC14CByteMtoByte,j8bC14CByteMtoByte,0
j8bC11CByteMByte:
ldi r16,6
ldi r17,0
mcall os_dram_alloc
std z+0,r16
std z+1,r17
std z+2,c0x00
ldi r16,low(_j8b_meta10*2)
std z+3,r16
ldi r16,high(_j8b_meta10*2)
std z+4,r16
mcall j8bproc_clear_fields_nr
_j8b_cinit12:
ldd r16,y+0
std z+5,r16
_j8b_methodend13:
ret
j8bC14CByteMtoByte:
ldd r16,z+5
jmp _j8b_methodend15
_j8b_methodend15:
ret
;======== leave CLASS Byte ========================
j8bCmainMmain:
push_z
ldi zl,low(_j8b_retpoint20)
push zl
ldi zl,high(_j8b_retpoint20)
push zl
ldi zl,8
push zl
jmp j8bC11CByteMByte
_j8b_retpoint20:
pop_z
mov r20,r16
mov r21,r17
_j8b_ifbegin22:
push_z
mov r30,r20
mov r31,r21
ldi r17,15
mcall j8bproc_instanceof_nr
pop_z
brne _j8b_ifend25
_j8b_ifthen23:
push_z
ldi zl,low(_j8b_retpoint21)
push zl
ldi zl,high(_j8b_retpoint21)
push zl
mov r30,r20
mov r31,r21
ldi r16,13
ldi r17,0
jmp j8bproc_invoke_method_nr
_j8b_retpoint21:
pop_z
mcall os_out_num8
_j8b_methodend19:
_j8b_ifend25:
_j8b_methodend18:
ret
;======== leave CLASS Main ========================
Одна из функций RTOS(код сырой, может содержать ошибки)
.IFNDEF J8BPROC_INVOKE_METHOD_NR
;-----------------------------------------------------------
J8BPROC_INVOKE_METHOD_NR: ;NR-NO_RESTORE - не восстанавливаю регистры
;-----------------------------------------------------------
;Переходим на код метода
;IN: Z-адрес HEAP,ACCUM_L-ид интерфейса, ACCUM_H-порядковый
;номер метода в интерфейсе
;-----------------------------------------------------------
PUSH_Z
ADIW ZL,0x03
LD ACCUM_EH,Z+
LD ZH,Z
MOV ZL,ACCUM_EH
ADIW ZL,0x01 ;Пропускаем ид типа класса
LPM ACCUM_EH,Z+ ;Получаем количество пар(ид интерфейс + кол-во методов)
MOV YL,ACCUM_EH ;Вычисляю адрес блока адресов методов
LDI YH,0x00
LSL YL
ROL YH
ADD YL,ZL
ADC YH,ZH
LDI TEMP_L,0x00 ;Порядковый номер метода в классе
_J8BPROC_INVOKE_METHOD_NR__IFACEIDS_LOOP:
LPM ACCUM_EL,Z+ ;Получаю id интерфейса
CP ACCUM_EL,ACCUM_L
BREQ _J8BPROC_INVOKE_METHOD_NR__GOT_IFACE
LPM ACCUM_EL,Z+ ;Получаю количество методов в интерфейсе
ADD ACCUM_H,ACCUM_EL
DEC ACCUM_EH
BRNE _J8BPROC_INVOKE_METHOD_NR__IFACEIDS_LOOP
_J8BPROC_INVOKE_METHOD_NR__GOT_IFACE:
POP_Z
LSL ACCUM_H ;Смещаюсь на адрес с учетом порядкового номера метода в классе
ADD YL,ACCUM_H
ADC YH,C0x00
PUSH_Y
RET
.ENDIF
Ключевые фрагменты сгенерированного ассемблерного кода:
1. Метаданные класса:
Компилятор автоматически формирует структуру для поддержки RTTI (Run-Time Type Information), необходимую для instanceof.
_j8b_meta10:
.db 15,2,13,1,14,2 ; <-- Вот эти метаданные класса `Byte`
.dw j8bC14CByteMtoByte, j8bC14CByteMtoByte, 0
2. Динамическое создание объекта в куче:
Код конструктора new Byte(0x08) транслируется в вызов менеджера динамической памяти (os_dram_alloc) и инициализацию полей.
j8bC11CByteMByte:
ldi r16,6 ; Размер объекта: 6 байт!
mcall os_dram_alloc
std z+5, r16 ; Инициализация поля `value`
3. Проверка типа (is / instanceof):
Оператор if(b1 is Byte) компилируется в вызов процедуры j8bproc_instanceof_nr, которая проверяет метаданные объекта.
mcall j8bproc_instanceof_nr ; Магия проверки типа происходит здесь!
brne _j8b_ifend25 ; Условный переход на основе результата
4. Полиморфный вызов метода:
Вызов b1.toByte() через интерфейс Number преобразуется в универсальный механизм поиска и диспетчеризации метода.
; invokeInterfaceMethod byte Number.toByte
ldi r16, 13
ldi r17, 0
jmp j8bproc_invoke_method_nr ; Динамический вызов метода!
5. Интеграция с системными сервисами:
Вывод в "консоль" (System.out) — это вызов системного сервиса ОСРВ.
mcall os_out_num8 ; Вывод числа через системный вызов RTOS
Что это значит?
Это доказывает, что подход vm5277 работоспособен. Мы можем писать на высокоуровневом ООП-языке, а под капотом получать код, который:
Эффективно использует память: объекты размещаются в куче, метаданные компактны.
Сохраняет производительность: ключевые операции (выделение памяти, проверка типов) вынесены в оптимизированные ассемблерные процедуры.
Является переносимым: этот же Java-like-код, после завершения работы над платформами, сможет работать на PIC и STM8 (ограничений почти нет).