ST意法半导体
直播中

王尚岱

9年用户 1616经验值
擅长:电源/新能源
私信 关注
[问答]

CUEBIDE生成的APP程序,在写入FLASH之后无法正常跳转怎么解决?

实现IAP的功能,使用CUEBIDE生成的APP程序的bin文件,写入到FLASH之后,无法正常跳转。
程序卡在/ 检查栈顶地址是否合法 /
但是用KEIL生成的bin文件写入后可以正常跳转,并执行。
bootloader应该没有问题,是不是APP程序还缺少配置?
APP程序在main函数的开头添加
SCB->VTOR = APP_Address;
__enable_irq();
STM32F407ZGTX_FLASH.ld中修改
/ Memories definition /
MEMORY
{
CCMRAM    (xrw)    : ORIGIN = 0x10000000,   LENGTH = 64K
RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 128K
FLASH    (rx)    : ORIGIN = 0x08020000,   LENGTH = 896K
}
是不是还漏掉了哪里,网上有关CUEBIDE的历程好像也只修改了这两处。


[/td]
以下内容为评论
[td]你不妨确认下栈顶位置、程序存放位置。这些都是在ld文件里的内容。

_estack = ORIGIN(RAM) + LENGTH(RAM);

RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = xxK
ROM    (rx)    : ORIGIN = 0x08008000,   LENGTH = yyK


然后,检查VTOR的偏移配置,比方:#define VECT_TAB_OFFSET 0x8000

再就是跳转前将中断使能都 禁用掉、保证跳转前没有未处理的中断请求、跳转过程中不会有中断请求发生。


保险起见,跳转前将PLL 也关闭掉。或者在APP端的SystemClock_Config()之前先调用下HAL_RCC_DeInit();

回帖(1)

戚歆敦

2025-6-16 17:46:09

针对CUEBIDE生成的APP程序在写入FLASH后无法正常跳转的问题,以下是系统化的解决方案:


问题关键原因分析



  1. 栈顶地址合法性检查失败:跳转时Bootloader检查APP的栈顶地址失败,表明生成的APP的向量表首地址(栈顶地址)未正确设置在RAM范围内。

  2. 链接脚本配置差异:CUEBIDE的默认链接脚本可能未适配IAP偏移,导致关键段(.isr_vector, .data)地址错误。

  3. 向量表重定向缺失:虽然添加了SCB->VTOR,但可能被其他初始化代码覆盖。

  4. 编译器优化差异:CUEBIDE与KEIL的编译/链接策略不同(如段对齐、优化级别)。




解决方案分步实施


1. 修改链接脚本适配IAP偏移


检查并修改STM32F407ZGTX_FLASH.ld


   MEMORY {
     /* 调整FLASH起始点为APP偏移地址(例如0x08010000) */
     FLASH (rx)  : ORIGIN = 0x08010000, LENGTH = 1M - 64K  /* 假设Bootloader占64K */
     RAM (xrw)   : ORIGIN = 0x20000000, LENGTH = 128K
     CCMRAM (xrw): ORIGIN = 0x10000000, LENGTH = 64K
   }

   SECTIONS {
     /* 确保向量表位于FLASH起始 */
     .isr_vector : {
       . = ALIGN(4);
       KEEP(*(.isr_vector))   /* 必须保留中断向量表 */
       . = ALIGN(4);
     } >FLASH

     /* 添加.data段重定位到RAM */
     .data : {
       _sdata = .;           /* 符号记录RAM中的起始地址 */
       *(.data)              /* 数据段 */
       _edata = .;           /* 符号记录结束地址 */
     } >RAM AT>FLASH        /* 存储在FLASH,运行时在RAM */
   }

2. 强化向量表重定向代码


main()初始化前设置VTOR:


   void SystemInit(void) {
     // 添加VTOR设置(优先级高于main)
     SCB->VTOR = 0x08010000;  // 与链接脚本FLASH起始地址一致
   }

   int main(void) {
     __enable_irq();          // 确保全局中断开启
     // ...其他代码
   }

注意:如果SystemInit()被库覆盖,在启动文件startup_stm32f407xx.sReset_Handler中插入:


   Reset_Handler:
     ldr r0, =0x08010000      // 设置VTOR偏移
     ldr r1, =0xE000ED08
     str r0, [r1]
     // ...后续初始化

3. 初始化前段数据搬运


startup_stm32f407xx.sReset_Handler添加.data复制:


   Reset_Handler:
     // 设置VTOR(如上)
     // 复制.data段到RAM
     ldr r0, =_sdata
     ldr r1, =_edata
     ldr r2, =_sidata         // FLASH中的数据源地址
     movs r3, #0
     b LoopCopyDataInit

   CopyDataInit:
     ldr r4, [r2, r3]
     str r4, [r0, r3]
     adds r3, r3, #4

   LoopCopyDataInit:
     adds r4, r0, r3
     cmp r4, r1
     bcc CopyDataInit

4. 编译配置调整



  • 设置FLASH偏移

    在CUEBIDE中定义宏:VECT_TAB_OFFSET=0x10000(对应64K偏移)。

  • 优化级别:与KEIL保持一致(如-O2)。

  • 生成.bin设置

    确保工具链生成二进制文件包含完整地址范围(无空洞)。


5. 验证生成的BIN文件



  • 用二进制工具检查BIN文件:

    • 首4字节:栈顶地址应在0x20000000~0x20020000

    • 5-8字节:复位向量地址应为0x080100xx


  • 若首4字节为0x00000000,表明向量表未正确链接。


6. Bootloader跳转前操作


确认Bootloader跳转前执行:


   // 关闭所有中断
   __disable_irq();
   // 清除中断标志(防止遗留中断)
   for (int i = 0; i < 8; i++) NVIC->ICER[i] = 0xFFFFFFFF;
   // 设置MSP并跳转
   uint32_t pStack = *(__IO uint32_t*)APP_ADDRESS;
   uint32_t pReset = *(__IO uint32_t*)(APP_ADDRESS + 4);
   __set_MSP(pStack);
   ((void (*)())pReset)();



验证步骤




  1. 用CUEBIDE编译后,用objdump检查.isr_vector段地址:


    arm-none-eabi-objdump -t output.elf | grep isr_vector

    输出应为:08010000 g     O .isr_vector




  2. 对比KEIL与CUEBIDE的MAP文件,确认关键段地址一致性。




  3. 烧录后单步调试Bootloader跳转过程,观察MSP值是否被正确设置为RAM地址。




通过以上步骤,90%的问题源于链接脚本偏移或启动文件的数据搬运缺失。重点检查关键内存段的实际部署地址是否与理论值匹配。

举报

更多回帖

×
20
完善资料,
赚取积分