硬汉嵌入式论坛

 找回密码
 立即注册
查看: 5028|回复: 15
收起左侧

[有问必答] 求助:STM32F407的boot、app程序跳转失败

[复制链接]

1

主题

15

回帖

18

积分

新手上路

积分
18
发表于 2021-12-29 15:42:27 | 显示全部楼层 |阅读模式
MCU:STM32F407VET6环境:STM32CubeMX + Keil
目标:在片内FLASH分区放置boot(0x0000_0000-0x0000_FFFF)与app(0x0001_0000-0x0007_FFFF),由boot执行引导后跳转到app区域执行
问题:无法实现跳转
附件 SPI_STM32F4.7z (12.76 MB, 下载次数: 13) :源码,boot、app公用一套代码,通过两个工程(SPI_STM32F4为boot,SPI_STM32F4_app为app)中的Flash划分与宏定义区分,用keil分别烧写boot、app


核心代码:
1、boot部分
void flash_run_app(uint32_t Address)
{
    // pFunction Jump_To_Application;
    void (*SysMemBootJump)(void);        /* 声明一个函数指针 */
    uint32_t JumpAddress = 0;

    DBG_PRINTF("app start addr:0x%08X", Address);

    /* Jump to user application */
    // JumpAddress = *(__IO uint32_t*) (Address + 0x04);
    SysMemBootJump = (void (*)(void)) (*((__IO uint32_t *) (Address + 4)));
    // Jump_To_Application = (pFunction) JumpAddress;
    /* Initialize user application's Stack Pointer */

    // 关总中断
    __set_PRIMASK(1);   

    /* 关闭滴答定时器,复位到默认值 */
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;

    /* 设置所有时钟到默认状态,使用HSI时钟 */
    HAL_RCC_DeInit();

    /* 关闭所有中断,清除所有中断挂起标志 */
    for (int i = 0; i < 8; i++)
    {
        NVIC->ICER=0xFFFFFFFF;
        NVIC->ICPR=0xFFFFFFFF;
    }

    // 开总中断
    __set_PRIMASK(0);  

    // __set_MSPLIM(0);

    __set_MSP(*(__IO uint32_t*) Address);
    //__set_PSP(*(__IO uint32_t*) Address);

    __set_CONTROL(0);

    SysMemBootJump();

    while(1)
    {

    };
}


2、app部分:
int main(void)
{
  /* USER CODE BEGIN 1 */

    #if 0 == ENA_BOOT_START_MODE

        /*重定向中断向量表*/
        SCB->VTOR = ADDR_APP_ENTRANCE;

    #endif

  /* USER CODE END 1 */


  其余省略...
}






回复

使用道具 举报

1

主题

15

回帖

18

积分

新手上路

积分
18
 楼主| 发表于 2021-12-29 15:44:57 | 显示全部楼层
硬汉哥审核速度堪称神速
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2021-12-29 16:11:58 | 显示全部楼层
boot程序的main函数里面直接跳转测试下

不要做任何其它操作

回复

使用道具 举报

1

主题

15

回帖

18

积分

新手上路

积分
18
 楼主| 发表于 2021-12-29 16:39:29 | 显示全部楼层
直接在boot main()最开始的地方调用flash_run_app(0x10000);还是跳转不过去,把app设置到flash位置app可以正常运行,但设置到0x10000,由boot引导跳转还是失败。现在是否可以说明是app初始化的问题?还是boot跳转有问题?或者都有问题?
回复

使用道具 举报

1

主题

15

回帖

18

积分

新手上路

积分
18
 楼主| 发表于 2021-12-29 17:00:02 | 显示全部楼层
更正一下,代码中的地址0x10000,应该改为0x08010000,已改并测试,还是跳转失败。
回复

使用道具 举报

1

主题

15

回帖

18

积分

新手上路

积分
18
 楼主| 发表于 2021-12-29 17:26:01 | 显示全部楼层
以下是硬汉的回复,方便遇到类似问题的坛友参考,根据硬汉的建议除了降级使用AC5没做,其他的都做了,跳转失败。(降级使用AC5一堆错误)

看来你的app有点问题
1、这个不要开,不支持DMA


1.png
2 工程改成用AC5测试,先不要用AC6.

3 中断向量表位置直接在这里设置好。
2.png

别的问题得逐步排查应用了
回复

使用道具 举报

1

主题

15

回帖

18

积分

新手上路

积分
18
 楼主| 发表于 2021-12-29 20:10:56 | 显示全部楼层
根据硬汉哥的提示,在之前的版本上修正了入口地址错误,改为正确的0x08010000,在boot(keil工程名:SPI_STM32F4)不开启优化O0,无法进行跳转,开启O1优化可实现跳转,汇编下跳转函数分别如下:
  1. // O1优化,可跳转:

  2. // flash_run_app()汇编

  3.   421: {
  4.    422:     // pFunction Jump_To_Application;
  5.    423:     void (*SysMemBootJump)(void);        /* 声明一个函数指针 */
  6.    424:     uint32_t JumpAddress = 0;
  7.    425:  
  8. 0x08002A88 B082      SUB           sp,sp,#0x08
  9.    426:     DBG_PRINTF("app start addr:0x%08X", Address);
  10.    427:  
  11.    428:     /* Jump to user application */
  12.    429:     // JumpAddress = *(__IO uint32_t*) (Address + 0x04);
  13. 0x08002A8A F2435115  MOVW          r1,#0x3515
  14. 0x08002A8E 4604      MOV           r4,r0
  15. 0x08002A90 F6C00100  MOVT          r1,#0x800
  16. 0x08002A94 A308      ADR           r3,{pc}+0x24  ; @0x08002AB8
  17. 0x08002A96 2001      MOVS          r0,#0x01
  18. 0x08002A98 F44F72D5  MOV           r2,#0x1AA
  19. 0x08002A9C 9400      STR           r4,[sp,#0x00]
  20. 0x08002A9E F7FFFFC3  BL.W          0x08002A28 bsp_dbg_print_lvl
  21.    430:     SysMemBootJump = (void (*)(void)) (*((__IO uint32_t *) (Address + 4)));
  22. 0x08002AA2 6860      LDR           r0,[r4,#0x04]
  23. 0x08002AA4 2100      MOVS          r1,#0x00
  24.    405:   __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
  25. 0x08002AA6 F3818810  MSR           PRIMASK,r1
  26.    458:     __set_MSP(*(__IO uint32_t*) Address);
  27.    459:     //__set_PSP(*(__IO uint32_t*) Address);
  28.    460:  
  29.    461:     //__set_CONTROL(0);
  30.    462:      
  31. 0x08002AAA 6821      LDR           r1,[r4,#0x00]
  32.    324:   __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : );
  33. 0x08002AAC F3818808  MSR           MSP,r1
  34.    463:     SysMemBootJump();
  35.    464:      
  36. 0x08002AB0 4780      BLX           r0
  37. 0x08002AB2 BF00      NOP           
  38.    465:     while(1)
  39. 0x08002AB4 E7FE      B             0x08002AB4
复制代码
  1. // O0优化,不可跳转:

  2. // flash_run_app()汇编   

  3.   421: {
  4.    422:     // pFunction Jump_To_Application;
  5.    423:     void (*SysMemBootJump)(void);        /* 声明一个函数指针 */
  6. 0x0800395C B580      PUSH          {r7,lr}
  7. 0x0800395E B088      SUB           sp,sp,#0x20
  8. 0x08003960 9005      STR           r0,[sp,#0x14]
  9. 0x08003962 2000      MOVS          r0,#0x00
  10.    424:     uint32_t JumpAddress = 0;
  11.    425:  
  12. 0x08003964 9002      STR           r0,[sp,#0x08]
  13. 0x08003966 9003      STR           r0,[sp,#0x0C]
  14.    426:     DBG_PRINTF("app start addr:0x%08X", Address);
  15.    427:  
  16.    428:     /* Jump to user application */
  17.    429:     // JumpAddress = *(__IO uint32_t*) (Address + 0x04);
  18. 0x08003968 9805      LDR           r0,[sp,#0x14]
  19. 0x0800396A 4669      MOV           r1,sp
  20. 0x0800396C 6008      STR           r0,[r1,#0x00]
  21. 0x0800396E F2444155  MOVW          r1,#0x4455
  22. 0x08003972 F6C00100  MOVT          r1,#0x800
  23. 0x08003976 F24443A7  MOVW          r3,#0x44A7
  24. 0x0800397A F6C00300  MOVT          r3,#0x800
  25. 0x0800397E 2001      MOVS          r0,#0x01
  26. 0x08003980 F44F72D5  MOV           r2,#0x1AA
  27. 0x08003984 F7FFFFA4  BL.W          0x080038D0 bsp_dbg_print_lvl
  28.    430:     SysMemBootJump = (void (*)(void)) (*((__IO uint32_t *) (Address + 4)));
  29. 0x08003988 9802      LDR           r0,[sp,#0x08]
  30. 0x0800398A 9905      LDR           r1,[sp,#0x14]
  31. 0x0800398C 6849      LDR           r1,[r1,#0x04]
  32. 0x0800398E 9104      STR           r1,[sp,#0x10]
  33. 0x08003990 9006      STR           r0,[sp,#0x18]
  34.    405:   __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
  35. 0x08003992 9806      LDR           r0,[sp,#0x18]
  36. 0x08003994 F3808810  MSR           PRIMASK,r0
  37.    458:     __set_MSP(*(__IO uint32_t*) Address);
  38.    459:     //__set_PSP(*(__IO uint32_t*) Address);
  39.    460:  
  40.    461:     //__set_CONTROL(0);
  41.    462:      
  42. 0x08003998 9805      LDR           r0,[sp,#0x14]
  43. 0x0800399A 6800      LDR           r0,[r0,#0x00]
  44. 0x0800399C 9007      STR           r0,[sp,#0x1C]
  45.    324:   __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : );
  46. 0x0800399E 9807      LDR           r0,[sp,#0x1C]
  47. 0x080039A0 F3808808  MSR           MSP,r0
  48.    463:     SysMemBootJump();
  49.    464:      
  50. 0x080039A4 9804      LDR           r0,[sp,#0x10]
  51. 0x080039A6 4780      BLX           r0
  52.    465:     while(1)
复制代码
完整源码如下: SPI_STM32F4.7z (13.07 MB, 下载次数: 1)

STM32F407VET6,Keil + STM32CubeMX

请帮忙分析一下原因。不胜感激。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2021-12-30 09:11:19 | 显示全部楼层
你当前的工程是特地没有勾MicroLib微库支持吗。可以勾上试试。
还要就是这里的延迟有必要修改下。:

QQ截图20211230090939.png
回复

使用道具 举报

1

主题

15

回帖

18

积分

新手上路

积分
18
 楼主| 发表于 2021-12-30 10:12:10 | 显示全部楼层
硬汉哥,
按照
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2021-12-30 10:27:54 | 显示全部楼层

内容没有发布成功。
回复

使用道具 举报

1

主题

15

回帖

18

积分

新手上路

积分
18
 楼主| 发表于 2021-12-30 10:32:18 | 显示全部楼层
eric2013 发表于 2021-12-30 10:27
内容没有发布成功。

正在编辑,不小心碰到了。
回复

使用道具 举报

1

主题

15

回帖

18

积分

新手上路

积分
18
 楼主| 发表于 2021-12-30 10:47:26 | 显示全部楼层
硬汉哥:
      按照你的建议修改了,还是无法跳转,换成AC5不开优化可以跳转。还是跳转函数被优化的问题。简化后的跳转函数如下:AC6,O0优化等级,加了static可以跳转,不加不能跳转。
  1. void flash_run_app(uint32_t Address)
  2. {
  3.     // pFunction Jump_To_Application;
  4.     static void (*SysMemBootJump)(void);        /* 声明一个函数指针 */

  5.     /* Jump to user application */
  6.     // JumpAddress = *(__IO uint32_t*) (Address + 0x04);
  7.     SysMemBootJump = (void (*)(void)) (*((__IO uint32_t *) (Address + 4)));

  8.     // 开总中断
  9.     __set_PRIMASK(0);  
  10.    
  11.     // __disable_irq();
  12.     // __enable_irq();

  13.     // __set_MSPLIM(0);
  14.    
  15.     __set_MSP(*(__IO uint32_t*) Address);

  16.    
  17.     SysMemBootJump();
  18.    
  19.     while(1)
  20.     {

  21.     };
  22. }
复制代码


回复

使用道具 举报

1

主题

15

回帖

18

积分

新手上路

积分
18
 楼主| 发表于 2021-12-30 11:00:54 | 显示全部楼层
加了static的汇编:
  1.    446: {
  2.    447:     // pFunction Jump_To_Application;
  3.    448:     static void (*SysMemBootJump)(void);        /* 声明一个函数指针 */
  4.    449:  
  5. 0x080029C8 B580      PUSH          {r7,lr}
  6. 0x080029CA B084      SUB           sp,sp,#0x10
  7. 0x080029CC 9001      STR           r0,[sp,#0x04]
  8.    450:     SysMemBootJump = (void (*)(void)) (*((__IO uint32_t *) (Address + 4)));
  9.    451:  
  10.    452:     // 开总中断
  11.    453:     __set_PRIMASK(0);   
  12.    454:        
  13. 0x080029CE 9801      LDR           r0,[sp,#0x04]
  14. 0x080029D0 6841      LDR           r1,[r0,#0x04]
  15. 0x080029D2 F2400010  MOVW          r0,#0x10
  16. 0x080029D6 F2C20000  MOVT          r0,#0x2000
  17. 0x080029DA 6001      STR           r1,[r0,#0x00]
  18. 0x080029DC 2100      MOVS          r1,#0x00
  19. 0x080029DE 9102      STR           r1,[sp,#0x08]
  20.    405:   __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
  21. 0x080029E0 9902      LDR           r1,[sp,#0x08]
  22. 0x080029E2 F3818810  MSR           PRIMASK,r1
  23.    455:     __set_MSP(*(__IO uint32_t*) Address);
  24.    456:     
  25. 0x080029E6 9901      LDR           r1,[sp,#0x04]
  26. 0x080029E8 6809      LDR           r1,[r1,#0x00]
  27. 0x080029EA 9103      STR           r1,[sp,#0x0C]
  28.    324:   __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : );
  29. 0x080029EC 9903      LDR           r1,[sp,#0x0C]
  30. 0x080029EE F3818808  MSR           MSP,r1
  31.    457:     SysMemBootJump();
  32.    458:      
  33. 0x080029F2 6800      LDR           r0,[r0,#0x00]
  34. 0x080029F4 4780      BLX           r0
  35.    459:     while(1)
  36. 0x080029F6 E7FF      B             0x080029F8
  37. 0x080029F8 E7FE      B             0x080029F8
  38. 0x080029FA 0000      MOVS          r0,r0
复制代码



不加static的:
  1.    446: {
  2.    447:     // pFunction Jump_To_Application;
  3.    448:     void (*SysMemBootJump)(void);        /* 声明一个函数指针 */
  4.    449:  
  5. 0x080029C8 B580      PUSH          {r7,lr}
  6. 0x080029CA B084      SUB           sp,sp,#0x10
  7. 0x080029CC 9001      STR           r0,[sp,#0x04]
  8.    450:     SysMemBootJump = (void (*)(void)) (*((__IO uint32_t *) (Address + 4)));
  9.    451:  
  10.    452:     // 开总中断
  11.    453:     __set_PRIMASK(0);   
  12.    454:        
  13. 0x080029CE 9801      LDR           r0,[sp,#0x04]
  14. 0x080029D0 6840      LDR           r0,[r0,#0x04]
  15. 0x080029D2 9000      STR           r0,[sp,#0x00]
  16. 0x080029D4 2000      MOVS          r0,#0x00
  17. 0x080029D6 9002      STR           r0,[sp,#0x08]
  18.    405:   __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
  19. 0x080029D8 9802      LDR           r0,[sp,#0x08]
  20. 0x080029DA F3808810  MSR           PRIMASK,r0
  21.    455:     __set_MSP(*(__IO uint32_t*) Address);
  22.    456:     
  23. 0x080029DE 9801      LDR           r0,[sp,#0x04]
  24. 0x080029E0 6800      LDR           r0,[r0,#0x00]
  25. 0x080029E2 9003      STR           r0,[sp,#0x0C]
  26.    324:   __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : );
  27. 0x080029E4 9803      LDR           r0,[sp,#0x0C]
  28. 0x080029E6 F3808808  MSR           MSP,r0
  29.    457:     SysMemBootJump();
  30.    458:      
  31. 0x080029EA 9800      LDR           r0,[sp,#0x00]
  32. 0x080029EC 4780      BLX           r0
  33.    459:     while(1)
  34. 0x080029EE E7FF      B             0x080029F0
  35. 0x080029F0 E7FE      B             0x080029F0
复制代码


回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2021-12-30 11:17:05 | 显示全部楼层
SUNRAIN 发表于 2021-12-30 10:47
硬汉哥:
      按照你的建议修改了,还是无法跳转,换成AC5不开优化可以跳转。还是跳转函数被优化的问题 ...

干脆此方案走起。

实战技能分享,一劳永逸的解决BOOT跳转APP失败问题,含MDK AC5,AC6和IAR,同时制作了一个视频操作说明
https://forum.anfulai.cn/forum.p ... 9595&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

1

主题

15

回帖

18

积分

新手上路

积分
18
 楼主| 发表于 2021-12-30 11:20:04 | 显示全部楼层
这个可以有
回复

使用道具 举报

1

主题

15

回帖

18

积分

新手上路

积分
18
 楼主| 发表于 2021-12-30 15:43:57 | 显示全部楼层
还是觉得有必要把最后的验证结果公布一下,万一有人遇到了呢。
两个关键点:
1、boot实现跳转申明的函数指针在Keil AC6编译器下需要定义为static(也可以定义为全局变量),否者该函数指针变量会被优化;
  1. void flash_run_user_app(uint32_t Address)
  2. {
  3.     // static类型
  4.     static void (*SysMemBootJump)(void);        /* 声明一个函数指针 */

  5.     /* Jump to user application */
  6.     SysMemBootJump = (void (*)(void)) (*((__IO uint32_t *) (Address + 4)));

  7.     // 开总中断
  8.     __set_PRIMASK(0);  
  9.    
  10.     __set_MSP(*(__IO uint32_t*) Address);
  11.    
  12.     SysMemBootJump();
  13.    
  14.     while(1)
  15.     {

  16.     }
  17. }
复制代码

2、在app中系统初始化前要复位中断向量。 1640850115(1).jpg
或者
// 大小自定义
SCB->VTOR = 0x00010000;
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-14 01:49 , Processed in 0.051353 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表