DIY编程器网

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 683|回复: 0
打印 上一主题 下一主题

基于ARM920T和嵌入式linux的bootloader设计

[复制链接]
跳转到指定楼层
楼主
发表于 2012-1-27 19:27:47 | 只看该作者 回帖奖励 |正序浏览 |阅读模式

  
         
    Development of Bootloader Based on ARM9 and Embedded Linux System
摘要:以ARM920T和嵌入式linux为平台,并根据方便移植和通用性的要求,按依赖于cpu与否和执行效率的要求分两部分设计出嵌入式引导程序(bootloader),第一部分用汇编编写,第二部分用C语言编写。在中断处理、硬件初始化以及地址映射和最终引导linux内核等一系列关键技术上做了详细的设计并给出了一般性的方案,该设计思路对其它不同的处理器和应用系统也有很好的借鉴价值。
关键词: ARM MMU BootLoader 嵌入式系统
Abstract  Based one ARM920T and embedded linux system, according to the convenience for transplant, versatility, relies on cpu or not and executive efficiency designed bootloader as two parts. Part1 is writen by assembly language, part two is desgined by c language .In essential technology such as the booloader start, the interrupt processing,the hardware initialization as well as the address mapping and boot linux kernel and so on given detailed design and general plan.this design mentality had the very good model value to other different processors and application system.
Keywords: ARM MMU Bootloader embedded system
                             1.引言
在嵌入式开发中其中不可避免的一环就是bootloader的设计[1],它统筹软硬件资源,使得资源最优配置,嵌入式系统对功耗,性能,以及成本要求很苛刻,它要求在达到用户要求的前提下把成本和资源利用降为最低,Booloader不是驱动开发的一部分,但一个好的booloader可以决定该产品在市场上的成败[2]。
采用Samsung公司的ARM920T[3]处理器与Linux2.4.18嵌入式操作系统,根据处理速度和效率的不同采用分阶段实现的方法,在具体实现时不拘泥于该处理器和操作系统版本,使之更有普遍性和通用性。
2.bootloader概述
引导加载程序bootloader是系统加电后运行的第一段代码[4],功能类似pc机的BIOS,在ARM中一般都是位于地址0x00000000,这段代码可以实现初始化硬件设备,建立内存空间映射图,从而将系统的软硬件带到一个合适的状态,以便最终为调用操作系统内核和用户应用程序准备好正确的环境。
Bootloader的启动可以单阶段也可以多阶段,为了方便移植和增加系统的执行效率一般分为两个阶段stage1用汇编编写和stage2用C语言编写,stage1主要进行与CPU与存储设备相关的工作进行必要的初始化工作,是一些依赖于体系结构的代码,例如初始化CPU运行的时钟频率,初始化Flash和内存的数据宽度、读/写访问周期和刷新周期,初始化中断系统,初始化系统中各种片内片外设备和I/O口,初始化系统各种运行模式下的寄存器和堆栈。stage2是用C语言实现一般的流程以及对板级驱动的支持,包括初始化要用到用到的内核映像和文件系统映像,并将PC指针指向操作系统内核的入口处,为操作系统的运行作好准备。这样设计代码具有很好的移植性和可读性,对于相同的CPU只需修改stage2,对于不同的CPU只需修改stage1。
3.stage1设计
3.1.建立二级中断向量表
每当有中断或者异常发生时,ARM处理器便强制把PC指针指向向量表中对应中断类型的地址值。为了加快中断响应,在Flash的0x0地址存放能跳转到0x33ffff00地址处中断向量的跳转指令,即在RAM中建立一个二级中断向量表,起始地址为0x33ffff00,除复位外,其它异常入口地址由Flash跳转得到,部分实现代码如下
#define _ISR_STARTADDRESS   (SDRAM_END-0x100)  //0x33ffff00     
definepISR_RESET (*(unsigned *)(_ISR_STARTADDRESS+0x0))// x33ffff00
#define pISR_UNDEF    (*(unsigned *)(_ISR_STARTADDRESS+0x4))// x33ffff04
如表1所示:


500)this.style.width=500;" border=0>
3.2 拷贝Stage2至RAM
习惯上把stage2拷贝到RAM地址的最顶部1MB开始的空间,RAM的起始地址为0x30000000。实现代码如下所示:
/*计算stage2在flash中的位置,假设该映像不超过64K,自行可修改该值*/
Adr r0,_start
Add r2,r0,#(64*1024)
Add r0,ro,#0x1000
Ldr r1 ,BLOB_START
/*开始复制stage2到RAM,R0=源起始地址,R1=目的地址,r2源结束地址*/
copy_loop:
ldmia r0!,{r3-r10}
stmia r1!, {r3-r10}
cmp r0,r2
ble copy_loop
ldr r0,BLOB_START //复制完跳转到RAM执行由此入口进入stage2   
3.3.设置堆栈指针
系统堆栈初始化取决于用户使用了哪些中断,以及系统需要处理哪些错误类型。一般情况下,管理者堆栈必须设置,如果使用了IRQ中断,则IRQ堆栈也必须设置,下面以IRQ堆栈为例进行设置。
IRQMode 堆栈
orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1; IRQMode
ldr sp,IRQStack
4. stage2设计
4.1.可执行映像stage2的入口
由于在编译和链接Bootloader这样的c程序时不能使用glibc库支持的函数,所以直接把main()函数的起始地址作为第二阶段的入口点是最直接的想法。可以用汇编编写一段trampoline(弹簧床)小程序用CPU跳转指令跳到main()函数去执行,当mian()函数返回时会再次回到trampoline程序,具体汇编代码如下:
@get read to call c functions
ldr sp DW_STACK_START  @ setup stack pointer
mov fp ,#0               @ no previous frame,so fp=0
mov a2, #0               @set argv to NULL
bl  main                @call main
mov pc,#FLASH_BASE    @otherwise,reboot
如果正常不出错就不会再回到trampoline程序,否则就会回到最后一条语句重起系统。
4.2 内存影射
一般s3c2410上配置的SDRSAM大小为64M,该SDRAM的物理地址范围是0x3000 0000"0x33FF FFFF(属于Bank 6),由于1个Section的大小是1M,所以该物理空间可以被分成64个物理段(页框)。
由于bootloader没有对MMU的管理代码,处理器在运行时直接访问物理地址。同时,因为ARM体系结构中数据缓冲(Dcache)必须通过MMU开启,所以bootloader效率比较低,可通过平板映射(flat,既虚拟地址和物理地址相同)方式开启MMU,从而使用内存空间的Dcache,提高bootloader的运行速度。
如图1所示:
      



500)this.style.width=500;" border=0>
映射关系代码如下:
void mem_mapping_linear(void)
{   unsigned long descriptor_index, section_base, sdram_base, sdram_size;
     sdram_base=0x30000000;
sdram_size=0x 4000000;
for(section_base=sdram_base,descriptor_index=section_base>>20;Ssection_base>20)| MMU_OTHER_SECDESC;}
}
4.3.装载内核映像和根文件系统映像
像ARM这样的嵌入式CPU通常都是在统一的内存地址空间中寻址 Flash 等固态存储设备的,因此从Flash上读取数据与从 RAM单元中读取数据用一个简单的循环就可以完成从Flash 设备上拷贝映像的工作:
其中count为根文件系统映像的大小或内核映像的大小。
While(count){
*dest++=*src++;//src为fash中的地址,dest为RAM中的地址
count-=4;}
4.4.置内核的启动参数
内核启动可以从Nand Flash或Nor Flash中启动运行linux,需要修改启动命令如下:
#ifdef CONFIG_S3C2410_NAND_BOOT
Char Linux_cmd[]=“noinit root=/dev/bon/2 init =/Linuxrc console=tty0 console=ttys0”;
#else
CharLinux_cmd[]=“CharLinux_cmd[]=”noinit root=/dev/bon/3 init =/Linuxrc console=tty0 console=ttys0”;
其中noinitrd不使用ramdisk。
root根文件系统所在Mtd分区。
Init内核运行入口命令文件。
console 内核信息控制台,ttyS0表示串行口0。
ttys0表示虚拟终端LCD启动参数一般都包括root、init和console。
5.结论
设计bootloader是一项很复杂的工作,需要对硬件资源和所用的操作系统有很深的理解,在实际开发中可以根据需要简化设计,去除不必要的系统功能,这样可以大大提高程序执行的效率和稳定性。
本文作者创新点:bootloader随硬件不同设计也尽相同,但本质的原理是一样的,本文给出了一种层次分明设计简练较之通用的设计方法,使嵌入式工作者可以快速的了解bootloader的实现从而写出符合需要的启动程序。
参考文献
[1] 万永波 张根宝 田泽 杨峰,基于ARM的嵌入式系统Bootloader启动流程分析, 微计算机信息, 2005年,第21卷11-2期,90页.
[2] 嵌入式linux设计与应用.邹思轶. 北京:清华大学出版社 2002.
[3] SUMSUANG ELECtrONICS. S3C2410X User’s Manual[Z].Republic of Korea: Sumsang,2003.
[4] 马学文, 朱明日, 程小辉.嵌入式系统中 Bootloader的设计与实现.计算机工程,2005年,第31卷7期,96页.
作者简介:罗磊,男,(1980-),汉,硕士研究生,主要研究方向:嵌入式系统及其应用,机器人控制。
戴学丰,男,(1962-),汉,教授,控制理论与控制工程博士后,研究方向为机器人智能控制。
刘树东,男,(1965-),汉,教授,通讯与信息系统专业博士,研究方向为通讯系统仿真与机器人。
作者详细联系方式:
作者:罗磊
通讯地址:黑龙江省齐齐哈尔市齐齐哈尔大学计控学院  
邮编:161006
[1]
         
          [/td]
        [/tr]
      
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|文字版|手机版|DIY编程器网 ( 桂ICP备14005565号-1 )

GMT+8, 2025-8-14 14:56 , 耗时 0.080325 秒, 19 个查询请求 , Gzip 开启.

各位嘉宾言论仅代表个人观点,非属DIY编程器网立场。

桂公网安备 45031202000115号

DIY编程器群(超员):41210778 DIY编程器

DIY编程器群1(满员):3044634 DIY编程器1

diy编程器群2:551025008 diy编程器群2

QQ:28000622;Email:libyoufer@sina.com

本站由桂林市临桂区技兴电子商务经营部独家赞助。旨在技术交流,请自觉遵守国家法律法规,一旦发现将做封号删号处理。

快速回复 返回顶部 返回列表