资源预览内容
第1页 / 共5页
第2页 / 共5页
第3页 / 共5页
第4页 / 共5页
第5页 / 共5页
亲,该文档总共5页全部预览完了,如果喜欢就下载吧!
资源描述
基于 ARM920T 和嵌入式 linux 的 bootloader 设计摘要:以 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 system1引言在嵌入式开发中其中不可避免的一环就是 bootloader 的设计1,它统筹软硬件资源,使得资源最优配置,嵌入式系统对功耗,性能,以及成本要求很苛刻,它要求在达到用户要求的前提下把成本和资源利用降为最低,Booloader 不是驱动开发的一部分,但一个好的 booloader 可以决定该产品在市场上的成败2。采用 Samsung 公司的 ARM920T3处理器与 Linux2.4.18 嵌入式操作系统,根据处理速度和效率的不同采用分阶段实现的方法,在具体实现时不拘泥于该处理器和操作系统版本,使之更有普遍性和通用性。2bootloader 概述引导加载程序 bootloader 是系统加电后运行的第一段代码 4,功能类似 pc 机的BIOS,在 ARM 中一般都是位于地址 0x00000000,这段代码可以实现初始化硬件设备,建立内存空间映射图,从而将系统的软硬件带到一个合适的状态,以便最终为调用操作系统内核和用户应用程序准备好正确的环境。Bootloader 的启动可以单阶段也可以多阶段,为了方便移植和增加系统的执行效率一般分为两个阶段 stage1 用汇编编写和 stage2 用 C 语言编写,stage1 主要进行与 CPU 与存储设备相关的工作进行必要的初始化工作,是一些依赖于体系结构的代码,例如初始化 CPU 运行的时钟频率,初始化 Flash 和内存的数据宽度、读/写访问周期和刷新周期,初始化中断系统,初始化系统中各种片内片外设备和 I/O 口,初始化系统各种运行模式下的寄存器和堆栈。stage2 是用 C 语言实现一般的流程以及对板级驱动的支持,包括初始化要用到用到的内核映像和文件系统映像,并将 PC 指针指向操作系统内核的入口处,为操作系统的运行作好准备。这样设计代码具有很好的移植性和可读性,对于相同的 CPU 只需修改 stage2,对于不同的 CPU 只需修改 stage1。3stage1 设计31建立二级中断向量表每当有中断或者异常发生时,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 所示:32 拷贝 Stage2 至 RAM习惯上把 stage2 拷贝到 RAM 地址的最顶部 1MB 开始的空间,RAM 的起始地址为 0x30000000。实现代码如下所示:/*计算 stage2 在 flash 中的位置,假设该映像不超过 64K,自行可修改该值*/Adr r0,_startAdd r2,r0,#(64*1024)Add r0,ro,#0x1000Ldr r1 ,BLOB_START/*开始复制 stage2 到 RAM,R0=源起始地址,R1=目的地址,r2 源结束地址*/copy_loop:ldmia r0!,r3-r10 stmia r1!, r3-r10cmp r0,r2ble copy_loopldr r0,BLOB_START /复制完跳转到 RAM 执行由此入口进入 stage2 33设置堆栈指针系统堆栈初始化取决于用户使用了哪些中断,以及系统需要处理哪些错误类型。一般情况下,管理者堆栈必须设置,如果使用了 IRQ 中断,则 IRQ 堆栈也必须设置,下面以 IRQ 堆栈为例进行设置。IRQMode 堆栈 orr r1,r0,#IRQMODE|NOINT msr cpsr_cxsf,r1; IRQMode ldr sp,IRQStack4 stage2 设计41可执行映像 stage2 的入口由于在编译和链接 Bootloader 这样的 c 程序时不能使用 glibc 库支持的函数,所以直接把 main()函数的起始地址作为第二阶段的入口点是最直接的想法。可以用汇编编写一段 trampoline(弹簧床)小程序用 CPU 跳转指令跳到 main()函数去执行,当 mian()函数返回时会再次回到 trampoline 程序,具体汇编代码如下:get read to call c functionsldr sp DW_STACK_START setup stack pointermov fp ,#0 no previous frame,so fp=0mov a2, #0 set argv to NULL bl main call mainmov pc,#FLASH_BASE otherwise,reboot如果正常不出错就不会再回到 trampoline 程序,否则就会回到最后一条语句重起系统。42 内存影射一般 s3c2410 上配置的 SDRSAM 大小为 64M,该 SDRAM 的物理地址范围是0x3000 00000x33FF FFFF(属于 Bank 6),由于 1 个 Section 的大小是 1M,所以该物理空间可以被分成 64 个物理段(页框)。由于 bootloader 没有对 MMU 的管理代码,处理器在运行时直接访问物理地址。同时,因为 ARM 体系结构中数据缓冲(Dcache)必须通过 MMU 开启,所以bootloader 效率比较低,可通过平板映射( flat,既虚拟地址和物理地址相同)方式开启 MMU,从而使用内存空间的 Dcache,提高 bootloader 的运行速度。如图 1 所示:映射关系代码如下: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_base20;Ssection_base20)| MMU_OTHER_SECDESC; 43装载内核映像和根文件系统映像像 ARM 这样的嵌入式 CPU 通常都是在统一的内存地址空间中寻址 Flash 等固态存储设备的,因此从 Flash 上读取数据与从 RAM 单元中读取数据用一个简单的循环就可以完成从 Flash 设备上拷贝映像的工作: 其中 count 为根文件系统映像的大小或内核映像的大小。While(count)*dest+=*src+;/src 为 fash 中的地址,dest 为 RAM 中的地址count-=4;44置内核的启动参数内核启动可以从 Nand Flash 或 Nor Flash 中启动运行 linux,需要修改启动命令如下:#ifdef CONFIG_S3C2410_NAND_BOOTChar Linux_cmd=“noinit root=/dev/bon/2 init =/Linuxrc console=tty0 console=ttys0”;#elseCharLinux_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 的实现从而写出符合需要的启动程序。
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号