157 lines
14 KiB
Markdown
157 lines
14 KiB
Markdown
# 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 выполняет этот загрузчик.
|