Можно ли заставить функцию жить в загрузочном секторе, не перезаписывая загрузчик?

Не для каких-либо практических целей, а просто из любопытства, я хочу злоупотреблять флэш-памятью и динамически записывать ее во время выполнения. Это, в некотором смысле, то, что делает загрузчик. Насколько я понимаю, единственный способ изменить флэш-память - это сделать это из инструкций, записанных в загрузочный сектор. Можно ли туда воткнуть простенькую функцию, которая пишет во флеш-память, и вызывать ее из работающего кода? Если да, то как мне его туда поставить? У меня нет проблем с вызовом функций из указателей на функции, поэтому я не думаю, что у меня возникнут проблемы с фактическим вызовом функции, как только я доберусь туда, но мне нужно знать, как в первую очередь вставляться во flash.

, 👍3


1 ответ


Лучший ответ:

8

В Optiboot версии 8 есть функция do_spm, которую можно вызывать из приложения. Репозиторий Optiboot содержит пример использования этой функции.

SPM — это инструкция ЦП AVR для записи во флэш-память. Optiboot оборачивает это в функцию. Указатель на эту функцию помещается в «векторную таблицу» в начале загрузчика. Первый указатель переходит на main, второй указатель переходит на do_spm. Затем optiboot.h имеет функцию (версия для небольшой Optiboot)

typedef void (*do_spm_t)(uint16_t address, uint8_t command, uint16_t data);
const do_spm_t do_spm = (do_spm_t)((FLASHEND-511+2)>>1)

Я улучшил это, добавив функции copy_flash_pages с возможностью сброса для загрузки AVR с собственной флэш-памяти. . Он добавляется как третья запись в «таблицу векторов» Optiboot. Он используется в моей библиотеке ArduinoOTA для микроконтроллеров AVR.

typedef void (*copy_flash_pages_t)(uint32_t dest, uint32_t src, uint16_t page_count, uint8_t reset);
const copy_flash_pages_t copy_flash_pages = (copy_flash_pages_t)((FLASHEND-1023+4)>>1);
,

Это очень интересно, спасибо. Я это проверю, @Michael Stachowsky