打印

GD32 IAP固件升级跳转 (Bootloader APP)踩坑解答

[复制链接]
798|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
c17|  楼主 | 2022-11-23 15:52 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
GD32升级进入HardFaultHandler()原因分析

大家好!随着全球芯片紧缺,许多企业纷纷选择了国产芯片。今天我就GD32(兆易创新)MCU的固件升级所遇到的问题给大家说说我的看法。相信使用GD芯片的工程师,都看过GD给出的Demo例程,关于IAP的,有一个BOOT(LED慢闪),按下按键跳转至APP(LED快闪)的例程。 这里看似没啥问题,大家注意其中有2个坑

使用特权

评论回复
沙发
c17|  楼主 | 2022-11-23 15:58 | 只看该作者
第一个坑

BOOT程序(或者叫IAP程序) 和 APP FLASH划分

    BOOT通常来说比较小 最多也就10K多,大家看看我的配置

    BOOT程序起始地址:0x8000000
    SIZE我分配了0x2000 ,也就是8k字节 , BOOT程序编译下来需要比8k小

使用特权

评论回复
板凳
c17|  楼主 | 2022-11-23 16:01 | 只看该作者
app程序起始地址:0x8010000

SIZE我分配了0x80000(最大) , 实际上APP程序不会有这么大,没关系就写这个。

使用特权

评论回复
地板
c17|  楼主 | 2022-11-23 16:01 | 只看该作者
第二个坑

跳转问题:
1.BOOT跳转至APP时,调用这个代码即可
__disable_irq(); // 可以使用这个函数 关闭总中断

JumpAddress = *( __IO uint32_t* )( ApplicationAddress + 4 );            //用户代码区第二个字存储为新程序起始地址(新程序复位向量指针)
Jump_To_Application = ( pFunction ) JumpAddress;
__set_MSP( *( __IO uint32_t* ) ApplicationAddress );                    //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)


Jump_To_Application();                                                  //设置PC指针为新程序复位中断函数的地址

    1
    2
    3
    4
    5
    6

这一步都没啥问题,把跳转地址填对(就是APP程序的起始地址)

使用特权

评论回复
5
c17|  楼主 | 2022-11-23 16:02 | 只看该作者
2.APP跳转至BOOT
这里问题就大了,用BOOT的方法,将地址替换成BOOT的起始地址0x8000000,你会发现,也可以成功,但是,再从BOOT跳转至APP的时候 就有问题了, 进入APP程序后,初始化外设时,会进入HardFaultHandler();硬件错误中断函数,一直停留在while(1); 这是为啥???

使用特权

评论回复
6
c17|  楼主 | 2022-11-23 16:03 | 只看该作者
函数指针跳转 和 系统复位 的区别

大家看到没有,BOOT跳转至APP的方法是,使用函数指针,调用时,使得PC指针指向APP所在位置,但是这个方法用在 APP跳向BOOT的时候,却不严谨。

使用特权

评论回复
7
c17|  楼主 | 2022-11-23 16:10 | 只看该作者
函数指针跳转

函数指针跳转,仅仅是将PC指针 指向 目标地址,MCU是有堆栈的呀,光跳转过去,不清除堆栈.有可能出现RAM溢出(你的APP程序占用RAM比较大就会出现这个情况), 进入HardFault硬件错误中断的情况之一:堆栈溢出。 就会出现 BOOT第一次跳转至APP,都正常 ,APP跳转BOOT之后 , 第二次再从BOOT使用函数指针跳转APP,进入 HardFault硬件错误中断 , 因为第一次从BOOT跳转APP时,BOOT并没有占用太多的RAM, 所以哪怕不清除堆栈, 依然够用, 那么第二次再跳转APP的时候,. 之前在APP时已经初始化太多变量和函数,消耗了太多的RAM,这时不清除堆栈,再次进入APP, MCU就会因为堆栈不够,发生溢出,导致进入了硬件错误中断。

使用特权

评论回复
8
c17|  楼主 | 2022-11-23 16:12 | 只看该作者
系统复位
前面我已经说了跳转导致进入硬件错误中断的原因, 知道了原因问题就已经解决了一半,怎么解决? 我清除堆栈不就行了麻。 怎么清除? 大家麻烦去百度一下 这个函数 NVIC_SystemReset(); 看名字就知道,是系统复位函数, 是的,这个函数会将相关标志位清除,具体是哪一行我不知道,但是这个函数确实能清除堆栈,使用这个函数,实现 APP跳转至 BOOT, 就能够避免因为堆栈溢出,而导致进入硬件错误中断。

使用特权

评论回复
9
c17|  楼主 | 2022-11-23 16:20 | 只看该作者
给大家上源码看看
        __disable_irq();  // 可以使用这个函数 关闭总中断
        __set_FAULTMASK(1);        //关闭中断,确保跳转过程中 不会进入中断,导致跳转失败
        NVIC_SystemReset();          //系统复位,复位后默认从MCU的起始地址开始, 也就是BOOT的起始地址开始, 这样程序就从APP回到了BOOT,再从BOOT跳转至APP的时候, 堆栈已经清除了,也就不会发生溢出









        上面是我写给自己的, 避免以后再犯错, 在下能力有限 如有不对之处,恳请大佬指点,感激不尽!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

c17

37

主题

307

帖子

1

粉丝