嵌入式课程设计报告完整版

  • 格式:doc
  • 大小:77.00 KB
  • 文档页数:11

第 1 页 共 11 页 目录

前言 .............................................................................................. 2

一、U-Boot分析 ........................................................................ 3

1、引导程序U-Boot第一阶段分析 ................................... 3

2、引导过程 .......................................................................... 4

3、程序流程图 ...................................................................... 8

二、程序设计 ............................................................................. 8

三、心得体会 ............................................................................. 9

第 2 页 共 11 页

前言

ARM嵌入式处理器已被广泛应用于消费电子厂品、无线通信、网络通信和工业控制等领域。在嵌入式操作系统中,Linux、Vxworks、WinCE三足鼎立,其中Linux由于其开源性、稳定性、安全性、可裁剪性更是一支独秀。在嵌入式系统中,如何实现在ARM平台下Linux操作系统的引导工作是嵌入式技术开发的重要环节。BootLoader就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。在嵌入式系统中,通常并没有像BIOS那样的固件程序(注,有的嵌入式CPU也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由BootLoader来完成。比如在一个基于ARM7TDMI core的嵌入式系统中,系统在上电或复位时通常都从地址0x00000000处开始执行,而在这个地址处安排的通常就是系统的BootLoader程序。

第 3 页 共 11 页 一、U-Boot分析

嵌入式Linux系统中常用的Bootloader引导程序有U-Boot,redboot, blob和vivii等,其中U-Boot遵循GPL条款的开放源码项目,功能最为强大,U-Boot对PowerPC系列处理器支持最丰富,同时还支持MIPS,x86,ARM,XScale等诸多常用系列的处理器;U-Boot引导程序分为Stage1和Stage2量大部分,Stage1中主要包括设备初始化、中断设置、时间设置和储存器初始化等工作,并且采用汇编语言实现,而一些通用功能大多采用C语言实现,放在Stage2中。

1、引导程序U-Boot第一阶段分析

Stage1的代码在CPU/arm920t/start.s中定义,它包括从系统上电后在0x00000000地址开始执行的部分。这部分代码系统启动后,从NADA FLASH自动加载到SDRAM中,它包括S3C2410A中寄存器的初始化和将U-Boot的Stage2代码从FLASH拷贝到SDRAM。Stage2的起始地址是在Stage1代码中指定的,被复制到SDRAM后,就从第一阶段跳到这个入口地址,开始执行剩余部分代码;其系统工作图如下:

第 4 页 共 11 页

2、引导过程

U-Boot启动内核的过程可以分成为两个阶段,但在本次课程设计中我们只对其的第一个阶段代码进行分析。第一阶段的功能主要包括硬件设备初始化,加载U-Boot第二阶段代码到RAM空间,设置好栈,跳转到第二阶段代码入口。第一阶段对应的文件是cpu/arm920t/start.S和board/samsung/mini2440

/lowlevel_init.S,当系统上电后第一个链接的是cpu/arm920t/start.o,进而执行其代码。

1) 设置异常向量,从而保证系统上电后出现异常时,CPU根据异常号在异常向量表中找到对应的异常向量,然后执行异常向量处的跳转指令,CPU就跳转到对应的异常处理程序执行;

2) 设置CPU模式为SVC模式并将中断禁止位和快中断禁止位置一,从而屏硬件设备初始化

复制U-Boot第二阶段代码到ARM空间

设置堆栈指针

清空BSS段

跳转到第二阶段入口 系统上电

第 5 页 共 11 页 蔽了IRQ和FIQ中断;

mrs r0,cpsr

bic r0,r0,#0x1f

orr r0,r0,#0xd3

msr cpsr,r0

3) 设置控制寄存器地址

#if defined(CONFIG_S3C2410A)

# define pWTCON 0x15300000

# define INTMSK 0x14400008 /* Interupt-Controller base addresses */

# define CLKDIVN 0x14800014 /* clock divisor register */

#elif defined(CONFIG_S3C2410A)

# define pWTCON 0x53000000

# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */

# define INTSUBMSK 0x4A00001C

# define CLKDIVN 0x4C000014 /* clock divisor register */

#endif

4) 设置关闭看门狗:

LDR R0, =Pwtcon

MOV R1,#0x0

STR R1, [R0]

以上代码向看门狗控制寄存器写入0,关闭看门狗。否则在U-Boot启动过程中,CPU将不断重启。

5) 设置主中断屏蔽寄存器,禁止所以中断,INTMSK是主中断屏蔽寄存器,每一位对应SRCPND(中断源引脚寄存器)中的一位,表明SRCPND相应位代表的中断请求是否被CPU所处理。

mov r1, #0xffffffff

ldr r0, =INTMSK

str r1, [r0] //关闭所有

6)设置MPLLCON,UPLLCON, CLKDIVN ,CPU上电几毫秒后,晶振输出稳定,FCLK=Fin(晶振频率),CPU开始执行指令。但实际上,FCLK可以高于Fin,为了提高系统时钟,需要用软件来启用PLL。这就需要设置CLKDIVN,MPLLCON,UPLLCON这3个寄存器。

#if defined(CONFIG_S3C2410A) || defined(CONFIG_S3C2410)

ldr r0, =pWTCON

mov r1, #0x0

str r1, [r0] //关闭watchdog

mov r1, #0xffffffff

ldr r0, =INTMSK

str r1, [r0] //关闭所有的中断

# if defined(CONFIG_S3C2410A)

ldr r1, =0x3ff

ldr r0, =INTSUBMSK

str r1, [r0] //关闭所有的中断

第 6 页 共 11 页 # endif

/* FCLK:HCLK:PCLK = 1:2:4 */

/* default FCLK is 120 MHz ! */

//设置HCLK为FCLK/2, PCLK为FCLK/4, FCLK为CPU产生clock,HCLK为AHB总线上的设备产生//clock, PCLK为APB总线上的设备产生clock,

7)初始化RAM控制寄存器,在程序代码中lowlevel_init是来完成内存初始化的工作,由于内存初始化是依赖于开发板的,因此lowlevel_init的代码一般放在board下面相应的目录中(lowlevel_init在board/samsung/mini2440/lowlevel_init.S中定义)。U-Boot在NAND Flash启动时,lowlevel_init.o将自动被读取到CPU内部4KB的内部RAM中。因此第137~146行的代码将从CPU内部RAM中复制寄存器的值到相应的寄存器中。对于U-Boot在NOR Flash启动的情况,由于U-Boot连接时确定的地址是U-Boot在内存中的地址,而此时U-Boot还在NOR

Flash中,因此还需要在NOR Flash中读取数据到RAM中。由于NOR Flash的开始地址是0,而U-Boot的加载到内存的起始地址是TEXT_BASE,SMRDATA标号在Flash的地址就是SMRDATA-TEXT_BASE。综上所述,lowlevel_init的作用就是将SMRDATA开始的13个值复制给开始地址[BWSCON]的13个寄存器,从而完成了存储控制器的设置。

8)复制U-Boot第二阶段代码到RAM,由于cpu/arm920t/start.S原来的代码是只支持从NOR Flash启动的,所以要修改现在U-Boot的NOR Flash和NAND Flash上就能启动了。而U-Boot的启动可能是在NAND Flash启动或NOR Flash启动,所以在启动程序中要专门一段程序来对启动方式进行判定。无论是从NOR Flash还是从NAND Flash启动,地址0处为U-Boot的第一条指令“ b start_code”,对于从NAND Flash启动的情况,其开始4KB的代码会被自动复制到CPU内部4K内存中,因此可以通过直接赋值的方法来修改;对于从NOR Flash启动的情况,NOR Flash的开始地址即为0,必须通过一定的命令序列才能向NOR Flash中写数据,所以可以根据这点差别来分辨是从NAND Flash还是NOR Flash启动:向地址0写入一个数据,然后读出来,如果发现写入失败的就是NOR Flash,否则就是NAND Flash。

9)设置堆栈

stack_setup:

ldr r0, _TEXT_BASE

sub r0, r0, #CFG_MALLOC_LEN

sub r0, r0, #CFG_GBL_DATA_SIZE

#ifdef CONFIG_USE_IRQ

sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

#endif

sub sp, r0, #12

只要将sp指针指向一段没有被使用的内存就完成栈的设置了。根据上面的代码可以知道U-Boot内存使用情况了,如下图所示: