8.5 KiB
hmmmm
Модульный эмулятор микроконтроллеров с сетевым интерфейсом
hmmmm — это эмулятор микроконтроллеров, который позволяет эмулировать AVR и другие архитектуры с возможностью управления через WebSocket. Эмулятор поддерживает динамическую загрузку устройств, композицию сложных устройств и потоковую передачу изменений памяти в реальном времени.
Возможности
- Эмуляция AVR-микроконтроллеров — поддержка ~99 инструкций AVR
- Модульная архитектура — устройства загружаются как динамические библиотеки (.so)
- Композиция устройств — создание сложных устройств через TOML-конфигурацию
- WebSocket интерфейс — управление эмуляцией и получение данных в реальном времени
- Потоковая передача — подписка на изменения памяти (чтение/запись)
- Аутентификация — SHA-512 токен с временным окном (TOTP-подобный)
- Сегментированная память — PS (программная), GP_REGS, IO_REGS, DS (данные)
Структура проекта
hmmmm/
├── src/ # Исходный код эмулятора
│ ├── main.c # WebSocket сервер, главный цикл
│ ├── hmmmm.c # Загрузка динамических библиотек
│ ├── config.c # Парсинг TOML-конфигураций
│ └── proto/ # Обработчики WebSocket-протокола
├── inc/ # Заголовочные файлы
├── devices/ # Реализации эмулируемых устройств
│ ├── avr_generic/ # Универсальный эмулятор AVR
│ └── avr_gpio/ # GPIO устройство
├── flatbuffers/ # FlatBuffers схемы протокола
├── deps/ # Внешние зависимости
├── hmmmm_scripts/ # Python скрипты и утилиты
└── Makefile # Основной файл сборки
Требования
- GCC с поддержкой C23
- OpenSSL (для SHA-512)
- Git (для клонирования зависимостей)
- Python 3.12+ (опционально, для скриптов)
Сборка
1. Инициализация зависимостей
# Клонирование и сборка внешних зависимостей
make deps
Это клонирует следующие зависимости в deps/:
tomlc99— TOML парсерptQueue— lock-free очередьwsServer— WebSocket серверflatcc— FlatBuffers runtime для Cflatbuffers— Google FlatBuffers (flatc компилятор)
2. Генерация FlatBuffers кода
# Генерация C заголовков из .fbs схем
make proto
# Генерация Python bindings (опционально)
make python-proto
3. Сборка эмулятора
# Основная сборка
make build
# Полная пересборка
make rebuild
# Очистка
make clean
После успешной сборки исполняемый файл будет находиться в out/main.elf.
Быстрый старт
1. Подготовка конфигурации
Создайте TOML-файл с конфигурацией эмулятора:
# example.toml
[dev]
avr = "devices/avr_generic/AVRrc.toml"
[clock]
limiter = 16000000 # 16 MHz
[mem]
# Настройка памяти
2. Запуск эмулятора
./out/main.elf example.toml
Эмулятор запустит WebSocket сервер на порту 8181.
3. Подключение клиента
Используйте Python-клиент для подключения:
cd ../hmmmm_client_py
poetry install
poetry run python -m model.client
Конфигурация
TOML-конфигурация устройства
Пример конфигурации AVR устройства:
[device]
type = "avr_generic"
libpath = "devices/avr_generic/AVRrc_build/device.so"
firmware = "test.bin"
[memory]
ps_size = 65536 # Program space
ds_size = 4096 # Data space
io_regs = 256 # I/O registers
gp_regs = 32 # General purpose registers
Композиция устройств
Сложные устройства создаются через композицию:
[dev]
core = "avr_generic.toml"
gpio_a = "avr_gpio.toml"
[clock]
limiter = 16000000
[mem.intercept.PORTA]
base_at = "core"
point_at = "gpio_a"
addr = 0
seg = "reg_io"
Протокол
Эмулятор использует FlatBuffers over WebSocket для обмена сообщениями.
Типы сообщений
Клиент → Сервер:
- AuthRequest — аутентификация (SHA-512 токен + timestamp)
- ExecCtrlMessage — управление эмуляцией (старт/стоп/сброс)
- MemReadRequest/MemWriteRequest — операции с памятью
- StreamRegRequest — подписка на изменения памяти
Сервер → Клиент:
- AuthResponse — подтверждение аутентификации (seat_id)
- ExecNotifyMessage — уведомления о состоянии эмуляции
- MemReadResponse — данные из памяти
- StreamDataPush — потоковые изменения памяти
Аутентификация
import hashlib
import time
def generate_auth(access_token: str) -> bytes:
now = int(time.time())
prepared = f'{access_token}{now // 30}'
return hashlib.sha512(prepared.encode()).digest()
Токен действителен в течение 30 секунд.
API устройств
Каждое устройство должно экспортировать интерфейс device_lib_t:
typedef struct {
uint8_t devType;
device_public_context_t* (*init)(void*, char* errbuf);
uint8_t (*makeDeviceTick)(device_public_context_t* devInfo);
void* extendedHandlers;
void* (*parseSpecsFromConfig)(const conf_dev_t* devConf, char* errbuf);
void (*freeSpecs)(void* specs);
void (*freeDevMem)(device_mem_t* mem);
void (*fillSmartReadSpecs)(void* specs, smart_read_spec_t*, uint64_t);
void (*fillSmartWriteSpecs)(void* specs, smart_write_spec_t*, uint64_t);
} device_lib_t;
Отладка
Генерация compile_commands.json
Для интеграции с clangd:
./.gen_compile_commands.sh
Логирование
Эмулятор выводит отладочную информацию в stdout. Для подробного логирования можно модифицировать src/main.c.
GDB
gdb ./out/main.elf
(gdb) run example.toml
Производительность
- Тактовая частота — до 16 MHz (эмулируемая)
- WebSocket — асинхронная отправка сообщений
- Lock-free очереди — эффективный межпоточный обмен
- FlatBuffers — сериализация с нулевым копированием
Известные ограничения
- Абсолютные пути в конфигурационных файлах (требует замены на относительные)
- Хардкод токена аутентификации (требует выноса в ENV)
- Отсутствие graceful shutdown (обработка SIGINT/SIGTERM)
- Нет unit-тестов для основного кода
Лицензия
Проект разработан @nikto_b. Все права защищены.
Контакты
- Документация: https://about.hmmmm.nikto-b.ru/
- Автор: @nikto_b