# 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. Инициализация зависимостей ```bash # Клонирование и сборка внешних зависимостей make deps ``` Это клонирует следующие зависимости в `deps/`: - `tomlc99` — TOML парсер - `ptQueue` — lock-free очередь - `wsServer` — WebSocket сервер - `flatcc` — FlatBuffers runtime для C - `flatbuffers` — Google FlatBuffers (flatc компилятор) ### 2. Генерация FlatBuffers кода ```bash # Генерация C заголовков из .fbs схем make proto # Генерация Python bindings (опционально) make python-proto ``` ### 3. Сборка эмулятора ```bash # Основная сборка make build # Полная пересборка make rebuild # Очистка make clean ``` После успешной сборки исполняемый файл будет находиться в `out/main.elf`. ## Быстрый старт ### 1. Подготовка конфигурации Создайте TOML-файл с конфигурацией эмулятора: ```toml # example.toml [dev] avr = "devices/avr_generic/AVRrc.toml" [clock] limiter = 16000000 # 16 MHz [mem] # Настройка памяти ``` ### 2. Запуск эмулятора ```bash ./out/main.elf example.toml ``` Эмулятор запустит WebSocket сервер на порту **8181**. ### 3. Подключение клиента Используйте Python-клиент для подключения: ```bash cd ../hmmmm_client_py poetry install poetry run python -m model.client ``` ## Конфигурация ### TOML-конфигурация устройства Пример конфигурации AVR устройства: ```toml [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 ``` ### Композиция устройств Сложные устройства создаются через композицию: ```toml [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** — потоковые изменения памяти ### Аутентификация ```python 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`: ```c 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: ```bash ./.gen_compile_commands.sh ``` ### Логирование Эмулятор выводит отладочную информацию в stdout. Для подробного логирования можно модифицировать `src/main.c`. ### GDB ```bash 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