# F28335 + M95M02: CAN, отдельный загрузчик и A/B Реализация состоит из Flash-загрузчика `projects/ccs/f28335`, переносимого `f28335_boot_store.c`, аппаратного `f28335_boot_hw.c` и адаптера `f28335_can_boot.c`. Приложение подключает общий `f28335_can_application.c` прямой ссылкой linked resource из templates в CCS Debug/Release. В сборке `EEPROM_M95M02=0` CAN Boot отключён. Для установленной M95M02 — значение 1. ## Адрес и формат Адрес определяется физическим номером **PERIPH 0–31** по новой Excel-таблице: Type = 1 + PERIPH / 16 (целая часть), Device ID = PERIPH mod 16. **УМП1 — 1/5, УМП2 — 1/6, задатчик — 1/8**. Product **0x2833**, HW **1** описывают существующую аппаратную совместимость F28335 и не являются CAN-адресом. Имена паспорта для назначенных плат — `UMP1`, `UMP2`, `Zadatchik`. Приложение передаёт Mode в `F28335CanBoot_Init(Mode)`. Загрузчик независимо читает те же активные низким уровнем GPIO21/20/22/51 с весами 1/2/4/8 и базой 1. Поэтому существующие перемычки ПМ35 задают номера 1–16; номера 0 и 17–31 поддерживаются адресным контрактом, но требуют другого источника физического номера. Общий адрес 3/7 больше не принимается. Чужие адреса отбрасываются аппаратным mailbox, ISR и ядром до записи EEPROM, включая данные A/B и управляющие команды. В приложении FW берётся из `firmware_version.h`, формат `major<<24 | minor<<16 | patch`; для версии 1.1.2 это `0x01010002`. Загрузчик сообщает версию подтверждённого образа из журнала, при отсутствии такого образа — 0. Версия кандидата передаётся в BEGIN_COMPAT. CAN **250000 бит/с**, Extended ID, окно **16 блоков по 8 октетов**. Для задатчика и session=1: ENTER_BOOT `0x11890102`, STATUS `0x198C0102`. ## Общий запуск Flash и резервной EEPROM Сектор A и аппаратный boot `0x33FFF6` принадлежат постоянному загрузчику. Flash-приложение использует `[0x300000,0x338000)`: первые 16 слов — описание FAB1, остальные — собственные LOAD-секции. `f28335_flash_app.c` проверяет magic/version, entry, границы, инверсию entry, маркеры и CRC32 IEEE всего диапазона после заголовка, включая промежутки, заполненные `0xFFFF`. Python-контракт `python/protocan/f28335_flash.py` заполняет зарезервированные 32 октета COFF по смещению, подтверждённому TI OFD, после линковки. Загрузчик даёт трёхсекундное окно CAN, затем запускает исправную внутреннюю Flash в приоритете. Отсутствующая/повреждённая Flash ведёт к прежнему выбору EEPROM A/B с trial/CONFIRM/rollback. ENTER_BOOT удерживает CAN recovery. Handoff running=`0xFE` обозначает проверенную внутреннюю Flash; 0/1 — EEPROM A/B, `0xFF` — отсутствие запущенного приложения. Flash-приложение обслуживает PING и ENTER_BOOT, но не подменяет подтверждение EEPROM-кандидата. Обновление EEPROM по CAN не меняет приоритет исправной Flash после reset. RS Flash должен стирать только B–H, публиковать FAB1 после проверки остальных данных и запрещать любые адреса сектора A. В SETGUI соответствующие JTAG маски задаются явными TI `FlashSectorA..H`: A для установки boot, B–H для приложения. Полное стирание чипа внешним программатором не ограничивается linker. Старая самостоятельная Flash-сборка с codestart `0x33FFF6` несовместима с этим размещением и не должна передаваться как обновление приложения. Образ — 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 загрузчик не использует. 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: `python c/protocan-boot/projects/build.py --device f28335 --compiler <путь-к-ti-cgt-c2000>`. Результат — `projects/ccs/f28335/Debug/F28335_CAN_AB.out` и MAP. 3. Установить обновлённый OUT через JTAG и выбрать аппаратный Flash boot согласно схеме платы. При переходе с общего адреса 3/7 обновить и приложение, и загрузчик: старый загрузчик не перейдёт на новый адрес после reset сам. В SETCAN выбрать «Прошивка → CAN / ProtoCAN Boot → Устройство PERIPH» и нужное назначение. Не загружать поверх загрузчика старый 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 и реальные COFF LOAD-адреса проверены; физические CAN/SPI/reset на плате требуют стендовой проверки. Отдельные проекты и команды сборки описаны в [инструкции CCS](../../projects/README.md). 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 выполняет этот загрузчик. Проект предоставляет `f28335_can_application_config.h` в include paths. Он задаёт `F28335_CAN_BOOT_APPLICATION_ENABLED` (0/1) и при включённом модуле `F28335_CAN_BOOT_FIRMWARE_VERSION` из версии приложения. В 167 это ручной `firmware_version.h`; профиль включён только при M95M02 без `FLASH_BOOT`. Локальный `Source/Internal/can_boot.c` содержит только `F28335Boot_Quiesce` со штатной остановкой нагрузки. Общие `.c` повторно включать в него не нужно: они компилируются единственным linked resource общей библиотеки. Постоянный Flash-загрузчик по-прежнему собирается отдельным проектом `projects/ccs/f28335` и не линкуется в RAM-приложение.