完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
对于很多人来说,BootLoader并不是一个陌生的词,甚至会经常用到它。因为在很多情况下我们都需要BootLoader程序,比如我们需要对系统在线升级时就需要它,还有当我们需要在外部存储器中运行程序时也需要用到它。在这里我们就来设计一个应用于STM32系列MCU的BootLOader程序。
1、BootLoader的基本原理 既然我们想要实现一个面向STM32的BootLOader程序,那么首先我们必须来了解一下BootLOader程序的基本原理。 顾名思义,BootLOader程序肯定是要实现系统的引导,这是BootLOader程序的基本功能。对于STM32系列MCU来说,系统启动后都会从内部Flash存储器的起始地址开始执行程序。然后进入应用程序并按既定的顺序执行下去,这时BootLoader与应用程序是一体的,具体如图所示: 但有些时候,我们希望应用程序并不是直接运行,如我们希望对系统实现IAP的时候;或者我们希望应用程序并不在我们的内部Flash中运行;又或者应用程序虽然在内部Flash运行,但我们希望应用程序从我们指定的内部Flash地址运行等等。在这些时候我们就需要一个单独的BootLoader程序。系统首先启动BootLoader程序,系统准备就绪后进入到应用程序执行,具体如图所示: 在上图中,我们实际上将应用程序存储在内部Flash的指定位置,这样做当然是为了实现我们某种需求,如系统IAP。当然我们也可以让应用程序存储于外部Flash中,然后BootLoader程序跳转到外部Flash去执行应用程序,不过前提是外部Flash内购执行程序。具体过程如下: 当然,这只是一种示例,对于不同的存储器我们只需要修改地址就可以了。至于在BootLoader程序中要实现的功能就看使用情况了。原则上我们可以添加我们任意想要的功能,如硬件检测、系统升级等等。 2、目标BootLoader设计 我们的目标是实现一个面向STM32的BootLoader程序。那么接下来我们就设计如何实现一个面向STM32的BootLoader程序。 2.1、Flash规划 我们以STM32F407IGT6为目标MCU,这款MCU具有1M的Flash和192K的SRAM。我们将Flash划分为2个部分,一个是启动程序区(0x0800 0000 - 0x0800 3FFF )大小为16K Bytes,剩下的为应用程序区(0x0800 4000 - 0x080F FFFF)。具体分配如下图: 我们让BootLoader程序占用16K的存储空间。但它是可以操作整个Flash存储空间的。 2.2、BootLoader程序结构 我们来考虑一下BootLoader程序的结构问题。我们设计BootLoader程序的主要目的就是为了对应用程序进行升级。那么在BootLoader程序中主要需要实现哪些功能呢?有几个方面是必须要包括的,一是基本的配置,如时钟等,我们在主程序中实现;二是对Flash的操作,我们升级应用程序肯定会对Flash进行查处和写入操作;三是跳转控制程序,我们最终是需要去执行应用程序的,跳转功能必不可少。当然根据不同的需求可能会有其它的需要。具体如下图所示: 上图中,我们除了签署的三项基本实现外,还添加了IAP文件的获取功能。这部分功能也是需要的,但在不同的模式下可能会有较大区别。因为获取文件的方式可以是各类通讯如以太网口、串口等。也可以是各类存储器,如SD卡、U盘等。所以这一功能虽然必不可少但实现方式则非常灵活,在后续实现中,我们具体问题具体分析。 3、目标BootLoader实现 我们已经确定了Flash的划分,也基本明白了BootLoader的基本工作流程。在接下来我就来讨论一下究竟怎么实现一个BootLoader程序。 3.1、BootLoader编码 我们知道芯片上电时先运行BootLoader程序,然后跳转到应用程序区执行应用程序。所以我们在编写BootLoader程序时我们首先判断系统是否有IAP的需求,如果有IAP请求则进入IAP模式,完成后再跳转到应用程序执行,如果没有IAP请求则直接跳转到应用程序执行。具体流程如下: 关于IAP的处理在不同的情况下会有不同的处理方式,在这里我们主要看一看跳转控制程序。首先定义应用程序的首地址并声明一个函数指针类型。具体如下: #define ApplicationAddress 0x08004000 //应用程序首地址定义 typedef void (*pFunction)(void); //定义跳转函数指针类型 可能有人要问问什么定义这样一个函数指针类型,因为我们最终是跳转到Reset_Handler函数,所以必须要一个可以指向这个函数的函数指针。接下来我们就可以实现跳转程序了。 /*跳转到应用程序处理函数*/static void JumpToApplication(void){ uint32_t StackAddr; //应用程序栈地址 uint32_t ResetVector; //应用程序中断向量表的地址 pFunction JumpToApp; //定义跳转函数指针 __set_PRIMASK(1); //关闭全局中断 StackAddr = *(__IO uint32_t*)ApplicationAddress; //0x08004000; ResetVector = *(__IO uint32_t*)(ApplicationAddress + 4); //0x08004004; if((StackAddr&0x2FFC0000)==0x20000000) //检查栈顶地址是否合法. { __set_MSP(StackAddr); //初始化应用程序栈指针 JumpToApp = (pFunction)ResetVector; JumpToApp(); }} 3.2、应用程序处理 实现了BootLoader的编码后,要想正确的跳转到App运行,我们还需要对App作相应的修改。重要的修改有2处。如果应用程序是裸机程序则在配置时钟前我们需要打开全局中端。 /*开启全局中断,在BootLoader中关闭的*/ __set_PRIMASK(0); 同时,还需要修改中端向量表的偏移量地址。对于我们所使用的STM32F07可直接在system_stm32f4xx.c文件中修改就可以了。 #define VECT_TAB_OFFSET 0x4000 /*!< Vector Table base offset field. 实现了上述修改并不能达到我们想要的目的,我们还需要在开发环境中做必要的修改。以我们使用的IAR EWARM V8.4为例。修改icf文件中对中断向量表和Flash存储区域的设定。具体如下图: 完成上述配置后我们下载应用程序和BootLoader程序就可以实现正确的跳转了。 4、小结 本篇中,我们只是实现了一个简单的BootLoader程序。下载到目标MCU后实现了跳转,应用程序也正常运行,说明我们的设计是正确的,后续可在次基础上添加各种功能实现相应的IAP应用。 需要注意的是在BootLoader程序中我们关闭了全局中断,在应用程序初始化系统时钟之前一定要记得打开全局中断,否则SystemTick不能工作会产生硬件故障(hardfault)。不过如果App是运行在RTOS上,则打开中断可能会出错,这一点需要注意。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1632 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1559 浏览 1 评论
985 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
688 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1605 浏览 2 评论
1869浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
652浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
522浏览 3评论
539浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
508浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-25 13:05 , Processed in 0.637191 second(s), Total 48, Slave 41 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号