我想从STM32L072KBUx微控制器中的用户应用程序跳转到系统内存。
我认为有人已经回答了这个问题,但是不幸的是,我不明白这段代码:
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.PageAddress = Data_Address;
EraseInitStruct.NbPages = 1;
First_jump = *(__IO uint32_t *)(Data_Address);
if (First_jump == 0) {
HAL_FLASH_Unlock();
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Data_Address, 0xAAAAAAAA);
HAL_FLASH_Lock();
/* Reinitialize the Stack pointer and jump to application address */
JumpAddress = *(__IO uint32_t *)(0x1FF00004);
}
if (First_jump != 0) {
HAL_FLASH_Unlock();
HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError);
HAL_FLASH_Lock();
/* Reinitialize the Stack pointer and jump to application address */
JumpAddress = (0x1FF00369);
}
Jump_To_Application = (pFunction) JumpAddress;
__set_MSP(*(__IO uint32_t *)(0x1FF00000));
Jump_To_Application();
是否可以使用内部EEPROM而不是使用闪存进行跳转?
如果有人可以帮助我在自己的应用程序中使用此代码,我将不胜感激。
非常感谢。
答案 0 :(得分:1)
您根本不需要FLASH调用。这些是一些检查,以验证是否已存储有效的应用程序代码。
只需从引导加载程序向量表中加载堆栈指针和重置地址,然后跳转到重置地址即可。
void (*JumpToSystemBootloader)(void);
// set vector table start address
// volatile uint32_t addr = 0x1FFF0000; // for STM32F4
volatile uint32_t addr = 0x1FF00000; // for STM32L07xxx
// load reset vector address @+0x4
JumpToSystemBootloader = (void (*)(void)) (*((uint32_t *)(addr + 4)));
// load stack pointer address @+0x0
__set_MSP(*(uint32_t *)addr);
// jump to address loaded previously from @+0x4
JumpToSystemBootloader();
在进入系统引导加载程序之前,您可能还需要禁用所有中断并恢复几个控制器状态。
另请参阅:https://stm32f4-discovery.net/2017/04/tutorial-jump-system-memory-software-stm32/
Edit2: 只要bank1或bank2中有效的堆栈指针位于向量表中,设备的新引导加载程序版本都会始终再次跳转至应用程序代码。 如果从应用程序代码跳转到引导加载程序,情况也是如此。
Edit3: 您提供的代码是强制进入引导加载程序的一种卑鄙的方式。 因此,魔术字存储在闪存的某个位置。 在早期重新输入应用程序代码的过程中, 检查该值以重新输入引导加载程序。 要绕过bank,请提供一个新的跳转地址(0x1FF00369)。 (由逆向工程确定吗?) 假定控制器和RAM之前已经正确初始化。
因为供应商可以随时更改引导加载程序代码 使用此代码段时应格外小心。 我的建议是完全不使用此代码。
使用SRAM中的魔术值跳转到Bootloader [非用于生产]
参考:https://stackoverflow.com/a/43072025/5388805
// vector table start address (STM32L07xxx)
volatile uint32_t u32_boot_vector_addr = 0x1FF00000;
// bootloader bypass offset address
volatile uint32_t u32_boot_vector_offset = 0x369; // substituted from https://stackoverflow.com/a/43072025/5388805
// bootloader check definitions
volatile uint32_t * pu32_boot_tag = (volatile uint32_t *)0x20001800; // AN2606 states bootloader uses up to 5kByte RAM, add some offset
const uint32_t u32_boot_tag_reenter = 0xCAFEFEED;
const uint32_t u32_boot_tag_clear = 0xFFFFFFFF;
// call this at an early stage during startup (preferably right after entering the reset routine)
void checkBootloader()
{
// if magic tag is set jump back to bootloader
if (*pu32_boot_tag == u32_boot_tag_reenter)
{
// erase magic tag
*pu32_boot_tag = u32_boot_tag_clear;
// load bypass address
void (*JumpToSystemBootloader)(void) = (void (*)(void)) (*((uint32_t *)(u32_boot_vector_addr + u32_boot_vector_offset)));
// load stack pointer address @+0x0
__set_MSP(*(uint32_t *)u32_boot_vector_addr);
// jump to bypass address
JumpToSystemBootloader();
}
}
// call this anywhere from your application code
void jumpToBootloader()
{
// set magic tag
*pu32_boot_tag = u32_boot_tag_reenter;
// load reset vector address @+0x4
void (*JumpToSystemBootloader)(void) = (void (*)(void)) (*((uint32_t *)(u32_boot_vector_addr + 4)));
// load stack pointer address @+0x0
__set_MSP(*(uint32_t *)u32_boot_vector_addr);
// jump to address loaded previously from @+0x4
JumpToSystemBootloader();
}