基于ARM的通用bootloader的设计

原创 2006年06月22日 17:27:00

基于ARM的通用bootloader的设计

摘要

在嵌入式系统当中,系统架构一般可分为三部分:引导加载程序、内核、应用程序。引导加载程序工作在系统的最底层,服务于内核启动,以及应用系统开发。因此,设计实现一个可靠的引导加载程序具有非常重要的意义。本文主要把目光集中在通用的引导加载程序的设计思想和实现技术。另外,基于对引导加载程序工作原理和系统启动流程的深入理解,笔者开发了一种不同于传统的,高效的,依赖引导加载软件的硬件测试技术。

关 键 字 Linux ARM 引导加载程序 U-Boot

1 引言

随着信息化进程的推进,嵌入式系统以软硬件的可剪裁性、体积的小型性、技术的集成性等特点广泛应用在信息终端、工业控制和信息家电等领域。采用ARM技术IP核的各种微处理器遍及各类产品市场。ARM技术以其较高的性能和功效,使其在嵌入式系统中得到广泛应用,世界上几乎所有的主要半导体厂商都生产基于ARM体系结构的通用芯片, 可以说,ARM技术无处不在。另外在嵌入式开发板上运行GNU/Linux已经变得越来越流行,ARM Linux的广泛应用使得围绕它的一些实现、应用和支持都成为热门的研究方向。一个标准的嵌入式系统模型可以分为三个部分:Bootloader、内核、应用程序;简单地说,Bootloader就是在操作系统内核运行前运行的一段小程序。通过这段小程序,初始化必要的硬件设备,创建内核需要的一些信息,从而将系统的软硬件环境带到一个合适的状态,最终调用操作系统内核,起到引导和加载内核的作用[1]。另外,在嵌入式系统的硬件测试工具方面,bootloader也是一个值得考虑的选择。传统硬件测试是基于JTAG仿真设备完成的,调试过程复杂,存在局限性。笔者认为只要在bootloader中适当开发部分外设驱动程序并提供部分内存指令,完全可以满足工程中对外部设备的调测需求,这种硬件测试方法独立于JTAG测试,实用性好,运用简洁,几乎无外部硬件限制,完全可以成一种新的硬件测试方法。

2 实现通用bootloader的可行性分析

引导加载程序是系统加电后运行的第一段代码。我们熟悉的PC中的引导程序由BIOS和位于MBROS BootloaderLILO或者GRUB)一起组成。然而在嵌入式系统中通常没有像BIOS那样的固件程序,因此整个系统的加载启动任务就由bootloader完成。Bootloader严重地依赖于硬件而实现,特别是在嵌入式系统中。不同的体系结构需要的bootloader是不同的;除了体系结构,bootloader还依赖于具体的嵌入式板级设备的配置。也就是说,对于两块不同的嵌入式板而言,即使它们基于相同的CPU构建,运行在其中一块板子上的bootloader,未必能够运行在另一块上。但是,我们仍然可以对bootloader归纳出一些通用的概念来,特别是针对某一特定的体系结构。

系统加电或复位后,所有的CPU通常都从某个由CPU制造商预先安排的地址上取指令。比如,基于ARM7TDMI coreCPU在复位时通常都从地址0x00000000取它的第一条指令[2]。而基于CPU构建的嵌入式系统通常都有某种类型的固态存储设备(比如:ROMEEPROMFLASH)被映射到这个预先安排的地址上。因此在系统加电后,CPU可以首先执行bootloader程序。不同体系结构的CPU之间软件编程接口差异很大,实现起来具备一定的难度,但是同一体系结构的CPU由于其编程控制接口的连续性和继承性,使得实现一种可以在其上运行的通用bootloader是有可能的,以ARM结构的CPU为例,ARM7ARM9系都遵循同样的启动流程,系统复位后从0x00000000开始执行,CPU工作在系统态,需要关闭所有外部中断,关闭看门狗定时器,设置时钟源,初始化动态存储器,设置PLL参数,自加载到动态存储器运行,根据需要初始化串口、网卡等外部设备,提供一个用户接口或直接加载内核。而且,出于设计通用bootloader的考虑,最小化bootloader所处理的硬件范围,采用将硬件结构上的差异隔离出启动代码的方法,模块化与阶段化启动源代码的结构,将更多的功能放在尽量靠后的阶段。通过这一系列设计技术实现一个基本上通用于ARM结构CPUbootloader

3 Bootloader中硬件差异的隔离技术

Bootloader中最复杂、变化最大的就处理硬件细节问题了,任何两种型号的CPU总是存在一定的差异。特别是在嵌入式领域,多样化的应用需求决定了任何一处理器不可能胜任所有的应用场合。同时市场为了满足不同层次用户的需要,衍生出了很多不同型号的CPU。作为通用bootloader的设计目标,要尽可能支持更多的硬件,那么这些硬件细节上的差异是必须面对的。对于ARM结构的CPU来说,这些差异主要体现在程序访问接口上面。比如说SDRAM控制器寄存器组的地址和各自的功能定义,PLL支持的参数等。对于嵌入式系统来说,更主要的差异存在于多样化的外围设备,比如说SDRAM工作参数,LCD控制器寄存器组,FLASH芯片组,串口控制器等。但是,它们也有很多重要的共同之处,比如机器指令、启动步骤CPU内部寄存器组(R1-R15MMU等。正是基于这些共同点,加上运用特殊的技术手段,屏蔽硬件细节上的差异,按照最小化设计原则,实现一个通用的bootloader才成为可能。

目前根据需要,常采用的硬件差异隔离技术基本上可以分为编译时隔离技术和运行时隔离技术。编译时隔离技术运用简单,但是缺乏灵活性,硬件细节差异本质上与程序主体集成在一起,遇到硬件发生变化的场合需要获得源代码,并重新编译以匹配硬件差异。编译时隔离技术的核心在于采用统一的CPU描述体系,将该描述体系从代码中抽象出来,形成一个不依赖于其他任何部分的模块,程序主体对该模块拥有受限制的访问权限,通过该模块提供的访问接口,获得对CPU的具体描述。模块的实现规模根据不同场合可大可小,可以简单到只有一个CPU定义头文件,也可以复杂到数个C文件及数个头文件。实作中结合最小化设计原则,一个CPU描述头文件是可以满足大部分需求的。实现的关键在于必须定义一个统一的、包容的、适度的CPU描述体系。另外一种运行时隔离技术具备相当的灵活性,可以同时支持数种CPU而不需对程序主体进行任何改动,当然它在应用上就要相对复杂一些,采用的实现技术相对也要多一些。实施当中,较为常用的三种设计手段有参数块、函数指针、面向对象设计里的继承,也包括这三种方法的综合运用。参数块类似于操作系统当中进程的环境变量,以一种结构化的方式记录CPU相关的信息,甚至可以是一般的数组,将参数块的起始地址传递给程序主体,程序主体再按照协议对参数块进行访问。函数指针与参数块本质上没有太大的区别,主要的差异在于参数块传递的是数据,而函数指针传递的是代码,函数实现要分为组合语言函数和C语言函数,组合语言函数没有特殊要求,C语言函数必须要求先设置堆栈区域。继承的概念运用到bootloader当中是对面向对象设计思想的进一步扩展,一般说来,大部分工程项目都可以在面向对象设计的思想中获得益处。Bootloader运用继承和面向对象设计思想的最佳场合就是设备驱动与协议栈,完全可以借鉴Linux设备驱动程序访问接口的设计模型,定义一套标准的类似于系统调用的函数接口,设备驱动负责处理物理设备并且向程序主体注册逻辑设备,程序主体通过统一的函数接口,以逻辑设备为访问对象,实现对物理设备的访问控制。网络协议栈的层次化设计是面向对象思想运用实践的优秀案例,协议中存在很多逻辑上的实体可以用对象方式表示。比如说bootloader中常用的TFTP协议,存在的协议逻辑实体就有TFTPUDPIPFRAME。结合层次化设计,各实体负责封装和解封装对应的协议头和协议内容并提供相应的访问接口,对上层隐藏实体的内部实现,提供一个程序访问接口以便上层实体可以利用下层实体的服务。最后,综合运用这三种技术,发挥协作优势,克服各自的缺陷,以获得更好设计实现。

4 Bootloader的模块化设计技术

模块化设计技术已经广泛地运用于各种大型应用系统的开发当中,模块化的设计为项目实施带来的好处是系统结构性强,开发过程清晰,代码易于维护。在如bootloader这类的系统软件或底层软件中应用模块化设计技术是开发通用型的bootloader软件的重要手段之一。该技术一般将bootloader按功能划分为各自独立、粒度合理的模块,各模块采用松散藕合、层次化组合的方式设计。在开发过程中根据模块的重要程度分先后序完成,基础的模块在开发前期实现并调试通过,再完成其它的模块。一个通用的bootloader可以分成这样几个模块:CPU复位模块、SDRAM配置模块、内核引导模块、硬件驱动模块、硬件调试模块、网络协议模块、用户交互接口。对于CPU复位模块来说,任何其它模块必须在其完成之后才能工作,因此是要首先实现并调试通过的,它执行CPU复位后需要完成的一系列步骤,包括识别CPU型号,关闭外部中断,设置时钟源、GPIOPLL及相关的寄存器组,然后SDRAM配置模块接管下面的工作,至此该模块的生命结束。而对于SDRAM配置模块来说,它仅仅需要了解CPU已经工作在了一个确定的状态,目前应该根据SDRAM芯片规格设置SDRAM控制器工作参数,如存储器宽度、行刷新频率、列刷新频率、访问时序周期信号,然后搬移bootloaderSDRAM,设置PLL参数提CPU主频、总线频率、外围设备频率,使软件在SDRAM中运行。有了这两个模块的正常工作,一个最小化的启动程序就已经完成了,其后的工作都是按需实施了。可见模块化设计技术在简化软件设计、降低实现难度、加快开发进度方面有着关键性的作用。

5 Bootloader的阶段化设计技术

阶段化设计是bootloader使用的特殊技术,其它的工程项目还没有将该设计思想提高到一种设计模式的高度,几乎所有的引导加载程序都在使用该技术,包括PC系统第一阶段由BIOS完成,第二阶段由MBR完成。通常有两阶段的启动,个别还有三阶段的启动。阶段化设计的中心思想是将一件工作按时间序及不同阶段之间的差异性划分为两个或多个阶段,每一个阶段解决相对独立、集中的问题,同时为下一阶段好必要的准备。后一阶段在前一阶段的基础上工作,但是并不显示依赖提供的任何服务,除开提供的运行环境外,这一点区别于模块化设计以及层次化设计。任何一件工作都可以分为几个阶段来完成,只是没有引导加载软件这么明显。嵌入式系统中的bootloader更是如此,最常用的情况是按照其在什么存储介质上执行代码分为两阶段的设计方案。在第一阶段,它在FLASHROM上运行,处理一些必须的初始化事务后,移交控制权,为了达到代码短小精悍的目的,这一阶段采用汇编语言实现,同时bootloader有必要采用硬件差异隔离技术以获得较好的通用性。第二阶段在SDRAM上运行,这里除了利用第一阶段提供的确定状态的CPUSDRAM外,与第一阶段没有任何瓜葛,第一阶段所做的工作这里完全可以重新处理,这一阶段主要处理外围设备如串口等,引导内核,FLASH编程、提供网络传输及用户交互接口等,可以结合模块化设计技术和面向对象设计思想来实现这一阶段的代码结构,采用C语言开发代码,以获得良好的可读性和可移植性[3]。阶段化设计技术应该和前面提到的两项技术结合使用,单独地使用这三种技术带来的好处是有限的另外,这三种技术的运用也没有一成不变的模式,需要在设计当中灵活运用,获得最佳的效果。

6 Bootloader的硬件测试应用技术

6.1 Bootloader硬件测试的原理分析

近来,硬件测试技术的发展异常迅速。作为芯片级测试技术,JTAG标准在嵌入式系统开发中已经得到广泛的应用。JTAG标准规定对于数字集成电路的每个引脚都对应一个或多个移动寄存器单元,称为边界扫描单元BSC。它将JTAG电路与内核逻辑电路联系起来,同时隔离内核电路和芯片引脚。集成电路的所有边界扫描单元构成了边界扫描寄存器BSR,它仅在进行JTAG测试时有效,在集成电路正常工作时无效,不影响集成电路的工作[4]JTAG技术是目前最为有效的测试方法,可对芯片内逻辑和芯片间逻辑进行测试,但遗憾的是该技术需要其他辅助设施,测试技术复杂,不适合简单场合。笔者在理解bootloader工作原理后,认为bootloader是可以测试硬件设备的,特别是芯片间逻辑测试。

ARM体系结构规定系统内存区域和I/O区域统一编址,从软件的角度看,任何硬件的访问与内存的访问都是一致的,硬件的控制/状态寄存器组就相当于一个内存单元,占用一个或多个内存地址。利用这个特点,结合硬件驱动实现,适当的提供用户控制接口,即可以完成对硬件的测试。

6.2 利用bootloader对以太网卡进行测试

以太网卡在嵌入式系统的研发发挥着重要作用,让以太网卡工作起来也是引导加载程序所必须的。以太网卡通常集成MAC子层与物理层,从软件编程上需要设置网卡的工作方式、物理层参数以及进行报文收发为了对网卡进行测试,笔者实现了一系列控制台命令,包括:

(1) Xor实现对寄存器的某一位作异或运算

(2) And实现对寄存器的某一位作与运算

(3) Or实现对寄存器的某一位作或运算

(4) No实现对寄存器的某一位作非运算

(5) Send实现向MAC子层的内部FIFO送出一个报文

(6) Receive实现从MAC子层的内部FIFO取出一个报文

(7) MallocFree实现全局堆存储管理

通过这些控制台命令以及网卡驱动程序的组合运用,参照以太网卡芯片手册,可以配置以太网卡、访问卡内FIFO,查看设备中断状态,控制报文收发。

除了以太网卡外,bootloader也可支持其他的外设测试。这种测试方法不需要其他设施如仿真器、集成调试环境的辅助,测试成本,测试效率高,满足芯片间逻辑测试要求,具有更接近于真实运行参数的优点,是区别于JTAG测试的又一种测试技术。

7 结束语

面对市场上越来越多的不同的硬件,即使是一个非常通用的bootloader也很难一网打尽。通用并不是意味着万能。在现有的技术条件和市场选择下,获得统一的嵌入式CPU体系结构几乎是不可能的,不同的嵌入式CPU面向的应用领域是不一样的,不可能设计出一款能够在所有应用场合都游刃有余的CPU为此,设计一个通用的bootloader对于嵌入式系统的开发有着极为重要的意义。虽然不可能支持所有的嵌入式CPU,但是它带来了优秀的代码结构,简洁的扩展接口,快速的开发周期,以及支持广泛的嵌入式CPU。这些优势使得它更加容易移植到其它的嵌入式CPU上面,从而进入一个良性循环。硬件细节差异隔离技术、模块化阶段化设计技术是当前广泛使用的设计技术手段,但是对这三技术的使用不是一成不变的,只有技术的不断革新及已掌握技术的交叉综合运用才能解决不断变化的问题。利用bootloader对硬件测试就是对已有技术的发展及新应用,在关于外围硬件测试的场合里是一种非常有效的手段,测试结果准确、无需仿真器支持、而且不损伤硬件设备


The Design of The General Bootloader Based On ARM

Abstract

In any embedded system application, the system architecture can be divided into three parts: Bootloader, Kernel, and Application. Bootloader works at the bottom of the architecture stack, and facilitates kernel booting, also application development. It is very important to implement a reliable bootloader. This paper will mainly focus on the general bootloader design and implement. Otherwise, based on the deeply understanding of the principle and the process of booting, the author discovers a new efficient technology for testing peripheral, which is different with the classic peripheral hardware testing method.

Key words Linux ARM Bootloader U-Boot

Bootloader 设计蓝图 和 ARM 的启动流程

Bootloader 设计蓝图 和 ARM 的启动流程

基于mini2440 的 bootloader 设计 ---- 3、ARM指令学习

开发环境:                电脑系统:RedHat Enterprise Linux6   kernel version : linux-2.6.32                ...

【嵌入式开发】 Bootloader 详解 ( 代码环境 | ARM 启动流程 | uboot 工作流程 | 架构设计)

对 BootLoader 架构 功能进行了详细的分析

【嵌入式开发】 Bootloader 详解 ( 代码环境 | ARM 启动流程 | uboot 工作流程 | 架构设计)

作者 : 韩曙亮 博客地址 : http://blog.csdn.net/shulianghan/article/details/42462795 转载请著名出处 相关资...
  • haiwil
  • haiwil
  • 2015年01月14日 23:05
  • 7262
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:基于ARM的通用bootloader的设计
举报原因:
原因补充:

(最多只允许输入30个字)