STM32--IAP程序升级实验

1. STM32程序升级方法

1.1 ST-link / J-link下载

        将编译生成的hex文件使用ST-Link/J-Link工具直接下载进 Flash 即可。Keil中点击下载也能一键下载。下载后的代码会存放在Flash的起始地址0x0800 0000

简单补充一句,bin文件hex文件的区别:

  • bin文件不带地址信息,因此下载的时候需要指定下载地址。
  • hex文件自带地址信息,直接点击下载自己会找到要下载到的地址(默认0x0800 0000)。

ST-LINK/J-LINK方式支持在线调试

1.2 ISP(In System Programing) 

        我们常见的一键下载电路就是用的这种方式。这个是利用了 STM32 自带的 Bootloader 升级程序。可以通过USB转串口,再通过ISP软件导入程序

在用户参考手册中,可以看到下表,关于启动模式设置的。

ISP根据读取到的FLASH大小自动确定下载地址

STM32启动模式

        ST公司在系统存储器中存放了BootLoader引导程序,通过BootLoader引导程序可完成自启动,并通过向量表跳转至用户APP程序。一般可通过USART1、USART3、CAN2、USB对Flash重新编程。系统BootLoader的起始地址0x1FFF F000,进入系统自带的BootLoader后可利用STM32CubeProgrammer更新程序

        代码下载的位置不一样,但是运行都是从0x0000 0000去找MSP,0x0000 0004去找PC的。

1.3 IAP(In Application Programing)

IAP 和 ISP 其实基本上是一样的,都是通过串口接收程序,存放到FLASH中的某段地址。

ISP 是由厂商已经提供好的,因此接口固定(串口1);

IAP可以自定义使用任何接口接收应用程序。因为这一点,用户可以用多种方式更新程序。

1.3.1 正常程序运行流程

正常情况下,程序从Flash启动时的流程如下:

1. 程序从Flash启动,根据中断向量表找到复位中断处理函数的地址。(0x0800 0004处是中断向量表的起始地址,也是中断向量表的起始,记录了复位中断处理函数的地址)。

2. 执行复位中断处理函数,初始化系统环境后跳转到main函数

3. 在main函数的死循环中运行,直到有中断发生

4. 中断发生时,跳转到中断向量表起始处,根据中断信号源跳找到相应的中断处理函数

5. 中断处理函数执行完后返回到main函数继续运行。

1.3.2 IAP时程序运行流程

引入IAP后的启动流程如下图所示。在Flash中存储了两套程序:

Bootloader程序:自举程序。负责接收数据(APP应用程序代码)并将其存储到Flash中。

APP应用程序:我们真正的应用程序。

  1. 程序从Flash启动,根据中断向量表找到复位中断处理函数的地址。
  2. 执行复位中断处理函数后,跳转到Bootloader的main函数。该函数检查并保存新的APP程序到Flash,然后跳转到第二套程序运行。
  3. 一旦进入新的APP程序,根据中断向量表找到复位中断处理函数,进入App程序的main函数运行。
  4. 为确保中断能正确跳转到APP程序的中断处理函数,需要在APP程序中修改中断向量表的偏移,确保中断发生时能正确执行APP程序的中断处理函数

ISPIAP
在系统存储器中存储了一套接收串口1数据的程序IAP是将Flash分成了两份,在第一份中存储了一套接收某个接口的程序
使用硬件BOOT引脚设置进行跳转使用软件(直接修改PC指针)进行跳转
仅能使用芯片厂商设置好的接口(串口1)用户自定义,理论上只要能接收数据的接口都可以用

2. STM32 Bootloader实现

bootloader基本概念

首先贴上参考文献,这位老哥开源了自己测试的代码,大家可以直接下载,此处做个补充完善

STM32深入系列02——BootLoader分析与实现_stm32 bootloader-CSDN博客文章浏览阅读3.3k次,点赞34次,收藏96次。stm32 bootloader功能分析与实现_stm32 bootloaderhttps://blog.csdn.net/weixin_46253745/article/details/135321134先说BootLoader的思想,对于新手来讲认识的编译后的程序就是.HEX文件,常见做法就是各种下载器或者usb转串口用ISP程序进行烧录,但是企业场景不可能每个设备挨个拿串口去传输,我要远程升级怎么办?

答案就是.BIN文件和BOOTLOADER自举思路。

在 默认方式下,我们的嵌入式程序是以连续二进制的方式烧录到 STM32 的可寻址 Flash 区域上 的。如果我们用的 Flash 容量大到可以存储两个或多个的完整程序,在保证每个程序完整的情 况下,上电后的程序通过修改 MSP 的方式,就可以保证一个单片机上有多个有功能差异的嵌 入式软件,这就是我们要讲解的 IAP 的设计思路。

通常实现 IAP 功 能时,即用户程序运行中作自身的更新操作,需要在设计固件程序时编写两个项目代码,第一个项目代码通过USB、USART等方式接收更新程序并执行更新,第二个项目代码执行用户真正的功能。

我们将第一个项目代码称之为 Bootloader程序,第二个项目代码称之为 APP程序,他们存放在 STM32F429 FLASH 的不同地址范围。

bootloader原理

        我们知道的复位方式有三种:上电复位,硬件复位和软件复位。当产生复位,并且离开复位状态后,CM4 内核做的第一件事就是读取下列两个 32 位整数的值:

(1)从地址 0x0000 0000 处取出堆栈指针 MSP 的初始值,该值就是栈顶地址。

(2)从地址 0x0000 0004 处取出程序计数器指针 PC 的初始值,该值指向复位后执行的第 一条指令。下面用示意图表示,如图 9.1.1 所示。

上述过程中,内核是从 0x0000 0000 和 0x0000 0004 两个的地址获取堆栈指针 SP 和程序计数器指针 PC。事实上,0x0000 0000 和 0x0000 0004 两个的地址可以被重映射到其他的地址空间。

例如:我们将 0x0800 0000 映射到 0x0000 0000,即从内部 FLASH 启动,那么内核会从地址 0x0800 0000 处取出堆栈指针 MSP 的初始值,从地址 0x0800 0004 处取出程序计数器指针 PC 的初始值。CPU 会从 PC 寄存器指向的地址空间取出的第 1 条指令开始执行程序,就是开始执行复位中断服务程序 Reset_Handler。 将 0x0000 0000 和 0x0000 0004 两个的地址重映射到其他地址空间,就是启动模式选择。

当STM32上电时,无论哪种启动模式,程序都将会从地址0x0000 0000开始执行,三种启动模式只是将各自存储空间映射到地址0x0000 0000。事实上,原存储空间的内容仍然被保留,也就是说从地址0x0000 0000和原存储地址都可以开始访问程序。

flash、sram等存储空间都被映射到4GB的虚拟地址上。

测试过程的碎碎念

注意,划分Flash的时候,注意App程序起始地址,根据芯片不同起始地址倍数关系也不同

STM32F1:地址必须是4的倍数,因为每次写入只能写入32位数据,即4个字节。
STM32F4:地址可以从任意地址开始,因为每次写入可以写入8位数据,每个地址就是1个字节。
STM32L4:地址必须是8的倍数,因为每次写入只能写入64位数据,即8个字节。

Stm32的flash都是从0x08000000开始的,结束地址看片子的flash大小

Stm32的sram都是从0x20000000开始的,结束地址看片子的sram大小

理论上我们只需要确保APP起始地址在Bootloader之后,并且偏移量为0X200的倍数即可(相关知识,请参考:NVIC的向量表偏移寄存器设置问题(已解决)-OpenEdv-开源电子网

检查栈顶地址是否合法.0x20000000是sram的起始地址,也是程序的栈顶地址;

appxaddr存放的是用户程序Flash的首地址,(*(volatile u32*)appxaddr)的意思是取用户程序首地址里面的数据,这个数据就是用户代码的堆栈地址,堆栈地址指向RAM,而RAM的起始地址是0x20000000。

在保存了一个完整的 APP 到了对应的位置后,我们需要对栈顶进行检查操作,初步检查 程序设置正确再进行跳转。我们以 FlashAPP 为例,用 bin 文件查看工具(A 盘→6,软件资料 →1,软件→winhex),可以看到 bin 的内容默认为小端结构

中断向量表一个中断占4个字节,正好是一个指针的大小。

  • 18
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值