Обновите пользовательское приложение с помощью пользовательского загрузчика через UART (STM32)

Я использую плату STM32L4, и моя флэш-память выглядит так:

|______________
|
| ПОЛЬЗОВАТЕЛЬСКОЕ приложение
|
|
|______________
|Таблица векторов(UA)
|______________ 0x8000 - 8000
|
| Пользовательский загрузчик
|
|
|______________
|Таблица векторов(BL)
|______________ 0x8000 - 0000

Моя плата подключена к другой плате с помощью UART (давайте определим другую плату как Master, а мою плату как Slave).
Основная плата должна иметь возможность обновлять пользовательское приложение ведомой платы через UART. Идея в том, чтобы отправить бинарный файл по UART и записать его в раздел пользовательского приложения.

Согласно примечанию к применению ST, существует команда, называемая командой записи в память:

Команда записи в память используется для записи данных в любой действительный адрес памяти (см. примечание ниже), т. е. в ОЗУ, флэш-память, область дополнительных байтов.
Когда загрузчик получает команду записи в память, он передает байт ACK приложению. После передачи байта ACK загрузчик ожидает адрес (4 байта, байт 1 — старший бит адреса, байт 4 — младший бит) и байт контрольной суммы, после чего проверяет полученный адрес. Для области байтов опций начальный адрес должен быть базовым адресом области байтов опций (см. примечание), чтобы избежать несвоевременной записи в этой области.

если полученный адрес действителен и контрольная сумма верна, загрузчик передает байт ACK, в противном случае он передает байт NACK и прерывает выполнение команды. Когда адрес действителен и контрольная сумма верна, загрузчик:

• получает байт N, который содержит количество байтов данных, которые должны быть получены

• получает пользовательские данные ((N + 1) байт) и контрольную сумму (исключающее ИЛИ N и всех байтов данных)

• программирует пользовательские данные в память, начиная с полученного адреса

• в конце команды, если операция записи прошла успешно, загрузчик передает байт ACK; в противном случае он передает байт NACK приложению и прерывает выполнение команды.

• Максимальная длина записываемого блока для STM32 составляет 256 байт.

Это означает, что я могу обновить только 256 байт с помощью пакета, идущего с основной платы на подчиненную.

Теперь предположим, что на основной плате есть SD-карта с бинарным файлом, и я хочу прошить этот файл в раздел пользовательского приложения. Как я могу это сделать? Следует прочитать двоичный файл и отправить серию из 256 байтов, по 256 в каждом пакете?

Ответы (2)

Да. Очевидно, вы можете отправить несколько пакетов.

Существует компромисс между эффективностью и стоимостью неправильного получения пакета. С небольшими пакетами общие накладные расходы больше на объем фактически доставленных данных. Однако в случае ошибки потребуется повторно отправить меньше данных.

Тем не менее, ошибки в данных случаются или, по крайней мере, должны быть редки. Обычно вы отправляете пакеты максимального размера до тех пор, пока не останется меньше полного пакета данных.

Их алгоритм контрольной суммы скорее шуточный, скажем так, в лучшем случае "примитивный". Пакеты меньшего размера имеют большую защиту контрольной суммы, потому что на каждый бит данных фактически приходится больше битов контрольной суммы.

Конечно, вы не застряли с этим загрузчиком. Вы можете написать тот, который делает все, что вы хотите. См. этот вопрос для получения дополнительной информации о загрузчиках в целом.

Подробнее о проверке

Как указал Питер в комментарии, правильность данных важна для загрузчика.

Это хороший аргумент в пользу отказа от этого загрузчика и смехотворно наивного алгоритма контрольной суммы. Что я обычно делаю, так это даже не пытаюсь вычислить контрольную сумму отдельных пакетов. Я разрабатываю протокол для разумной эффективности, но добавляю хорошую контрольную сумму ко всему образу.

Передача данных с хоста на устройство — это только часть проблемы. Затем его необходимо правильно записать в энергонезависимую память. Это на самом деле гораздо более вероятно, чтобы потерпеть неудачу. Например, сбой питания или нажатие пользователем кнопки сброса в неподходящее время может привести к повреждению.

Моя стратегия, как правило, заключается не в том, чтобы беспокоиться о возможных ошибках на отдельных этапах процесса, а в том, чтобы проверять конечный результат. Обычно я помещаю что-то вроде 24- или 32-битной контрольной суммы CRC в конце загруженного изображения. Прежде чем загрузчик запускает основное приложение, он проверяет контрольную сумму. В случае сбоя он запрашивает новый образ, запускает предыдущий образ, сигнализирует об ошибке или что-то в этом роде. Никогда не запускайте поврежденный образ.

Из комментария:

Бинарный файл содержит прошивку (некоторые .c и .h и библиотеки, созданные с помощью встроенной IDE, например Keil).. Как добавить эту контрольную сумму в сам образ? Безопасно ли изменять такой файл?

Нет, бинарный файл не содержит файлов .c и .h. Это бинарный файл. Вам нужно сделать шаг назад и узнать, что делают компилятор, библиотекарь и компоновщик, и какая информация содержится в различных типах файлов. Вы не можете заниматься разработкой кода там, где вы находитесь близко к оборудованию, не понимая этих вещей.

Добавление контрольной суммы в двоичный файл (часто в формате Intel Hex) — один из способов добавить контрольную сумму в образ. Вы можете написать отдельный инструмент, который запускается после компоновщика. Этот инструмент считывает образ, вычисляет контрольную сумму и встраивает ее обратно в образ в известном месте.

Другой способ — заставить программу загрузки добавить контрольную сумму на лету. Загрузчик читает немодифицированный двоичный файл и добавляет контрольную сумму в известные места, обычно в последние несколько байтов изображения. Этот модифицированный образ затем отправляется загрузчику, но бинарный файл никогда не изменяется.

эффективность не является главной проблемой при обновлении прошивки. Корректность данных
Поправьте меня, если я ошибаюсь, я беру бинарный образ, отправляю его пакет за пакетом до последней его части. Как только я закончу, я отправляю 32-битный CRC двоичного файла и проверяю, совпадает ли он с рассчитанным на моей плате?
Вы всегда можете проверить правильность, прочитав запрограммированные данные. Это также проверит наличие ошибок программирования флэш-памяти, а не просто проверит связь. Я бы определенно продолжал использовать загрузчик ПЗУ, потому что он останется доступным, даже если вы каким-то образом случайно сотрете всю флэш-память.
@Pryda: Я думаю, что лучше встроить контрольную сумму прямо в само загружаемое изображение. Таким образом, правильность образа всегда можно проверить, а не только во время связи загрузчика с хостом.
Олаф. я обычно реализую двойную проверку. Контрольная сумма изображения является частью образа. Контрольная сумма передачи является чем-то сверх этого. Обычно (на самом деле всегда в наши дни) я также шифрую изображение.
Нормально ли возиться с сгенерированным двоичным файлом? Бинарный файл содержит прошивку (некоторые .c и .h и библиотеки, созданные с помощью встроенной IDE, например Keil).. Как добавить эту контрольную сумму в сам образ? Безопасно ли изменять такой файл?

Вы хотите написать свой собственный загрузчик, но цитируете примечание к приложению для встроенного. Забудь об этом.

Напишите загрузчик и читайте только Справочное руководство. Забудьте о встроенном загрузчике и его «командах».