Files
hmmmm/README.md

8.5 KiB
Raw Permalink Blame History

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 для C
  • flatbuffers — 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. Все права защищены.

Контакты