Привет!
В общем такой вот вопрос, как в названии темы - как-то можно из программы перейти в заводской загрузчик STM32, без подачи сигналов на ножки BOOT?
Можно использовать вариант с RC-цепочкой. То есть к пину BOOT подключаются внешние дополнительные резистор и конденсатор, с другой стороны цепочка подключается к любому свободному выводу.
Подаем на этот вывод 1, конденсатор заряжается. Затем перезапускаем контроллер. При включении на выходе BOOT будет нужный уровень для входа в System Bootloader (из-за накопленного заряда). Далее выполняем прошивку, конденсатор за некоторое время разряжается через резистор и после следующего перезапуска попадаем снова в основную программу.
Здесь нужно учитывать подключаемые номиналы конденсатора и резистора для задания определенной постоянной времени RC-цепи.
Но мы редко такой вариант используем из-за того, что, во-первых, требуется пусть и минимальная но дополнительная обвязка. А это лишнее место на плате, лишние компоненты, лишний монтаж итд )
Поэтому второй вариант - непосредственно из основной программы перейти на адрес, по которому расположен System Bootloader. Здесь тоже есть свой нюанс, который заключается в правильной перенастройке некоторой периферии перед jump инструкцией. Для разных контроллеров здесь могут быть разные дополнительные условия, которые нужно выполнить.
У вас какой контроллер? Я сделаю пример кода конкретно для него.
Спасибо за такой подробный ответ 👍
Да, мне больше второй вариант подойдет, без дополнительных компонентов.
Контроллер STM32F042, буду очень рад примеру))
@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();
@aveal Забыл поблагодарить... Вчера все запустил, идеально работает, спасибо!!