|
在基于 STM32系列微控制器的应用过程中,In-Application Programming(IAP)允许在运行时更新应用程序固件。实现稳定可靠的IAP跳转,需要关注多个细节。由于在STM32 IAP类似应用中出现跳转失败是个非常高频的问题,在此较为系统地总结了STM32 IAP跳转设计中的应用提醒,涵盖内存配置、中断管理、缓存维护、时钟复位及跳转代码示例,助力开发者构建高效稳定的STM32芯片的IAP方案。 一、内存布局与链接脚本配置 1.1 不同 IDE 下的内存配置 STM32CubeIDE 基于GCC工具链,使用GNU ld链接脚本(.ld文件)管理内存布局。 链接脚本通常位于项目目录下的STM32xxxx_FLASH.ld文件。 内存定义示例: MEMORY { FLASH (rx) : ORIGIN = 0x08008000, LENGTH = 256K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K }
_estack = ORIGIN(RAM) + LENGTH(RAM); 修改时直接编辑.ld文件,调整ORIGIN和LENGTH即可。 IAR Embedded Workbench 使用链接描述文件(.icf文件)配置内存布局。 .icf文件通常在项目目录下,名称类似project.icf。 内存配置示例: define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; define symbol __ICFEDIT_region_RAM_end__ = 0x20010000; define symbol __ICFEDIT_region_ROM_start__ = 0x08008000; define symbol __ICFEDIT_region_ROM_end__ = 0x08040000; place in RAM_region { readonly section .no_init }; place in ROM_region { readonly }; 栈顶通常在启动文件或.icf中定义,需确保与RAM区域匹配。 当然,基于IAR IDE图形界面做相应调整也可以。 Keil MDK-ARM (uVision) 使用Scatter文件(.sct)定义内存布局。 .sct文件一般在项目目录里,名称如STM32xxxx.sct。 内存定义示例: LR_IROM1 0x08008000 0x00040000 { ; load region size_region ER_IROM1 0x08008000 0x00040000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x20000000 0x00010000 { ; RW data .ANY (+RW +ZI) } } 栈顶定义通常在启动文件中,需与RAM区域对应。 同样,基于ARM KEIL IDE图形界面做相应调整也可以实现,也很方便。 二、中断向量表偏移( VTOR )配置 定义中断向量表偏移量,匹配应用程序起始地址: define VECT_TAB_OFFSET 0x8000 // 例如0x08008000起始地址跳转前的系统控制块寄存器VTOR的最终值为: SCB->VTOR = ApplicationAddress + VECT_TAB_OFFSET; 确保中断向量表指向正确的应用程序入口。 三、缓存管理【若相关 STM32 系列支持 D-CAHCE, 比方 STM32H7 等】 跳转前关闭D-Cache,避免缓存数据与主存不一致导致跳转异常: SCB_DisableDCache(); DMA写入内存后,建议调用SCB_InvalidateDCache_by_Addr失效缓存,保证CPU读取最新数据。 跳转前根据实际缓存策略,执行相应缓存维护操作,确保数据一致性。 四、 MSP 检查 MSP初始化时,需根据实际RAM地址区域,正确判断MSP地址是否有效: if ((((__IO uint32_t ) ApplicationAddress) & 0x2FFE0000) == RAM_BASE_ADDRESS) { // MSP有效,继续跳转 } 确保MSP指向正确的栈顶地址。 五、中断管理 跳转前逐一禁用外设端所有已使能的中断,包括SYSTICK的关闭。 SysTick->CTRL = 0; // 禁用SYSTICK __disable_irq()仅仅暂停CPU响应中断,并未禁用外设端的中断使能,既不能清除中断标志,也不能禁止外设端的中断请求产生,故需逐个禁用外设端中断请求和清除相关中断事件标志。对于禁用外设中断使能,这里有个比较简单有效的方法就是对相关外设进行复位。 六、时钟和 PLL 管理 跳转前关闭 PLL和相关时钟,避免时钟配置冲突。 使用STM32库函数的话,比较简单的做法就是调用HAL_RCC_DeInit(); 确保应用程序能从干净的时钟环境重新配置系统时钟。 七、跳转代码参考示例 typedef void (*pFunction)(void ); void JumpToApplication (uint32_t ApplicationAddress) { uint32_t JumpAddress; pFunction JumpToApp; // 校验MSP是否有效(根据所用RAM区域具体调整) if ((((__IO uint32_t )ApplicationAddress) & 0x2FFE0000) == 0x20000000) { // __disable_irq(); // 关闭D-Cache,避免缓存不一致 SCB_DisableDCache(); // 关闭PLL和复位时钟配置 HAL_RCC_DeInit(); // 设置中断向量表偏移 SCB->VTOR = ApplicationAddress; // 设置MSP为应用程序栈顶 __set_MSP((__IO uint32_t )ApplicationAddress); // 获取复位向量(入口地址) JumpAddress = (__IO uint32_t )(ApplicationAddress + 4); JumpToApp = (pFunction)JumpAddress; // 切换到主线程模式,使用MSP __set_CONTROL(0); // 跳转到应用程序入口 JumpToApp(); } } 八、下面就 IAP 应用过程中基本步骤及操作做个总结,见下表:
在STM32 IAP类似应用中发生跳转失败是个比较常见的问题,这里稍加总结罗列相关环节及步骤在此,应用时可以灵活参考。 |
实战经验 | 碰到hardfault问题你还在死磕代码吗?
【福利三:逢7发帖赢大礼】想要充分利用STM32H743VI片内的RAM空间(但并不顺利)
【逢7发帖赢大礼】STM32开发之WIFI实时时钟
【逢7发帖赢大礼】STM32开发之指纹识别!
【逢7发帖赢大礼】STM32开发之环境空气质量监测
【逢7发帖赢大礼】STM32开发之人体实时运动信息监测!
HAL2架构与项目工程格式使用方法
【STM32U3 评测】CAN报文接收及过滤
STM32 硬核调试技巧:用 DWT 硬件监控内存读写与函数调用
OpenBLT移植到STM32F103战舰开发板上适用于所有STM32F103系列的Bootloader
微信公众号
手机版