zoukankan      html  css  js  c++  java
  • STM32的IAP设计(一)bootloader设计

        稍微复杂一点的电子产品,程序中都设计有bootloader,有bootloader的好处是:烧写程序以后,如果发现了新的BUG或者用户增加、修改需求,就可以在不拆壳子(产品出厂一般都是用环氧树脂密封固化)的情况下,通过预留的通信口给产品升级。再有产品到用户手里后,程序进行了升级,那我们可以将新程序的.bin文件发送给用户,让用户自己升级,从而避免了返厂的费用。

        IAP即在应用编程,需要为STM32程序设计一个bootloader,在此bootloader中,要设计进入bootloader下载的触发条件,并且设计通信端口协议,如串口、网口、SD卡等等,将接收到的bin文件烧写到内部的flash中。以前设计过的激光车检器的bootloader,为modbus协议,用在了山海路限高杆上;本程序是串口TTL通信协议,设计用于电喷ECU中的bootloader,已测试并量产。

        硬件平台是STM32F103RCT6,为STM32F10X_HD类型,FLash:256K,RAM:48K,Flash每2K一个扇区。本程序是在ST官方IAP程序AN2557的基础上修改优化而来的。ST官方程序是:刚上电检测外部按键是否按下,如果按下,则进入程序升级代码,使用Ymodem协议传输.bin文件。我们程序进入IAP升级的方法上电后长按键盘c,程序在200ms内检测字符c,如果200ms内按下c,则进入下一个500ms检测,如果没有按下,则判断是否有应用程序,如果有,则跳转到应用程序执行。这里为何前一个是200ms?因为在APP程序中设计有看门狗复位,如果看门狗复位后bootloader等待时间过长,则发动机在转速比较低的情况下容易因为看门狗复位而熄火,所以实测200ms看门狗不会熄火,而且在按键盘c触发IAP升级,人的手速也来得及,不受影响。

        若改为MD或者LD类型,则在option里面选择相应型号的芯片,启动文件更换相应的启动文件(有ld、md、hd),宏定义里使用STM32F10X_LD或者STM32F10X_MD。    

        RAM使用总48K, 即:0x20000000 ———— 0x2000C000
        Flash使用前64K,即:0x8000000 ———— 0x8010000

        配置如图1、图2,则bootloader使用flash的前64K,注意图2是要必须选择的,尤其在APP程序中,如果不选的话,APP生成的.bin文件是从flash起始地址开始的。

             

                                                                                                                   图1
             

                                                                                                                     图2

    主函数如下,上电后首先执行startup.s文件,初始化堆栈、PC指针然后进入上电复位程序,最终跳转到main()函数中。

    #include "include.h"
    
    
    volatile uint32_t cnt_ms;
    
    /**
      * @brief  Main program.
      * @param  None
      * @retval None
      */
    int main(void)
    {  
        char recv_data;    
        volatile uint8_t state;
        
        RCC_Configuration();                       //init system clock,72MHz
                                                                                     
        FLASH_Unlock();                            //Flash unlock 
                                                                                     
        IAP_Init();                                //USART1 初始化
        
        delay_init();  
        SysTick->CTRL |=  SysTick_CTRL_ENABLE_Msk; //使能滴答定时器
        
       //开机0.2S内是否接收到字符c,如果没接收到,则执行应用程序
       //如果接收到字符c,则判断下个0.5S是否能接收到c,如果接收到
       //字符c,则进入bootloader升级程序,否则跳转到应用程序    
        cnt_ms = 200;                     
        while(cnt_ms)
          {
             if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)
               {
                 recv_data = USART_ReceiveData(USART1);
                 USART_ClearFlag(USART1, USART_FLAG_RXNE);
                        
                 if('c' == recv_data)
                   {
                     break;
                   }                        
               }                    
          }
        
        if(cnt_ms)  //前0.2内接收到字符c,则继续判断下一个0.5S内是否接收到字符c    
          {
            cnt_ms = 500;
            USART_ClearFlag(USART1, USART_FLAG_RXNE);
            while(cnt_ms)
              {
                if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)
                  {
                      recv_data = USART_ReceiveData(USART1);
                      USART_ClearFlag(USART1, USART_FLAG_RXNE);
                        
                      if('c' == recv_data)
                        {
                          break;
                        }
                   }                    
              }     
            state = (cnt_ms > 0) ? 1:0;                
          }
        else      //前0.5内没有接收到字符c,则跳转到应用程序  
          {
            state = 0;
          }
            
        if(state) //Execute the IAP driver in order to re-program the Flash 
        { 
          SerialPutString("
    ======================================================================");
          SerialPutString("
    =  (C) COPYRIGHT 2020 ShanDong ***** Aviation Engine Co., Ltd.       =");
          SerialPutString("
    =                                                                    =");
          SerialPutString("
    =  In-Application Programming Application  (Version 1.0.0)           =");
          SerialPutString("
    =                                                                    =");
          SerialPutString("
    =  By Yuan Anbin R & D Team                                          =");
          SerialPutString("
    ======================================================================");            
          SerialPutString("
    
    ");
          Main_Menu();
        }
      else      //Keep the user application running
        {
          //Test if user code is programmed starting from address "ApplicationAddress" 
          if(((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)//检查栈顶地址是否合法,即检查此段Flash中是否已有APP程序
            { 
              //Jump to user application
              __disable_irq();                                         //关闭总中断
                        
              JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);//取得APP代码区第二个字    
              Jump_To_Application = (pFunction) JumpAddress;           //将APP代码区第二个字强制转换,即取得复位中断函数地址
              
              __set_MSP(*(__IO uint32_t*) ApplicationAddress);         //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
                                  
              Jump_To_Application();                                   //跳转到APP复位中断函数,从而进入APP的main()执行
            }
        }
    
      while(1)
        {
             
        }
    }

     

    定时中断服务函数在stm32f10x_it.c文件中,如下:

    /**
      * @brief  This function handles SysTick Handler.
      * @param  None
      * @retval None
      */
    extern volatile uint32_t cnt_ms;     
    
    void SysTick_Handler(void)                 //1ms定时中断
    {
        if(cnt_ms != 0x00)
          { 
              cnt_ms--;
          }    
    }

     

      

  • 相关阅读:
    浅谈分层图最短路问题
    [Luogu P2574]XOR的艺术
    luogu P2419 [USACO08JAN]牛大赛Cow Contest
    luogu P1119 灾后重建
    [国家集训队]跳跳棋
    洛谷P4147 玉蟾宫
    [ZJOI2007]棋盘制作
    树状数组模版
    Nearest Common Ancestor
    P1260 工程规划
  • 原文地址:https://www.cnblogs.com/xyelectric/p/13959101.html
Copyright © 2011-2022 走看看