将U—Boot移植STM32F103浅析Bootloader技术在低端嵌入式平台上的应用
2019-10-21许世文王慧
许世文 王慧
摘 要 Bootloader是嵌入式系統的重要组成部分,一般来说,Bootloader最重要的作用是用来加载操作系统,为调用操作系统内核准备好正确的环境。不过随着半导体产业的发展,许多高性价比的MCU(微处理器)不断推出市场,这些MCU有着丰富的外设资源,但是内部的存储资源不足以运行嵌入式操作系统,只能运行微实时内核或无操作系统的应用,用来满足低成本但相对智能化且需求易变的应用需求。由于应用功能的定制化以及系统维护等因素,也需要加入Bootloader来提高系统的灵活性。本文主要通过将著名的开源Bootloader(U-Boot)移植到ST(意法半导体)公司的一款高性价比微处理器STM32F103来阐述Bootloader的运行机理,需要说明的是,U-Boot虽然对多种处理器平台、多种操作系统有着良好的支持,但其框架仅支持那些运行在内存(SRAM/DRAM/SDRAM)的操作系统且自身也需运行在内存中,而STM32F103的SRAM仅64K,不足以用来运行程序,故需对U-Boot的框架进行改造,使其不但自身运行在闪存(FLASH)中,并且可以直接引导闪存中的应用程序。这样可使得类似于STM32F103这样的“低端”嵌入式平台也能共享U-Boot丰富的命令集和灵活的配置功能。
关键词 Bootloader;U-Boot;STM32F103;嵌入式;FLASH
引言
嵌入式系统,是一种“完全嵌入受控器件内部,为特定应用而设计的专用计算机系统”。一般来说,计算机系统都具有相应的引导程序,它的作用是初始化硬件设备、完成必要的初始化过程,加载操作系统等。对于嵌入式系统来说,出于对成本、体积、性能、功耗等多方面因素考虑,除了使得Bootloader的设计不但严重依赖于硬件,甚至很多时候不再需要Bootloader。但一些特殊情况下,某些平台的存储资源不足以运行操作系统,仅能运行无操作系统的应用或者微型实时内核(如ucos-ii、FreeRTOS等),但又需要对系统的应用做灵活定制,这时也需要加入Bootloader让系统变得更加灵活且方便维护。
本文主要内容是将著名的开源Bootloader -- U-Boot移植到一款“低端”嵌入式处理器平台上,这里所谓的“低端”并非指档次低,而是其存储资源相对于U-Boot目前现支持的平台来说要匮乏,需要对U-Boot进行相对较大的改动才足以支撑在其之上运行。事实上,这些“低端”的处理器在各个领域内的应用也是非常广泛,这里要移植的处理器STM32F103就是当前非常流行的一款高性价比MCU,Cortex-M3核心,由ST公司出产。通过将U-Boot移植在这款MCU上,一方面能更好地理解Bootloader的运行机理,另一方面给出移植思路,方便读者结合自己的项目灵活运用这款开源软件,给项目的调试和应用带来便利。
1 U-Boot移植STM32F103
1.1 设计思路
首先,先来看U-Boot的内存映射图,U-Boot的设计者并不考虑那些仅运行在FLASH的嵌入式系统,如果按照图中的存储映射图直接移植的话,即便进行裁剪,经过编译后的映像也在60K左右,以STM32F103的内存(64K)肯定是无法满足的,需要对U-Boot进行改造,将U-Boot驻留在FLASH中,就需要省去U-Boot将自身“搬移”到SRAM的步骤,使得内存中就剩下堆栈(.bss)和数据 (.data)。
其次,估算U-Boot除去自身映像之外对内存的需求,也就是图中SDRAM除U-Boot映像之外的区域大小,由于STM32F103的中断方式较为简单,是靠中断向量表直接跳转,没有单独栈区,则IRQ&FIQ栈区也可省去。可先下载U-Boot源码并找一种常用的平台并编译,得到内存映射文件后,计算U-Boot的内存需求。
最后,分析U-Boot的源码框架和启动流程,设计启动流程框图,搭建移植环境,并按照启动流程图设计程序,结合STM32F103的实际内存映射图确认编译和链接参数,编译调试并最终得到正确的结果[1]。
1.2 设计过程
(1)估算内存需求
首先下载U-Boot源码,为便于研究和移植,需要下载较老的版本u-boot.2010.06,较新的版本采用了动态链接地址的方法且编译选项比较复杂,不利于我们对源码的分析,方便起见,直接根据移植后的内存映射文件u-boot.map将存储占用情况统计如下表,这里仅统计主要的数据和代码段,还有一些段占用存储较小直接略去。
从上表可以看出,前两个段是代码段和只读段,可以驻留在FLASH中,后面的段是数据段,需要放在SRAM中,总大小不超过8K,加上堆和栈区,64K数据空间也已足够。
(2)启动分析
U-Boot对于很多平台来说启动流程大体相似,第一阶段与硬件体系平台相关,第二阶段是通用功能,需要移植的重点主要在第一阶段,以S3C2440单板为例,第一阶段启动大致工作为设置CPU模式和时钟,判断处理器启动方式并重定位U-Boot映像,计算并设置堆栈指针,初始化bss段,与此同时建立CPU各个模式的中断入口和独立栈区,最终跳转到通用功能的函数_start_armboot。
对于STM32F103来说,其硬件体系结构相对简单。首先,其栈地址需要放在第一条指令中,被自动赋予sp(堆栈指针),故需要固定一个堆栈指针地址。其次,不需要考虑重定位,重定位其实就是判断U-Boot自身是否运行在内存中,如果是运行在内存中,则不需要搬移直接跳转到后面的代码运行,否则将自身“搬运”至内存中,这是因为用仿真器来下载程序时,可能会将映像直接下载至内存中,而对于STM32F103映像始终是驻留在FLASH中,故程序流程图如下所示:
(3)程序设计
按照U-Boot的目錄结构建立好相关文件,先根据CPU体系架构构造中断向量表,中断向量表可被所有Cortex-M3核心系列的MCU所共享,vectors_m.S文件的内容如下:
链接脚本.lds文件可根据其他平台来设计编写。然后通过编译和调试就可以让U-Boot在STM32F103上启动了,需要移植的最基本的硬件驱动为定时器,串口,FLASH用来达到U-Boot最简单的运行条件。
1.3 调试与应用
在调试的过程中,需要对存储的分布有着清晰的理解和认识,编译过后可以分析内存映射文件来确定数据代码段是否放置在了正确的地址中,可避免盲目的调试。
移植完成后,应用程序的编写也需要注意两点,一是应用程序的运行地址,应用程序在编译时,需要修改链接脚本保证FLASH空间的合理分配。二是应用程序需要将中断向量表定位,当应用程序发生中断时,默认会跳转到FLASH的低地址的中断向量表中运行程序,如果不重映射,那么会跳至U-Boot的中断向量中(若低位地址存放U-Boot映像),需要在应用程序代码中加入设置中断向量表的语句,且MCU本身也支持[3]。
2 应用趋势
当前,STM32系列的微处理器通过其超高的性价比以及良好的软件服务,已经取得了非常好的市场占有额,其中的软件服务就包括ST官方提供的STM32系列的Bootloader,其可以支持从多种接口引导,但是作为第三方软件对一些系统的支持并非完全免费,网上还有很多开发者为STM32系列设计的Bootloader,但是其功能比起U-Boot还是稍逊一筹。
虽然在最新的U-Boot源码下已经支持ST的一些单板平台,但是其框架依旧是需要在DRAM/SDRAM中运行,并不能较好的支持在FLASH中运行,希望通过这篇文章给广大嵌入式系统开发者一些思路,让U-Boot支持更多的”低端”嵌入式平台,给我们的系统调试和灵活设置带来便利。
参考文献
[1] 陈海军,申卫昌,史颖.嵌入式系统引导程序详探[J].计算机技术与发展,2006,16(1):123-125.
[2] 严菊明.基于ARM嵌入式系统的通用Bootloader的设计与实现[D].南京:东南大学,2005.
[3] 陈为军,李正明,孙俊,等.基于U-BOOT的S3C44B0引导程序设计实现[J]微计算机信息,2007,23(2):113-115.