feat(protocan-boot): Добавь порты MCU и сервисы загрузки

Обеспечь единый процесс обновления для STM32F103/F407/G474 и TMS320F2812/F28335: discovery, служебные ответы, BUSY, тайм-аут сессии и подтверждение приложения. Добавь самостоятельные проекты CCS, аппаратные хранилища и Python-клиент.

Совместимость: структуры конфигурации и порта расширены, поэтому потребители должны пересобраться и обнулить новые поля. Для C28x callbacks используют pcan_boot_byte_t; периодический pcan_boot_poll обслуживает discovery и настроенный тайм-аут.
This commit is contained in:
2026-10-23 14:16:19 +03:00
parent 876b58517c
commit c6390ae1c9
147 changed files with 42760 additions and 104 deletions
+4
View File
@@ -0,0 +1,4 @@
# Служебные и выходные файлы CCS остаются локальными; исходники проектов хранятся выше этих каталогов.
ccs/*/Debug/
# Release использует собственные объекты, метаданные и архивы, чтобы не смешивать конфигурации.
ccs/*/Release/
+207
View File
@@ -0,0 +1,207 @@
# Отдельные проекты CCS: F28335 и F2812
Весь комплект находится внутри `templates/c/protocan-boot`: проекты CCS,
исходники загрузчиков, аппаратные порты, linker command files, необходимая
поддержка TI, CLI-сборка, тесты и документация. Зависимости от исходников
`28335_periph` и `BALZAM_167` при сборке отсутствуют. Требуется установленный
TI C2000 compiler с поддержкой **COFF ABI**; проверена версия **22.6.0.LTS**.
| Проект CCS | Контроллер | Обновляемая память | Схема |
| --- | --- | --- | --- |
| `ccs/f28335` — `F28335_CAN_AB` | TMS320F28335 | M95M02, 256 КиБ | A/B, trial, CONFIRM, rollback |
| `ccs/f2812` — `F2812_CAN_NOR` | TMS320F2812 / ПМ67 | AM29LV800BT-70EI, 1 МиБ, x16 | Один выделенный NOR-слот, проверяемый manifest, CAN recovery |
F2812 не использует EEPROM. Его карта, GPIO, частота CAN, допустимые адреса
приложения и состояние протокола отделены от F28335.
## Открытие в Code Composer Studio
1. **Project → Import CCS Projects**, каталог поиска — `c/protocan-boot/projects/ccs`.
2. Выбрать `F28335_CAN_AB` и `F2812_CAN_NOR`. Оставить проекты в исходном
расположении: **не включать Copy projects into workspace**, поскольку
переносимые ссылки `PCAN_ROOT` ведут к общей библиотеке выше проектов.
3. Выбрать **Debug** либо **Release**, затем **Build Project**. Оба проекта
содержат собственные `.project`, `.cproject`, `.ccsproject`.
4. OUT/MAP появятся в `ccs/<контроллер>/<Debug|Release>/`.
В `targetConfigs` сохранены существующие конфигурации Sauris SAU510:
F28335 — Iso Plus v.2, F2812 — Iso Plus. Для другого адаптера выбрать свой
Connection в Target Configuration. Компиляция и импорт не подключаются к JTAG
и не программируют плату.
Для отдельных workspace с ограниченными правами CCS допускает переменную
`TI_APPDATA_DIR` с доступным для записи каталогом. Это служебный cache IDE,
он не относится к исходникам загрузчиков.
## Сборка без запуска IDE
Из корня **templates**:
```powershell
python c/protocan-boot/projects/build.py --device f28335
python c/protocan-boot/projects/build.py --device f2812
python c/protocan-boot/projects/build.py --device f28335 --configuration Release
python c/protocan-boot/projects/build.py --device f2812 --configuration Release
```
Можно передать `--compiler <каталог-ti-cgt-c2000>` и `--output <каталог>`.
Скрипт читает состав исходников и настройки из этих же CCS-проектов, полностью
пересобирает их и проверяет реальные COFF LOAD-адреса официальным `ofd2000`.
Проверка отклоняет загружаемый RAM-код без Flash LOAD, пересечения, отсутствующие
boot branch/C entry, запись CSM/OTP и посторонних внутренних секторов.
Рядом с OUT сохраняются MAP, `build.log` и manifest с SHA-256.
Результаты:
- `ccs/f28335/Debug/F28335_CAN_AB.out`;
- `ccs/f2812/Debug/F2812_CAN_NOR.out`.
OUT — постоянный загрузчик для первоначальной установки через JTAG во
**внутреннюю Flash** соответствующего TMS. Образ самого приложения передаётся
по CAN в его внешнюю память. Для автоматического запуска должен быть выбран
внутренний Flash boot; у ПМ67 необходимо также учитывать штатную логику CPLD
выбора источника reset/boot из `big_dsp_module` платы.
## Prebuild/postbuild и копирование в SETGUI
В `.cproject` обоих проектов настроены **Debug и Release**. Prebuild вызывает
`projects/build.py --step prepare`: сохраняет UTC, Git-ревизию templates,
контроллер, конфигурацию и SHA-256 исходников в
`${BuildDirectory}/generated/canboot_build.json`. Это внешний паспорт сборки
загрузчика; номер версии приложения 167 не изменяется.
Postbuild вызывает тот же скрипт с `--step postbuild`. Он требует подготовку
той же конфигурации и неизменные исходники, проверяет фактические COFF LOAD-адреса,
C entry и аппаратный boot-переход через TI `ofd2000`, затем сохраняет OUT/MAP,
`.out.manifest.json`, `.out.sha256` и `firmware_identity.json` в локальном архиве
`${BuildDirectory}/firmware/HASH_дата_UTC+3`. Manifest содержит контроллер,
Debug/Release, назначение `canboot`, адреса проверки и SHA-256 точного OUT.
`firmware/latest_build.json` указывает текущие локальную и экспортированную папки.
Проверенный архив автоматически копируется в SETGUI по следующей схеме:
```text
SETGUI/..periph_28335/firmware/periph28335/balzam167/canboot/
28335/HASH_дата_UTC+3/F28335_CAN_AB.out
2812/HASH_дата_UTC+3/F2812_CAN_NOR.out
```
MAP, manifest, SHA-256 и метаданные лежат рядом с соответствующим OUT.
`..periph_28335` — буквальное имя существующего каталога SETGUI с двумя точками
в начале. Время имени папки берётся из prebuild; `+` после HASH означает изменения
в templates. Debug и Release имеют отдельные BuildDirectory и свои метаданные.
В **Project Properties → Build → Steps** команды уже заполнены для обеих
конфигураций. Пример для F28335 Debug, каждая команда вводится одной строкой:
```bat
python "${PROJECT_LOC}/../../build.py" --device f28335 --configuration Debug --compiler "${CG_TOOL_ROOT}" --output "${BuildDirectory}" --step prepare
python "${PROJECT_LOC}/../../build.py" --device f28335 --configuration Debug --compiler "${CG_TOOL_ROOT}" --output "${BuildDirectory}" --step postbuild --export "${PROJECT_LOC}/../../../../../../SETGUI/..periph_28335/firmware/periph28335/balzam167/canboot/28335"
```
Для F2812 используются `--device f2812` и конечная папка `2812`; для Release —
`--configuration Release`. При другом расположении SETGUI измените `--export`
в postbuild обеих конфигураций. Все пути с пробелами должны оставаться в кавычках.
CLI-сборка из раздела выше выполняет те же prepare/postbuild и копирует в эти же
каталоги; аргумент `--export <каталог>` переопределяет место копирования.
При ошибке компиляции, проверки OUT, отсутствии MAP или изменении исходников
после prebuild новый комплект в SETGUI не копируется. После изменения исходников
выполните **Rebuild Project**, чтобы обновить и OUT, и подготовку.
В диалоге SETGUI **Flash JTAG (OUT)** для установки постоянного загрузчика F28335
выбирайте `canboot/28335/HASH_дата_UTC+3/F28335_CAN_AB.out`.
`F2812_CAN_NOR.out` предназначен для JTAG соответствующего F2812.
Копирование файлов не запускает программирование платы и сетевую публикацию.
## F28335 / M95M02
Проект использует существующий порт и формат журнала без изменения адресов:
**PERIPH 0–31: Type = 1 + PERIPH / 16, Device ID = PERIPH mod 16**.
УМП1 — **1/5**, УМП2 — **1/6**, задатчик — **1/8**.
Product **0x2833**, HW **1**, CAN **250000 бит/с**. Приложение и загрузчик
используют один аппаратный номер платы; прежний общий адрес **3/7** отменён.
Код загрузчика — внутренний сектор A `0x338000..0x33FF7F`, boot — `0x33FFF6`.
Слоты M95M02 имеют по **130560 октетов**, параметры — прежние 258 октетов
по адресу `0x3FEFC`. Приложение загружается в RAM ниже CPU word-адреса `0xE000`.
После установки постоянного загрузчика новое приложение 167 передаётся
существующим клиентом SETGUI **CAN / ProtoCAN Boot**. Оно обязано содержать
hooks READY/CONFIRM и watchdog: пример интеграции реализован в ветке 167.
Без CONFIRM следующий reset возвращает подтверждённый active.
Полная последовательность — [документация порта F28335](../ports/tms320f28335/README.md).
## F2812 / AM29LV800BT
Профиль: **Device Type 3, Device ID 6, Product 0x2812, HW 1,
CAN 250000 бит/с, SYSCLKOUT 150 МГц**. CAN находится на **GPIOF6 TX / GPIOF7 RX**.
F2812 использует программную арифметику `rts2800_ml.lib`; F28335 — FPU32
и `rts2800_fpu32.lib`.
Внутренний сектор A загрузчика: `0x3F6000..0x3F7F7F`, boot — `0x3F7FF6`.
Внешняя NOR подключена по **CPU word-адресу `0x100000`**. Новый CAN-раздел
задан явно в `ports/tms320f2812/boot2812.h`:
| Область | CPU word-адреса включительно | Размер |
| --- | --- | ---: |
| Существующая нижняя область: прежние образы/параметры/FPGA | `0x100000..0x15FFFF` | 768 КиБ |
| Новый SCI8 CAN-образ: обычные сектора 12/13/14 | `0x160000..0x177FFF` | **192 КиБ** |
| Неизменяемые этим загрузчиком top-boot сектора 15/16/17 | `0x178000..0x17DFFF` | 48 КиБ |
| Новый manifest: последний top-boot сектор 18 | `0x17E000..0x17FFFF` | 16 КиБ |
Это **новое явное размещение CAN-образа**, а не автоматическое определение
свободного места в уже заполненном чипе. Перед первоначальной установкой
согласовать эти два выделенных участка с фактической картой NOR конкретной
платы. В известном исходнике FPGA начинается с `0x130000`, а новый CAN-слот
находится выше; драйвер не изменяет ничего ниже `0x160000` и в секторах 15–17.
После reset доступно **3 секунды** для ENTER_BOOT. Открытая сессия удерживает
загрузчик; пустой/повреждённый manifest оставляет CAN recovery постоянно.
Для обновления уже работающего приложения нужно войти в это окно после reset;
приложение F2812 само по себе пока не получает обработчик ENTER_BOOT от добавления
отдельного проекта загрузчика.
Перед записью требуется AMD manufacturer **`0x0001`**, device **`0x22DA`**.
Сначала стирается сектор manifest, затем три сектора образа. Запись проверяет
каждое слово. VERIFY повторно читает NOR, проверяет CRC32, SCI8, entry,
перекрытия и запрещённые назначения. COMMIT повторяет проверку, сохраняет
manifest с собственной CRC, два magic-слова публикуются последними.
Стирание сообщает BUSY каждые 250 мс, продлевая живую сессию.
Это single-slot схема: при обрыве обновления последнего CAN-образа остаётся
recovery, автоматический A/B rollback для F2812 не заявляется. Полное стирание
NOR, запись внутренней Flash по CAN и программирование FPGA отсутствуют.
Образ приложения — **TI SCI8 `AA 08`**, максимум **196608 октетов**. Старый
flat BIN основного контроллера автоматически не мигрируется. Допустимый payload:
- L0 `0x8000..0x8EFF`;
- H0 `0x3F8000..0x3F9FFF`;
- внешняя SRAM zone2 `0x80000..0xFFFFF`.
Стек M1, L1 `0x9000..0x9FFF`, RAM InitFlash `0x8F00..0x8FFF`, периферия,
внутренняя Flash и NOR не допускаются как назначения SCI8. `.ebss` приложения
может занять L1 после перехода в его C runtime; инициализированный payload
работающую RAM загрузчика перезаписывать не должен. Настройка приложения
F2812/его linker — отдельная от импорта загрузчика операция.
Геометрия x16, ID и команды AA/55/A0/80/30/F0 взяты из
[оригинального datasheet AMD Am29LV800B](https://cms.nacsemi.com/content/AuthDatasheets/FASLS02690-1.pdf).
Аппаратные GPIO/CPLD и XINTF-тайминги перенесены из действующих
`big_dsp_module.c` / `flash_tools.c` ПМ67, без зависимости от этих файлов при сборке.
## Проверки
```powershell
$env:CC = 'C:/msys64/ucrt64/bin/gcc.exe'
python c/protocan-boot/tests/run_tests.py
```
Проверяются протокол, CRC, сессии/BUSY, A/B F28335 с trial/rollback/CONFIRM,
NOR F2812 с настоящими AMD command cycles, ID, readback, запрещёнными секторами,
обрывами COMMIT, повреждением CRC/SCI8 и тайм-аутом DQ7.
Вариант с CMake/CTest также поддерживается.
Подтверждены реальные import/build обоих проектов в CCS 12.3, CLI-сборки
Debug/Release TI 22.6 COFF и проверки секций OUT. Физические JTAG/CAN/XINTF,
режим boot и поведение конкретной платы при отключении питания требуют стенда;
физическое программирование этим комплектом автоматически не выполнялось.
+69
View File
@@ -0,0 +1,69 @@
# STM32: подключение исходных проектов к templates
Канонические загрузочные реализации находятся в `c/protocan-boot/ports`.
В проектах сохранены прежние пути файлов, содержащие только include общего
исходника из их submodule. Это сохраняет внешний API и настройки Keil,
не оставляя локальных копий state machine, Flash writer или boot-control.
| Проект | Submodule | Подключённый порт | Сборки |
|---|---|---|---|
| `KONOR_ds18b20` | `lib` | `stm32f103` CMSIS, BKP request, CAN/UART | Keil app и BOOT |
| `home/climate` | `third_party/templates` | `stm32f407` CMSIS boot, HAL app control | Keil app и BOOT |
| `CANdle_stm32` | `templates` | `stm32g474` HAL FDCAN/Flash, CAN/UART, startup/control | Keil app/BOOT, CMake app/BOOT |
## Что перенесено
- Общие `pcan_boot.c/.h` используются через submodule; устаревшая копия
`Libraries/ProtoCanBoot` climate заменена совместимыми include-обёртками.
- F103/F407 CMSIS transport, Flash, CRC readback, безопасный naked handoff,
single-slot callbacks и таймеры используют общий `boot_native.inc`.
- F103 UART firmware flow теперь использует имеющийся общий `rs485-boot`;
приложение KONOR продолжает использовать свой прикладной parser `proto.c`.
- G474 локальная CAN state machine полностью заменена текущим `pcan_boot`.
Единый Flash writer используется CAN/UART; вход из приложения и startup
также принадлежат `templates`.
- Конфигурации ядра заполняются по именам полей. Сохранены исходные Device ID,
скорости CAN/UART, границы Flash и режим одного логического слота A.
- В F407 BOOT и G474 app/BOOT linker исключает последние восемь байт используемой
SRAM, где хранится запрос обновления. Initial MSP G474 согласован с этим.
- В GCC-таблице IRQ G474 размер выведен из самого старшего назначенного IRQ:
прежний предел по USB_LP не вмещал USART1 и ломал CMake app-сборку.
Clock tree, USB–CAN приложение, трансивер, GPIO board-support, настройки
программирования ST-Link и application linker остаются в исходных проектах.
Нативные `boot_main.c` не нужно компилировать вместе с альтернативным HAL boot
main в одном target. Изменения не прошивают подключённые устройства.
## Зависимости и публикация
CANdle получен из `https://git.rd12.ru/setcorp/CANdle_stm32.git`, исходный HEAD
`61a93c5`. Записанный там gitlink `templates` указывает на отсутствующий на
сервере объект `520788491c803e07ba1889e1fa60ed1550afb848`. Для локальной
интеграции submodule переключён на доступный локальный HEAD `templates`,
после чего текущие общие исходники синхронизированы в рабочее дерево.
Рабочие копии submodule KONOR/climate также содержат соответствующие текущие файлы.
Подключение проверено локально. Для воспроизводимого нового клонирования
потребуется зафиксировать и опубликовать изменения `templates`, затем обновить
gitlinks в исходных проектах на этот доступный commit. Коммиты и push не являются
частью этой локальной интеграции; чужие незавершённые изменения не включались в commit.
## Проверка
21 октября 2026 года проверены настоящие Keil/Arm Compiler 6.22 сборки
BOOT и приложения каждого из трёх проектов. Все загрузчики помещаются в
исходные лимиты 12/32/32 КиБ. G474 дополнительно проверен ARM GCC/CMake
для `STM32G474VE_CAN_bootloader` и `STM32G474VE_DevBoard_fw`.
Включённые в G474 BOOT строгие диагностики Arm Compiler выдают предупреждения
о layout структур, GNU-расширениях и обычном C-доступе к буферам в HAL/общих
модулях; компиляция и линковка завершаются без ошибок. GNU/newlib конфигурация
также сообщает о заглушках syscall при отключённом semihosting. Эти сообщения
не подавлялись общими флагами проекта.
Host CMake/CTest: 10 тестов, включая три production HAL-порта. G474 проверяется
в DBANK=0 и DBANK=1: весь слот, переход между банками, отказ swap/неверной
плотности, все хвосты DATA, CRC readback, тайм-аут и TX ACK до reset.
Проверки интеграции climate подтверждают реальную цепочку include/Keil и границы
Flash/SRAM. Аппаратное обновление, питание и восстановление после обрыва на
физических платах в эту проверку не входят.
File diff suppressed because one or more lines are too long
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<?ccsproject version="1.0"?>
<projectOptions>
<!-- Описывает ccsVersion: 12.3.0. -->
<ccsVersion value="12.3.0" />
<!-- Описывает deviceVariant: TMS320C28XX.TMS320F2812. -->
<deviceVariant value="TMS320C28XX.TMS320F2812" />
<!-- Описывает deviceFamily: C2000. -->
<deviceFamily value="C2000" />
<!-- Описывает deviceEndianness: little. -->
<deviceEndianness value="little" />
<!-- Описывает codegenToolVersion: 22.6.0.LTS. -->
<codegenToolVersion value="22.6.0.LTS" />
<!-- Описывает isElfFormat: false. -->
<isElfFormat value="false" />
<!-- Описывает rts: rts2800_ml.lib. -->
<rts value="rts2800_ml.lib" />
<!-- Описывает isTargetManual: false. -->
<isTargetManual value="false" />
</projectOptions>
File diff suppressed because one or more lines are too long
+106
View File
@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<!-- Описывает name: name. -->
<name>F2812_CAN_NOR</name>
<!-- Описывает comment: comment. -->
<comment>Отдельный постоянный загрузчик ProtoCAN для F2812</comment>
<!-- Описывает projects: projects. -->
<projects />
<!-- Описывает buildSpec: buildSpec. -->
<buildSpec>
<!-- Описывает buildCommand: buildCommand. -->
<buildCommand>
<!-- Описывает name: name. -->
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<!-- Описывает arguments: arguments. -->
<arguments />
</buildCommand>
<!-- Описывает buildCommand: buildCommand. -->
<buildCommand>
<!-- Описывает name: name. -->
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<!-- Описывает arguments: arguments. -->
<arguments />
</buildCommand>
</buildSpec>
<!-- Описывает natures: natures. -->
<natures>
<!-- Описывает nature: nature. -->
<nature>com.ti.ccstudio.core.ccsNature</nature>
<!-- Описывает nature: nature. -->
<nature>org.eclipse.cdt.core.cnature</nature>
<!-- Описывает nature: nature. -->
<nature>org.eclipse.cdt.core.ccnature</nature>
<!-- Описывает nature: nature. -->
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<!-- Описывает nature: nature. -->
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
<!-- Описывает linkedResources: linkedResources. -->
<linkedResources>
<!-- Подключает исходник или linker из общей библиотеки: link. -->
<link>
<!-- Описывает name: name. -->
<name>ti/DSP281x_CpuTimers.c</name>
<!-- Описывает type: type. -->
<type>1</type>
<!-- Описывает locationURI: locationURI. -->
<locationURI>PCAN_ROOT/vendor/ti/f2812/source/DSP281x_CpuTimers.c</locationURI>
</link>
<!-- Подключает исходник или linker из общей библиотеки: link. -->
<link>
<!-- Описывает name: name. -->
<name>ti/DSP281x_GlobalVariableDefs.c</name>
<!-- Описывает type: type. -->
<type>1</type>
<!-- Описывает locationURI: locationURI. -->
<locationURI>PCAN_ROOT/vendor/ti/f2812/source/DSP281x_GlobalVariableDefs.c</locationURI>
</link>
<!-- Подключает исходник или linker из общей библиотеки: link. -->
<link>
<!-- Описывает name: name. -->
<name>ti/DSP281x_PieCtrl.c</name>
<!-- Описывает type: type. -->
<type>1</type>
<!-- Описывает locationURI: locationURI. -->
<locationURI>PCAN_ROOT/vendor/ti/f2812/source/DSP281x_PieCtrl.c</locationURI>
</link>
<!-- Подключает исходник или linker из общей библиотеки: link. -->
<link>
<!-- Описывает name: name. -->
<name>ti/DSP281x_SysCtrl.c</name>
<!-- Описывает type: type. -->
<type>1</type>
<!-- Описывает locationURI: locationURI. -->
<locationURI>PCAN_ROOT/vendor/ti/f2812/source/DSP281x_SysCtrl.c</locationURI>
</link>
<!-- Подключает исходник или linker из общей библиотеки: link. -->
<link>
<!-- Описывает name: name. -->
<name>ti/DSP281x_usDelay.asm</name>
<!-- Описывает type: type. -->
<type>1</type>
<!-- Описывает locationURI: locationURI. -->
<locationURI>PCAN_ROOT/vendor/ti/f2812/source/DSP281x_usDelay.asm</locationURI>
</link>
<!-- Подключает исходник или linker из общей библиотеки: link. -->
<link>
<!-- Описывает name: name. -->
<name>DSP281x_Headers_nonBIOS.cmd</name>
<!-- Описывает type: type. -->
<type>1</type>
<!-- Описывает locationURI: locationURI. -->
<locationURI>PCAN_ROOT/vendor/ti/f2812/cmd/DSP281x_Headers_nonBIOS.cmd</locationURI>
</link>
</linkedResources>
<!-- Описывает variableList: variableList. -->
<variableList>
<!-- Описывает variable: variable. -->
<variable>
<!-- Описывает name: name. -->
<name>PCAN_ROOT</name>
<!-- Описывает value: value. -->
<value>$%7BPARENT-3-PROJECT_LOC%7D</value>
</variable>
</variableList>
</projectDescription>
@@ -0,0 +1,28 @@
MEMORY /* Постоянный загрузчик F2812 хранится во внутренней Flash, обновляемые данные — во внешней AM29LV800BT. */
{ /* Адреса указаны в 16-битных словах C28x, независимо от размера файлов CAN. */
PAGE 0: /* Исполняемый код и его копируемая RAM-часть. */
FLASHA : origin = 0x3F6000, length = 0x001F80 /* Сектор A исключает зарезервированные слова CSM в верхних 128 словах. */
BEGIN : origin = 0x3F7FF6, length = 0x000002 /* Аппаратный Flash boot F2812 начинает длинный переход из двух слов. */
RAMFUNCS : origin = 0x008F00, length = 0x000100 /* Последние 256 слов L0 содержат InitFlash и исключены из SCI8 payload приложения. */
RESET : origin = 0x3FFFC0, length = 0x000002 /* ROM reset не программируется при установке загрузчика. */
PAGE 1: /* Рабочая RAM постоянно работающего загрузчика не должна входить в загружаемый файл. */
RAMM0 : origin = 0x000050, length = 0x0003B0 /* Исключает первые 80 слов Boot ROM scratch. */
RAMM1 : origin = 0x000400, length = 0x000400 /* Отдельный стек на 1024 слова совпадает с аппаратным банком M1. */
RAMDATA : origin = 0x009000, length = 0x001000 /* Банк L1 хранит очередь CAN и состояния загрузчика до перехода в приложение. */
} /* Верхний H0 и внешняя SRAM остаются доступны payload приложения. */
SECTIONS /* Ни одна загружаемая секция OUT не записывается во внешнюю NOR автоматически. */
{ /* Все команды программирования NOR исполняются из внутреннего сектора A. */
codestart : > BEGIN, PAGE = 0 /* Направляет аппаратный boot в watchdog-safe C startup. */
.text : > FLASHA, PAGE = 0 /* Размещает общий ProtoCAN, driver NOR и проверку SCI8 в постоянной Flash. */
.fast_run : > FLASHA, PAGE = 0 /* Штатный DSP281x_usDelay вызывается ещё из InitSysCtrl до копирования ramfuncs, поэтому его LOAD/RUN должны сразу находиться во Flash. */
.cinit : > FLASHA, PAGE = 0 /* Таблицы ROM-модели инициализируют состояние до main. */
.pinit : > FLASHA, PAGE = 0 /* Сохраняет стандартный startup для возможных статических конструкторов. */
.econst : > FLASHA, PAGE = 0 /* Константы не расходуют ограниченную RAM L1. */
.switch : > FLASHA, PAGE = 0 /* Таблицы switch остаются доступны во время erase внешнего чипа. */
ramfuncs : LOAD = FLASHA, RUN = RAMFUNCS, LOAD_START(_RamfuncsLoadStart), LOAD_END(_RamfuncsLoadEnd), RUN_START(_RamfuncsRunStart), PAGE = 0 /* InitFlash копируется в внутреннюю RAM до изменения таймингов Flash. */
.stack : > RAMM1, PAGE = 1 /* Стек не пересекает RAM назначения проверяемого образа. */
.ebss : > RAMDATA, PAGE = 1 /* Состояния очереди и текущей сессии исключены из разрешённых SCI8 адресов. */
.esysmem : > RAMDATA, PAGE = 1 /* Поддерживает стандартную секцию runtime, хотя алгоритм не требует heap. */
.fast_vars1 : > RAMDATA, PAGE = 1 /* Подключает штатный HSPCLK выбранного TI SDK без размещения случайной orphan-секции. */
.reset : > RESET, PAGE = 0, TYPE = DSECT /* Не выдаёт ROM reset за программируемую часть OUT. */
} /* Не создаёт секции OTP или паролей CSM. */
@@ -0,0 +1,30 @@
#include "DSP281x_Device.h" /* Использует оригинальные TI определения GPIO и XINTF F2812. */
#include "../../../ports/tms320f2812/boot2812.h" /* Получает отдельный аппаратный профиль внешней NOR ПМ67. */
static void operation(unsigned int a, unsigned int b, unsigned int c, unsigned int d) /* Повторяет управляющую защёлку CPLD из big_dsp_module.c штатной платы. */
{ /* GPIOA13/A14/A15 и GPIOB13 задают код, GPIOB15 формирует строб. */
EALLOW; /* Разрешает запись системных GPIO платы. */
GpioDataRegs.GPADAT.bit.GPIOA13 = a; GpioDataRegs.GPADAT.bit.GPIOA14 = b; /* Первые два бита аппаратной команды соответствуют oper_mode1/2. */
GpioDataRegs.GPADAT.bit.GPIOA15 = c; GpioDataRegs.GPBDAT.bit.GPIOB13 = d; /* Третий и четвёртый биты повторяют штатный write_oper. */
asm(" NOP"); GpioDataRegs.GPBDAT.bit.GPIOB15 = 0; /* Снимает строб после установки всех четырёх битов команды. */
asm(" RPT #2 || NOP"); GpioDataRegs.GPBDAT.bit.GPIOB15 = 1; /* Даёт защёлке время установления и формирует активный фронт. */
asm(" RPT #2 || NOP"); GpioDataRegs.GPBDAT.bit.GPIOB15 = 0; /* Возвращает строб в исходное состояние с выдержкой как в рабочем драйвере. */
asm(" RPT #2 || NOP"); EDIS; /* Завершает длительность импульса до следующей команды CPLD. */
} /* Команда не изменяет выбранные аппаратные boot-перемычки контроллера. */
void Boot2812_BoardInit(void) /* Настраивает подтверждённую схему ПМ67 с AM29LV800BT на XINTF zone6. */
{ /* Значения линий взяты из setup_oper_line/init_flash/xintf_zone6and7_timing действующего проекта BALZAM_167. */
EALLOW; /* GPIO mux/direction и XINTF изменяются в разрешённом защищённом контексте. */
GpioMuxRegs.GPAMUX.bit.C1TRIP_GPIOA13 = 0; GpioMuxRegs.GPAMUX.bit.C2TRIP_GPIOA14 = 0; GpioMuxRegs.GPAMUX.bit.C3TRIP_GPIOA15 = 0; /* Выбирает GPIO для трёх командных линий CPLD вместо функций event manager. */
GpioMuxRegs.GPBMUX.bit.C4TRIP_GPIOB13 = 0; GpioMuxRegs.GPBMUX.bit.C6TRIP_GPIOB15 = 0; /* Освобождает четвёртый бит команды и строб CPLD. */
GpioMuxRegs.GPADIR.bit.GPIOA13 = 1; GpioMuxRegs.GPADIR.bit.GPIOA14 = 1; GpioMuxRegs.GPADIR.bit.GPIOA15 = 1; /* Переводит командные линии A в выходы, как рабочий драйвер платы. */
GpioMuxRegs.GPBDIR.bit.GPIOB13 = 1; GpioMuxRegs.GPBDIR.bit.GPIOB15 = 1; /* Разрешает выдачу четвёртого бита и импульса защёлки. */
XintfRegs.XINTCNF2.bit.XTIMCLK = 1; XintfRegs.XINTCNF2.bit.WRBUFF = 0; /* XTIMCLK=SYSCLKOUT/2; отключённая буферизация сохраняет порядок unlock-циклов AMD. */
XintfRegs.XINTCNF2.bit.CLKOFF = 0; XintfRegs.XINTCNF2.bit.CLKMODE = 0; XintfRegs.XINTCNF2.bit.MPNMC = 0; /* Повторяет штатный режим XCLKOUT и микроконтроллерный boot платы. */
XintfRegs.XTIMING6.bit.XWRLEAD = 3; XintfRegs.XTIMING6.bit.XWRACTIVE = 7; XintfRegs.XTIMING6.bit.XWRTRAIL = 3; /* Времена записи NOR повторяют проверенный flash_tools/init_flash платы в единицах XTIMCLK. */
XintfRegs.XTIMING6.bit.XRDLEAD = 3; XintfRegs.XTIMING6.bit.XRDACTIVE = 3; XintfRegs.XTIMING6.bit.XRDTRAIL = 3; /* Времена чтения соответствуют штатному профилю AM29LV800BT-70EI. */
XintfRegs.XTIMING6.bit.X2TIMING = 0; XintfRegs.XTIMING6.bit.USEREADY = 0; XintfRegs.XTIMING6.bit.READYMODE = 0; XintfRegs.XTIMING6.bit.XSIZE = 3; /* Выбирает 16-битную зону без внешнего READY и без дополнительного удвоения тактов. */
XintfRegs.XTIMING2.bit.XWRLEAD = 3; XintfRegs.XTIMING2.bit.XWRACTIVE = 7; XintfRegs.XTIMING2.bit.XWRTRAIL = 3; /* Консервативный x16 режим внешней SRAM позволяет загружать приложение в zone2. */
XintfRegs.XTIMING2.bit.XRDLEAD = 3; XintfRegs.XTIMING2.bit.XRDACTIVE = 7; XintfRegs.XTIMING2.bit.XRDTRAIL = 3; /* Удлинённое чтение SRAM не зависит от коротких прикладных таймингов. */
XintfRegs.XTIMING2.bit.X2TIMING = 0; XintfRegs.XTIMING2.bit.USEREADY = 0; XintfRegs.XTIMING2.bit.READYMODE = 0; XintfRegs.XTIMING2.bit.XSIZE = 3; /* Не включает неподтверждённую линию READY платы. */
asm(" RPT #7 || NOP"); EDIS; /* Сбрасывает pipeline после изменения XINTF до первого внешнего чтения. */
operation(1U, 1U, 1U, 1U); operation(1U, 0U, 1U, 0U); operation(0U, 0U, 0U, 0U); /* Штатные select_nothing, select_strob_67_for_flash, select_work_with_flash выбирают CPU-доступ к NOR. */
} /* Изменение схемы CPLD требует отдельного профиля платы, а не другого размера EEPROM. */
@@ -0,0 +1 @@
#include "../../../ports/tms320f2812/boot_store.c" /* Подключает проверку SCI8 и публикацию NOR manifest без копирования кода в проект CCS. */
@@ -0,0 +1,12 @@
.ref _c_int00 ; Стандартный COFF startup применяет .cinit и вызывает main после отключения раннего watchdog.
.sect "codestart" ; Boot ROM передаёт управление двухсловному переходу по аппаратному адресу слова 0x33FFF6.
LB flash_boot_start ; Переходит к короткой подготовке C28x во Flash, сохраняя точный размер аппаратного входа два слова.
.text ; Последовательность взята из штатного TI DSP2833x_CodeStartBranch.asm и размещается в секторе основного кода.
flash_boot_start: ; Отключает watchdog до возможной длительной обработки таблиц инициализации C, а не только после входа в main.
SETC OBJMODE ; Выбирает C28x object mode, требуемый стандартным COFF startup процессора F28335.
EALLOW ; Разрешает запись защищённого регистра WDCR перед запуском C runtime.
MOVZ DP, #7029h>>6 ; Адрес слова WDCR=0x7029 из карты F28335; DP выбирает соответствующую страницу по 64 слова.
MOV @7029h, #0068h ; Значение 0x0068 содержит контрольные биты WDCHK=101 и WDDIS=1, как официальный TI startup.
EDIS ; Возвращает защиту системных регистров перед переходом в библиотечную инициализацию.
LB _c_int00 ; Применяет штатную ROM-модель инициализации и затем запускает текущий main 167.
.end ; Завершает модуль, не добавляя произвольных данных рядом с CSM-паролями сектора A.
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
#include "../../../ports/tms320f2812/nor_flash.c" /* Собирает канонический драйвер AM29LV800BT из templates, сохраняя hardware callbacks отдельно от протокола. */
@@ -0,0 +1 @@
#include "../../../src/pcan_boot.c" /* Подключает общий ProtoCAN codec, сессии и CRC32 без второй реализации протокола. */
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<configurations XML_version="1.2" id="configurations_0">
<configuration XML_version="1.2" id="configuration_0">
<instance XML_version="1.2" desc="Sauris SAU510-USB Iso Plus Emulator" href="connections/SAU510USBIsoPlus_Connection.xml" id="Sauris SAU510-USB Iso Plus Emulator" xml="SAU510USBIsoPlus_Connection.xml" xmlpath="connections"/>
<connection XML_version="1.2" id="Sauris SAU510-USB Iso Plus Emulator">
<instance XML_version="1.2" href="drivers/sau510c28x.xml" id="drivers" xml="sau510c28x.xml" xmlpath="drivers"/>
<platform XML_version="1.2" id="platform_0">
<instance XML_version="1.2" desc="TMS320F2812" href="devices/f2812.xml" id="TMS320F2812" xml="f2812.xml" xmlpath="devices"/>
</platform>
</connection>
</configuration>
</configurations>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<?ccsproject version="1.0"?>
<projectOptions>
<!-- Описывает ccsVersion: 12.3.0. -->
<ccsVersion value="12.3.0" />
<!-- Описывает deviceVariant: TMS320C28XX.TMS320F28335. -->
<deviceVariant value="TMS320C28XX.TMS320F28335" />
<!-- Описывает deviceFamily: C2000. -->
<deviceFamily value="C2000" />
<!-- Описывает deviceEndianness: little. -->
<deviceEndianness value="little" />
<!-- Описывает codegenToolVersion: 22.6.0.LTS. -->
<codegenToolVersion value="22.6.0.LTS" />
<!-- Описывает isElfFormat: false. -->
<isElfFormat value="false" />
<!-- Описывает rts: rts2800_fpu32.lib. -->
<rts value="rts2800_fpu32.lib" />
<!-- Описывает isTargetManual: false. -->
<isTargetManual value="false" />
</projectOptions>
File diff suppressed because one or more lines are too long
@@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<!-- Описывает name: name. -->
<name>F28335_CAN_AB</name>
<!-- Описывает comment: comment. -->
<comment>Отдельный постоянный загрузчик ProtoCAN для F28335</comment>
<!-- Описывает projects: projects. -->
<projects />
<!-- Описывает buildSpec: buildSpec. -->
<buildSpec>
<!-- Описывает buildCommand: buildCommand. -->
<buildCommand>
<!-- Описывает name: name. -->
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<!-- Описывает arguments: arguments. -->
<arguments />
</buildCommand>
<!-- Описывает buildCommand: buildCommand. -->
<buildCommand>
<!-- Описывает name: name. -->
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<!-- Описывает arguments: arguments. -->
<arguments />
</buildCommand>
</buildSpec>
<!-- Описывает natures: natures. -->
<natures>
<!-- Описывает nature: nature. -->
<nature>com.ti.ccstudio.core.ccsNature</nature>
<!-- Описывает nature: nature. -->
<nature>org.eclipse.cdt.core.cnature</nature>
<!-- Описывает nature: nature. -->
<nature>org.eclipse.cdt.core.ccnature</nature>
<!-- Описывает nature: nature. -->
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<!-- Описывает nature: nature. -->
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
<!-- Описывает linkedResources: linkedResources. -->
<linkedResources>
<!-- Подключает исходник или linker из общей библиотеки: link. -->
<link>
<!-- Описывает name: name. -->
<name>ti/DSP2833x_ADC_cal.asm</name>
<!-- Описывает type: type. -->
<type>1</type>
<!-- Описывает locationURI: locationURI. -->
<locationURI>PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_ADC_cal.asm</locationURI>
</link>
<!-- Подключает исходник или linker из общей библиотеки: link. -->
<link>
<!-- Описывает name: name. -->
<name>ti/DSP2833x_CpuTimers.c</name>
<!-- Описывает type: type. -->
<type>1</type>
<!-- Описывает locationURI: locationURI. -->
<locationURI>PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_CpuTimers.c</locationURI>
</link>
<!-- Подключает исходник или linker из общей библиотеки: link. -->
<link>
<!-- Описывает name: name. -->
<name>ti/DSP2833x_GlobalVariableDefs.c</name>
<!-- Описывает type: type. -->
<type>1</type>
<!-- Описывает locationURI: locationURI. -->
<locationURI>PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_GlobalVariableDefs.c</locationURI>
</link>
<!-- Подключает исходник или linker из общей библиотеки: link. -->
<link>
<!-- Описывает name: name. -->
<name>ti/DSP2833x_PieCtrl.c</name>
<!-- Описывает type: type. -->
<type>1</type>
<!-- Описывает locationURI: locationURI. -->
<locationURI>PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_PieCtrl.c</locationURI>
</link>
<!-- Подключает исходник или linker из общей библиотеки: link. -->
<link>
<!-- Описывает name: name. -->
<name>ti/DSP2833x_SysCtrl.c</name>
<!-- Описывает type: type. -->
<type>1</type>
<!-- Описывает locationURI: locationURI. -->
<locationURI>PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_SysCtrl.c</locationURI>
</link>
<!-- Подключает исходник или linker из общей библиотеки: link. -->
<link>
<!-- Описывает name: name. -->
<name>ti/DSP2833x_usDelay.asm</name>
<!-- Описывает type: type. -->
<type>1</type>
<!-- Описывает locationURI: locationURI. -->
<locationURI>PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_usDelay.asm</locationURI>
</link>
<!-- Подключает исходник или linker из общей библиотеки: link. -->
<link>
<!-- Описывает name: name. -->
<name>DSP2833x_Headers_nonBIOS.cmd</name>
<!-- Описывает type: type. -->
<type>1</type>
<!-- Описывает locationURI: locationURI. -->
<locationURI>PCAN_ROOT/vendor/ti/f28335/cmd/DSP2833x_Headers_nonBIOS.cmd</locationURI>
</link>
</linkedResources>
<!-- Описывает variableList: variableList. -->
<variableList>
<!-- Описывает variable: variable. -->
<variable>
<!-- Описывает name: name. -->
<name>PCAN_ROOT</name>
<!-- Описывает value: value. -->
<value>$%7BPARENT-3-PROJECT_LOC%7D</value>
</variable>
</variableList>
</projectDescription>
@@ -0,0 +1,30 @@
MEMORY /* Отделяет постоянный загрузчик от адресов RAM payload приложения 167. */
{ /* Все адреса и длины указаны в 16-битных словах CPU C28x. */
PAGE 0: /* Исполняемые секции и их Flash LOAD-адреса. */
FLASHA : origin = 0x338000, length = 0x007F80 /* Сектор A до зарезервированной CSM-области содержит постоянный загрузчик. */
BEGIN : origin = 0x33FFF6, length = 0x000002 /* Два слова аппаратного Flash boot перехода; пароли CSM не выделяются. */
RAMFUNCS : origin = 0x00F800, length = 0x000800 /* Верхние 2048 слов RAM загрузчика нужны InitFlash и не входят в SCI8 payload приложения. */
ADC_CAL : origin = 0x380080, length = 0x000009 /* Заводская калибровка TI используется без записи/стирания. */
RESET : origin = 0x3FFFC0, length = 0x000002 /* Аппаратный reset находится в ROM и не программируется. */
PAGE 1: /* Рабочие данные не пересекают код RAM-приложения ниже E000. */
BOOT_SHARED : origin = 0x000050, length = 0x000008 /* Общие с приложением восемь слов NOINIT handoff после ROM scratch 0..4F. */
RAMM0 : origin = 0x000058, length = 0x0003A8 /* Малый банк доступен служебным неинициализированным данным. */
RAMM1 : origin = 0x000400, length = 0x000400 /* Стек на 1024 слова не меняет расположение при переходе в приложение. */
RAMDATA : origin = 0x00E000, length = 0x001800 /* 6144 слова store/очереди; приложение использует их только после перехода в C startup. */
} /* Завершает физическую карту постоянного загрузчика. */
SECTIONS /* Не выделяет ни одного загружаемого слова в RAM приложения. */
{ /* Инициализированные Flash-секции остаются в секторе A. */
codestart : > BEGIN, PAGE = 0 /* Аппаратный переход передаёт управление watchdog-safe C startup. */
.text : > FLASHA, PAGE = 0 /* Весь постоянный алгоритм и библиотеки исполняются из Flash A. */
.cinit : > FLASHA, PAGE = 0 /* Таблицы ROM-модели подготавливают данные загрузчика до main. */
.pinit : > FLASHA, PAGE = 0 /* Сохраняет стандартный порядок C runtime, если компилятор создаст эту секцию. */
.econst : > FLASHA, PAGE = 0 /* Константы протокола и имена сервиса не расходуют рабочую RAM. */
.switch : > FLASHA, PAGE = 0 /* Таблицы переходов находятся в постоянной области загрузчика. */
ramfuncs : LOAD = FLASHA, RUN = RAMFUNCS, LOAD_START(_RamfuncsLoadStart), LOAD_END(_RamfuncsLoadEnd), RUN_START(_RamfuncsRunStart), PAGE = 0 /* InitFlash копируется до изменения настроек самой Flash. */
.boot_shared : > BOOT_SHARED, PAGE = 1, TYPE = NOINIT /* Не обнуляет session/slot, полученные через watchdog reset. */
.stack : > RAMM1, PAGE = 1 /* Стек не пересекает ни handoff, ни загружаемые секции SCI8. */
.ebss : > RAMDATA, PAGE = 1 /* Размещает очередь, журнал и структуры драйвера вне RAM payload. */
.esysmem : > RAMDATA, PAGE = 1 /* Поддерживает стандартную секцию runtime без использования heap в алгоритме. */
.reset : > RESET, PAGE = 0, TYPE = DSECT /* Reset-вектор ROM описывается, но не попадает в программируемый OUT. */
.adc_cal : > ADC_CAL, PAGE = 0, TYPE = NOLOAD /* Сохраняет заводские данные ADC TI при установке загрузчика. */
} /* Не создаёт секций CSM, OTP или паролей. */
@@ -0,0 +1,12 @@
.ref _c_int00 ; Стандартный COFF startup применяет .cinit и вызывает main после отключения раннего watchdog.
.sect "codestart" ; Boot ROM передаёт управление двухсловному переходу по аппаратному адресу слова 0x33FFF6.
LB flash_boot_start ; Переходит к короткой подготовке C28x во Flash, сохраняя точный размер аппаратного входа два слова.
.text ; Последовательность взята из штатного TI DSP2833x_CodeStartBranch.asm и размещается в секторе основного кода.
flash_boot_start: ; Отключает watchdog до возможной длительной обработки таблиц инициализации C, а не только после входа в main.
SETC OBJMODE ; Выбирает C28x object mode, требуемый стандартным COFF startup процессора F28335.
EALLOW ; Разрешает запись защищённого регистра WDCR перед запуском C runtime.
MOVZ DP, #7029h>>6 ; Адрес слова WDCR=0x7029 из карты F28335; DP выбирает соответствующую страницу по 64 слова.
MOV @7029h, #0068h ; Значение 0x0068 содержит контрольные биты WDCHK=101 и WDDIS=1, как официальный TI startup.
EDIS ; Возвращает защиту системных регистров перед переходом в библиотечную инициализацию.
LB _c_int00 ; Применяет штатную ROM-модель инициализации и затем запускает текущий main 167.
.end ; Завершает модуль, не добавляя произвольных данных рядом с CSM-паролями сектора A.
+127
View File
@@ -0,0 +1,127 @@
#include "DSP2833x_Device.h" /* Использует действующую частоту и штатную карту регистров той же платы 167. */
#include "DSP2833x_Examples.h" /* Предоставляет InitSysCtrl, InitPieCtrl, InitFlash и управление Timer1. */
#include "../../../ports/tms320f28335/f28335_can_boot.h" /* Подключает адрес, сервисы и очередь существующего загрузчика. */
#include "../../../ports/tms320f28335/f28335_boot_platform.h" /* Использует общий handoff, SPI и энергонезависимый A/B-журнал. */
#include <string.h> /* Копирует ramfuncs до настройки времен доступа Flash. */
extern Uint16 RamfuncsLoadStart, RamfuncsLoadEnd, RamfuncsRunStart; /* Адреса LOAD/RUN задаёт отдельный linker загрузчика в словах C28x. */
static f28335_boot_store_t image_store; /* Журнал загрузки остаётся в RAM E000..FFFF до перехода в приложение. */
interrupt void boot_tick(void) /* Timer1 продолжает миллисекундные тайм-ауты общего CAN/SPI порта. */
{ /* Этот ISR принадлежит постоянному загрузчику, а не кандидату приложения. */
CpuTimer1.InterruptCount++; /* Один тик равен одной миллисекунде согласно ConfigCpuTimer ниже. */
ServiceDog(); /* Длительные CRC/SPI операции загрузчика не должны сбрасывать аппарат во время обновления. */
} /* Возвращает управление основному циклу загрузчика. */
interrupt void boot_can_rx(void) /* CAN IRQ выполняет только короткий перенос принятых кадров в общую очередь. */
{ /* Запись EEPROM, CRC и публикация pending остаются в главном цикле. */
F28335CanBoot_RxISR(); /* Читает только выделенные mailbox 3 и 6 существующего адаптера. */
PieCtrlRegs.PIEACK.all = 0x0100U; /* Бит 8 подтверждает группу PIE9, в которой находится ECAN0INTA. */
} /* Позволяет принять следующее окно CAN, пока main занят SPI. */
static void boot_can_init(void) /* Настраивает тот же физический CAN-A и 250 кбит/с, что приложение 167. */
{ /* Загрузчик не использует прикладные mailbox 0..2 и не меняет адрес общего порта. */
Uint32 shadow; /* Защищённые eCAN-регистры изменяются только полными 32-битными обращениями. */
EALLOW; /* Разрешает настройку мультиплексора, eCAN и таблицы векторов. */
GpioCtrlRegs.GPAMUX2.bit.GPIO30 = 1; /* GPIO30 служит CANRXA, как в штатном InitCan проекта. */
GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 1; /* GPIO31 служит CANTXA того же трансивера. */
ECanaRegs.CANTIOC.all = 8UL; /* Бит TXFUNC включает функцию CAN у выхода контроллера. */
ECanaRegs.CANRIOC.all = 8UL; /* Бит RXFUNC включает аппаратный вход CAN. */
ECanaRegs.CANME.all = 0UL; /* Изменяет mailbox и фильтры только при выключенных ящиках. */
ECanaRegs.CANMIM.all = 0UL; /* Ни один старый mailbox не должен создавать IRQ во время настройки. */
ECanaRegs.CANMIL.all = 0UL; /* Направляет служебные mailbox на ECAN0INTA группы PIE9. */
ECanaRegs.CANMC.all = 0x00003080UL; /* SCB=1 выбирает eCAN, ABO=1 автоматическое восстановление, CCR=1 режим настройки битового времени; SRES остаётся нулём. */
while (!ECanaRegs.CANES.bit.CCE) {} /* Не пишет CANBTC до аппаратного подтверждения режима настройки. */
shadow = ((Uint32)(CLKMULT * 3L - 1L) << 16) | 0x0000017AUL; /* BRP=CLKMULT*3-1, SJW=1, TSEG1=15, TSEG2=2 как в приложении: 250000 бит/с при текущем SYSCLKOUT. */
ECanaRegs.CANBTC.all = shadow; /* Передаёт параметры одним 32-битным обращением к eCAN. */
ECanaRegs.CANMC.all &= ~0x00001000UL; /* Снимает CCR после настройки тактов CAN. */
while (ECanaRegs.CANES.bit.CCE) {} /* Ждёт возврата контроллера к обычной работе перед включением фильтров. */
ECanaRegs.CANTA.all = 0xFFFFFFFFUL; /* Удаляет старые TX ACK, которые не относятся к новой сессии. */
ECanaRegs.CANRMP.all = 0xFFFFFFFFUL; /* Удаляет старые RX-флаги до включения IRQ. */
ECanaRegs.CANRML.all = 0xFFFFFFFFUL; /* Начинает контроль потери mailbox с чистого состояния. */
ECanaRegs.CANGIF0.all = 0xFFFFFFFFUL; /* Снимает накопленные флаги линии CAN0. */
ECanaRegs.CANGIM.all = 1UL; /* I0EN разрешает mailbox IRQ по линии 0; ошибки не требуют прикладного ISR. */
PieVectTable.ECAN0INTA = &boot_can_rx; /* Использует постоянный обработчик загрузчика вместо кода RAM-приложения. */
PieCtrlRegs.PIEIER9.bit.INTx5 = 1; /* Разрешает ECAN0INTA в группе PIE9. */
EDIS; /* Возвращает защиту аппаратной конфигурации. */
IER |= M_INT9; /* Разрешает группе CAN доставлять IRQ ядру после общего EINT. */
} /* Общий порт затем настроит адресные mailbox 3/4/6. */
static unsigned int boot_periph_id(void) /* Повторяет аппаратное чтение Mode из peripher.c, чтобы после reset адрес загрузчика совпадал с приложением. */
{ /* Четыре активных низким уровнем перемычки существующей ПМ35 задают номера 1–16. */
unsigned int periph_id; /* Номер является ID PERIPH из Excel, а не уменьшенным на единицу индексом старого CAN. */
EALLOW; /* Разрешает настройку только четырёх входов адресных перемычек. */
GpioCtrlRegs.GPAMUX2.bit.GPIO20=0; /* GPIO20 работает входом адреса с весом 2, как в get_Mode приложения. */
GpioCtrlRegs.GPAMUX2.bit.GPIO21=0; /* GPIO21 работает входом адреса с весом 1, а не альтернативной периферией. */
GpioCtrlRegs.GPAMUX2.bit.GPIO22=0; /* GPIO22 работает входом адреса с весом 4. */
GpioCtrlRegs.GPBMUX2.bit.GPIO51=0; /* GPIO51 работает входом адреса с весом 8. */
GpioCtrlRegs.GPADIR.bit.GPIO20=0; /* Запрещает выходной драйвер, чтобы загрузчик не воздействовал на перемычку. */
GpioCtrlRegs.GPADIR.bit.GPIO21=0; /* Оставляет младшую адресную перемычку входом. */
GpioCtrlRegs.GPADIR.bit.GPIO22=0; /* Оставляет третий разряд аппаратного номера входом. */
GpioCtrlRegs.GPBDIR.bit.GPIO51=0; /* Оставляет старшую перемычку входом порта B. */
EDIS; /* Восстанавливает защиту конфигурации GPIO до чтения физического номера. */
periph_id=1U+!GpioDataRegs.GPADAT.bit.GPIO21; /* Штатный Mode начинается с 1; замкнутая GPIO21 добавляет единицу. */
periph_id+=2U*!GpioDataRegs.GPADAT.bit.GPIO20; /* Замкнутая GPIO20 добавляет два к номеру платы. */
periph_id+=4U*!GpioDataRegs.GPADAT.bit.GPIO22; /* Замкнутая GPIO22 добавляет четыре к номеру платы. */
periph_id+=8U*!GpioDataRegs.GPBDAT.bit.GPIO51; /* Замкнутая GPIO51 добавляет восемь; аппаратный диапазон заканчивается на 16. */
return periph_id; /* Общий CAN-порт преобразует номер 16 в Type 2 / Device 0 согласно Excel. */
} /* Приложение и recovery используют один и тот же физический адрес без общего значения 3/7. */
static bool ram_word(void *user, uint32_t address, uint16_t value) /* Аппаратная запись одного слова уже проверенной таблицы SCI8. */
{ /* Повторяет нижнюю защиту RAM даже при ошибке вызывающего слоя. */
(void)user; /* Контекст не нужен для единственной внутренней RAM данного F28335. */
if (address < 0x8000UL || address >= 0xE000UL) return false; /* Не позволяет таблице затронуть периферию, handoff, стек или RAM загрузчика. */
*(volatile Uint16 *)address = value; /* Адрес измеряется в 16-битных словах C28x, значение уже декодировано из SCI8. */
return true; /* Сообщает полную запись слова, а не частичное выполнение секции. */
} /* После загрузки всех слов общий store вернёт проверенную точку входа. */
static uint16_t flash_word(void *user, uint32_t address) /* Читает только фиксированный заголовок и проверенный диапазон приложения ниже сектора A. */
{ /* Загрузчик остаётся во Flash A, поэтому чтение H–B не меняет выполняемый код. */
(void)user; /* Единственная внутренняя Flash не требует отдельного контекста источника. */
return *(volatile Uint16 *)address; /* C28x адресует Flash 16-битными словами; разбиение на октеты выполняет общий валидатор CRC. */
} /* Никакая запись или стирание Flash при выборе источника запуска не выполняется. */
static void start_application(uint32_t entry, unsigned int source) /* Передаёт управление Flash либо EEPROM только после проверки соответствующего образа. */
{ /* Останавливает собственные IRQ до C startup приложения, который заново настроит периферию и рабочую RAM. */
DINT; IER = 0U; IFR = 0U; /* Старые прерывания не должны войти в очередь или стек завершённого загрузчика. */
CpuTimer1Regs.TCR.bit.TSS = 1; /* Прекращает миллисекундные IRQ до запуска прикладного InitSysCtrl. */
ECanaRegs.CANMIM.all = 0UL; /* Не доставляет CAN IRQ во время смены векторов приложения. */
F28335Boot_SetRunning(source); /* Сохраняет достоверный источник: 0/1 для EEPROM A/B либо FE для проверенной Flash. */
((void (*)(void))entry)(); /* Вызывает watchdog-safe startup Flash или проверенную точку C runtime RAM-образа. */
for (;;) {} /* Ошибочный возврат приложения не использует перезаписанное состояние загрузчика. */
} /* Возврат к boot происходит только аппаратным reset с согласованным handoff. */
void F28335Boot_Quiesce(void) /* Перед повторным входом загрузчика его собственные IRQ будут отключены общим Reset. */
{ /* Силовые выходы загрузчик не включает; прикладная остановка выполняется до входа в него. */
CpuTimer2Regs.TCR.bit.TSS = 1; /* Удерживает старый SPI Timer2 остановленным перед watchdog reset. */
} /* Общий аппаратный слой сохранит session и включит watchdog. */
void main(void) /* Постоянный загрузчик запускается аппаратным Flash boot по адресу 33FFF6. */
{ /* Пустая EEPROM и неподтверждённый кандидат оставляют доступным CAN recovery. */
f28335_boot_io_t io; /* Доступ к M95M02 предоставляет существующий переносимый SPI-порт. */
unsigned int slot, session, periph_id; /* Слот, сессия handoff и физический номер PERIPH сохраняются отдельно от адресов памяти. */
uint32_t entry, started; /* Адрес запуска измеряется словами CPU; started хранит миллисекунды стартового окна CAN. */
InitSysCtrl(); /* Повторяет PLL и SYSCLKOUT проекта 167, отключая watchdog на раннем старте. */
DINT; /* Не использует IRQ до настройки таблицы векторов и Timer1. */
IER = 0U; IFR = 0U; /* Исключает доставку старых прерываний после watchdog reset. */
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, &RamfuncsLoadEnd - &RamfuncsLoadStart); /* Переносит InitFlash в RAM до изменения времен доступа Flash. */
InitFlash(); /* Настраивает доступ к постоянному коду по штатной процедуре TI. */
InitPieCtrl(); /* Очищает разрешения и флаги всех групп PIE перед установкой двух собственных векторов. */
InitCpuTimers(); /* Останавливает Timer0/1/2 и сбрасывает их управляющие структуры. */
ConfigCpuTimer(&CpuTimer1, SYSCLKOUT / 1000000L, 1000UL); /* Период 1000 мкс даёт единый миллисекундный tick для протокола и SPI WIP. */
EALLOW; PieVectTable.XINT13 = &boot_tick; EDIS; /* Привязывает прямое прерывание Timer1 к постоянному ISR загрузчика. */
CpuTimer1Regs.TCR.all = 0x4020U; /* Разрешает прерывание Timer1 и запускает счётчик, как приложение 167. */
IER |= M_INT13; /* Разрешает миллисекундные прерывания ядра. */
periph_id=boot_periph_id(); /* Читает реальные перемычки до адресных mailbox и до ответа на ENTER_BOOT после reset. */
boot_can_init(); /* Настраивает трансивер и физическую скорость до общих фильтров и первой передачи. */
session = F28335Boot_RequestedSession(); /* Потребляет только достоверный запрос приложения с magic и XOR-контролем. */
F28335CanBoot_Init(periph_id); /* Открывает журнал и адресные Boot mailbox только для физического PERIPH данной платы. */
PieCtrlRegs.PIECTRL.bit.ENPIE = 1; /* Разрешает таблицу PIE после записи обоих используемых векторов. */
EINT; /* Приём окна CAN продолжается во время синхронных SPI-транзакций main. */
if (session) F28335CanBoot_Resume(session); /* Отвечает ENTER_BOOT после reset с той же session и остаётся в recovery. */
else { /* Обычный reset даёт CAN окно, затем предпочитает проверенную внутреннюю Flash и использует EEPROM как резерв. */
started = F28335Boot_Now(); /* Отсчитывает три секунды от готового CAN, а не от начала настройки PLL и SPI. */
while ((uint32_t)(F28335Boot_Now()-started)<3000UL && !F28335CanBoot_Active()) { F28335CanBoot_Service(); ServiceDog(); } /* ENTER_BOOT удерживает recovery; обычный PING не изменяет выбранный источник запуска. */
F28335CanBoot_Service(); /* Разбирает кадр на границе трёхсекундного окна до последней проверки активного сеанса. */
if (!F28335CanBoot_Active()) { /* Не запускает основную или резервную программу поверх открытого сеанса CAN Boot. */
if (f28335_flash_app_validate(flash_word, 0, &entry)) start_application(entry, F28335_BOOT_FLASH_SLOT); /* Flash приоритетна только при правильном FAB1, допустимых адресах и совпавшей CRC всех LOAD-секций. */
io.read = F28335Boot_Read; io.write = F28335Boot_Write; io.user = 0; /* Передаёт store ту же аппаратную реализацию, что обслуживает CAN. */
if (f28335_boot_open(&image_store, &io) && f28335_boot_select(&image_store, &slot) && slot < 2U && f28335_boot_load(&image_store, slot, ram_word, 0, &entry)) { /* Проверяет CRC/SCI8, сохраняет attempted до пробного запуска и копирует только допустимую RAM. */
start_application(entry, slot); /* Резервный EEPROM-образ получает прежние trial/CONFIRM и автоматический откат A/B. */
} /* При ошибке чтения, CRC, таблицы или журнала не выполняет неизвестный entry. */
F28335CanBoot_Init(periph_id); /* При переходе в recovery перечитывает журнал, сохраняя прежний физический адрес платы. */
} /* Открытый CAN-сеанс сохраняет метаданные, выбранный слот и подтверждения без повторного Init. */
} /* Завершает выбор между адресным входом и обычным запуском приложения. */
F28335Boot_SetRunning(F28335_AB_NONE); /* Отмечает режим загрузчика, сохраняя уже восстановленную session в RAM автомата. */
for (;;) { F28335CanBoot_Service(); ServiceDog(); } /* Обслуживает обновления и остаётся доступным при пустой/повреждённой EEPROM. */
} /* Нормальный выход выполняется только через запуск RAM-приложения либо watchdog reset. */
@@ -0,0 +1,5 @@
#include "../../../src/pcan_boot.c" /* Подключает единственный общий автомат ProtoCAN Boot и CRC32. */
#include "../../../ports/tms320f28335/f28335_boot_store.c" /* Использует проверенный A/B-журнал, readback, SCI8 и откат. */
#include "../../../ports/tms320f28335/f28335_flash_app.c" /* Проверяет FAB1 и CRC приложения ниже сектора A перед выбором основного Flash либо резервной EEPROM. */
#include "../../../ports/tms320f28335/f28335_boot_hw.c" /* Подключает те же SPI, watchdog и handoff, что RAM-приложение. */
#include "../../../ports/tms320f28335/f28335_can_boot.c" /* F28335_BOOT_LOADER=1 разрешает запись слотов только постоянному загрузчику. */
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<configurations XML_version="1.2" id="configurations_0">
<configuration XML_version="1.2" id="Sauris SAU510-USB Iso Plus v.2 Emulator_0">
<instance XML_version="1.2" desc="Sauris SAU510-USB Iso Plus v.2 Emulator_0" href="connections/SAU510USBIsoPlusV2_Connection.xml" id="Sauris SAU510-USB Iso Plus v.2 Emulator_0" xml="SAU510USBIsoPlusV2_Connection.xml" xmlpath="connections"/>
<connection XML_version="1.2" id="Sauris SAU510-USB Iso Plus v.2 Emulator_0">
<instance XML_version="1.2" href="drivers/sau510c28x.xml" id="drivers" xml="sau510c28x.xml" xmlpath="drivers"/>
<platform XML_version="1.2" id="platform_0">
<instance XML_version="1.2" desc="TMS320F28335_0" href="devices/f28335.xml" id="TMS320F28335_0" xml="f28335.xml" xmlpath="devices"/>
</platform>
</connection>
</configuration>
</configurations>