本帖最后由 DKENNY 于 2023-12-24 15:19 编辑
最近了解了IAP相关知识,发现在APM32系列,存在3中IAP的跳转方式,下面简单介绍一下。由于篇幅较长,将分为上、下两节分享,这篇主要讲一下固件及IAP的启动方式。
1. 固件的简单介绍
固件(Firmware)就是写入ROM(只读存储器)中的程序,即固件是嵌入在硬件设备中的软件,通常用于控制设备的功能和行为,固件担任着一个系统最基础最底层工作,直接控制硬件。
固件升级:
固件升级是指对嵌入式系统或设备中的固件进行更新或升级的过程。 固件升级的目的: 1). 修复漏洞和错误:固件升级可以修复之前版本中发现的漏洞、错误或安全漏洞,从而提高设备的稳定性和安全性。 2). 改进功能和性能:通过固件升级,可以添加新功能、改进现有功能或提高设备的性能,以满足用户的需求或适应新的技术标准。 3). 兼容性和互操作性:升级固件可以使设备与其他设备或软件更好地互操作,以提供更好的用户体验。 4). 支持新硬件:当设备硬件发生变化或更新时,固件升级可以确保固件与新硬件兼容。 5). 增加设备的寿命:通过升级固件,设备制造商可以延长设备的使用寿命,使其更具持久性,减少设备更换的需求。
固件升级的方式: ISP(In-SystemProgramming):在系统编程,使用引导程序(Bootloader)加上外围UART/SPI等接口进行烧录。 ICP(In-circuitprogrammer):在电路编程,使用SWD/JTAG接口。 IAP(In-ApplicationProgramming):指MCU可以在系统中获取新代码并对自己重新编程,即用程序来改变程序。
2. APM32的启动方式 APM32有两个BOOT引脚,通过配置不同的高低电平,可以让单片机从不同的地址开始运行。 Main Flashmemory :内置的Flash,一般我们使用JTAG / SWD 烧录代码都是直接烧录到这个存储区间,重启后也直接从这里的代码开始执行; System memory:这种模式启动的程序功能是由厂家设置的,存储区间内部预置了一段BootLoader(即ISP 程序),这段程序出厂后无法修改。BootLoader 一般支持UART 协议,可以让我们直接通过串口将程序代码烧录到Main Flash memory 中; SRAM:这个启动模式一般用于程序调试,假如我只修改了代码中一个很小的地方,重新烧录到Flash比较费时,可以从内存中启动代码,进行快速的程序调试,等程序调试完成后,再将程序烧录到MainFlash memory 中。
3. 固件升级比较 3.1 ISP(In-SystemProgramming) 从APM32的启动模式可以看出,ISP通过USB接口直接烧录代码,主要是靠Systemmemory 中预置的Bootloader代码提供的UART协议实现的,要想使用Systemmemory 中的ISP代码,需要将BOOT0设置为高电平、BOOT1设置为低电平,然后按下复位键,MCU从Systemmemory 启动BootLoader,靠ISP代码中提供的UART协议,用户可以通过串口将程序代码烧录到MainFlash memory 中。通过串口烧录代码完成后,需要将BOOT0设置为低电平,然后按下复位键,MCU就可以从刚才烧录进去的代码处(也即MainFlash memory)开始执行了。
3.2 ICP(In-circuit programmer ) 一种用于对微控制器或芯片进行编程的技术,它允许在目标设备的电路板上进行编程,而不需要将芯片从电路板中取出。 编程时,所有芯片需上电,利用jlink和stlink等工具进行编程也属于电路编程。
3.3 IAP(In-Application Programming ) IAP的原理与上面两种有较大区别,这种方式将主存储区又分成了两个区域(根据实际需要由开发者自行分配),08000000起始处的这部分,存储一个开发者自己设计的Bootloader程序,另一部分存储真正需要运行的APP程序。 假如Bootloader程序时,需要进行升级(比如APP程序运行时,接收到升级指令,可以在flash中的特定位置设置一个标志,然后触发重启,重启后进入Bootloader程序,Bootloader程序根据标志位就能判断是否需要升级),则会通过某种方式先将接收到的程序写入存储区中存储APP程序的那个位置,写入完成后再跳转到该位置,即实现了程序的升级。
4. IAP固件升级及流程
4.1 中断向量表 中断向量表,用于存储处理器中各种中断的处理程序的入口地址。当发生中断时,处理器会根据中断类型查找中断向量表,并跳转到相应的处理程序。 SCB->VTOR寄存器用于指定中断向量表的基地址。通过修改该寄存器的值可以将中断向量表的位置从默认的地址(通常是0x00000000)更改为其他地址。 例如: SCB->VTOR = 0x8000000
4.2 芯片有无SCB->VTOR寄存器的对比 ① 有SCB->VTOR的情况: 中断向量表的加载形式是通过将中断向量表的起始地址写入SCB->VTOR寄存器来实现。通常,中断向量表是存储在Flash存储器中的一段连续内存区域。当发生中断时,处理器会根据中断号从中断向量表中读取对应的中断处理函数地址,并跳转到该地址执行中断处理。 ② 没有SCB->VTOR的情况: 中断向量表的加载形式是通过固定的地址来实现。通常,中断向量表是存储在Flash存储器的固定地址处。当发生中断时,处理器会根据中断号从固定地址处读取对应的中断处理函数地址,并跳转到该地址执行中断处理。 4.3 IAP启动
Cortex-M内核规定,中断向量表开始的4个字节存放的是堆栈栈顶的地址,其后是中断向量表各中断服务程序的地址。当发生中断后程序通过查找该表得到相应的中断服务程序入口地址,然后再跳到相应的中断服务程序中执行,中断服务程序中最终调用用户实现的各函数。例如:main函数就是复位中断服务函数中调用的!
在没有IAP时,上电后从0x08000004处取出复位中断向量的地址,然后跳转到复位中断程序的入口(标号①所示),执行结束后跳转到main函数中(标号②所示)。通常main函数是个死循环,不会退出。在执行main函数的过程中发生中断,则STM32强制将PC指针指回中断向量表处(标号④所示),从中断向量表中找到相应的中断函数入口地址,跳转到相应的中断服务函数(标号⑤所示),执行完中断函数后再返回到main函数中来(标号⑥所示)。
在添加IAP后,上电后仍然从0x08000004处取出复位中断向量的地址,然后跳转到复位中断程序的入口(标号①所示),执行结束后跳转到小程序的main函数中(标号②所示)。在执行小程序main函数的过程中发生中断,则STM32强制将PC指针指回中断向量表处(标号④所示),从中断向量表中找到相应的中断函数入口地址,跳转到相应的中断服务函数(标号⑤所示),执行完中断函数后再返回到main函数中来(标号⑥所示)。而想要大程序执行,则必须在小程序中显示强制跳转(标号⑦)。
在大程序的main函数的执行过程中,如果CPU得到一个中断请求,由于我们设置了中断向量表偏移量为N+M,因此PC指针被强制跳转到0x08000004+N+M处的中断向量表中得到相应的中断函数地址,再跳转到相应新的中断服务函数,执行结束后返回到main函数中来。
需要注意的是,复位中断比较特殊。产生复位后,PC的值会被硬件强制置为0x08000004。因为,在发生复位后,负责中断向量偏移的寄存器VTOR变为了0,因此,复位后的中断就变为了0x08000004。而其他中断发生时,VTOR为已经设置好的终端向量表偏移。
4.4 IAP升级 具体而言,无非就是一包一包地接收数据,然后一包一包地写入flash。一般分为两个阶段,防止升级文件传输不完整或损坏。 (1) 文件下发阶段:接收到的升级包不要直接写入flash的APP区域,先存到另外的flash空间或外部存储区(如SD卡); (2) 更新阶段:等全部接收完成,再一次性将外部存储空间的数据写入flash的APP区域。 其中,通信是通过串口,自己定义协议传送数据,将程序数据拆成N个包,一包一包地传输,例如设定3条协议,分别是:开始升级、发送升级数据、升级完成确认。
如有问题,欢迎各位发表评论,一起讨论。
|
赞