微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 基于ARM的嵌入式BootLoader设计与启动过程

基于ARM的嵌入式BootLoader设计与启动过程

时间:05-21 来源:互联网 点击:

f, NOINT = 0x80

msr cpsr_cxsf,r1 ;转到IRQ模式

ldr sp,=IRQStack ;设置SP_irq

orr r1,r0,#FIQMODE

msr cpsr_cxsf,r1 ;转到FIQ模式

ldr sp,=FIQStack

3.4 C例程全局变量初始化

全局变量的初始化,就是完成从ROM到RAM的数据传输和内容清零。可执行程序的映像结构由RO段、RW段和ZI段三部分组成,分别为只读数据段、可写数据段和堆栈段。其中RO段在Flash和RAM里都可运行;而RW和ZI段是必须转移到RAM中去的。尽管RAM的运行速度比Flash快的多,但由于RO段比较小,拷贝到RAM也需要时间,还要程序跳转,一比较两者的启动时间差不多,最终我们选择让RO段在Flash中运行。

开发工具中的链接器(Linker)提供了一定的机制来帮助我们完成这部分工作,其中|Image$$ZI$$Base|,|Image$$ZI$$Limit|,|Image$$RW$$Base|,|Image$$RO$$Limit| 是由链接器定义输出的。主要是输出段的起始和终止定位信息,具体程序实现如下:

startram : LDR a1,=|Image$$ZI$$Base| ;ZI段在RAM里面的起始地址

MOV a3,#0 ;寄存器清0

LDR a2,=|Image$$ZI$$Limit| ;ZI段在RAM里面的结束地址

CMP a1,a2

BEQ move_data

clear_loop : STR a3,[a1],#4 ;清一个字为0, a1 += 4

CMP a1,a2

BNE clear_loop

move_data LDR a1,=|Image$$RW$$Base| ;RW段在RAM中的起始地址

LDR a2,=|Image$$RO$$Limit| ;RW段在ROM中的起始地址

LDR a3,=|Image$$ZI$$Base| ;RW段在RAM中的结束地址

CMP a1,a3

BEQ goto_main

move_loop : LDR a4,[a2],#4

STR a4,[a1],#4 ;拷贝一个字,a1 += 4, a2 += 4

CMP a1,a3

BNE move_loop

goto_main : BL Main

3.5 呼叫主程序

当系统初始化完成后,就要转入主程序,可由跳转指令来完成。这部分代码为C程序,主要负责uCLinux内核拷贝、 Ramdisk文件系统加载、设置启动参数和串口通信等功能.程序最终完成内核压缩文件和Ramdisk到RAM的拷贝,后跳转到RAM中Linux Kernel的首地址,并交出控制权,到此Bootloader的任务完成。其中uCLinux在RAM中的空间分配为0x0c000000

-0x0c008000(uCLinux内核调度用),0x0c008000-0x0c300000(uCLinux Kernel),0x0c300000

-0x0c800000(uCLinux Ramdisk)。以下程序为uCLinux内核和Ramdisk文件系统拷贝过程,FLASH_UC_KERNEL,FLASH_UC_RAMDISK分别为内核和文件系统在Flash的起始地址,RAM_UC

_ZIMAGE,RAM_UC_RAMDISK分别为RAM中uCLinux内核和文件系统的起始地址,FLASH_LEN_UC_

KERNEL,FLASH_LEN_UC_RAMDISK分别为两者大小,拷贝完后,PC指针指向RAM_UC_ZIMAGE。程序主要部分如下:

/* Copy uClinux Kernel */

pSource = (unsigned int *)FLASH_UC_KERNEL;

pDest = (unsigned int *)RAM_UC_ZIMAGE;

for (loopcnt = 0;loopcnt (FLASH_LEN_UC_KERNEL>>2);loopcnt++)

{ *pDest++ = *pSource ++; }

/* Copy ramdisk */

pSource = (unsigned int *)FLASH_UC_RAMDISK;

pDest = (unsigned int *)RAM_UC_RAMDISK;

for (loopcnt = 0;loopcnt (FLASH_LEN_UC_RAMDISK>>2); loopcnt++)

{ *pDest++ = *pSource ++; }

/* Start Kernel */

fp = (UClinux_Entry)RAM_UC_ZIMAGE;

(*fp)(0);

4 uCLinux操作系统启动过程

本系统采用RAM中启动方式,将Flash中的内核先拷贝到RAM的某一段地址区间,再从该区间的首地址运行 uCLinux内核。当Bootloader完成系统初始化和拷贝完内核和Ramdisk以后,交出控制权,系统开始从RAM中执行uCLinux内核的引导程序Head.s,并将控制权交给它。在uCLinux中,Head.s在uCLinux-dist/linux-2.4.x/arch /armnommu/boot/compressed/head.s

里。Head.s非常关键,它完成了加载内核的大部分工作,主要是调用Misc.c中的解压内核函数 (decompress_kernel)来完成,另外内核的加载还必须知道系统必要的硬件信息,该硬件信息在hardware.h中并被Head.s所引用。最后跳转到调用内核函数(call_kernel),将控制权交给解压后的uCLinux系统[4]。系统启动后将加载Ramdisk文件系统,进入用户shell程序。
5 结束语

本系统采用Bootloader完成操作系统内核和文件系统拷贝到RAM的设计方法,提高了系统的实时性。目前,启动代码已经正常引导uCLinux操作系统,并实现了对轮式移动机器人驱动系统的控制,该嵌入式系统运行稳定,完全实现了设计目的。由于所选处理器的关系,本文的Bootloader是不支持Remap芯片的,但启动装载程序的原理都一样,只要稍作修改就可用于支持Remap和MMU的芯片,而且对于其他操作系统同样适用。

参考文献

1 严国清

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top