251 lines
8.5 KiB
Markdown
251 lines
8.5 KiB
Markdown
# 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
|