# F28335 + M95M02: CAN, отдельный загрузчик и A/B Реализация состоит из Flash-загрузчика `periph_167/Bootloader`, переносимого `f28335_boot_store.c`, аппаратного `f28335_boot_hw.c` и адаптера `f28335_can_boot.c`. Приложение подключает их через `Source/Internal/can_boot.c`. В сборке `EEPROM_M95M02=0` CAN Boot отключён. Для установленной M95M02 — значение 1. ## Адрес и формат Device Type **3**, Device ID **7**, имя **F28335-M95M02**, Product **0x2833**, HW **1**. В приложении FW берётся из `firmware_version.h`, формат `major<<24 | minor<<16 | patch`; для версии 1.1.2 это `0x01010002`. Загрузчик сообщает версию подтверждённого образа из журнала, при отсутствии такого образа — 0. Версия кандидата передаётся в BEGIN_COMPAT. CAN **250000 бит/с**, Extended ID, окно **16 блоков по 8 октетов**. ENTER_BOOT для session=1: `0x13790102`, STATUS: `0x1B7C0102`. Образ — SCI8 BIN (`AA 08`), чётная длина от 24 до **130560 байт** включительно. Числа в протоколе little endian. Адреса внутри SCI8: сначала старшее 16-битное слово, затем младшее; каждое слово little endian. В C28x `char` 16-битный, поэтому `pcan_boot_byte_t` хранит октет в младших 8 битах. ## Разметка EEPROM, байтовые адреса | Область | Начало | Конец включительно | Размер | |---|---:|---:|---:| | Журнал 0 | 0x00000 | 0x000FF | 256 | | Журнал 1 | 0x00100 | 0x001FF | 256 | | Slot A | 0x00200 | 0x1FFFF | 130560 | | Slot B | 0x20000 | 0x3FDFF | 130560 | | Резерв | 0x3FE00 | 0x3FEFB | 252 | | Параметры | 0x3FEFC | 0x3FFFD | 258 | | Последнее слово | 0x3FFFE | 0x3FFFF | 2 | В каждой странице журнала первые 64 октета содержат magic `FAB2`, версию 1, sequence, active/pending/attempted, два manifest, CRC32 первых 56 октетов и commit marker в октетах 60..63. Сначала обнуляется marker запасной страницы, затем записывается тело с проверкой чтением, последним — marker. Предыдущая страница остаётся действующей до полной публикации новой. Выбор sequence учитывает переполнение u32. После ошибки публикации журнал перечитывается; ошибка чтения блокирует последующие записи. ## Сценарий обновления и отката 1. Приложение принимает ENTER_BOOT, останавливает управление нагрузкой, выставляет 4 мА и выдерживает секундный STOP, затем сохраняет session в NOINIT RAM 0x50..0x57. Watchdog выполняет reset. ACK ENTER_BOOT отправляет уже Flash-загрузчик; приложение ничего не стирает. 2. BEGIN_IMAGE/BEGIN_COMPAT проверяют размер, Product, HW и сессию. Неактивный слот выбирается автоматически; при первом образе это A. ERASE инвалидирует только его manifest. Полного стирания EEPROM не требуется. 3. Последовательные DATA_A/B записываются с немедленным readback. VERIFY проверяет потоковый CRC32, CRC32 EEPROM и полную таблицу SCI8. Разрешена загрузка только в CPU word RAM `[0x8000,0xE000)`: максимум 64 секции, без пересечений, усечений и хвостовых данных; entry должен попасть в секцию. Запись в Flash, периферию, стек, RAM загрузчика и handoff запрещена. 4. COMMIT повторно проверяет образ и публикует pending в журнале. Подтверждённый слот сохраняется. Повтор COMMIT безопасен. REBOOT выполняется после физического CAN ACK ответа. Потеря ACK/тайм-аут передачи отменяет запрос reset. 5. Перед первым запуском кандидата загрузчик сохраняет attempted=1, затем проверяет и копирует SCI8 в RAM. Следующий reset без CONFIRM сбрасывает pending и запускает прежний active. Если прежнего образа нет — остаётся CAN recovery. 6. Новое приложение включает watchdog в начале запуска. До подтверждения прерывания не кормят watchdog вместо основного цикла. После READY, 100 проходов main и 5 секунд выполняется автоматический CONFIRM. Неудача сохранения подтверждения через 10 секунд прекращает кормление watchdog, вызывая откат. Адресная команда CONFIRM с ненулевой session также разрешена после READY. CONFIRM в загрузчике и до первого запуска кандидата отклоняется. PING, IDENTIFY и паспорт доступны без ENTER_BOOT. QUERY_PROGRESS/ABORT привязаны к сессии. Сессия в RAM истекает через 30 секунд без подходящих команд/данных. После reset передачу начинают заново; параметры и подтверждённый образ остаются. ABORT после COMMIT не отменяет опубликованный pending. Для его пробного запуска можно открыть новую сессию и отправить REBOOT. Pending запрещено перезаписывать. Повторы ENTER_BOOT, метаданных, ERASE до первого блока, VERIFY и COMMIT учитывают потерю ответа. Broadcast никогда не разрешает запись. ## Сервисные команды Запрос: MsgType=9, Body=`session<<8 | command`. IDENTIFY/PING/паспорт не требуют сессии. Ответ паспорта: MsgType=D, Body=`page<<8 | command`, DLC=8. | Код | Имя | DLC запроса | Ответ | |---:|---|---:|---| | 01 | IDENTIFY | 0 | Product:u16, HW:u8, protocol:u8, FW:u32; Body=1 | | 0C | PING | 0 | protocol, state, active, target, session, slot_count, last_status, 0 | | 0D | CAPABILITIES | 0 | flags:u32, slot_capacity:u32 | | 0E | DEVICE_NAME | 1 (page) | 8 ASCII-октетов имени; последний фрагмент с NUL | | 0F | MEMORY_INFO | 1 (page) | Страницы ниже | MEMORY_INFO 0: EEPROM bytes:u32, page bytes:u16, mode:u8 (0 app/1 boot), running:u8. Страница 1: адреса A:u32, B:u32. Страница 2: active, pending, attempted, storage_healthy, session_timeout_ms:u32. Страница 3: parameters_offset:u32, parameters_bytes:u32. Слот FF означает отсутствие образа/запущенного приложения. CAPABILITIES bits 0..11: ping, discovery, identify, name, memory, A/B, confirm, rollback, separate loader, session timeout, readback, SCI8 validation. Приложение, запущенное старым SPI ROM без handoff загрузчика, сообщает только базовые сервисы (0x1F) и отклоняет ENTER_BOOT. Обнаружение: MsgType=D, Body=0, DLC=0, Route=0. Адресный запрос или общий DeviceType=7/DeviceID=15. Ответ IDENTIFY приходит с адреса прибора через `2*(1+16*DeviceType+DeviceID)` мс. При нескольких одинаковых адресах конфликт остаётся: каждому физическому устройству нужен уникальный адрес. Python API: `protocan.can_boot.CanBootServices` — запросы и разбор паспорта; `CanBootTransfer` — загрузка. Кнопка «Пинг» доступна в режиме ProtoCAN Boot окна прошивки SETGUI. Для ENTER/VERIFY/COMMIT клиент ждёт до 15 секунд. ## Аппаратная интеграция MBOX3 — адресные входящие Boot; MBOX4 — ответы; MBOX6 — точный broadcast discovery. MBOX0..2 сохраняют legacy/UMP, MBOX5 остаётся heartbeat. ISR помещает сообщения в очередь на 31 кадр. Чужие адреса, RTR и неподходящие типы отбрасываются до очереди. При переполнении/потере mailbox сессия отменяется; повторная запись начинается заново. SPI-драйвер загрузчика имеет ограничение ожидания байта и WIP, 24-битный адрес, разбиение по страницам 256 байт и восстановление конфигурации SPI приложения. Он работает только при остановленном Timer2. Обычный Seeprom_write приложения ограничен областью параметров; старый RS EXTEND 0x44 запрещён для A/B. Загрузчик исполняется из внутренней Flash A 0x338000..0x33FF7F, entry 0x33FFF6. Его RAM — 0xE000..0xFFFF; стек — 0x400..0x7FF. Приложение M95M02 использует 0x8000..0xD7FF для кода, 0xD800..0xDFFF для констант/инициализации, 0xE000..0xFFFF для .ebss после перехода в C runtime. Linker резервирует NOINIT handoff в обоих проектах. CAN не содержит операций записи внутренней Flash. ## Первичная установка 1. Собрать приложение с EEPROM_M95M02=1 и обновлённым F28335.cmd; получить SCI8 BIN. Старые BIN/OUT автоматически не заменены. Приложение должно содержать интеграцию READY/CONFIRM, иначе на следующем reset оно останется неподтверждённым кандидатом. 2. Собрать отдельный загрузчик TI C2000 COFF compiler: `Bootloader/build.ps1 -CompilerRoot <путь-к-ti-cgt-c2000>`. Результат — `Bootloader/build/F28335_CAN_AB.out` и MAP. 3. Один раз установить этот OUT через JTAG и выбрать аппаратный Flash boot согласно схеме платы. Не загружать поверх него старый application OUT с секцией codestart во Flash. 4. После reset пустая EEPROM или старая разметка автоматически ведут в CAN recovery. Передать новое приложение через ProtoCAN Boot, дождаться пробного запуска и проверить MEMORY_INFO page 2: pending=FF, active=A. Затем проверить обновление в B. Старая SPI-ROM разметка с AA08 по адресу 0 несовместима с новым журналом. Первое обновление заменяет её; параметры по прежнему адресу сохраняются. Загрузчик не выполняет скрытую миграцию и не меняет boot pins программно. ## Проверки и границы проверенного `python c/protocan-boot/tests/run_tests.py` (переменная CC — clang/gcc) проверяет ядро, приложение/загрузчик, wide-octet режим, журнал, обрыв публикации на каждом из 69 возможных положений, пробный запуск, CONFIRM, откат, SCI8 и границы памяти. Python-тесты проверяют клиентские запросы, паспорт, фильтрацию ответов и лимит A/B. Проверка синтаксиса использует настоящие DSP2833x headers. Сборка TI/CCS, раскладка итогового MAP и физические CAN/SPI/reset на плате ещё не подтверждены. CRC32 защищает от повреждения, криптографической подписи и anti-rollback по версии в этом порту нет. Удалённый CONFIRM подтверждает готовность приложения, но не заменяет проверку датчиков/силовой части на стенде. Аппаратный формат SPI boot описан в [TI Boot ROM Reference Guide](https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/171/2742.Boot-ROM.pdf). В A/B-схеме ROM выбирает Flash, а разбор EEPROM выполняет этот загрузчик.