【发布时间】:2021-01-16 14:29:41
【问题描述】:
我有一个问题。 我正在为我的 STM32F446RE 板开发 IAP(应用内编程)工具,但我被卡住了。 我已经开发了所有必要的实用程序,以便让微控制器从 GUI 接收二进制 (.bin) 编译文件,将其写入特定的闪存扇区并执行它。 我的问题是,从上传的代码中,我想再次跳转到存储在闪存扇区 0 上的引导加载程序,我看到代码没有跳转到引导加载程序,而是继续执行用户应用程序代码。我调试了代码,发现引导加载程序代码的所有地址(msp 和重置处理程序)都已正确设置,并且与上传的代码相比,它们有所不同。
我想要实现的流程如下:
1 --> 执行存储在扇区 0 上的引导加载程序代码(从地址 0x0800 0000 开始,当接收到来自用户按钮的中断时)并将新接收到的代码写入扇区 2(从地址 0x0800 8000 开始)
2 --> 设置msp地址(@0x0800 8000)和reset handler地址(0x0800 8004)
3 --> 跳转到新代码的reset handler地址(@0x0800 8004)
4 --> 执行新上传的代码。
5 --> 在用户代码执行期间,如果接收到中断(来自用户按钮),则设置引导加载程序 msp 地址、复位处理程序并跳转到引导加载程序
6 --> 从第一步开始重复。
这是用于从引导加载程序跳转到用户应用程序的代码:
IAP_loadProgram(&data);
//pointer to the user application reset handler address
void (*user_resetHandler)(void);
//set the user application MSP address (user application starts on the flash SECTOR2
uint32_t msp_addr = *(volatile uint32_t *)APPLICATION_ADDRESS;
__set_MSP(msp_addr);
//Set now the addres of the reset handler
uint32_t resetAddr = *(volatile uint32_t *)(APPLICATION_ADDRESS + 4);
user_resetHandler = (void *)resetAddr;
//When there, the bootloader sector will be leaved and the user code execution starts
user_resetHandler();
最后,用于从用户应用程序代码跳转到引导加载程序的代码是:
if(toBootloader){
toBootloader = 0;
//pointer to the user application reset handler address
void (*bootLoader_resetHandler)(void);
//set the user application MSP address (user application starts on the flash SECTOR2
uint32_t msp_addr = *(volatile uint32_t *)BOOTLOADER_ADDRESS;
__set_MSP(msp_addr);
//Set now the address of the reset handler
uint32_t bootLoaderResetAddr = *(volatile uint32_t *)(BOOTLOADER_ADDRESS + 4);
bootLoader_resetHandler = (void *)bootLoaderResetAddr;
//When there, the user code sector will be leaved and the bootloader code execution starts
bootLoader_resetHandler();
}
其中 APPLICATION_ADDRESS 为 0x0800 8000,BOOTLOADER_ADDRESS 为 0x0800 0000。
bootloader代码前两个地址的内容为:
0x08000000: 20020000
0x08000004: 080044DD
同时应用代码前两个地址的内容为:
0x08008000: 20020000
0x08008004: 0800A1F1
我所做的最后修改是在用户应用程序链接器 (.ld) 文件上,我将闪存开始设置为地址 0x0800 8000(而不是地址 0x0800 0000)。
所有中断都正常工作,在上传代码之后,如果我进行硬件复位,结果是一样的,代码执行从用户应用程序代码开始,而不是从引导加载程序开始。 有什么建议吗?
【问题讨论】:
-
您没有更改 VTOR - 这意味着您的向量表没有被更改。应用程序不太可能具有与引导加载程序完全相同的中断处理程序。您的逻辑很奇怪,对问题的描述不清楚。
-
要进行跳转(无论哪种方式),您都应该从向量表中加载 SP 和 PC,而不是使用将返回地址压入堆栈的函数调用。你的方法还有很多问题。
标签: c embedded bootloader flash-memory