你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32固件升级之基础知识(一)

[复制链接]
STMCU小助手 发布时间:2022-11-27 21:00
这里以 KEIL 开发环境和 STM32F103RET6 为例。

2 D' j; c: m2 k* F8 g+ @上电时单片机首先进入复位中断 Reset_Handler,即汇编文件的复位中断处理函数。

' m4 B3 C4 E; |% U2 u! I
微信图片_20221126213335.jpg

' d/ R0 z7 @9 m7 P4 Z并且有一个中断向量表默认存在于 flash 地址开始处。

- m, c! ?+ I* J9 q% l8 @- }! D
微信图片_20221126213332.jpg
* \$ j1 V9 _# q7 g( X
为什么说是默认呢?这是因为如果没有特殊要求的话很少会去改中断向量表。实际上这个中断向量表是可以更改的。但是在更改向量表之前必须在地址开始处建立一个向量表,因为在复位后,程序默认(硬件决定的)从 flash 开始的第一个字读取栈指针,第二字就是复位中断的入口,并根据该指针最终进入复位处理函数中执行相应的函数。如果没有这个中断向量表程序是无法启动的。

  Y" F" n. d; N7 ?那么既然前面说可以重新设定中断向量表的位置,那必然有一个寄存器记录着这张表的位置,这就是 VTOR 寄存器。从《Cortex-M3 权威指南》可以看该寄存器的介绍:
! H2 |! c) g" ?  X% b
微信图片_20221126213307.jpg
, k2 \5 w+ P2 C3 b: U
并且向量表的偏移量有如下要求:

/ j# ~# x$ m; p; H, d
微信图片_20221126213328.jpg

9 j2 A  B  m3 f( N; M  N) x$ k" D
64*4 是因为一个表项为 4 字节。
1 g; T3 ]" h. [+ @
更具体的关于更改向量表的信息查看《Cortex-M3 权威指南》。
2 n" H, `+ {# a9 G! N4 H
在复位处理函数中有进入 SystemInit 函数执行,在函数里有一个设置中断向量表的位置的语句。
) ^# F! x# ~5 k% J4 a
微信图片_20221126214019.jpg
! b6 q' O  S* P( \
VECT_TAB_OFFSET 默认情况下就是 0。
1 o0 \+ `+ p" o* ^& M/ a- q
因为这是官方库函数,并且上电之后必定进入复位中断函数处理,因此必定会执行重新定位向量表的操作。因此只要修改宏定义就可以重新定位向量表。
& L6 R- \/ r$ S: D1 j% u
先准备两个程序,一个为 bootloader,用于更新程序,一个为 APP,即固件程序。
3 `0 U+ K* l( F8 `/ b; j; g
首先确定 BootLoader 为上电最先执行的函数,需要通过下载器下载,而 APP 则可以通过有线(spi、i2c、usart、usb)、无线(Bluetooth、WiFi)等各种方式下载,只要能够正确传输数据即可。
' f, |& o) H0 K5 G, ^& Q9 ?
微信图片_20221126212940.png

" A. C+ d/ ]  x' K8 r
因为两个程序中只能有一个程序正在运行,所以可以共用 RAM。所以这个时候对一些变量就有必要进行初始化,以防 APP 程序使用的 RAM 空间存在之前的数据。

0 Q+ j" l; H! P
上电之后,因为硬件问题(可能是 VTOR 寄存器断电不保存数据吧),导致单片机自动从中断向量表 1 中寻找复位中断处理函数,此时必然最终会进入 BootLoader 程序中执行。因为向量表第一个字(32 字节)存放的地址就是 BootLoader 程序编译出来的中断处理函数地址。所以在这个程序一般就是初始化传输方式,然后在一定时间里判断是否需要更新固件,需要则将更新固件并跳转到第二个复位中断函数中执行,而如果超时则自动跳转到第二个复位中断函数中执行。

  S  Z4 ^/ @: v+ N1 }# R" I
一般更新固件的文件类型为 bin 文件,文件可以直接拷贝到 flash 中并且执行。那么 bin 文件应该是怎样的呢?下面的就是通过 KEIL 生成的 bin 文件所含有的信息。(有关如何生成 bin 文件查看前面章节)
, R, X: S8 n8 G
微信图片_20221126212933.png

# P# R: ~- j4 Q和普通程序的生成没多大区别,都是编译器编译得到的目标的程序。但是我们要如何让编译将程序放在该放的地址呢,即在得到这个 bin 文件之后,当从向量表的第二字获取的地址刚好指向了 Reset_Handler 函数呢?即这里面存放的地址应该是绝对地址。
8 ?5 e# A8 {4 F1 I! C1 l
通过设置 KEIL 即可:

* L# U) |: m5 o: ~
微信图片_20221126212930.jpg
+ y  U) X) w) W, X$ ?* j% d
上面设置为 0x8001000,这样在编译过程中就会将整个程序的开始放在 0x8001000,并且其他函数地址也会根据该地址自动确定地址,而变量和栈等数据则存放在 0x20000000 开始处(和 BootLoader 一样,所以它们其实是共用 RAM),这样程序才能正确执行。但是 BootLoader 怎么找到 APP 的第一个函数的地址并进入执行呢?就是从接收到的 bin 文件里找。之前说过程序的开始处就是一张向量表(编译器自动处理的),也就是这个程序的向量表开始就在 0x8001000,而 bin 文件可以直接看成一个 flash 空间,程序应该放在 0x8001000,在 bin 文件就是在文件的开始处,这样就能找到栈顶指针和复位中断处理函数了。有点绕,看示意图(数字无意义):
) ]; m) A6 n- \3 H
微信图片_20221126212923.jpg

6 [+ t$ u2 `: x* Y# k# T' L但是 BootLoader 虽然找到了 APP 程序的复位向量地址,并且整个 APP 程序拷贝到 0x08001000 开始处了,BootLoader 程序可以通过跳转语句调到复位中断处理函数执行,并且能从向量表出得到栈顶位置,并且其他函数地址也由编译器确定了,执行应该是没问题的。但是一旦中断来了,根据 stm32 的中断机制,肯定会从中断向量表中找地址,而找中断向量表是通过 VTOR 来定位的,而在跳转后虽然进入了复位中断处理函数,并进入了 SystemInit()中执行,也执行了重新设置 VTOR 寄存器的操作,但是你的 VECT_TAB_OFFSET 还是 0……这样一旦中断发生,通过 VTOR 定位又跑到 BootLoader 的向量表去执行处理程序了。所以在进入 APP 函数后,需要重新定位我们新的向量表,只需要修改 VECT_TAB_OFFSET 即可,而这个偏移量有限制……,而且这个偏移量其实也就是给 BootLoader 程序预留的空间,所以在这里 VECT_TAB_OFFSET 设置为 0x1000,符合限制条件,并且这个偏移量应该大于 BootLoader 程序的总大小,这样就 OK 了。

% }/ G% l- Z, w8 A3 ^跳转到复位中断处理函数之前,必须重新设置栈顶位置,虽然是共用 RAM,但毕竟 BootLoader 程序编译下的 RAM 分配和 APP 程序编译下的 RAM 分配可能是不同的,需要重新确定栈顶位置。
2 l( T5 h* K% A6 l) [2 N/ d
微信图片_20221126212919.jpg

# B6 |: f! U* U/ `! I) {% w
& ^  v. V+ c' j+ K
总结:

7 f6 r7 G+ ~( _- _) ~' j( b3 V1、BootLoader 两个功能,一个是一定时间内判断是否需要更新 APP,如果需要则接收并将其烧写到指定地址的 flash 空间中,并从该地址中获取栈顶指针和 Reset_Handler 指针,并跳转到该函数执行;另一个就是超时直接在该地址直接获取之前的栈顶指针和 Reset_Handler 指针并跳转执行。
, o% Q7 |( D6 p) P& Q0 w& p" ^  J
2、APP 程序需要让编译器将程序存放在指定地址空间里,并重新定位中断向量表的位置。
' ^6 x# p8 K6 x  {; k+ e* R
3、每次上电复位之后程序都会直接从 BootLoader 的 Reset_Handler 函数执行,而不是从 APP 中执行。
2 R& j6 [4 Q" n7 ?9 I  Z
4、这个地址有两个限制:BootLoader 程序大小和向量表地址限制,必须两者都符合要求。
' y2 D0 j' G7 x2 J% d4 L( k
转载自:鱼鹰谈单片机/ t1 k; R5 X/ C! A
赞 收藏 评论0 发布时间:2022-11-27 21:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版