STMCU小助手
发布时间:2022-2-26 16:47
|
对于 STM32 用户,经常会涉及到通过用户启动程序实现对用户应用程序的更新升级。一般来讲,用户启动程序主要用来跟外界通信,获取新的用户程序代码并实现对用户代码区的应用程序升级。用户应用程序是指实现各种用户功能的代码。9 A/ l/ m2 q$ P% ^( v2 s6 h6 P4 T 在这个过程中,往往需要做从用户引导程序区(以下简称【BOOT 区】)到用户应用程序区(以下简称【APP 区】)的跳转,有时可能还需实现从用户应用程序区跳回到用户启动程序区,甚至不同用户程序区的互相跳转等操作。在这些跳转过程中,常常有人的开发工作在此遇到阻碍,甚至破费周折。+ `9 Z3 F! }8 I+ Y+ F. s STM32F0 代码区跳转# x$ ?* o8 M, \; { 在此我们以 STM32F0 为例,就芯片内不同程序区的跳转问题做些交流与介绍,限于篇幅,这里仅直接介绍具体操作和注意事项,不做过多拓展介绍。相关知识点可阅读 STM32 芯片参考手册、STM32 相关内核编程手册。 下面介绍中提及的集成编译环境是指 ARM MDK,硬件基于 STM32F072RB Nucleo 开发板。后面我将逐一介绍不同跳转操作的基本流程和注意事项,涉及以下三种情况: 从【BOOT 区】跳转到【APP 区】 从【APP 区】跳转到另外新【APP 区】- }$ I# o: ], i b( a 从【APP 区】跳回【BOOT 区】0 d8 r5 p; z3 g2 E4 d7 c2 m. H6 } 一般来讲,不同区段的执行代码我们通过建立不同的工程项目来实现,最终将不同区段执行代码写入芯片。这里假定 BOOT 区对应的内部 FLASH 地址段为 0x8000000—0x8004000,APP1 区对应的内部 FLASH 地址段为 0x8004000—0x8008000, APP2 区对应的内部 FLASH 地址段为 0x8008000—0x800C000.
从【BOOT 区】跳转到【APP 区】/ l6 G; a5 v) H" o; W r. s( i; r7 f3 S# q: k4 B f 先说从 BOOT 区跳转到 APP 区。这个跳转代码比较简洁、简单,注意跳转前要关闭刚才程序区开启过的所有中断使能,保证所有中断请求位都被清除,不是简单的关闭总中断,否则往往隐患多多。BOOT 区相关跳转代码如下:% b9 u. Y0 [( `! y( S; Q, S
这个从 BOOT 区到 APP 区的跳转最终能否成功,关键还是取决于 APP 区代码相关配置及准备工作。假设这里的 APP 区是上面提到的 APP1 区,内部 FLASH 地址段为 0x8004000—0x8008000,那么在 MDK 的 option 项里的 memory 配置板块要做正确配置,即 flash 空间与 ram 空间的配置,如下图所示:
IROM1 的配置就是 APP1 代码摆放的起始空间地址及长度。IRAM 的配置要注意先保留 48个字的空间用来存放中断矢量表的内容。因为 stm32F0 芯片的中断矢量表的大小就是 48个字(即 0xc0 字节)。至于剩下的内部 RAM 空间大小由芯片本身的 RAM 容量决定(这里是基于 STM32F072RB 芯片,其内部 RAM 总容量为 0x40000)。 : g$ K# d9 I7 Q+ I+ C* c% O 另外一件很重要的事情就是做中断矢量表的拷贝。在 APP1 区的 main()程序开头部分,将放在 flash 程序空间起始部分的连续 48 个中断矢量地址表拷贝到内部 RAM 的起始地址段。即将矢量表从 0x8004000 地址开始拷到 0x20000000 开始的连续 48 个字空间(前面提到的存储配置正是为了配合这个拷贝操作)。基于 MDK 环境的参考代码如下: : i9 y2 w" p, \6 F2 `8 b - v; U! o) ~3 A) Z9 q
。。。。。。 后面为用户功能代码。。。。。。 0 U2 Q7 ]7 l, {! P' j# X3 k 6 x" [$ N; s8 l/ D" R: b 上面代码中绿色语句就是实现中断矢量表从内部 flash 到内部 RAM 的拷贝,而红色语句则是为了实现将程序执行的 0 地址域的重映射,即将程序运行的 0 地址从内部 flash 的0x8000000 通过重映射机制切换到 0x20000000,为的是在 APP1 区发生中断时 CPU 能从正确的地方准确获取相应中断矢量地址去执行中断服务程序。 到此,从 BOOT 区跳转到 APP1 区就算完成了。 从【APP 区】调转到新【APP 区】 * I- _& Q. A! o& ~! l 那么,如果想从 APP1 区跳转到另外 APP2 代码区呢?这个跟从 BOOT 区跳转到 APP1 区类似。在 APP1 区的跳转代码这里就不说了,地址给对、代码写对就好。APP2 区的代码也同样必须做中断矢量表的拷贝和 0 地址域的重映射。但因为在 APP1 代码里已经做过了 0 地址的重映射,所以就不必重复做了。 m) T( F- V- B( y* Y! `* H8 x$ B 假定 APP2 代码区的内部 flash 空间安排在为 0x8008000—0x800C000。则 MDK 里 memory布局配置如下:$ o, u: K W2 P p' D+ \' F 6 K/ ^2 M, p+ a3 z
从【APP 区】跳转到【BOOT 区】6 O/ N% K j2 J7 h N2 c0 G: d" j' d3 ?! Y8 G 有时我们还希望或需要程序能从 APP 区跳回用户 BOOT 区,那如何操作呢?对于 STM32F0芯片而言,程序执行区从 APP 区跳回 BOOT 区跟从 BOOT 区跳到 APP 区还不太一样,经常有人在这个跳转过程中卡壳,对于跳得出而跳不回感到难以理解。 0 d J! q- i4 a* q' b! M8 i- v' S 假设从 APP2 区跳回 BOOT 区,在 APP2 区做跳转准备时除了给定正确的跳转地址外,另一个要做的就是将之前通过重映射将 0 地址程序空间从内部 SRAM 切换回内部 flash 区。实际应用中,我们往往因为忽视了这点,跳回去后一碰到中断就问题来了。另外,从 APP2 S- _0 A3 U7 N) b 区跳回 BOOT 区无须矢量表的拷贝操作。所以在 APP2 区执行跳转前需将 0 地址重映射回内部 flash 空间,通过运行如下库代码完成:0 g# Z/ \; Q& B" K) e% d __HAL_SYSCFG_REMAPMEMORY_FLASH();6 _( ]4 H0 @, k; u& q" P 5 m* |1 o. N* W2 r | u! s4 i 几点重要经验总结% E/ s0 z' l' D ( s) y6 ], J' o0 K8 q, P 通过以上几种不同情况下操作过程的描述,我们可以知道,想要避免 STM32F0 在代码调转中出错,应该遵循以下几条关键的经验:; h& r8 J$ M: ]+ S7 J9 Q7 Q: e8 r7 ` 从【BOOT 区】跳转到【APP 区】,在【APP 区】要做中断矢量表的拷贝和将 0 地址从内部 flash 切换到内部 SRAM 起始地址。 3 t8 B9 L( u: l4 n. K$ i 从【APP 区】跳转到其它新的【APP 区】,只需在新的【APP 区】的代码里再做中断矢量表的拷贝,并保证相关存储配置的正确。 4 Q Z4 `" M$ V; j& O" ^ 从【APP 区】跳回【BOOT 区】,该过程无矢量表的拷贝,只需将 0 地址执行域重新映射回内部flash 区。: ~+ `: L( b1 S; N$ e! z 不论从什么区跳往什么区,跳转前禁用当前用户打开过的所有中断使能、确保无未处理的中断请求存在或在跳转过程中发生中断。 以上操作流程主要针对基于 COMTEX M0 内核的 STM32F0 系列芯片。 ' m" K6 D) d- t7 S( H. L * Q6 Y: p# V j4 E8 w+ @1 Z- M G2 F0 a3 y5 u9 C+ l , V. f) O5 R. {8 b 6 ?. u& q3 m( c3 r( z * ? `9 O9 {0 f( U9 S3 I5 W |
DMA 原理从 0 到 1:为什么它能解放 CPU?一文讲透 DMA 的工作流程
小白也能明白的STM32的低功耗与唤醒机制
STM32系统中2种数据掉电保护的方法
分享STM32F051中文参考手册(重制书签版)
AI工具训练营-用ChatGPT解决HID Keyboard实现的问题
STM32固件库分享,超全系列整理
STM32小白入门指南:从基础到OTA实现方案
STM32超详细学习笔记
新手必看!STM32单片机应该怎么学?
如果你解决了这些问题,就可以直接学STM32
微信公众号
手机版