# Универсальное адресное пространство эмуляторов Общий код находится в `templates/c/set-protocol`. Прошивка платы задаёт память, GPIO и аппаратные callbacks; протокол и модели не включают STM32/HAL/USB/ОС, не выделяют heap и не читают системное время. Все вызовы одного экземпляра сериализуются главным циклом или блокировкой вызывающего. ## Слои и точка расширения - `set_regmap.h/.c`: таблица непересекающихся регионов и общий вызов `set_regmap_request(map, function, address, value, out, capacity, &count)`. Function 3 читает `value` слов, function 6 пишет одно слово. - `set_emu_ump`, `set_emu_tms`, `set_emu_igbt`, `set_wavegen`: независимые экземпляры моделей. Callbacks получают **относительный offset**, а не внешний адрес. Один модуль можно разместить несколько раз по разным адресам. - `set_emu_server`: готовая композиция для текущего стенда, режим УМП/2812, подготовка настроек с применением через 500 тиков. - `set_regmap_rtu` и `set_regmap_can`: готовые транспортные кодеки над одной картой. `set_emu_server_rtu/can` дополнительно сохраняют legacy поведение стенда. USB CDC, UART, TCP или иной поток только доставляет полный RTU-кадр. Другой протокол разбирает собственную оболочку и вызывает `set_regmap_request`. Вызов с неизвестной функцией возвращает 1; неизвестный адрес, RO-запись, чтение через границу региона — 2; неверное значение или размер буфера — 3; ошибка аппаратного порта — 4; занятый модуль — 6. При ошибке `count=0`. Длина успешного чтения равна запрошенной, запись возвращает адрес/значение. Максимум — 124 слова. RTU-обёртка требует буфер 253 байта до выполнения команды; CAN — 124 слова. Недостаточный буфер не может выполнить запись без ответа. При ошибке содержимое выходного буфера не используется. `set_regmap_init` проверяет границы 16-битного пространства, пересечения, права и callbacks. Таблица и состояния принадлежат вызывающему и должны жить дольше карты. После регистрации таблица неизменна; для изменения карты инициализируйте её заново в момент, когда нет обслуживаемых запросов. ## Каталог и стандартная карта Каталог доступен на адресе 0 через любой транспорт. | Слово заголовка | Значение | |---|---| | 0 | 0x5345, сигнатура SE | | 1 | версия каталога 1 | | 2 | количество регионов | | 3 | начало дескрипторов: 8 | | 4 | длина дескриптора: 8 | | 5 | максимум слов в одном чтении: 124 | | 6, 7 | резерв: 0 | Дескриптор: `kind, version, instance, base, words, flags, 0, 0`. Flags: bit0 чтение, bit1 запись. Права описывают возможности региона; отдельные регистры внутри могут быть только для чтения. Пропуски внутри региона возвращают ошибку, если модуль их не поддерживает. | Kind | Стандартный адрес | Размер | Модуль | |---|---|---|---| | 1 | 0x1000 | 0x17C | УМП: статус, окно, онлайн | | 2 | 0x1200 | 36 | управление, конфигурация и indexed capability | | 3 | 0x1300 | 8 | генератор DAC | | 4 | 0x1400 | 112 | IGBT, версия 3 | | 5 | 0x1500 | 80 | 2812 через регистры | | 6 | 0x2000 | capacity × 40 | архив/банк УМП | | 7 | 0xA000 | wave capacity | таблица DAC | Эта карта — готовая композиция, а не требование к новым платам. `set_regmap` позволяет выбирать адреса, подмножество и несколько экземпляров модуля; каталог сообщает фактическую карту. Настройка UART и выбор УМП/2812 принадлежат только готовому `set_emu_server`. Максимальная ёмкость УМП в этой карте — 819 записей на банк; текущая STM32 использует 800. В режиме 2812 прямое обращение к регистрам УМП возвращает busy, legacy RTU/CAN к этим диапазонам игнорируются для совместимости. Остальные сервисы и каталог доступны. Регистры управления 2812 принимают запись только в режиме 2812. Чтение его состояния не запускает модель. ## IGBT Предыдущий локальный диапазон IGBT 0x1300 конфликтовал с DAC. Его alias сохранить нельзя: он обращается к генератору. Используйте каталог kind=4 или новый стандартный адрес 0x1400. | Offset | Назначение | |---|---| | 0, 1 | 0x4947, версия 3 | | 2 | enable 0/1; выключение сразу очищает состояние RX и ожидаемые ACK | | 3 | чтение последнего TX; запись подготовленной TX-маски | | 4 | RX-маска | | 5 | резерв 0 | | 6 | FAULT-маска 0…255 | | 7 | задержка ACK 0…1000 мс | | 8 | ширина ACK 1…255 мс | | 9 | счётчик фронтов modulo 65536; запись 0 сбрасывает | | 10 | число каналов 8 | | 11 | один шаг модели = 1 мс | | 12 | источник TX: 0 переданные GPIO, 1 подготовленная маска | | 13 | подготовленная TX-маска, чтение/запись | | 14 | запись маски запуска одиночного TX; чтение 0 | | 15 | длина записи канала: 12 слов | Версия 3 сохраняет первые 14 регистров. Общие delay/width при записи устанавливают значения для всех каналов; при чтении показывают последнее общее задание, а не поканальные значения. Полное состояние: FC03 0x1400 / 112 слов. Запуск TX требует enabled=1, source=1, разрешённого TX канала и низкого TX; повторный запуск высокого TX отвергается кодом 6. Длительность отсчитывает сама модель, не клиент COM. Ручная запись TX отменяет все текущие TX-импульсы. Выключение эмуляции отменяет импульсы и сбрасывает их TX; статическое задание TX сохраняется. PB остаются входами: тестовый TX — внутренняя подстановка, физическая обратная связь RX выводится на PC0…PC7. Поканальные регистры: `0x1410 + 12 * channel`, channel=0…7. | Offset канала | Значение | |---|---| | 0 | flags: bit0 разрешение TX, bit1 разрешение RX, bit2 ACK active-low | | 1 | RX mode: 0 ACK, 1 физический 0, 2 физическая 1, 3 пропуск ACK | | 2, 3 | задержка ACK ON 0…1000 мс, ширина 1…1000 мс | | 4, 5 | задержка ACK OFF 0…1000 мс, ширина 1…1000 мс | | 6 | одиночный TX: 1…60000 мс | | 7 | маска фронтов для ACK: bit0 ON, bit1 OFF | | 8 | ширина FAULT 1…60000 мс; 0 — удержание до снятия FAULT | | 9 | RO счётчик фронтов канала, modulo 65536 | | 10, 11 | RO оставшаяся задержка / длительность ACK в мс | Изменение flags/mode отменяет ожидаемый и активный ACK канала. Отключённый RX и выключенная модель всегда дают физический 0. Инверсия применяется к автоматическому ответу и idle при пропуске ACK; ручные уровни 0/1 не инвертируются. Сброс общего счётчика сбрасывает и канальные. FAULT моделирует длинный/удерживаемый ответ после фронта; это не модель Vce, Vge, DESAT, внутренней защиты или блокировки конкретного силового драйвера. `set_igbt_tick(state, pins)` получает маску входов от порта платы. Фронт на тике T запускает ACK на T+delay. Повторный фронт до начала ACK перезапускает задержку; это определённая модельная обработка слишком частых команд. Каждый из восьми каналов независим. FAULT удерживает RX после его активации; снятие FAULT освобождает только ранее аварийные каналы и сохраняет обычные ACK. Чтобы TX через регистры не перезаписывался GPIO, выберите source=1. **Текущая IGBT-модель имеет шаг 1 мс.** Она проверяет логическую последовательность Vin/Vstat, но не воспроизводит ACK 250/380 нс и ширины профилей 1SP/1SD в DSLogic. Такую аппаратную точность нельзя получить переносом модели или вызовом из SysTick: для неё требуется отдельный быстрый аппаратный порт и соответствующая модель времени. ## 2812 Состояние едино для legacy CMD_STD и адресного API: | Offset | Назначение | |---|---| | 0, 1 | 0x544D, версия 1 | | 2, 3, 4 | running, частота и задание (int16 ×100 Гц) | | 8…11 | четыре подготовленных analog int16 | | 12…17 | шесть подготовленных управляющих байт (значение 0…255) | | 18 | записать 1: атомарно применить подготовленную команду | | 32…45 | 28 байт дискретов; младший байт слова — первый байт | | 46…79 | 34 аналоговых int16 | | остальные | чтение 0 | Модель остаётся упрощённой BALZAM_7: Go, выбор remote, Setspeed, разгон 10 Гц/с и синтетическая телеметрия. Legacy CMD_STD имеет отдельный адрес 2812, запрос 18 и ответ 101 байт, с проверкой CRC до изменения состояния. Буфер ответа менее 101 байта запрещает выполнение команды. ## УМП и DAC УМП сохраняет прежние записи по 40 слов, банк/архив, фронтовой триггер, постинтервал 1000 мс и indexed-чтение без изменения курсора. Два разных буфера по `capacity*40` слов предоставляет плата. Размещение SRAM/CCM не является частью библиотеки. DAC использует прежний `set_wave_port` с `start/stop`, транзакционную загрузку, commit, чтение таблицы и запрет изменений при работе. Регистровые callbacks и прежний `set_wave_rtu` вызывают одну реализацию. До повторного init вызывающий останавливает аппаратный вывод; библиотека не угадывает текущее состояние DMA. ## Обёртки и новая плата Пример: [ports/example-emulator/service.c](../ports/example-emulator/service.c). Он регистрирует два экземпляра IGBT и показывает прямой, RTU и CAN вызов. Порт новой платы должен: 1. Создать состояния и таблицу регионов, вызвать init и проверить результат. 2. Предоставить буферы и аппаратный DAC-порт, если нужен генератор. 3. Передавать реальные тики и входы; читать результат модели и обновлять GPIO. 4. Доставлять запросы через выбранную оболочку в одну карту, сериализуя доступ. CAN-envelope совместим с UMP: BE address/value/0x1F00/token/function. Идентификаторы CAN и маршрутизацию задаёт порт. Ответ делится по два слова, нечётное чтение дополняется нулём до чётного числа; клиент отбрасывает последнее слово по длине исходного запроса. Токен 1…255; один незавершённый ответ на соединение. Проверенная копия слов хранится до отправки всех фрагментов. `set_emu_stream` — только сборщик известных запросов FC03/FC06 и CMD_STD, по одному экземпляру на поток. Он принимает монотонные uint32 миллисекунды, сохраняет кадр между USB-пакетами, сбрасывает незавершённый после паузы >1000 мс и восстанавливается после плохого CRC. Это не универсальный Modbus-парсер FC16/FC23: для другого формата нужна другая тонкая оболочка. ## Сборка и проверки C99-ядро подключается через `setprotocol_static`/DLL, определения публичного API экспортируются через PCAN_ABI_API. Включить `set_regmap.h` или `set_emu_server.h`. Для иной архитектуры проверить наличие uint8/16/32_t; существующий 16-битный C28x octet-порт UMP остаётся отдельным, этот новый байтовый API пока не проверен TI-компилятором. `test_emulator_services.c` проверяет каталог, пересечения, границы и короткие буферы, два экземпляра, переназначение адресов, RTU/CAN/stream, совместное состояние 2812 и DAC, длинные задержки IGBT и освобождение FAULT. Существующие тесты прошивки дополнительно проверяют архив УМП, USB-фрагментацию, смену режима/адресов и совместимость с декодерами SETGUI. ## Выбор единственного эмулятора В SETGUI: «Эмулятор → Настройки STM → Тип эмулятора», затем «Применить в STM и проверить» и «Открыть управление эмулятором». Конфигурация версии 3: режим 0 — УМП, 1 — 2812, 2 — IGBT, 3 — ЦАП. Регистр 0x1219 подготавливает режим; 0x1218 = 0xA55A применяет его через 500 мс после подтверждения. Статус FC03 0x1210 / 10 слов содержит версию 3, действующий режим в слове 8 и подготовленный в слове 9. При смене режима останавливаются TIM6/DMA/DAC, ЦАП устанавливается в ноль, IGBT отключается и его выходы обнуляются, 2812 сбрасывается, УМП останавливается. Новый режим не запускается автоматически. Для IGBT нужно явно включить эмуляцию; для ЦАП заново загрузить таблицу и дать команду пуска. Повторное применение того же режима не прерывает текущую работу. Записи невыбранным IGBT/ЦАП/2812 отклоняются с кодом 6; чтение статуса и явные команды остановки IGBT/ЦАП доступны. Настройки связи доступны всегда. После сброса выбран УМП, IGBT выключен, ЦАП не запущен.