STM32的BootLoader 从SD卡更新固件

本文章的百度网盘下载地址:http://pan.baidu.com/s/1bn4A2sR

顺便发个广告STM32的BootLoader <wbr>从SD卡更新固件

工程源代码等资料,欢迎大家索取:

http://item.taobao.com/item.htm?spm=686.1000925.1000774.13.FygESp&id=37435281766


STM32BootLoader SD卡更新固件 

by  coolweedman

2013-11-13 23:07:26

前言

  自从几个月前接触到有Bootloader这回事,就有一种强烈的冲动,想写一个BootLoader出来。很快在飞思卡尔的Cortex-M4单片机上实现,已经是好几个月前的事情了。然后关于BootLoader的事搁在一边好久了,这次弄个STM32BootLoader出来,Cortex-M3的,顺便发表下博客,跟大家分享一下。

 

 

目录

一、什么是BootLoader 3

二、BootLoader的作用 3

三、BootLoader预备知识 3

  3.1 复位序列 3

  3.2 重定位中断向量表 3

  3.3 C语言函数的地址 4

  3.4 hex文件和bin文件 5

四、分几步实现BootLoader 7

  4.1 FAT文件系统 7

  4.2 读写Flash程序 7

  4.3 跳转到新程序运行 8

五、具体流程 9

  5.1 主函数流程 9

  5.2 BootLoader流程 9

  5.3 跳转到新程序流程 10

六、参考文献 10

 

 

 

 

 

 

 

 

一、什么是BootLoader

  这个大家可以上网查一下,我在这里说说我自己比较片面的理解。BootLoader就是单片机启动时候运行的一段小程序,这段程序负责单片机固件更新,也就是单片机选择性的自己给自己下程序。可以更新也可以不更新,更新的话,BootLoader更新完程序后,跳转到新程序运行;不更新的话,BootLoader直接跳转到原来的程序去运行。

  BootLoader下载新程序后并不擦除自己,下次启动依然先运行BootLoader程序,又可以选择性的更新或者不更新程序,所以BootLoader就是用来管理单片机程序的更新。

  我的大概理解是这样,大家自己网上搜搜详细介绍吧。



二、BootLoader的作用

  BootLoader使单片机能自己给自己下载程序,所以在程序升级方面非常有作用。比如我们的BootLoader是通过GSM更新程序的,我们在升级单片机程序的时候,只要把新程序通过GSM发送给单片机,单片机自己实现程序更新,然后跳转到新程序执行,这样就省去我们很多升级的功夫啦。

  可以想象一下如果把单片机安装在非常高的地方,或者危险的工业现场,或者封装得很难拆下来,我们很难直接给单片机下载程序,那么BootLoader的作用就体现出来了。

  简单的说,有了BootLoader,我们省心又省力。



三、BootLoader预备知识

  我们这里是为ARMCortex-M3单片机写的BootLoader,需要了解一下M3内核的架构,并且要了解M3是怎么启动的等等。这个方面的知识,可以参考《Cortex-M3权威指南》,这里的话我只是简单介绍一下,大家有什么不清楚请参考权威指南。并且这里是以STM32为例说明问题的,并且使用的开发环境是RVMDK


3.1 复位序列

  这里参考的是《Cortex-M3权威指南》的3.8节,复位序列。

M3单片机复位后,从0x00000000取栈指针(SP), 从0x00000004取复位向量(PC),有了栈指针和复位向量后,单片机就按照正常流程运行了,在BootLoader里面,我们更新完程序后需要做的步骤之一就是设置栈指针,跳转到复位向量。


3.2 重定位中断向量表

  这里参考《Cortex-M3权威指南》的7.3节,向量表。

BootLoader是一个完整的程序,下载的新程序也是一个完整的程序。都包含中断向量表,所以的话,我们是有两个中断向量表。单片机启动默认先运行BootLoader,所以默认的中断向量表位置是BootLoader的中断向量表。为了新下载的程序可以正常运行,下载完新的程序后,我们需要把中断向量表重新定位到新下载的程序那里。

  Cortex-M3单片机有一个管理中断向量表的寄存器,叫做向量表偏移量寄存器(VTOR)(地址:0xE000_ED08具体可以看看截图:

STM32的BootLoader <wbr>从SD卡更新固件

  STM332BootLoader程序一般是在0x08000000,不是在0x00000000是因为STM32的重映射技术(不符合Cortex-M3,有点搞另类的感觉),所以BootLoader的中断向量表在0x08000000那里。如果我们新下载的程序在0x08060000,并且新程序的中断向量表在起始地址,那么下载完程序,为了新程序能正确运行,我们需要把中断向量表重定位到0x08060000那里,再跳转到新程序运行。


3.3 C语言函数的地址

  这一节设计的内容主要属于分散加载文件,大家具体上网了解,我只是简单介绍。

  我们知道C语言名就是函数的地址,并且STM32单片机ROM的其实地址是0x08000000,那么使用编译器编(我使用的是RVMDK)译程序的话,函数的地址默认都在以0x08000000为首的一段内容里面了。比如有可能我们一个函数的地址是0x08000167

  我们需要注意的问题是,如果不修改程序默认的起始地址的话,那么BootLoader和新下载的程序的起始地址都是0x08000000,也就是他们重叠了,这样的话肯定相互之间有影响,程序是不能正常工作的。

  我这里的解决方法是,BootLoader程序依然占用0x08000000为首的那段ROM,因为STM32Cortex-M3默认就是从0x08000000运行程序的,保持BootLoader程序先能正确运行。然后新程序使用除BootLoader占用ROM以外的空间。这里需要知道BootLoader到底占用了多少ROM,很简单,查看MAP文件就行了。这里以我的BootLoaderMAP文件为例说明一下,看截图:

STM32的BootLoader <wbr>从SD卡更新固件

  主要是这句话“Base: 0x08000000, Size: 0x00006da4, Max: 0x00080000”,我的BootLoader程序是从0x08000000开始,占用了0x00006DA4大小。只要我们的新程序不要和BootLoader程序冲突就可以了。

  编译新程序的时候,我们要修改程序的起始地址,我的修改方法如下(开发环境是RVMDK):

打开Target Option...,切换到Target选项卡,如下

STM32的BootLoader <wbr>从SD卡更新固件 

修改IROM1的起始地址和长度:

比如,为了不产生地址冲突,我将将下面的

STM32的BootLoader <wbr>从SD卡更新固件 

修改成

STM32的BootLoader <wbr>从SD卡更新固件 

再编译新程序。

 

注意:BootLoader程序是不需要修改的,只是新程序需要修改(新程序就是使用BootLoader下载的程序)。


3.4 hex文件和bin文件

  平时我们用j-Link或者串口下载程序的话,都是打开hex文件下载的,因为hex文件包含地址信息,可以知道应该下载到哪个地址。也就是hex文件是不能直接写进ROM的,一边写需要一边转换。

  然后介绍一下bin文件,很好理解,bin文件是直接下载的,也就是bin文件的内容跟下载ROM里面的内容是一样的。但是bin文件没有包含地址信息,所以在下载之前要知道具体下载到哪个地址。

  我们的BootLoader下载的是bin文件,直接写进STM32Flash里面,地址信息的话就是上一节的IROM0x08070000,连续写入,中间不间断。

  下面再介绍使用生成bin文件,工具的话是使用fromelf,熟悉命令行的同学可能会选择直接敲命令,不过这里我是使用RVMDK提供的用户命令。

打开Target Option...,切换到User选项卡,如下

STM32的BootLoader <wbr>从SD卡更新固件 

主要是在运行用户命令,Run #1

STM32的BootLoader <wbr>从SD卡更新固件 

具体命令是:

C:\Keil\ARM\ARMCC\bin\fromelf.exe --bin -o .\Output\MY_STM32.bin .\Output\MY_STM32.axf

简化一下是fromelf  --bin  -o  xxx.bin  xxx.axf

1、fromelf的地址,我的地址是C:\Keil\ARM\ARMCC\bin\fromelf.exe

2--bin,生成bin文件

3-o,输出

4.\Output\MY_STM32.bin生成的bin文件名

5.\Output\MY_STM32.axfaxf文件名,将axf转换成bin

 


四、分几步实现BootLoader

  有了前面的基础知识后,应该是比较容易理解BootLoader需要怎么实现了。这一章,我们分几个步骤,慢慢实现BootLoader


4.1 FAT文件系统

  我们的BootLoader是从SD卡更新程序的,把在电脑上编译后的程序,也就是bin文件,复制到SD卡中,然后让单片机可以读取相应的bin文件,就可以实现程序的更新。

  我跑的文件系统是FATFS_R0.07c,很经典的一个版本。如果大家对文件系统方面不了解的话,自己网上查找教程,或者说很多同学对这一步应该已经很熟悉啦。

  单片机上实现读取bin文件,结合Flash写入程序,就可以实现程序更新。


4.2 读写Flash程序

  要实现BootLoader,当然前提是可以写入Flash了。STM32的话是很容易实现的,因为我们有官方库。我使用的是3.0.0版本,参考官方例程,很容易实现Flash的读写,这里简单介绍一下。

  第一步是解锁Flash,然后写入前先擦除Flash,再写入,最后读取校验写入是否正确。

调用了几个官方的库函数。

1void FLASH_Unlock(void)Flash解锁

2FLASH_Status FLASH_ErasePage(uint32_t Page_Address)Flash擦除

3FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data)Flash写入

  我只是稍微封装了一下几个函数,实现Flash的读写验证,具体我实现的接口函数为一下截图,大家可以大概参考一下:

 

STM32的BootLoader <wbr>从SD卡更新固件 


4.3 跳转到新程序运行

  这一节要结合上面提到过的,Cortex-M3启动做了什么事情,然后我们更新程序后,就去做新程序需要做的事情,就算是调到新程序运行了。主要有三个步骤:

1、重定位中断向量表

2、设置栈指针

3、跳转到复位向量

我的实现如下,看截图:

STM32的BootLoader <wbr>从SD卡更新固件 

注意93行的( (void (*)()) (Reset) )();是一去就不返回的,所以95行的return FuncErr;只是形式而已,实际并不运行,而是在93行就直接跳转到新程序运行的。

 

至此,BootLoader实现步骤完了,相信熟悉了这几个步骤后,大家可以自己给自己的单片机写个BootLoader。顺便说一下,Cortex-M4BootLoaderCortex-M3几乎是一样的。我在STM32上的实现完全是参考自己上次在飞思卡尔Cortex-M4上的实现。下面形式的说一下我的主函数吧,看看具体流程。



五、具体流程

  先看看我的主函数,再啰嗦一下具体流程,可能有的同学已经有点厌烦啦,其实感觉有点多余。


5.1 主函数流程

STM32的BootLoader <wbr>从SD卡更新固件 

1、时钟初始化

2LED初始化(无关紧要)

3、调试接口初始化(无关紧要)

4Flash初始化(解锁Flash

5FAT初始化(挂载文件系统)

6、我们的BootLoader(重点,下面展开继续介绍)

7、主循环(实际不会运行到这里)


5.2 BootLoader流程

老样子,先上截图:

STM32的BootLoader <wbr>从SD卡更新固件 

1、打开bin文件,检查文件打开是否正确

2、设置Flash下载起始地址(新程序起始地址)

3、读取文件,检查读取是否正确

4、获取栈指针和复位向量

5、进入循环,条件为如果读取文件字节数不为零

6、将读取到的bin写入Flash,并判写入状态

7、调整Flash地址

8、继续读取bin文件,检查读取是否正确,回到5继续循环

9、这里已经将bin写入Flash完成了,准备跳转到新程序运行


5.3 跳转到新程序流程

其实上面已经讲过了,这里继续啰嗦,截图:

STM32的BootLoader <wbr>从SD卡更新固件 

1、重定位中断向量

2、设置栈指针

3、跳转到复位向量(开始运行新程序)

 

啰嗦了又一遍,BootLoader完全结束,感谢大家都支持啦~



六、参考文献

1】《CM3权威指南CnR2Joseph Yiu 著   宋岩 译

2ST官方库3.0.0

3】《C和指针》Kenneth A. Reek著   徐波 译

4FATFS文件系统

 其他互联网资料


没有更多推荐了,返回首页