Top.Mail.Ru
Уведомления
Очистить все

[Решено] Программный переход в System Bootloader STM32

coding_man
(@coding_man)
New Member

Привет!

В общем такой вот вопрос, как в названии темы - как-то можно из программы перейти в заводской загрузчик STM32, без подачи сигналов на ножки BOOT?

Цитата
Topic starter Размещено : 30.05.2021 13:25
Тэги темы
Aveal
(@aveal)
Illustrious Member Admin

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

Подаем на этот вывод 1, конденсатор заряжается. Затем перезапускаем контроллер. При включении на выходе BOOT будет нужный уровень для входа в System Bootloader (из-за накопленного заряда). Далее выполняем прошивку, конденсатор за некоторое время разряжается через резистор и после следующего перезапуска попадаем снова в основную программу.

Здесь нужно учитывать подключаемые номиналы конденсатора и резистора для задания определенной постоянной времени RC-цепи.

Но мы редко такой вариант используем из-за того, что, во-первых, требуется пусть и минимальная но дополнительная обвязка. А это лишнее место на плате, лишние компоненты, лишний монтаж итд )

Поэтому второй вариант - непосредственно из основной программы перейти на адрес, по которому расположен System Bootloader. Здесь тоже есть свой нюанс, который заключается в правильной перенастройке некоторой периферии перед jump инструкцией. Для разных контроллеров здесь могут быть разные дополнительные условия, которые нужно выполнить.

У вас какой контроллер? Я сделаю пример кода конкретно для него.

ОтветитьЦитата
Размещено : 31.05.2021 13:02
coding_man
(@coding_man)
New Member

@aveal

Спасибо за такой подробный ответ ?

Да, мне больше второй вариант подойдет, без дополнительных компонентов.

Контроллер STM32F042, буду очень рад примеру))

ОтветитьЦитата
Topic starter Размещено : 01.06.2021 17:31
Aveal
(@aveal)
Illustrious Member Admin

@coding_man, готово, для STM32F04xxx:

void BootloaderJump()
{
  FLASH_EraseInitTypeDef eraseStruct;
  eraseStruct.NbPages = 1;
  eraseStruct.PageAddress = 0x08000000;
  eraseStruct.TypeErase = FLASH_TYPEERASE_PAGES;
  
  uint32_t error = 0;
  
  HAL_DeInit();
  HAL_RCC_DeInit();
  __disable_irq();
  
  __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
    
  HAL_FLASH_Unlock();
  HAL_FLASHEx_Erase(&eraseStruct, &error);
  HAL_FLASH_Lock();
  
  const uint32_t ptr = (*((uint32_t *) SYSTEM_MEMORY_ADDR));
  void (*JumpToSystemMemory)(void);
  
  JumpToSystemMemory = (void (*)(void)) (*((uint32_t *) SYSTEM_MEMORY_ADDR + 4));
  __set_MSP(ptr);
  JumpToSystemMemory();
  
  while(1);
}

Здесь присутствует нюанс с очисткой flash-памяти перед переходом в System Memory. Это особенность именно этого семейства, из аппноута:

Due to empty check mechanism present on this product, it is not possible to jump from user code to system bootloader. Such jump results in a jump back to user Flash memory space.But if the first 4 bytes of User Flash (at 0x0800 0000) are empty at the moment of jump (i.e. erase first sector before jump or execute code from SRAM while Flash is empty), then system bootloader is executed when jumped to

Так, далее:

#define SYSTEM_MEMORY_ADDR                                      0x1FFFC400

Этот адрес также для разных контроллеров/семейств варьируется.

Вызываем просто из любого места программы:

BootloaderJump();
ОтветитьЦитата
Размещено : 02.06.2021 13:01
coding_man
(@coding_man)
New Member

@aveal Забыл поблагодарить... Вчера все запустил, идеально работает, спасибо!!

ОтветитьЦитата
Topic starter Размещено : 03.06.2021 16:06
Поделиться: