Объедини реализацию DEIF в C99-ядре, чтобы Python и Android использовали один кодек и общие эталонные кадры. Добавь две GAS-проекции единой карты STM Invertor и аппаратные порты эмулятора и загрузчика для платы HOPE STM32G474VET6. Проверки: сборка MSVC Debug, 24 теста CTest, 30 тестов Python и 29 дополнительных проверок, синтаксис 16 файлов Python.
5.3 KiB
STM Invertor: GAS 0x03 и GAS SLOT 0x04
Узел: DeviceType 0x7, DeviceID 0xE. Обработчик set_invertor_gas_handle() выбирает формат только по MsgType и использует существующие кодеки pcan_gas и pcan_gas_slot.
| Доступ | Адреса | Содержимое |
|---|---|---|
GAS 0x03 |
Регистры 0x0000…0x02ED / 0…749 |
По 1…4 последовательных 16-битных значения; DLC 2/4/6/8 |
GAS SLOT 0x04 |
Слоты 0x0000…0x00F9 / 0…249 |
Word0 — маска; Word1…Word3 — три значения; DLC 8 |
Это две проекции одних 750 значений. Отдельного массива слотов нет. Для слота s и полезного слова w=1…3: Register=3*s+w-1. Обратное отображение: Slot=Register/3, Word=1+Register%3. Word0 не является регистром.
Начальные адреса относятся к узлу 7/E и не перенумеровывают PERIPH. Наличие 750 адресов не требует выделения 1500 байт сплошной RAM: provider обслуживает только существующие данные и явно отклоняет неподключённые значения.
Примеры
Запись регистра 1 значением 0x1234: ID 0x17E30001, DLC 2, Data 34 12.
Запись того же значения через слот 0 / Word2: ID 0x17E40000, DLC 8, Data 04 00 00 00 34 12 00 00. Word1 и Word3 сохраняются.
Чтение любого представления использует DLC=0, Route=0. Ответ имеет Route=1. Первый регистровый ответ использует ID 0x1FE30000, слотный — 0x1FE40000. Прикладного ACK записи нет; при необходимости результат применения проверяется чтением статуса устройства.
Прикладной порт
read(context, address, value) возвращает ноль для достоверного значения. Ошибка не подменяется успешным нулём. Регистровое чтение останавливается на первом недоступном адресе; слотный ответ отмечает маской каждую доступную позицию. Полностью недоступный слот не возвращает пустую успешную маску.
write(context, addresses, values, count) получает выбранные адреса единым набором. Provider сначала проверяет все права, диапазоны, состояния и значения, затем применяет набор под общей блокировкой. Неотмеченные позиции слота ему не передаются. Масочная запись не делает скрытого чтения и не требует перезаписывать readonly-соседей.
Регистровый адаптер сначала собирает все слова через существующий кодек 0x03. Он не вызывает write-provider при частичном выходе за 750 регистров. Усиленная проверка относится к этому адаптеру изделия и не меняет общий контракт блочной записи pcan_gas для остальных устройств.
Вызовы обработки одного экземпляра сериализуются приложением. Снимок чтения и применение записи защищает приложение; библиотека не включает прерывания, аппаратные разрешения или HAL. Наличие запроса на запись не подтверждает физическое выполнение команды силовой частью.
Клиентские привязки
set_invertor_gas_build() возвращает готовые CAN ID и октеты; set_invertor_gas_decode() — проверенные тип, адрес и wire-слова ответа. Python/JNI не повторяют endian, маски идентификатора или формулу адресации. Размеры карт получают через set_invertor_gas_limit().
set_invertor_gas_register() и set_invertor_gas_coordinate() возвращают проверенные координаты, не меняя выходы при отказе. Диспетчер не переводит повреждённый 0x04 в 0x03 и не принимает запросы соседнего узла либо эхо ответа как запись.
Тест test_invertor_gas.c проверяет оба wire-вектора, общий источник данных, маски, сохранение соседей, readonly, единственное применение набора, границы 249/749, ошибочные длины, флаги и адреса, а также клиентский ABI.