• 正文
  • 相关推荐
申请入驻 产业图谱

GD32 IAP升级——boot和app相互跳转

2小时前
191
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

1 Keil工程设置

1.1 修改ROM

GD32内部Flash是一整块连续的内存,但是因为要分成boot和app,因此我们的boot工程和app工程要分别设置代码存放的地址。

举个例子:我这里用的是GD32E50x,内存大小为512k,我把前面16k作为boot分区,后面的496k作为app分区。那么Keil的ROM的配置如下:

分区 起始地址 大小
boot 0x8000000 0x04000
app 0x8004000 0x7C000

keil配置如下图:

boot工程配置:

app工程配置:

1.2 Keil烧录配置

如果需要使用Keil一键烧录的话,要先修改一下烧录的配置,具体根据自己boot和app的分区来设置。

boot配置参考:

app配置参考:

2 代码编写

2.1 app跳转

从boot跳转到app的代码参考:

app_func application;
uint32_t app_address;

void jump_to_app(uint32_t app_load_addr)
{
    if (((*(__IO uint32_t*)app_load_addr) & 0x2FFE0000U) == 0x20000000U) 
    {
        app_address = *(__IO uint32_t*) (app_load_addr + 4U);
        application = (app_func) app_address;

        /* initialize user application's stack pointer */
        __set_MSP(*(__IO uint32_t*) app_load_addr);

        /* jump to user application */
        application();
    }
}

完整用法示例:

#include "main.h"

#define APP_LOADED_ADDR    0x08004000U

app_func application;
uint32_t app_address;

void jump_to_app(uint32_t app_load_addr)
{
    if (((*(__IO uint32_t*)app_load_addr) & 0x2FFE0000U) == 0x20000000U) 
    {
        app_address = *(__IO uint32_t*) (app_load_addr + 4U);
        application = (app_func) app_address;

        /* initialize user application's stack pointer */
        __set_MSP(*(__IO uint32_t*) app_load_addr);

        /* jump to user application */
        application();
    }
}

int main(void)
{
    systick_config();

    jump_to_app(APP_LOADED_ADDR);
    while(1)
    {
    }
}

2.2 软件重启

在app运行期间,如果需要重新进入boot,可以通过软件重启实现,参考代码如下:

NVIC_SystemReset();

NVIC_SystemReset()函数原形如下:

/**
  \brief   System Reset
  \details Initiates a system reset request to reset the MCU.
 */
__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
{
  __DSB();                                                          /* Ensure all outstanding memory accesses included
                                                                       buffered write are completed before reset */
  SCB->AIRCR  = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos)    |
                           (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
                            SCB_AIRCR_SYSRESETREQ_Msk    );         /* Keep priority group unchanged */
  __DSB();                                                          /* Ensure completion of memory access */

  for(;;)                                                           /* wait until reset */
  {
    __NOP();
  }
}

2.3 app中断向量表偏移

GD32的Flash存放了程序固件,默认从0x08000000开始启动,前面的部分是中断向量表,在做了boot和app的区分后,从0x08000000开始运行的是boot的中断向量,它在跳转到app以后就失效了,因此需要重新映射app的中断向量表。

做法是在app的程序里面,修改中断向量表偏移,如下:

#define VECT_TAB_OFFSET  (uint32_t)0x4000            /* vector table base offset */

 

注:上述代码在`system_gd32e50x.c`里面定义,具体偏移多少取决于你app分区的起始地址,计算方法是:偏移 = app起始地址 - 0x08000000。

结束语

好了,关于GD32如何切换boot和app就讲到这里,有什么问题欢迎评论区留言。

相关推荐