ARM cortex-m IAP升级小记

本文深入探讨ARM Cortex-M3/M4芯片的In-Application Programming(IAP)原理及实现细节,涵盖启动流程、中断向量表重定位等关键概念,并提供STM32F系列芯片的具体实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

看了一下网上关于arm芯片IAP原理和具体实现的文章比较少,正好之前做过相关的项目,也踩过好多坑,所以简单写篇文章总结一下有关IAP的相关内容。

这篇文章主要针对arm cortex-m3/m4,硬件环境使用STM32F系列,软件环境为Keil mdk5。

硬件浅谈

想要搞通ARM 的IAP升级,首先要搞懂ARM芯片一些硬件原理,ARM芯片采用冯。诺依曼架构,代码和数据存储在相同存储体中(只是存储在逻辑上相同的存储体中,不一定存储在同一个存储体,有一些手段可以实现代码数据分离,这里不对此做过度延伸)。ARM芯片启动后起始执行位置取决于具体芯片,例如NXP LPC默认从0开始,STM32默认从0x08000000开始,起始位置的前端部分存放的是程序中断向量表,其中第一个位置存放堆栈初始化函数地址,第二个中断向量存放的是Reset_Handler,这也就决定了芯片启动后会首先初始化堆栈,然后执行芯片复位流程,随后再切入main函数。

启动流程

我们以stm32f1的startup.s为例简单了解一下arm芯片启动流程。

如图是第一个向量就是startup.s中存放的中断向量表,第一个是__initial_sp,第二个就是Reset_Handler。

堆栈初始化我们不需理会,我们来看看Reset_Handler做了什么

复位句柄同样在startup.s中,Reset_Handler首先把systeminit函数放入R0中,随后执行systeminit,初始化后就跳转main函数,开始执行主函数。

Systeminit主要就是初始化各种时钟,包括内置RC外置晶振主PLL外设时钟等等杂七杂八的一些,比较重要的是最后几行。

最后几行实际上只执行了一个功能:初始化中断向量表基址,这个基址实际上就是我们之前提到的程序的实际起始位置,在stm32中就是0x08000000。

之后就是执行main函数了,不再累述。

IAP实现原理

讲完了一些背景知识,我们可以切入正题了。实现IAP的核心原理很简单,就是在flash中保留一个小的升级程序,即boot loader。为了安全起见boot loader一般放在芯片默认启动起始位置,这样即使升级过程中发生错误,芯片依然可以通过重启进入boot。比较标准的方式是一个bootloader和一个app,bootloader主要负责和iap有关的工作,若启动后无IAP任务bootloader把CPU使用权转交给APP,开始正式工作。

Bootloader转交CPU使用权的过程中,就涉及到程序重定位问题,重定位方面的问题主要包括两个,其一是函数重定位问题:使用mdk时默认是以芯片基址作为程序的基址,这也就使得boot和app程序地址发生重叠,使用某个app函数可能会跳转到boot的某一段程序上。其二是中断向量表重定位的问题:发生中断事件时芯片以中断向量表基址+中断偏移量找到中断处理函数的地址存放位置,若app执行时中断向量表依然指向芯片默认起始位置,就可能出现在app中使用boot中断函数的尴尬局面。

除此之外,还有一个是中断问题,中断在iap过程中是一个要十分谨慎处理的部分,处理不好可能出现各种严重事故和各种难以追踪到的bug(相信我,你不会想在各种随缘复现的错误中找bug的)。

bootloader实现

原理讲完实现就是水到渠成的事了,首先要新建一个boot loader工程,默认情况下boot loader只需要简单跳转到app即可

主函数如图所示,首先要初始化一次中断向量表,随后初始化所需的硬件,判断跳转的条件是否满足,若满足则直接跳转到app,否则执行boot中的IAP主任务函数。

注意,下面是重点中的重点,搞懂了下面的部分,IAP就不是问题了

核心函数: IAP_JumpTo,进入函数后首先判断所给出的程序地址是否可能是有效的,即地址中第一组值是否是一个有效的内存值,若是,则正式开始跳转。

  1. 首先屏蔽所有中断,防止跳转前的预处理过程被打扰。
  2. 设置指针
  3. 关闭所有外设中断,所有的外设中断都要在这个函数里关掉,另外注意,滴答定时器的中断是没法通过正常的关中断方式关闭的,因此要单独处理,调用systick_deinit直接把滴答定时器关掉。
  4. 设置psp和msp,其中psp不是必须的,在没有使用RTOS的程序中可以不用管。
  5. 重定位中断向量表,这一步对应中断处理函数地址问题。
  6. 现在已经可以跳转,但在跳转之前还要做一点清尾工作:首先要清除所有的已挂起中断,防止隐藏中断出现,其次,重新打开全局中断,然后跳转到app的地址即可。

到这里boot跳转原理已经讲完,然后我们再来看一下app。

 

APP设置

与boot loader不同,app不需要在程序里特别处理什么,但项目设置要改

主要是两个部分,一个是target中的ROM基址要改,另一个是下载器的ROM基址要改,如下图所示

另外注意,一定要屏蔽app的systeminit函数中设置中断向量表的部分,否则可能影响中断向量表基址。

IAP的核心部分就是这样,之后就是在boot loader中添加接收app bin文件并写入芯片flash的功能。接收bin的方式有很多,例如常见的串口,usb,rs485,can甚至可以通过TF卡,网络等等。再调用芯片库函数中的flash操作函数将接收到的bin文件写入flash中即可,当然还可以在此基础上添加一些其他的功能和逻辑。本节先只讲一下核心原理,其余的部分可能会在之后讲到。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值