В настоящее время все больше встроенных устройств поддерживают удаленное автоматическое обновление без необходимости использования загрузчиков, что значительно упрощает обслуживание устройств. Чтобы включить удаленное обновление для устройства, необходимо написать программный код, поддерживающий процесс обновления. Эта программа обычно называется BootLoader.
По сути, программный код устройства делится на две части: BootLoader и APP. BootLoader отвечает за обновление APP и запуск его выполнения. APP, с другой стороны, отвечает за реализацию рабочих функций устройства, по сути, содержа в себе основные функции устройства.
Для микроконтроллеров серии Cortex-M для обеспечения безопасного перехода от BootLoader к APP требуются определенные настройки. В этой статье на примере микроконтроллеров STM32 описаны основные шаги настройки, необходимые для успешного перехода от BootLoader к APP.
BootLoader Перейти к приложению
Шаг 1: Раздел Flash
На этапе программирования и проектирования важно разделить флэш-память в соответствии с конкретными требованиями приложения. Это включает в себя определение места хранения BootLoader и APP, а также выделения места для каждого из них. Расположение хранилища напрямую влияет на выполнение программы и переходы.
Одна из простейших стратегий обновления предполагает наличие BootLoader и APP. BootLoader обрабатывает переходы и облегчает обновление APP. В данной статье эта стратегия обновления используется в качестве примера для объяснения.
Для микроконтроллеров STM32 адрес, сопоставленный для запуска программы, составляет 0x8000000.
BootLoader может храниться по адресу 0x8000000, а выделенное пространство может быть скорректировано в зависимости от конкретного размера флэш-памяти микросхемы, например, 0x10000 или 64 КБ.
Адрес хранения приложения находится после BootLoader, а именно по адресу 0x8010000. Оставшееся пространство в Flash может быть выделено для приложения.
Шаг 2: Настройка проекта BootLoader
Настройка проекта BootLoader включает в себя несколько шагов. На примере MDK программа BootLoader хранится в памяти FLASH по адресу 0x8000000 с размером 0x10000.

При переходе к APP с использованием программного кода учитывайте следующие моменты:
- Проверьте действительность верхнего адреса стека, то есть действительность начального адреса приложения.
if(((*(__IO uint32_t *)APP_FLASH_ADDR) & 0x2FFE0000) == 0x20000000)
- Отключите все прерывания, чтобы предотвратить помехи во время перехода, которые могут привести к исключениям.
- Получите начальный адрес программы APP, который хранится как второе слово (начальный адрес + 4, данные хранятся в Flash).
- Инициализируйте указатель стека (первое слово в области пользовательского кода содержит адрес вершины стека).
- Преобразуйте начальный адрес APP в тип указателя функции и выполните переход.
Конкретный код для перехода выглядит следующим образом:
/* Define type */
typedef void (*pFunction)(void);
/* APP flash address */
#define APP_FLASH_ADDR (0x8010000)
void jump_to_app(void)
{
uint32_t JumpAddress;
pFunction Jump_To_Application;
/* Check if the stack top address is valid */
if(((*(__IO uint32_t *)APP_FLASH_ADDR) & 0x2FFE0000) == 0x20000000)
{
/* Disable all interrupts to prevent disturbances during transition */
__disable_irq();
/* The second word in the user code area is the program's start address (reset address) */
JumpAddress = *(__IO uint32_t *) (APP_FLASH_ADDR + 4);
/* Initialize the user application's Stack Pointer */
__set_MSP(*(__IO uint32_t *) APP_FLASH_ADDR);
/* Type conversion */
Jump_To_Application = (pFunction) JumpAddress;
/* Transition to the APP */
Jump_To_Application();
}
}
Шаг 3: Настройка проекта APP
Аналогичным образом, проект APP требует определенных настроек. На примере MDK программа APP хранится в памяти FLASH по адресу 0x8010000 с размером 0x30000.

Конфигурация программы APP включает следующие шаги:
- Переместите внутреннюю таблицу векторов Flash в APP, изменив SCB->VTOR.
- После запуска APP необходимо включить прерывания в функции инициализации, чтобы обеспечить бесперебойное выполнение программы. Невыполнение этого требования может привести к сбоям в работе программы.
Обычно в файле запуска вызывается функция SystemInit(). Эта функция настраивает информацию об интерфейсе Flash.
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET

Измените значение макроопределения VECT_TAB_OFFSET на 0x10000.

После запуска программы APP очень важно включить глобальные прерывания. Вы можете поместить следующий код в раздел инициализации:
/* Enable interrupts */
__enable_irq();
APP Перейти к BootLoader
Во время работы устройства приложение работает и обрабатывает бизнес-функции. Если вы хотите обновить приложение, вам необходимо переключиться с приложения на BootLoader. Итак, как осуществить переход приложения на BootLoader? Существует два способа:
- Аппаратный режим, выключение устройства и перезапуск или нажатие кнопки сброса
- Программный режим: сброс MCU с помощью программного управления
В программном режиме команды управления могут быть добавлены в код приложения, и когда приложение получает команду перехода (или команду обновления), микроконтроллер сбрасывается. Следующий код может сбросить микроконтроллер:
/* reset chip */
HAL_NVIC_SystemReset();



