См. ниже. Контрольный код хранится где-то в середине прошивки,
вставляется туда через двойнную линковку и перекомпиляцию файлика с
контрольной суммой после её подсчёта (на PC для чего с помощью
objdump ELF превращается в BIN и самодельная программа считает
CRC). A потом полученный второй раз BIN программируется
бутлоадером. Вообще workflow такой: 1) зашивка программатором бутлоадера и тест-программы;
2) тестирование;
3) зашивка через bootloader BIN-файла с рабочей программой (он ещё зашифрован).
Более подробно: http://caxapa.ru/980919
О контрольных суммах, цитирую: http://caxapa.ru/768150:
Из функции _start (в C-стартапе, до main) пересчитывается CRC32 прошивки, например, и сравнивается с значениями записанными по специальным адресам (которые при чтении всегда принимаются нулевыми, например). Или контрольная сумма (тут можно подобрать, чтоб с самими байтами контрольной суммы вышел ноль). Или сумма Флетчера, или Адлера. Если контрольный код не верный -- отказ от работы, мигание диодом, азбукой морзе, матерного слова. Код осуществляющий проверку должен быть как можно проще, чтоб не был затронут отказом флеши.
Как добавить CRC в программу, да просто: const long flash_checksum = 0 в отдельном файлике. Потом делаешь elf файл, из него достаешь с помощью objcopy сегменты .rodata, .text (все, что во флеш), считаешь crc внешней программой (на входе hex или bin), потом линкуешь проект еще раз, но с другим содержимым отдельного файлика, где реальное значение crc вписано. Вместо файлика можно линкерскрипт специальный написать, но мороки больше, проще с файликом. Повторяю, при расчете в прошивке уже, 4 байта по адресу flash_checksum не считывать и принимать равными нулю.