板级支持包(BSP)
BSP是板级支持包(Board Support Package)的缩写,是通常用在嵌入行业中的一个术语,用来代表在一个特殊硬件平台上快速构建一个嵌入操作系统所需的原始资料或者二进制软件包。BSP的作用是支持操作系统,使之能够更好的运行于硬件平台。BSP是相对于操作系统而言的,不同的操作系统对应于不同定义形式的BSP,包括Windows CE、Linux、Vxworks等。SoC/CPU厂商应向其芯片的用户提供一个基本的BSP包,以支持主板厂商或整机制造厂商在此基础上定制和开发各种商用终端产品。
在嵌入式系统学习过程中设计到了Bootloader,下面讲述了Bootloader的基本作用,在后续的文章中我将对如何编写自己的Bootloader进行介绍。
1. Bootloader的基本概念:
简单地说,bootloader就是在操作系统内核运行前运行地一段小程序。通过这段小程序,可以对硬件设备,如CPU、SDRAM、Flash、串口等进行初始化,也可以下载文件到系统板、对Flash进行擦除和编程,真正起到引导和加载内核镜像的作用,但是随着嵌入式系统的发展,bootloader已经逐渐在基本功能的基础上,进行了扩展,bootloader可以更多地增加对具体系统的板级支持,即增加一些硬件模块功能上的使用支持,以方便开发人员进行开发和调试。从这个层面上看,功能扩展后bootloader可以虚拟地看成是一个微小的系统级的代码包。
bootloader是依赖于硬件而实现的,特别是在嵌入式系统中。不同的体系结构需求的bootloader是不同的;除了体系结构,bootloader还依赖于具体的嵌入式板级设备的配置。也就是说,对于两块不同的嵌入式板而言,即使它们基于相同的CPU构建,运行在其中一块电路板上的bootloader,未必能够运行在另一块电路开发板上。
BootLoader最为系统复位或上电后首先运行的代码,一般应写在起始物理地址0x0开始。Bootloader的启动过程可以是单阶段的,也可以是多阶段的。通常多阶段的bootloader能提供更为复杂的功能,以及更好的可移植性。从固态存储设备上启动的bootloader大多数是二阶段的启动过程,也即启动过程可以分为stage 1和stage 2两部分。
2. ARM Bootloader的一般作用
对于一个ARM系统来说,本质上,bootloader作为引导与加载内核镜像的“工具”,在实现上,必须提供以下几个功能,更确切地说,必须做到以下几点:
(1) 初始化RAM(必需):bootloader必须能够初始化RAM,因为将来系统要通过它保存一些Volatile数据,但具体地实现要依赖与具体的CPU以及硬件系统。
(2) 初始化串口(可选,推荐):bootloader应该要初始化以及使能至少一个串口,通过它与控制台联系进行一些debug的工作;甚至与PC通信。
(3 n启动内核镜像(必需):根据内核镜像保存的存储介质不同,可以有两种启动方式:FALSH启动以及RAM启动;但是无论是哪种启动方式,下面的系统状态必须得到满足:
l CPU寄存器的设置: R0=0;
R1=机器类型;
R2=启动参数标记列表在RAM中的起始地址;
这三个寄存器的设置是在最后启动内核时通过启动参数来传递完成的。
l CPU模式: 关闭中断;
属于SVC模式;
Bootloader中没有必要支持中断的实现,这属于内核机制以及设备驱动管理的管理范畴;SVC模式是系统的一种保护模式,这样就可以进行一些只能在SVC模式下的操作,例如一些特定寄存器访问操作。
l Cache和MMU的设置: MMU必须关闭;
数据cache必须关闭;
指令cache可以关闭也可以开启;
Bootloader中所有对地址的操作都是使用物理地址,是实在的实地址,不存在虚拟地址,因此MMU必须关闭。Bootloader主要是装载内核镜像,镜像数据必须真实写回SDRAM中,所以数据cache必须关闭;而对于指令cache,不存在强制性的规定,但是一般情况下,推荐关闭指令cache。
Bootloader启动内核镜像的方法是通过跳转语句直接跳转至内核镜像的第一句指令语句。
Bootloader存在的必要性
Bootloader的功能决定了在引导Linux系统时,必须使用bootloader,除非你对linux内核进行了修改。
Bootloader有两个主要功能:
1.在发布模式,自动引导linux系统,为系统初始化各种参数。
2.在调试模式,要能够方便的下载内核,引导内核。
Linux系统一定要bootloader支持吗?
答:是的。通用的Linux内核,启动时需要很多参数,这些参数必须通过bootloader传递。而且内核一般是压缩存放到外存上的,从外存到内存的拷贝也是由bootloader完成。
Bootloader为什么不和kernel放到一起呢?
答:不可以这样做。从bootloader的第二个功能就知道,bootloader是不能和内核放到一起。当然,在发布模式时,是可以集成到一起的,通常没必要。
从哪里可以得到bootloader?
答:目前通用的bootloader很多,不论是嵌入式还是桌面系统,比如lilo,grub,blob等。桌面用的bootloader我们就不讨论了,重点说一下嵌入式领域用的bootloader。采用通用的bootloader功能强大,开发容易,而且由专人维护升级,不过多是针对特定的CPU或者特定开发板的。如果是学习,推荐自己开发bootloader。
如何编写自己的bootloader?
答:编写一个bootloader只要能够完成前面提到的两个功能就可以了。分别描述一下这两个功能的实现:
1.该功能比较简单,就是从FLASH中拷贝数据到RAM。如果内核的存放不是基于文件系统的,直接采用汇编就可以完成块拷贝。然而如果内核存放在文件系统之上,比如内核存放到了基于ext2文件系统的CF卡上。首先我们的bootloader要能够访问CF卡,然后要能够识别文件系统,只有这样才能正确找到内核文件并拷贝到内存中。
2.该功能一般通过串口实现。对于ARM来说,驱动串口比较容易,直接从主机的串口接收内核数据存放到RAM中,就可以启动内核了。如果需要发布,还要实现把内核从RAM烧写到外存的能力。
为了提高速度,充分挖掘开发板和CPU的潜力,出现了许多用网口和USB接口下载内核的bootloader。使用网口,bootloader必须提供网卡驱动和TCP/IP协议的支持。使用USB接口,需要提高大容量存储类驱动。
为了拓展思路,你也可以使用红外,存储卡接口进行数据下载。使用红外接口,和串口基本一样,无非就是没有了连线。使用存储卡,通常需要文件系统的支持。比如,我们使用SD卡存放内核,在主机交叉编译好内核后,把内核存放到SD卡上。然后将XD卡插到目标板的插槽中,bootloader必须有能力把SD卡上的内核拷贝的RAM中,过程参考功能1的实现。 |