关于STM32的IAP编程的一些记录--BootLoader与APP相互跳转

1 篇文章 0 订阅
本文介绍了如何优化STM32的BootLoader以实现在上电或软件复位后的不同行为。通过在SystemInit函数中判断复位类型,软件复位时直接跳转至APP,提高系统响应速度。同时,添加了从APP主动跳转到BootLoader的功能,以便于随时进行固件升级。在实现过程中,需要注意外设和时钟配置的恢复,以避免运行异常。
摘要由CSDN通过智能技术生成

背景

在给STM32单片机做IAP(Flash分为两部分:BootLoader+APP)升级功能时,有如下需求- -

  1. 系统上电默认先进入BootLoader中,BootLoader会停留几百毫秒;
  2. 停留期间,系统会判断是否具有IAP请求,如果有则进行IAP升级,否则超时后跳转到APP中即可;

这样得逻辑很简单,但是有一个缺陷,就是不管上电还是复位后始终必须停留几百毫秒后才能跳转至APP,对于是实现要求高的、跑飞后需要立刻进行复位重启的系统,是不合理的。因此可以进行一个优化:

  • 在需求2的基础上,先判断复位类型是上电店复位还是软件复位,如果是软件复位,直接跳转至APP,不停留。

关键代码实现

以stm32f4为例,修改system_stm32f4xx.c中的SystemInit函数

void SystemInit(void)
{
    /* USER CODE BEGIN 1 */
    // 判断 app是否存在标志,app存在时跳转的前提
    uint8_t isAppExistFalg = *(__IO uint8_t*)(标记app是否存在的地址));
    // 判断是否为软件复位,软件复位就直接跳转到app中
    if( (1 == isAppExistFalg) && ((RCC->CSR) & 0x10000000) )
    {
       __HAL_RCC_CLEAR_RESET_FLAGS();

       extern void jump2aplication(void);
       jump2aplication();
    }
    /* USER CODE END 1 */
    ...
    省略
    ...
  // 注意:编译APP时,宏VECT_TAB_OFFSET要设定正确的偏移量,设定方法见文末
  /* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
}

其中 函数jump2aplication()实现为:

typedef void (* pFunc)(void);

void  jump2aplication(void)
{
    // 确定应用程序入口地址
    pFunc jump_to_application = (pFunc)(*(__IO uint32_t*)(APP的起始地址值 + 4));

    // 检查应用程序堆栈地址是否合法
    if(((*(__IO uint32_t *)APP的起始地址值) & 0x2FF80000) == 0x20000000)
    {
        // 初始化MSP
        __set_MSP(*(__IO UINT32 *)APP的起始地址值);

        // 跳转到应用程序
        jump_to_application(); 
    }

}

通过以上的修改,就可以实现BootLoader到APP的跳转。

更高级功能

现在,仔细思考后发现:如果想升级,就只能将设备断电,然后在上电的几百毫秒内握手升级(不然超时跳转到APP中)。能不能做到让APP主动跳转到BootLoader里面,这样不就可以随时进行升级?当然可以。
直接上代码:

typedef void (* pFunc)(void);

void  jump2bootloader(void)
{
    // 确定应用程序入口地址, FLASH_BASE=0x08000000,即stm32代码默认起始地址
    pFunc jump_to_bootloader = (pFunc)(*(__IO uint32_t*)(FLASH_BASE + 4));

    // 检查应用程序堆栈地址是否合法
    if(((*(__IO uint32_t *)FLASH_BASE ) & 0x2FF80000) == 0x20000000)
    {
        // 是所有设备的设置恢复到初始状态,否则跳转后可能产生硬错误
        __disable_irq();
        HAL_RCC_DeInit();
        
        // 初始化MSP
        __set_MSP(*(__IO UINT32 *)FLASH_BASE );

        // 跳转到应用程序
        jump_to_bootloader(); 
    }

}

注意:APP中一般会对外设、始终及中断做一系列配置,跳转至BootLoader后,并未经过复位操作,所以必须要调用HAL_RCC_DeInit()将所有外设和始终配置恢复初始化状态。我初次应用时就没有调用HAL_RCC_DeInit(),导致在main函数的 void SystemClock_Config(void)函数中进入错误死循环。至于APP,跳转至APP一般在复位或上电时刻,所有不执行HAL_RCC_DeInit()也无所谓。

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值