前言
Bootloader是系统加电运行的第一段软件代码。在嵌入式系统[2]中,通常并没有像BIOS那样的固件程序,因此整个系统的加载启动任务就完全由Bootloader来完成。Bootloader是底层硬件和上层应用软件之间的一个中间件软件。它创建内核需要的一些信息并将这些信息通过相关机制传递给内核,从而将系统的软硬件环境带到一个合适的状态。同时还提供基本输入、输出系统监控程序功能,还可具有一定的调试功能。
随着大规模集成电路的发展和现在工艺的进步,片上系统SoC逐渐成为主流的芯片设计形态。龙芯税控 SoC系统软件框架包括以下几个主要部分:工具链、模拟调试环境、仿真环境、Bootloader、操作系统以及应用程序。本文介绍了龙芯税控SoC软件中Bootloader的设计。
开发环境
Godson-1处理器
Godson-1是由中科院计算所研制出的一款兼顾通用和嵌入式应用需求的微处理器,是第一款我国自主研发的通用微处理器。龙芯一号实现了MIPS III指令系统的32位模式,支持4GB内存寻址,主频工作在200MHz-266MHz,芯片内部16KB的缓存,使用PQFP封装技术。目前,北京龙芯集成电路设计公司推出的网络计算机以及一系列的解决方案就是基于这款处理器的。
uCOS-II
uCOS-II是一款免费公开源代码、结构小巧、具有可剥夺实时内核的实时操作系统。uCOS-II 的前身是uCOS,是专门为计算机的嵌入式应用设计的,绝大部分代码是用C语言编写的。用户只要有标准的ANSI 的C交叉编译器,有汇编器、连接器等软件工具,就可以将uCOS-II嵌人到开发的产品中。
uCOS -II具有执行效率高、占用空间小、实时性能优良和可扩展性强等特点, 最小内核可编译至 2KB 。uCOS-II 已经移植到了几乎所有知名的CPU 上。但由于uCOS-II良好的可扩展性和源码开放,这些非必须的功能完全可以由用户自己根据需要分别实现。uCOS-II目标是实现一个基于优先级调度的抢占式的实时内核,并在这个内核之上提供最基本的系统服务,如信号量、邮箱、消息队列、内存管理、中断管理等。目前,uCOS-II已被广泛的应用于照相机,医疗器械,音响设备,发动机控制,高速公路电话系统,自动提款机等产品中。
嵌入式平台很少能给开发者提供完整的工具链,大部分软件设计工作在其他宿主机器上完成,常用的工具链是与gcc相关的编译工具。笔者所开发的Bootloader就是应用了gcc的编译工具编译和调试的。
Bootloader的设计分析
Bootloader的操作模式
大多数Bootloader都包含两种不同的操作模式:
(1)启动加载(Boot loading)模式:也称为“自主”模式。即Bootloader从目标机上的某个固态存储设备上将操作系统加载到RAM 中运行,整个过程并没有用户的介入。
(2)下载(Downloading)模式:在这种模式下,目标机上的Bootloader将通过串口或网络连接等通信手段从主机下载内核映像和根文件系统映像等。然后保存到目标机上的FLASH类固态存储设备中。
Bootloader 的这种模式通常在系统初次安装和更新时被使用,工作于这种模式下的Bootloader通常都会向它的终端用户提供一个简单的命令行接口。在我们的 Bootloader设计中我们同时支持这两种工作模式,采用的方法是:一开始启动时处于正常的启动加载模式,但并不立即启动进入uCOS-II内核.而是提示延时5秒,等待终端用户如果按下某一特定按键,则切换到下载模式,否则继续启动uCOS-II内核。
Bootloader的启动及初始化
龙芯税控SoC的硬件模块是可配置的。Bootloader分为stage 1和stage2两大部分。依赖于CPU体系结构的代码,通常都放在stage1中,而且在这一部分,我们直接对处理器内核和硬件控制器进行编程,这部分用MIPS汇编来实现。而stage2则用C语言来实现,这样可以实现更复杂的功能,而且代码会具有更好的可读性和可移植性。
Bootloader的stage 1
这部分代码必须首先完成一些基本的硬件初始化,为stage2的执行以及随后的kernel的执行准备好一些基本的硬件环境。Bootloader的 stage1的内容包括:定义程序人口点;设置异常向量表;初始化存储系统(包括地址重映射);初始化有特殊要求的端口,设备;初始化用户程序的执行环境;初始化堆栈指针寄存器,必要时改变处理器的模式;设置FIQ/IRQ中断处理程序人口;进入C程序。
在整个Bootloader的初始化过程中都不必响应中断,因此首先禁止系统的中断,然后程序设置CPU的速度和时钟频率,设置CPU内部指令数据cache,DRAM初始化,DRAM 初始化完成后即可拷贝ROM中的代码到DRAM中,然后内存重映射,程序开始进入DRAM中执行,然后再初始化一些用户有特殊要求的端口、设备,比如 LCD或串口等,可以通过点亮LCD,或者向串口打印一些调试信息,以此表明系统的状态是正常还是出错。然后准备进入C语言代码:拷贝 Bootloader的RW/RO段到相应的运行位置,初始化zI段,初始化系统堆栈,设置FIQ/IRQ中断处理程序人口,设置完成就可以进入到C代码了。
Bootloader的stage2
为了让程序跳人C语言的“start_bios”函数。我们采用直接将pc指针指向“start_bios”函数的方法,实现代码如下:
la a0, start_bios #把pc指针指向
函数入口,然后跳转
jr a0
nop
进入start_bios函数后即可以开始本阶段stage2的初始化任务,这包括:
(1)初始化至少一个串口,以便和终端用户进行交互;
(2)初始化计时器,延时并提示启动模式的选择,如果进入启动加载模式,则系统控制权交给uCOS-II操作系统,Bootloader任务完成,否则程序继续向下执行;
(3)初始化网络,包括网络基本信息配置等;
(5)初始化系统配备的其他外设;
(6)初始化Flash:检测是否支持该Flash芯片(可通过比较Flash ID的方式实现);
(7)初始化中断,包括屏蔽中断,清除中断悬挂标志,初始化中断向量表,注册需要的中断处理函数等;
(8)初始化命令控制台,等待用户键人命令。设备初始化完成后,可以通过串口输出一些打印信息,如程序名字字符串、版本号等。[page]
Bootloader的启动过程[3]如图1所示。
图1 Bootloader启动过程
关键技术—异常及中断处理
龙芯1支持32种例外模式,而其中又尤以外部中断模式(IRQ)应用较为广泛,其异常处理过程也较为复杂。本文下面将以IRQ异常处理为例,说明一个通用的中断使用及处理过程。Godson-1处理器通用的中断处理过程大致可以分为以下3步:
(1)异常响应:获取异常处理程序人口地址,并进入异常处理程序;
(2)现场保护及恢复:即进人中断服务程序(ISR)前后中断现场的保护和恢复;
(3)中断服务:计算中断源索引号,清中断,然后进入中断服务。
本例中IRQ异常处理相关代码如下:do_IRQ():
sub sp,sp,#4 ; #预留一个字的空间
用来保存PC的跳转地址
sb a0,(sp) ; #保存下面中断处理中
使用到的a0寄存器
la a0,ExceptHandler ;#将保存有异常
处理函数人口的地址读入a0
la a0,(a0); #将异常处理函数人口
读入a0
sw a0,4(sp); #将异常处理函数人口存
人堆栈中刚才预留的空间
jar a0 #跳入异常处理函数
SAVE_ALL #宏,用于保存例外现场
CLI # 关中断
中断响应入口:
mfc0 t0,CP0_CAUSE #获得要处理
的中断向量
mfc0 t1,CP0_STATUS # 获得被激
活的中断
and t0,t1 # 分离被允许的中断
andi t0,0xff00 # 获取中断号
beqz t0, 3f # 判断外部是否产生
突发中断
andi a0, t0, CAUSEF_IP7
beq a0, zero, 1f
move a0, sp
jal ite_timer_interrupt # 处理时间中断
RET_FROM_IRQ #宏, 中断返回
1: andi a0, t0, CAUSEF_IP2 # 该平台
北桥只支持一个中断源
beq a0, zero, 3f
move a0,sp
jal it8172_hw0_irqdispatch # 跳入北桥中
断处理程序
CLI
RET_FROM_IRQ
3: move a0, sp
jal mips_spurious_interrupt #处理突发中断
nop
RET_FROM_IRQ # 中断返回北桥
中断处理程序:
void it8172_hw0_irqdispatch(struct pt_regs *regs)
if (intstatus & 0x4)
{
/*PCI中断*/
}
else if (intstatus & 0x1)
{
/* 内部总线终端 */
}
Else if(intstatus & 0x2)
{
/* LPC总线中断 */
}
Irq+= IT8172_LPC_IRQ_BASE; /*计算中
断号*/
do_IRQ(irq, regs); /*北桥中断处理*/
}
从上面的代码可以得出,接收到IRQ中断请求后程序的执行流程是:
(1)读取CPU CP0协处理器的Cause和Status寄存器,跳入对应的中断处理程序;
(2)计算来自外部中断的中断向量号;
(3)进入中断处理do_IRQ()
(4)由do_IRQ()最后进入中断服务程序,RET_FROM_IRQ完成中断处理任务后返回。
结语
Bootloader与具体的硬件环境和操作系统是紧密联系在一起,针对某个CPU芯片编写Bootloader代码,首先要了解该CPU的内核结构、指令系统,其次是具体芯片的结构和各种片上资源,以及所采用的操作系统。本文给出的 Bootloader代码已经在龙芯税控SoC中上运行并测试通过。该Bootloader能够正常引导及更新uCOS-II内核,系统运行稳定,完全实现了设计目的,达到了嵌入式系统的设计要求。
参考文献:
1. 中国科学院计算技术研究所CPU研制组,Godson-1微处理器用户手册(版本1.0),2002.9.10
2. 詹荣开:嵌入式系统Bootloader技术内幕
3. 郑爱玲,张宏峰,孙荷琨:嵌入式系统的内核载入过程浅析,微型机与应用,200l,(I1),59—60
上一篇:高效率嵌入式程序开发
下一篇:μC/OS—II的嵌入式串口通信模块设计
推荐阅读最新更新时间:2024-03-16 13:00