• STM32使用bootloader的记录


    将FLASH规划成三个区域:bootloader,userdata,application。

    这里我们的bootloader主要用于IAP(In Application Program),区别于ISP,IAP是我们自己可以控制的区域,里面的逻辑都是我们自己去编写处理,而ISP是芯片出厂的时候直接固化在芯片内部的一小段启动引导代码,如果我们将STM32的启用引脚配置成“boot0=1,boot1=0”,那么系统就会进入ISP模式,此时我们使用ST官方提供的对应指令去执行刷机操作。

    如果我们自定义一个IAP在FLASH里面,那么我们完全可以做到联网自动升级,这就需要我们在IAP里面执行联网、下载、写FLASH等操作了,也可以自定义刷机工具,将自己的系统固件通过IAP刷入,这对于售后服务点应该是一种很友好的处理方式。

    分区规划

    /*
    FLASH分区规划
       +--------------------+ FLASH最大地址
       |                    |
       |                    |
       |    APPLICATION     | (应用程序放这里)
       |                    |
       |                    |
       +--------------------+
       |     USER DATA      | (用户数据放这里)
       +--------------------+
       |                    |   
       |     BOOTLOADER     | (IAP固件放这里)
       |                    |
       +--------------------+ 0x0800_0000, FLASH起始地址
       
       user data区域可能会被经常写入数据,而写入数据一般是要先擦除的。
       在没有其他外部存储的时候,折中的办法就是在FLASH上开辟一段固定的空间来使用。
       之所以放在前面,是因为STM32的MCU一般前面部分的段比较小,擦除时会更快,而且用户数据量一般也不会太大。
    */

    这里记录下我自己实际使用的一些关键代码。

     1 #define BOOLOADER_REGION_ADDR     (0x08000000)
     2 #define BOOLOADER_REGION_SIZE     (1024 * 32) 
     3 
     4 #define USERDATA_REGION_ADDR      (BOOLOADER_REGION_ADDR + BOOLOADER_REGION_SIZE)
     5 #define USERDATA_REGION_SIZE      (1024 * 16)
     6 
     7 #define APPLICATION_REGIOIN_ADDR  (USERDATA_REGION_ADDR + USERDATA_REGION_SIZE)
     8 
     9 
    10 
    11 
    12 /*
    13 BOOTLOADER.h
    14 */
    15 static bool jump_to_application(void)
    16 {
    17     /*
    18     参考连接:
    19     https://www.cnblogs.com/foxclever/p/13173493.html
    20     https://blog.csdn.net/weixin_38222172/article/details/103636362
    21     https://www.cnblogs.com/smulngy/p/5700283.html
    22     */
    23     uint32_t appStackAddr = *((volatile const uint32_t * const)APPLICATION_REGIOIN_ADDR);
    24 
    25     /*
    26     堆栈地址合法性检查
    27     */
    28     if (SRAM_BASE_ADDRESS == (appStackAddr & 0x2FFE0000) && (0x00 == (appStackAddr & 0x03)))
    29     {
    30         RCC_DeInit();
    31         __set_PRIMASK(TRUE); /*禁用所有中断*/
    32         __set_MSP(appStackAddr); /*设置堆栈地址*/
    33         ((FuncPtr)(*((volatile const uint32_t * const)(mAppAddr + 4))))(); /*跳转*/
    34         
    35         return true;
    36     }
    37     else
    38     {
    39         return false;
    40     }
    41 }
    42 
    43 int main(void)
    44 {   
    45     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    46     
    47     /*一些必要的处理逻辑*/
    48     
    49     /*跳转到APP区域*/
    50     if (!jump_to_application())
    51     {
    52         while(1)
    53         {
    54         }
    55     }
    56     
    57     return 0;
    58 }
    59 
    60 
    61 /*
    62 APPLICATION.c
    63 */
    64 int main(void)
    65 {
    66     /*
    67     1、在bootloader里面关闭了全局中断,所以这里要打开。
    68     2、要重新配置中断向量表(如果在bootloader里面没用到中断,我觉得不配置也是可以的)
    69     */
    70     NVIC_SetVectorTable(NVIC_VectTab_FLASH, APPLICATION_REGIOIN_ADDR);
    71     __set_PRIMASK(FALSE);
    72     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    73     
    74     /*一些必要的处理逻辑*/
    75     
    76     return 0;
    77 }
    View Code

     里面的RCC_DeInit函数是STM32的标准库里面的函数,在stm32f4xx_rcc.h里面声明。

    里面的 __set_PRIMASK 和 __set_MSP 两个函数定义在STM32官方库的 CMSIScore_cmFunc.h 里面。

    __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
    {
      __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
    }
    
    __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
    {
      __ASM volatile ("MSR msp, %0
    " : : "r" (topOfMainStack) : "sp");
    }
    typedef void (*FuncPtr)(void);

    当然我们使用keil时对应也要修改地址,一共两个地方:

    (1)修改工程选项下的“Target”标签中的ROM起始地址和大小;

    (2)修改工程选项下的“Debug”中J-link等刷机调试工具的设置对话框里面的“Flash Download”里的地址。

    对应的APPLICATION和BOOTLOADER工程都要修改。

    如果转载,请注明出处。https://www.cnblogs.com/ssdq/
  • 相关阅读:
    git 学习网站
    Vue 部署在 IIS 上
    Element UI 的坑
    Vue 中 Prop 传至的 一个Bug
    Asp.net Core 部署在 IIS上
    今天用UniApp开发, 用到 Vuex 中的 mutations, 设置值的时候好像只能传2个参数, 第一个是固定的state, 第二个是一个值, 不能传第三个了
    anxios 和 uni.request 访问Asp.net 服务器传参出错的坑
    内网计算机设置问题说明
    关于综合布线
    Android学习 -- Activity 以及Activity之间值传递
  • 原文地址:https://www.cnblogs.com/ssdq/p/13738205.html
Copyright © 2020-2023  润新知