0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

本跳转程序靠bug运行,请不要优化

鱼鹰谈单片机 来源:鱼鹰谈单片机 2023-07-11 14:59 次阅读

绝大多数产品开发,软件一般都会设计成 boot + app 的形式,这是方便后续软件更新,否则更新会变成一个很麻烦的事情。

网上随处可见的跳转程序大概如下:

#define APP_START_ADDR          0x08040000 


voidjump2app()
{
typedefvoid(*func_app_start)(void);
   
__disable_irq();

func_app_start app_start=(func_app_start)(*(__IOuint32_t*)(APP_START_ADDR+4));
  
__set_MSP(*(__IOuint32_t*)(APP_START_ADDR));//设置栈顶地址


app_start();
}

大多数情况下,该程序跳转正常,但当你改变了编译器优化级别时,可能直接就 hardfault 了。

此时你会莫名其妙,为什么???

从鱼鹰18接触到 boot 知识以来,都觉得这样的跳转程序理所当然,并且也没出现过问题,直到最近修改了优化级别,发现程序直接hardfault 了,根本没跳转到 app 中,才发现了这里隐藏的 bug。

调试发现,app_start 这个函数指针变成了异常值,但鱼鹰查看0x08040000 处的内存空间值是正常的。那只能是代码问题了。

因此结合汇编和在线调试,终于发现,执行__set_MSP 这条语句前app_start 的值是正常的,执行后,这个值就异常了。

再结合 C 语言关于栈、局部变量的知识,立刻就知道是因为重新设置栈顶地址,但汇编代码不变,但是从新栈位置偏移取函数地址,因此跳转失败。

如:

15bee072-1f9c-11ee-962d-dac502259ad0.png

新栈的位置,变量的值是未知的,用它进行跳转,失败是必然的。

但是为什么大部分情况下程序没有问题呢?

这是因为跳转程序很简单,局部变量少,那么这个app_start 局部变量编译器可能就不会从栈中分配,而直接用一个寄存器存储数据,而寄存器是不受栈顶位置影响的,自然程序能跳转了。

但我们不能让程序运行正常与否由编译器随机决定,因此我们要避免这个 bug,让程序不管在何种优化级别函数多复杂的情况下,依然可以正常运行,因此还是有必要进行优化的。

最简单的方法,就是把这个app_start 局部变量变成全局变量这样变量就不会受到栈顶位置影响,自然可以避免了。

如:

#define APP_START_ADDR          0x08040000 


voidjump2app()
{
typedefvoid(*func_app_start)(void);
   
__disable_irq();

static func_app_start app_start=(func_app_start)(*(__IOuint32_t*)(APP_START_ADDR+4));
  
__set_MSP(*(__IOuint32_t*)(APP_START_ADDR));//设置栈顶地址


app_start();
}

如有更好的优化方法,欢迎留言讨论。




声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    31

    文章

    5247

    浏览量

    119125
  • 函数
    +关注

    关注

    3

    文章

    4233

    浏览量

    61940
  • 变量
    +关注

    关注

    0

    文章

    607

    浏览量

    28251

原文标题:本跳转程序靠bug运行,请不要优化

文章出处:【微信号:emOsprey,微信公众号:鱼鹰谈单片机】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    西门子S7-1200 PLC程序控制指令:跳转与标签指令

    在S7-1200PLC中,程序控制指令主要包含两部分:一是改变程序执行顺序的的跳转指令;二是程序运行过程中用于控制的指令;本节主要分享
    发表于 03-07 10:25 6904次阅读

    与单片机Bug战斗的那些经历

    时我们可以知道是在哪一个地方。这点是相当的实用,对于无法仿真的51单片机,要了解程序内部运行的状态和变量现在的值,就显得很无语,简直束手无策。那么就加入串口程序的代码,利用串口将一些
    发表于 11-05 17:09

    与单片机Bug战斗的那些经历

    可以知道是在哪一个地方。这点是相当的实用,对于无法仿真的51单片机,要了解程序内部运行的状态和变量现在的值,就显得很无语,简直束手无策。那么就加入串口程序的代码,利用串口将一些重要变
    发表于 12-20 17:15

    IAP程序跳转到APP只能运行大约2秒

    );} 问题:如果设置了" __MSR_MSP (AppSpInitVal);//设置SP.,则跳转过去大约2秒就又回到IAP程序了;而不操作这个SP,则可以正常运行,实际上就是在IAP与APP同时
    发表于 03-14 08:05

    关于程序跳转的问题如何解决

    你好,我是一个初学者,有个问题想问一下就是关于DSP6747的在FLASH的0地址处加载一个AIS格式的bin文件,在这个程序读到RAM中运行的时候,我想让DSP跳转到另一个程序入口处
    发表于 05-22 14:49

    为了心爱的本本,不要吸烟

    为了心爱的本本,不要吸烟  问题:键盘里有很多烟灰,请问如何拆下,该如何清洗,工具哪有买,最好详细点,谢谢。我用的是COMPAQ的X1000   回答:
    发表于 01-25 13:04 374次阅读

    ---GD32F450---bootloader跳转到app无法运行

    问题描述:bootloader和app程序都能单独正常运行,但是在使用bootloader进行跳转时,程序跑飞。原因:bootloader在运行
    发表于 12-02 14:36 16次下载
    ---GD32F450---bootloader<b class='flag-5'>跳转</b>到app无法<b class='flag-5'>运行</b>

    KEIL上跳转程序的起始地址(未完成)

    //有任何想法,务必评论,共同进步一、keil设置二、程序设置内存上面做跳转,定义一个在此地址之后的量(数组函数都可以)三、程序起始运行
    发表于 12-03 09:06 12次下载
    KEIL上<b class='flag-5'>跳转</b><b class='flag-5'>程序</b>的起始地址(未完成)

    STM32 IAP - Boot跳转到APP

    简单IAP设计思路:单片机上电首先运行BootLoader程序; Bootloader如果检测到需要更新APP,则首先进行更新,更新完成后跳转到APP并运行; Bootloader如果
    发表于 12-03 14:21 8次下载
    STM32 IAP - Boot<b class='flag-5'>跳转</b>到APP

    【单片机程序和RAM】程序在RAM中调试的运行方式&程序固化后运行方式

    程序固化后运行方式: 程序开始运行后需要将RW 和ZI段搬移到RAM中去,程序下载进Flash中以后,上电后是怎样将RW ZI断搬移到RA
    发表于 12-03 15:21 4次下载
    【单片机<b class='flag-5'>程序</b>和RAM】<b class='flag-5'>程序</b>在RAM中调试的<b class='flag-5'>运行</b>方式&<b class='flag-5'>程序</b>固化后<b class='flag-5'>运行</b>方式

    BL(B)和LDR跳转范围是如何规定的

      LDR和BL在启动程序中,都是可以负责pc跳转的指令。   BL是地址无关指令,即和当前的运行地址无关。链接器脚本中标明了一个运行地址,但是arm中的代码实际是从地址0开始
    的头像 发表于 07-03 10:29 2112次阅读

    PLC跳转/标号指令的工作原理及应用举例

    跳转/标号执行是用来跳过部分程序使其不执行必须用在同一程序块内部实现跳转跳转/标号指令有两条,分别为
    的头像 发表于 10-08 09:59 5142次阅读

    SCL用GOTO语句执行程序跳转

    用GOTO语句能够执行程序跳转。此引起立即跳转到指定标号,为此而到同块中不同的语句。
    的头像 发表于 02-01 09:22 2399次阅读

    AN040 IAP程序跳转说明

    AN040 IAP程序跳转说明
    发表于 02-23 19:11 0次下载
    AN040 IAP<b class='flag-5'>程序</b><b class='flag-5'>跳转</b>说明

    PLC的条件跳转、子程序调用等

    当我们按下X000后,程序跳转指令开始运行程序跳转的位置为程序指针所在的位置,也就是标号10
    的头像 发表于 06-07 14:46 1188次阅读
    PLC的条件<b class='flag-5'>跳转</b>、子<b class='flag-5'>程序</b>调用等