IAP固件升级原理及实现详解

您所在的位置:网站首页 isp和iap的含义是什么 IAP固件升级原理及实现详解

IAP固件升级原理及实现详解

2024-07-13 04:59:52| 来源: 网络整理| 查看: 265

什么是IAP升级?

IAP,即In Application Programming,IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写。简单来说,就是开发者代码出bug了或者添加新功能了,能够利用预留的通讯接口,对代码进行升级

UART、SPI、IIC、USB等等,当然还有wifi、4G、蓝牙等无线通讯手段,都可以作为IAP升级的方式,今天主要介绍如何使用串口对固件进行升级

STM32的代码启动过程

要想设计IAP,首先需要对MCU的代码启动过程有个了解,先来看看STM32的代码启动过程是怎样的吧

此部分参考:https://www.cnblogs.com/gulan-zmc/p/12248509.html

在《Cortex-M3权威指南》有讲述:芯片复位后首先会从向量表里面取出两个值(下图来自Cortex-M3权威指南):

从0x0000 0000地址取出MSP(主堆栈寄存器)的值

从0x0000 0004地址取出PC(程序计数器)的值

然后取出第一条指令执行

启动文件源代码分析 ;******************** (C) COPYRIGHT 2011 STMicroelectronics ******************** ;* File Name          : startup_stm32f10x_hd.s ;* Author             : MCD Application Team ;* Version            : V3.5.0 ;* Date               : 11-March-2011 ;* Description        : STM32F10x High Density Devices vector table for MDK-ARM  ;*                      toolchain.  ;*                      This module performs: ;*                      (上电复位后会做下面的几件事情) ;*                      - Set the initial SP(设置堆栈,就是设置MSP的值) ;*                      - Set the initial PC == Reset_Handler(设置PC的值) ;*                      - Set the vector table entries with the exceptions ISR address(设置中断向量表的地址) ;*                      - Configure the clock system and also configure the external (设置系统时钟;如果芯片外部由挂载SRAM,还需要配置SRAM,默认是没有挂外部SRAM的) ;*                        SRAM mounted on STM3210E-EVAL board to be used as data  ;*                        memory (optional, to be enabled by user) ;*                      - Branches to __main in the C library (which eventually      (调用C库的__main函数,然后调用main函数执行用户的) ;*                        calls main()). ;*                      After Reset the CortexM3 processor is in Thread mode, ;*                      priority is Privileged, and the Stack is set to Main. ;*     ;******************************************************************************* ; ------------------分配栈空间---------------- Stack_Size      EQU     0x00000400      ;EQU指令是定义一个标号;标号名是Stack_Size; 值是0x00000400(有点类似于C语言的#define)。Stack_Size标号用来定义栈的大小                 AREA    STACK, NOINIT, READWRITE, ALIGN=3  ;AREA指令是定义一个段;这里定义一个 段名是STACK,不初始化,数据可读可写,2^3=8字节对齐的段(详细的说明可以查看指导手册) Stack_Mem       SPACE   Stack_Size   ;SPACE汇编指令用来分配一块内存;这里开辟内存的大小是Stack_Size;这里是1K,用户也可以自己修改 __initial_sp      ;在内存块后面声明一个标号__initial_sp,这个标号就是栈顶的地址;在向量表里面会使用到                                             ;  Heap Configuration ;     Heap Size (in Bytes)  ;  ; ------------------分配堆空间---------------- ;和分配栈空间一样不过大小只是512字节 Heap_Size       EQU     0x00000200                 AREA    HEAP, NOINIT, READWRITE, ALIGN=3 __heap_base        ;__heap_base堆的起始地址 Heap_Mem        SPACE   Heap_Size      ;分配一个空间作为堆空间,如果函数里面有调用malloc等这系列的函数,都是从这里分配空间的 __heap_limit       ;__heap_base堆的结束地址                 PRESERVE8 ;PRESERVE8 指令作用是将堆栈按8字节对齐                 THUMB;THUMB作用是后面的指令使用Thumb指令集 ; ------------------设置中断向量表---------------- ; Vector Table Mapped to Address 0 at Reset                 AREA    RESET, DATA, READONLY      ;定义一个段,段名是RESET的只读数据段                 ;EXPORT声明一个标号可被外部的文件使用,使标号具有全局属性                 EXPORT  __Vectors          ;声明一个__Vectors标号允许其他文件引用                           EXPORT  __Vectors_End      ;声明一个__Vectors_End标号允许其他文件引用                 EXPORT  __Vectors_Size     ;声明一个__Vectors_Size标号允许其他文件引用                  ;DCD 指令是分配一个或者多个以字为单位的内存,并且按四字节对齐,并且要求初始化 ;__Vectors 标号是 0x0000 0000 地址的入口,也是向量表的起始地址 __Vectors       DCD     __initial_sp               ;* Top of Stack     定义栈顶地址;单片机复位后会从这里取出值给MSP寄存器,                                                    ;* 也就是从0x0000 0000 地址取出第一个值给MSP寄存器 (MSP = __initial_sp)                                                     ;* __initial_sp的值是链接后,由链接器生成                 DCD     Reset_Handler              ;* Reset Handler    定义程序入口的值;单片机复位后会从这里取出值给PC寄存器,                                                    ;* 也就是从0x0000 0004 地址取出第一个值给PC程序计数器(pc = Reset_Handler)                                                    ;* Reset_Handler是一个函数,在下面定义                 ;后面的定义是中断向量表的入口地址了这里就不多介绍了,想要了解的可以参考《STM32中文手册》和《Cortex-M3权威指南》                 DCD     NMI_Handler                ; NMI Handler                       DCD     HardFault_Handler          ; Hard Fault Handler                 DCD     MemManage_Handler          ; MPU Fault Handler                 DCD     BusFault_Handler           ; Bus Fault Handler                 DCD     UsageFault_Handler         ; Usage Fault Handler                 .....由于文件太长这里省略了部分向量表的定义,完整的可以查看工程里的启动文件                 DCD     DMA2_Channel1_IRQHandler   ; DMA2 Channel1                 DCD     DMA2_Channel2_IRQHandler   ; DMA2 Channel2                 DCD     DMA2_Channel3_IRQHandler   ; DMA2 Channel3                 DCD     DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5 __Vectors_End                                    ;__Vectors_End向量表的结束地址 __Vectors_Size  EQU  __Vectors_End - __Vectors   ;定义__Vectors_Size标号,值是向量表的大小                 AREA    |.text|, CODE, READONLY  ;定义一个代码段,段名是|.text|,属性是只读 ;PROC指令是定义一个函数,通常和ENDP成对出现(标记程序的结束)                ; Reset handler Reset_Handler   PROC                                      ;定义 Reset_Handler函数;复位后赋给PC寄存器的值就是Reset_Handler函数的入口地址值。也是系统上电后第一个执行的程序                 EXPORT  Reset_Handler             [WEAK]  ;*[WEAK]指令是将函数定义为弱定义。所谓的弱定义就是如果其他地方有定义这个函数,                                                           ;*编译时使用另一个地方的函数,否则使用这个函数                                                                                                            ;*IMPORT   表示该标号来自外部文件,跟 C 语言中的 EXTERN 关键字类似                 IMPORT  __main                            ;*__main 和 SystemInit 函数都是外部文件的标号                 IMPORT  SystemInit                        ;* SystemInit 是STM32函数库的函数,作用是初始化系统时钟                 LDR     R0, =SystemInit                 BLX     R0                               LDR     R0, =__main                       ;* __main是C库的函数,主要是初始化堆栈和代码重定位,然后跳到main函数执行用户编写的代码                 BX      R0                 ENDP                  ; Dummy Exception Handlers (infinite loops which can be modified) ;下面定义的都是异常服务函中断服务函数 NMI_Handler     PROC                 EXPORT  NMI_Handler                [WEAK]                 B       .                 ENDP .....由于文件太长这里省略了部分函数的定义,完整的可以查看工程里的启动文件 SysTick_Handler PROC                 EXPORT  SysTick_Handler            [WEAK]                 B       .                 ENDP Default_Handler PROC                 EXPORT  WWDG_IRQHandler            [WEAK]                 EXPORT  PVD_IRQHandler             [WEAK]                 .....由于文件太长这里省略了部分中断服务函数的定义,完整的可以查看工程里的启动文件                 EXPORT  DMA2_Channel2_IRQHandler   [WEAK]                 EXPORT  DMA2_Channel3_IRQHandler   [WEAK]                 EXPORT  DMA2_Channel4_5_IRQHandler [WEAK] WWDG_IRQHandler PVD_IRQHandler TAMPER_IRQHandler .....由于文件太长这里省略了部分标号的定义,完整的可以查看工程里的启动文件 DMA2_Channel1_IRQHandler DMA2_Channel2_IRQHandler DMA2_Channel3_IRQHandler DMA2_Channel4_5_IRQHandler                 B       .                 ENDP                 ALIGN    ;四字节对齐 ;******************************************************************************* ; User Stack and Heap initialization ;******************************************************************************* ;下面函数是初始化堆栈的代码                  IF      :DEF:__MICROLIB                       ;如果定义了__MICROLIB宏编译下面这部分代码,__MICROLIB在MDK工具里面定义                  ;这种方式初始化堆栈是由 __main 初始化的                  EXPORT  __initial_sp   ;栈顶地址 (EXPORT将标号声明为全局标号,供其他文件引用)                  EXPORT  __heap_base    ;堆的起始地址                  EXPORT  __heap_limit   ;堆的结束地址                                   ELSE                  ;由用户初始化堆                  ;否则编译下面的                  IMPORT  __use_two_region_memory      ;__use_two_region_memory 由用户实现                  EXPORT  __user_initial_stackheap                   __user_initial_stackheap                                    LDR     R0, =  Heap_Mem              ;堆的起始地址                  LDR     R1, =(Stack_Mem + Stack_Size);栈顶地址                  LDR     R2, = (Heap_Mem +  Heap_Size);堆的结束地址                  LDR     R3, = Stack_Mem              ;栈的结束地址                  BX      LR                  ALIGN                  ENDIF                  END ;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE*****

STM32的启动步骤如下:

1、上电复位后,从 0x0000 0000 地址取出栈顶地址赋给MSP寄存器(主堆栈寄存器),即MSP = __initial_sp。这一步是由硬件自动完成的

2、从0x0000 0004 地址取出复位程序的地址给PC寄存器(程序计数器),即PC = Reset_Handler。这一步也是由硬件自动完成调用SystemInit函数初始化系统时钟

3、跳到C库的__main函数初始化堆栈(初始化时是根据前面的分配的堆空间和栈空间来初始化的)和代码重定位(初始RW 和ZI段),然后跳到main函数执行应用程序

IAP设计思路

大体分为两部分设计,bootloader、APP代码设计,bootloader用于检查APP区代码是否需要更新,以及跳转到APP区执行APP程序

调研了一下群里的小伙伴,下面这个流程比较通用一些,大概是下图所示升级流程:

升级流程图

Flash分区

是以STM32F103RET6为主控做的flash分区,主要功能:

boot区:0x0800 0000 到 0x0800 b7FF 地址的flash块划分给bootloader,用于升级固件,大小是46kb

用户参数区:0x0800 B800 到 0x0800 BFFF 的flash块划分为用户参数区(parameters),用于存储用户的一些参数,大小是2Kb

APP区:0x0800 C000 到 0x0804 3FFF 的flash块划分为APP区 ,(application)用于存放用户功能应用代码,大小是224Kb

APP缓存区:0x0804 4000 到 0x0807 BFFF 的flash块划分为APP缓存区 (update region),用于暂存下发的固件,大小跟应用程序区一样 224kb

未定义:0x0807 C000 到 0x0807 FFFF 的flash块划分未定义区,可以根据具体用途定义,大小是16Kb

代码实现

硬件:

fallingstar-board(已开源,打板验证)

软件:

内部flash读写

串口DMA+空闲中断

内部flash读写操作

这部分比较简单,直接上代码:

读flash操作:

/************************************************************   * @brief   读取2字节数据  * @param[in]   uint32_t faddr   * @return  NULL   * @github     * @date    2021-xx-xx   * @version v1.0   * @note    NULL   ***********************************************************/ uint16_t BSP_FLASH_ReadHalfWord(uint32_t raddr) {  return *(__IO uint16_t*)raddr;  } /************************************************************   * @brief      读取n(uint16_t)字节数据  * @param[in]   uint32_t ReadAddr  * @param[out]  uint16_t *pBuffer  * @param[in]   uint16_t len   * @return  NULL   * @github     * @date    2021-xx-xx   * @version v1.0   * @note    NULL   ***********************************************************/ void BSP_FLASH_Read (uint32_t ReadAddr, uint16_t *pBuffer, uint16_t len )     {  uint16_t i;    for(i=0;i


【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭