分享
 
 
 

用U-BOOT构建嵌入式系统的引导装载程序

王朝other·作者佚名  2006-03-10
窄屏简体版  字體: |||超大  

1 U-BOOT简介

U-BOOT是由德国的工程师Wolfgang Denk从8XXROM代码发展而来的,它支持很多处理器,比如PowerPC、ARM、MIPS和x86。目前,U-BOOT源代码在sourceforge网站的社区服务器中,Internet上有一群自由开发人员对其进行维护和开发,它的项目主页是http://sourceforge.net/projects/U-BOOT。U-BOOT的最新版本源代码可以在Sourceforge的CVS服务器中匿名获得。

#cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/U-BOOT login

#cvs -z6 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/U-BOOT \ co -P modulename

1.1 U-BOOT源代码目录结构

◆ board:和一些已有开发板有关的文件,比如Makefile和u-boot.lds等都和具体开发板的硬件和地址分配有关。

◆ common:与体系结构无关的文件,实现各种命令的C文件。

◆ cpu:CPU相关文件,其中的子目录都是以U-BOOT所支持的CPU为名,比如有子目录arm926ejs、mips、mpc8260和nios等,每个特定的子目录中都包括cpu.c和interrupt.c,start.S。其中cpu.c初始化CPU、设置指令Cache和数据Cache等;interrupt.c设置系统的各种中断和异常,比如快速中断、开关中断、时钟中断、软件中断、预取中止和未定义指令等;start.S是U-BOOT启动时执行的第一个文件,它主要是设置系统堆栈和工作方式,为进入C程序奠定基础。

◆ disk:disk驱动的分区处理代码。

◆ doc:文档。

◆ drivers:通用设备驱动程序,比如各种网卡、支持CFI的Flash、串口和USB总线等。

◆fs:支持文件系统的文件,U-BOOT现在支持cramfs、fat、fdos、jffs2和registerfs。

◆ include:头文件,还有对各种硬件平台支持的汇编文件,系统的配置文件和对文件系统支持的文件。

◆ net:与网络有关的代码,BOOTP协议、TFTP协议、RARP协议和NFS文件系统的实现。

◆ lib_arm:与ARM体系结构相关的代码。

◆ tools:创建S-Record格式文件 和U-BOOT images的工具。

1.2 U-BOOT的特点

U-BOOT支持SCC/FEC以太网、OOTP/TFTP引导、IP和MAC的预置功能,这一点和其它BootLoader(如BLOB和RedBoot等)类似。但U-BOOT还具有一些特有的功能。

◆ 在线读写Flash、DOC、IDE、IIC、EEROM、RTC,其它的BootLoader根本不支持IDE和DOC的在线读写。

◆ 支持串行口kermit和S-record下载代码,U-BOOT本身的工具可以把ELF32格式的可执行文件转换成为 S-record格式,直接从串口下载并执行。

◆ 识别二进制、ELF32、uImage格式的Image,对Linux引导有特别的支持。U-BOOT对Linux 内核进一步封装为uImage。封装如下:

#{CROSS_COMPILE}-objcopy -O binary -R.note -R.comment -S vmlinux \ linux.bin

#gzip -9 linux.bin

#tools/mkimage -A arm -O linux -T kernel -C gzip -a 0xc0008000 -e0xc0008000 -n “Linux-2.4.20” -d linux.bin.gz /tftpboot/uImage

即在Linux内核镜像vmLinux前添加了一个特殊的头,这个头在include/image.h中定义,包括目标操作系统的种类(比如Linux,VxWorks等)、目标CPU的体系机构(比如ARM、PowerPC等)、映像文件压缩类型(比如gzip、bzip2等)、加载地址、入口地址、映像名称和映像的生成时间。当系统引导时,U-BOOT会对这个文件头进行CRC校验,如果正确,才会跳到内核执行。如下所示:

WT-ARM9# bootm 0xc1000000

## Checking Image at 0xc100000 ...

Image Name: Linux-2.4.20

Created: 2004-07-02 22:10:11 UTC

Image Type: ARM Linux Kernel Image (gzip compressed)

Data Size: 550196 Bytes = 537 kB = 0 MB

Load Address: 0xc0008000

Entry Point: 0xc0008000

Verifying Checksum ... OK

Uncompressing Kernel Image ……… OK

◆ 单任务软件运行环境。U-BOOT可以动态加载和运行独立的应用程序,这些独立的应用程序可以利用U-BOOT控制台的I/O函数、内存申请和中断服务等。这些应用程序还可以在没有操作系统的情况下运行,是测试硬件系统很好的工具。

◆ 监控(minitor)命令集:读写I/O,内存,寄存器、内存、外设测试功能等

◆ 脚本语言支持(类似BASH脚本)。利用U-BOOT中的autoscr命令,可以在U-BOOT中运行“脚本”。首先在文本文件中输入需要执行的命令,然后用tools/mkimage封装,然后下载到开发板上,用autoscr执行就可以了。

① 编辑如下的脚本example.script。

echo

echo Network Configuration:

echo ----------------------

echo Target:

printenv ipaddr hostname

echo

echo Server:

printenv serverip rootpath

echo

② 用tools/mkimage对脚本进行封装。

# mkimage -A ARM -O linux -T script -C none -a 0 -e 0 -n "autoscr example script" -d example.script /tftpboot/example.img

Image Name: autoscr example script

Created: Wes Sep 8 01:15:02 2004

Image Type: ARM Linux Script (uncompressed)

Data Size: 157 Bytes = 0.15 kB = 0.00 MB

Load Address: 0x00000000

Entry Point: 0x00000000

Contents:

Image 0: 149 Bytes = 0 kB = 0 MB

③ 在U-BOOT中加载并执行这个脚本。

WT-ARM9# tftp 100000 /tftpboot/example.img

ARP broadcast 1

TFTP from server 10.0.0.2; our IP address is 10.0.0.99

Filename '/tftpboot/TQM860L/example.img'.

Load address: 0x100000

Loading: #

done

Bytes transferred = 221 (dd hex)

WT-ARM9# autoscr 100000

## Executing script at 00100000

Network Configuration:

----------------------

Target:

ipaddr=10.0.0.99

hostname=arm

Server:

serverip=10.0.0.2

rootpath=/nfsroot

WT-ARM9#

◆ 支持WatchDog、LCD logo和状态指示功能等。如果系统支持splash screen,U-BOOT启动时,会把这个图像显示到LCD上,给用户更友好的感觉。

◆ 支持MTD和文件系统。U-BOOT作为一种强大的BootLoader,它不仅支持MTD,而且可以在MTD基础上实现多种文件系统,比如cramfs、fat和jffs2等。

◆ 支持中断。由于传统的BootLoader都分为stage1和stage2,所以在stage2中添加中断处理服务十分困难,比如BLOB;而U-BOOT是把两个部分放到了一起,所以添加中断服务程序就很方便。

◆ 详细的开发文档。由于大多数BootLoader都是开源项目,所以文档都不是很充分。U-BOOT的维护人员意识到了这个问题,充分记录了开发文档,所以它的移植要比BLOB等缺少文档的BootLoader方便。

2 对U-BOOT-1.1.0的修改

为了使U-BOOT-1.1.0支持新的开发板,一种简便的做法是在U-BOOT已经支持的开发板中选择一种接近的进行修改。由于U-BOOT-1.10不支持ARM-922T内核,所以选择基于ARM-920T内核的smdk2400为模板。相关的源代码在board/smdk2400/下。

2.1 支持ARM-922T内核的代码修改

修改以下代码,使U-BOOT支持arm-922t内核。

① 在include/目录下新建文件arm922t.h,内容如下:

#ifndef __ARM922T_H__

#define __ARM922T_H__

#endif

② 在include/目录下新建文件wt-arm9.h,该文件描述了ARM922T中Timer、UART等寄存器的结构及若干宏定义。具体内容要参考相关处理器手册。

③ 在cpu/目录下新建目录arm922t,将目录arm920t下的内容复制后,参考手册分别修改cpu.c、interrupts.c和serial.c,其它文件不修改。

2.2 开发板的支持

建立自己开发板的目录和相关文件。

① 在include/configs目录中添加头文件lh7a400.h。这个文件是lh7a400开发板的配置文件,它包括开发板的CPU、系统时钟、RAM、Flash系统及其它相关的配置信息。其格式可参考include/configs/smdk2400.h。

② 在board/目录下新建wt-arm9目录,创建如下文件:flash.c、lhmemsetup.c、wt- arm9.c、Makefile和u-boot.lds。

◆ flash.c。U-BOOT 读、写和删除Flash设备的源代码文件。由于不同开发板中Flash存储器的种类各不相同,所以,修改flash.c时需参考相应的Flash芯片手册。它包括如下几个函数:

unsigned long flash_init (void ),Flash初始化;

void flash_print_info (flash_info_t *info),打印Flash信息;

int flash_erase (flash_info_t *info, int s_first, int s_last),Flash擦除;

volatile static int write_dword (flash_info_t *info, ulong dest, ulong data),Flash写入;

int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt),从内存复制数据。

◆ lhmemsetup.c。初始化时钟、SMC控制器和SDRAM控制器。

◆ wt-arm9.c。设置各种总线时钟,打开数据Cache和指令Cache,并设置相关内存参数。

◆ Makefile。直接拷贝board/smdk2400/Makefile,作如下修改:

OBJS := wt-arm9.o flash.o lhmemsetup.o

◆ u-boot.lds。设置U-BOOT中各个目标文件的连接地址,直接拷贝 board/smdk2400/u-boot.lds,作如下修改:

.text

{

cpu/arm922t/start.o (.text)

*(.text)

}

2.3 添加网口设备控制程序

在drivers/目录中添加网口设备控制程序dm9000.c 和dm9000.h,其中dm9000.c 主要包括以下函数:

int eth_init (bd_t *bd),初始化网络设备;

void eth_halt (void),关闭网络设备;

int eth_send (volatile void *packet,int len),发送数据包;

int eth_rx (void) 接收数据包。

用中断方式处理数据包的收发,因此还定义了另外两个函数:

void InitInterrupt (void) ,中断初始化;

void dm9000_irq (void) ,中断处理。

以上两个函数在cpu/arm922t/interrupts.c中被调用,最后在drivers/Makefile中加入dm9000.o。

2.4 修改Makefile

在u-boot-1.1.0/Makefile中加入

lh7a400_config : unconfig

@./mkconfig $(@:_config=) arm arm922t wt-arm9

其中“arm”是CPU的种类, arm922t 是ARM CPU对应的代码目录,wt-arm9是自己开发板对应的目录。

交叉编译器安装在/opt/arm/3.3/bin/目录下,所以把CROSS_COMPILE设置成相应的路径:

export CROSS_COMPILE = /opt/arm/3.3/bin/arm-elf-

2.5 生成目标文件

先运行make clean,

[zeng@localhost u-boot-1.1.0]$make clean

然后运行make lh7a400_config,

[zeng@localhost u-boot-1.1.0]$ make lh7a400_config

Configuring for lh7a400 board...

再运行make,

[zeng@localhost u-boot-1.1.0]$make

之后会生成三个文件:

u-boot——ELF格式的文件,可以被大多数Debug程序识别;

u-boot.bin——二进制bin文件,纯粹的U-BOOT二进制执行代码,不保存ELF格式和调试信息。这个文件一般用于烧录到用户开发板中;

u-boot.srec——Motorola S-Record格式,可以通过串行口下载到开发板中。

2.6 测 试

通过JTAG口将u-boot.bin烧写到Flash的零地址,复位后执行u-boot。若运行正常,会从串口返回如下信息:

U-Boot 1.1.0 (Aug 21 2004 ?18:44:37)

U-BooT code: C3F80000 -> C3FA51A0 BSS: -> C3FA96EC

IRQ Stack: c3f1ff7c

FIQ Stack: c3f1ef7c

RAM Configuration:

Bank #0: c0000000 8 MB

Bank #1: c1000000 8 MB

……

Flash: 32 MB

In: serial

Out: serial

Err: serial

WT-ARM9 #

输入help得到所有命令列表,help command 列出该命令的功能。紧接着测试Flash和网卡,如果都正常工作的话,表明移植U-BOOT的工作基本完成,可以接着调试内核和文件系统。

结 语

BootLoader是操作系统和硬件的枢纽,它为操作系统内核的启动提供了必要的条件和参数。在移植过程中,开发人员除了要掌握BootLoader的结构和工作流程外,还要对相关硬件有一定的了解。目前,笔者移植的U-BOOT已经能够稳定地运行在开发板上,而且可以通过Flash和网络加载内核和文件系统,为后续开发,特别是驱动程序的开发奠定了良好的基础。

基于Atmel at91rm9200的armlinux的bootloader启动代码分析

日期: 5月 05 @ 23:45:26 CST

文章主题: 编程开发

前阶段做了一次基于at91rm9200引导部分的技术分析,主要采用了u-boot,这里只面向使用at91rm9200板子的的朋友做个简单的推敲,希望起到抛砖引玉的作用

Author : balancesli

mail : balancesli@thizlinux.com.cn

前阶段做了一次基于at91rm9200引导部分的技术分析,主要采用了u-boot,这里只面向使用at91rm9200板子的

的朋友做个简单的推敲,希望起到抛砖引玉的作用.

关键词 :

u-boot: 一个开源的面向多个目标平台(ppc, mips, arm, x86)的bootloader.

at91rm9200 : Atmel 公司生产的基于arm9核的Soc处理器.

以下先给出at91rm9200引导流程图

Boot program Flow Diagram

Device Setup

|

|

Boot SPI DataFlash Boot --> Download from DataFlash --> run

|

|

TWI EEPROM Boot --> Download from EEPROM --> run

|

|

Parallel Boot --> Download from 8-bit Device -->

|

| Xmodem protocol

| |---DBGU Serial Download ---------------------> run

|____|

| DFU protocol

|-----USB download -----------------------> run

在这里我主要介绍通过片内引导和片外引导, 片内引导主要采用串口下载并引导u-boot,并完成程序被烧写到Flash上,

然后就可以通过跳线的方式从片外引导执行已经烧写到片外Flash上的引导程序(bootloader).

这里要提及的是at91rm9200内部本身有128k的片内rom,其固化了一个bootloader和uploader, 用来支持程序的

下载和引导,而且其内部固化的程序提供了很多内部服务接口(Internel Service)供我们来使用,例如Xmodem,Tempo

DataFlash, CRC, Sine服务接口,这样我们就可以利用它所提供的Service interface API完成程序的下载。

这里主要介绍Xmodem接口服务。

at91rm9200内部固化的代码在设计上采用了面向对象的设计方法,如下:

typedef struct _AT91S_Service

{

char data;

char (*MainMethod)();

char (*ChildMethod)();

}AT91S_Service, *AT91PS_Service;

char AT91F_MainMethod()

{

}

char AT91F_ChildMethod()

{

}

/*init the Service */

AT91PS_Service AT91F_OpenDevice(AT91PS_Service pService)

{

pService->data = 0;

pService->MainMethod = AT91F_MainMethod;

pService->ChildMethod = AT91F_ChildMethod;

}

//使用方法如下

AT91S_Service service;

AT91PS_Service pService = AT91F_OpenDevice(&service);

pService->AT91F_MainMethmod();

.....

通过如上代码片断可以看出它采用了类似面向对象的设计方法。

其实如果各位朋友接触过的话或者看过这本书的话,应该很容易便接受它。

下面以Xmodem服务为例子介绍:

at91rm9200内部提供的服务包含了几个服务对象, 这些对象在片内启动xmodem协议Host端和Targe端通讯时会用到.

typedef struct _AT91S_RomBoot

{

const unsigned int version;

// Peripheral descriptors

const AT91S_MEMCDesc MEMC_DESC;

const AT91S_STDesc SYSTIMER_DESC;

const AT91S_Pio2Desc PIOA_DESC;

const AT91S_Pio2Desc PIOB_DESC;

const AT91S_USART2Desc DBGU_DESC;

const AT91S_USART2Desc USART0_DESC;

const AT91S_USART2Desc USART1_DESC;

const AT91S_USART2Desc USART2_DESC;

const AT91S_USART2Desc USART3_DESC;

const AT91S_TWIDesc TWI_DESC;

const AT91S_SPIDesc SPI_DESC;

// Objects entry

const AT91PF_OpenPipe OpenPipe;

const AT91PF_OpenSBuffer OpenSBuffer;

const AT91PF_OpenSvcUdp OpenSvcUdp;

const AT91PF_OpenSvcXmodem OpenSvcXmodem;

const AT91PF_OpenCtlTempo OpenCtlTempo;

const AT91PF_OpenDfuDesc OpenDfuDesc;

const AT91PF_OpenUsbDesc OpenUsbDesc;

const AT91PF_OpenSvcDataFlash OpenSvcDataFlash;

const AT91PF_SVC_CRC16 CRC16;

const AT91PF_SVC_CRCCCITT CRCCCITT;

const AT91PF_SVC_CRCHDLC CRCHDLC;

const AT91PF_SVC_CRC32 CRC32;

// Array

const AT91PS_SVC_CRC_BIT_REV Bit_Reverse_Array;

const AT91PS_SINE_TAB SineTab;

const AT91PF_Sinus Sine;

} AT91S_RomBoot;

//AT91S_Pipe

typedef struct _AT91S_Pipe

{

// A pipe is linked with a peripheral and a buffer

AT91PS_SvcComm pSvcComm;

AT91PS_Buffer pBuffer;

// Callback functions with their arguments

void (*WriteCallback) (AT91S_PipeStatus, void *);

void (*ReadCallback) (AT91S_PipeStatus, void *);

void *pPrivateReadData;

void *pPrivateWriteData;

// Pipe methods

AT91S_PipeStatus (*Write) (

struct _AT91S_Pipe *pPipe,

char const * pData,

unsigned int size,

void (*callback) (AT91S_PipeStatus, void *),

void *privateData

);

AT91S_PipeStatus (*Read) (

struct _AT91S_Pipe *pPipe,

char *pData,

unsigned int size,

void (*callback) (AT91S_PipeStatus, void *),

void *privateData

);

AT91S_PipeStatus (*AbortWrite)(struct _AT91S_Pipe *pPipe);

AT91S_PipeStatus (*AbortRead)(struct _AT91S_Pipe *pPipe);

AT91S_PipeStatus (*AbortRead)(struct _AT91S_Pipe *pPipe);

AT91S_PipeStatus (*Reset)(struct _AT91S_Pipe *pPipe);

char (*IsWritten)(struct _AT91S_Pipe *pPipe, char const *pVoid);

char (*IsReceived) (struct _AT91S_Pipe *pPipe, char const *pVoid);

} AT91S_Pipe;

//AT91S_Buff

typedef struct _AT91S_SBuffer

{

AT91S_Buffer parent;

char *pRdBuffer;

char const *pWrBuffer;

unsigned int szRdBuffer;

unsigned int szWrBuffer;

unsigned int stRdBuffer;

unsigned int stWrBuffer;

} AT91S_SBuffer;

// AT91S_SvcTempo

typedef struct _AT91S_SvcTempo

{

// Methods:

AT91S_TempoStatus (*Start) (

struct _AT91S_SvcTempo *pSvc,

unsigned int timeout,

unsigned int reload,

void (*callback) (AT91S_TempoStatus, void *),

void *pData);

AT91S_TempoStatus (*Stop) (struct _AT91S_SvcTempo *pSvc);

struct _AT91S_SvcTempo *pPreviousTempo;

struct _AT91S_SvcTempo *pNextTempo;

// Data

unsigned int TickTempo; //* timeout value

unsigned int ReloadTempo;//* Reload value for periodic execution

void (*TempoCallback)(AT91S_TempoStatus, void *);

void *pPrivateData;

AT91E_SvcTempo flag;

} AT91S_SvcTempo;

// AT91S_CtrlTempo

typedef struct _AT91S_CtlTempo

{

// Members:

// Start and stop for Timer hardware

AT91S_TempoStatus (*CtlTempoStart) (void *pTimer);

AT91S_TempoStatus (*CtlTempoStop) (void *pTimer);

// Start and stop for Tempo service

AT91S_TempoStatus (*SvcTempoStart) (

struct _AT91S_SvcTempo *pSvc,

unsigned int timeout,

unsigned int reload,

void (*callback) (AT91S_TempoStatus, void *),

void *pData);

AT91S_TempoStatus (*SvcTempoStop) (struct _AT91S_SvcTempo *pSvc);

AT91S_TempoStatus (*CtlTempoSetTime)(struct _AT91S_CtlTempo *pCtrl, unsigned int NewTime);

AT91S_TempoStatus (*CtlTempoGetTime)(struct _AT91S_CtlTempo *pCtrl);

AT91S_TempoStatus (*CtlTempoIsStart)(struct _AT91S_CtlTempo *pCtrl);

AT91S_TempoStatus (*CtlTempoCreate) (struct _AT91S_CtlTempo *pCtrl,struct _AT91S_SvcTempo *pTempo);

AT91S_TempoStatus (*CtlTempoRemove) (struct _AT91S_CtlTempo *pCtrl,struct _AT91S_SvcTempo *pTempo);

AT91S_TempoStatus (*CtlTempoTick) (struct _AT91S_CtlTempo *pCtrl);

// Data:

void *pPrivateData; // Pointer to devived class

void const *pTimer; // hardware

AT91PS_SvcTempo pFirstTempo;

AT91PS_SvcTempo pNewTempo;

} AT91S_CtlTempo;

//以下代码是上面几个对象的使用范例,通过这样就可以完成Host端和Targe端之间的xmodem通讯,并可以下载代码了。

AT91S_RomBoot const *pAT91;

AT91S_SBuffer sXmBuffer;

AT91S_SvcXmodem svcXmodem;

AT91S_Pipe xmodemPipe;

AT91S_CtlTempo ctlTempo;

AT91PS_Buffer pXmBuffer;

AT91PS_SvcComm pSvcXmodem;

unsigned int SizeDownloaded;

/* Init of ROM services structure */

pAT91 = AT91C_ROM_BOOT_ADDRESS;//这里取得内部ROM服务的入口地址

/* Tempo Initialization */

pAT91->OpenCtlTempo(&ctlTempo, (void *) &(pAT91->SYSTIMER_DESC));

ctlTempo.CtlTempoStart((void *) &(pAT91->SYSTIMER_DESC));

/* Xmodem Initialization */

pXmBuffer = pAT91->OpenSBuffer(&sXmBuffer);

pSvcXmodem = pAT91->OpenSvcXmodem(&svcXmodem, (AT91PS_USART)AT91C_BASE_DBGU, &ctlTempo);

pAT91->OpenPipe(&xmodemPipe, pSvcXmodem, pXmBuffer);

xmodemPipe.Read(&xmodemPipe, (char *)AT91C_UBOOT_BASE_ADDRESS, AT91C_UBOOT_MAXSIZE,

AT91F_XmodemProtocol, 0);

while(XmodemComplete !=1);

//上面部分主要针对at91rm9200片内启动时我们可以使用的片内接口服务介绍,玩H9200的朋友可以参考一下便知道缘由。

下面主要介绍at91rm9200片外启动时所使用的bootloader-->u-boot.

一. bootloader

BootLoader(引导装载程序)是嵌入式系统软件开发的非常重要的环节,它把操作系统和硬件平台衔接在一起,

是跟硬件体系密切相关的。

1.1 典型的嵌入式系统软件部分Image memory layout : bootloader , bootloader param, kernel, rootfs.

1.2 引导模式 : 1. bootstrap或download

2. autoboot

1.3 u-boot简介 :

u-boot是由Wolfgang Denk开发,它支持(mips, ppc, arm, x86)等目标体系,

可以在http://sourceforge.net 上下载获得源码,

1.4 u-boot源代码目录结构

board:开发板相关的源码,不同的板子对应一个子目录,内部放着主板相关代码。

at91rm9200dk/at91rm9200.c, config.mk, Makefile, flash.c ,u-boot.lds等都和具体开发板的硬件和地址分配有关。

common:与体系结构无关的代码文件,实现了u-boot所有命令,

其中内置了一个shell脚本解释器(hush.c, a prototype Bourne shell grammar parser), busybox中也使用了它.

cpu:与cpu相关代码文件,其中的所有子目录都是以u-boot所支持的cpu命名.

at91rm9200/at45.c, at91rm9200_ether.c, cpu.c, interrupts.c serial.c, start.S, config.mk, Makefile等.

其中cpu.c负责初始化CPU、设置指令Cache和数据Cache等;

interrupt.c负责设置系统的各种中断和异常,比如快速中断、开关中断、时钟中断、软件中断、

预取中止和未定义指令等;

start.S负责u-boot启动时执行的第一个文件,它主要是设置系统堆栈和工作方式,为跳转到C程序入口点.

disk:设备分区处理代码。

doc:u-boot相关文档。

drivers:u-boot所支持的设备驱动代码, 网卡、支持CFI的Flash、串口和USB总线等。

fs: u-boot所支持支持文件系统访问存取代码, 如jffs2.

include:u-boot head文件,主要是与各种硬件平台相关的头文件,

如include/asm-arm/arch-at91rm9200/, include/asm-arm/proc-armv

net:与网络有关的代码,BOOTP协议、TFTP协议、RARP协议代码实现.

lib_arm:与arm体系相关的代码。(这里我们主要面向的是ARM体系,所以该目录是我们主要研究对象)

tools:编译后会生成mkimage工具,用来对生成的raw bin文件加入u-boot特定的image_header.

1.5 u-boot的功能介绍

u-boot支持SCC/FEC以太网、OOTP/TFTP引导、IP和MAC的功能.

读写Flash、DOC、IDE、IIC、EEROM、RTC

支持串行口kermit和S-record下载代码, 并直接从串口下载并执行。

在我们生成的内核镜像时,要做如下处理.

1. arm-linux-objcopy -O binary -R.note -R.comment -S vmlinux linux.bin

2. gzip -9 linux.bin

3. mkimage -A arm -O linux -T kernel -C gzip -a 0xc0008000 -e 0xc0008000 -n

"Linux-2.4.19-rmk7” -d linux.bin.gz uImage

即在Linux内核镜像vmLinux前添加了一个特殊的头,这个头在include/image.h中定义,

typedef struct image_header

{

uint32_t ih_magic; /* Image Header Magic Number */

uint32_t ih_hcrc; /* Image Header CRC Checksum */

uint32_t ih_time; /* Image Creation Timestamp */

uint32_t ih_size; /* Image Data Size */

uint32_t ih_load; /* Data Load Address */

uint32_t ih_ep; /* Entry Point Address */

uint32_t ih_dcrc; /* Image Data CRC Checksum */

uint8_t ih_os; /* Operating System */

uint8_t ih_arch; /* CPU architecture */

uint8_t ih_type; /* Image Type */

uint8_t ih_comp; /* Compression Type */

uint8_t ih_name[IH_NMLEN]; /* Image Name */

} image_header_t;

当u-boot引导时会对这个文件头进行CRC校验,如果正确,才会跳到内核执行.

如果u-boot启动以后会出现

u-boot>

敲入help, 会出现大量的命令提示,Monitor command

go - start application at address 'addr'

run - run commands in an environment variable

bootm - boot application image from memory

bootp - boot image via network using BootP/TFTP protocol

tftpboot- boot image via network using TFTP protocol

and env variables "ipaddr" and "serverip"

(and eventually "gatewayip")

rarpboot- boot image via network using RARP/TFTP protocol

diskboot- boot from IDE devicebootd - boot default, i.e., run 'bootcmd'

loads - load S-Record file over serial line

loadb - load binary file over serial line (kermit mode)

md - memory display

mm - memory modify (auto-incrementing)

nm - memory modify (constant address)

mw - memory write (fill)

cp - memory copy

cmp - memory compare

crc32 - checksum calculation

imd - i2c memory display

imm - i2c memory modify (auto-incrementing)

inm - i2c memory modify (constant address)

imw - i2c memory write (fill)

icrc32 - i2c checksum calculation

iprobe - probe to discover valid I2C chip addresses

iloop - infinite loop on address range

isdram - print SDRAM configuration information

sspi - SPI utility commands

base - print or set address offset

printenv- print environment variables

setenv - set environment variables

saveenv - save environment variables to persistent storage

protect - enable or disable FLASH write protection

erase - erase FLASH memory

flinfo - print FLASH memory information

bdinfo - print Board Info structure

iminfo - print header information for application image

coninfo - print console devices and informations

ide - IDE sub-system

loop - infinite loop on address range

mtest - simple RAM test

icache - enable or disable instruction cache

dcache - enable or disable data cache

reset - Perform RESET of the CPU

echo - echo args to console

version - print monitor version

help - print online help

? - alias for 'help'

u-boot支持大量的命令可用, 这里就不作介绍,大家有兴趣可以看看u-boot 的README文档

3.3 对u-boot-1.0.0的修改和移植

1.6 关于u-boot的移植如下,由于u-boot的软件设计体系非常清晰,它的移植工作并不复杂,

相信各位的代码阅读功力不错的话,参照如下就可以完成。

If the system board that you have is not listed, then you will need

to port U-Boot to your hardware platform. To do this, follow these

steps:

1. Add a new configuration option for your board to the toplevel

"Makefile" and to the "MAKEALL" script, using the existing

entries as examples. Note that here and at many other places

boards and other names are listed in alphabetical sort order. Please

keep this order.

2. Create a new directory to hold your board specific code. Add any

files you need. In your board directory, you will need at least

the "Makefile", a ".c", "flash.c" and "u-boot.lds".

3. Create a new configuration file "include/configs/.h" for

your board

4. If you're porting U-Boot to a new CPU, then also create a new

directory to hold your CPU specific code. Add any files you need.

5. Run "make _config" with your new name.

6. Type "make", and you should get a working "u-boot.srec" file

7. Debug and solve any problems that might arise.

[Of course, this last step is much harder than it sounds.]

为了使u-boot-1.0.0支持新的开发板,一种简便的做法是在u-boot已经支持的开发板中参考选择一种较接近板的进行修改,

幸运的是在u-boot-1.0.0中已经有了at91rm9200的支持。

1.7 与at91rm9200相关的u-boot代码

在include/configs/at91rm9200dk.h 它包括开发板的CPU、系统时钟、RAM、Flash系统及其它相关的配置信息。

在include/asm-arm/AT91RM9200.h, 该文件描述了H9200寄存器的结构及若干宏定义。

具体内容要参考相关处理器手册。

在cpu/at91rm9200/目录下别为cpu.c、interrupts.c和serial.c等文件.

在board/at91rm9200dk/目录下分别为flash.c、at91rm9200dk.c, config.mk, Makefile,u-boot.lds

flash.c : u-boot读、写和删除Flash设备的源代码文件。由于不同开发板中Flash存储器的种类各不相同,

所以,修改flash.c时需参考相应的Flash芯片手册。它包括如下几个函数:

unsigned long flash_init (void ),Flash初始化;

void flash_print_info (flash_info_t *info),打印Flash信息;

int flash_erase (flash_info_t *info, int s_first, int s_last),Flash擦除;

volatile static int write_dword (flash_info_t *info, ulong dest, ulong data),Flash写入;

int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt),从内存复制数据。

u-boot.lds :linker scripte, 设置u-boot中各个目标文件的连接地址.

网口设备控制程序

在drivers/目录中网口设备控制程序cs8900, bcm570x等, 还可以添加其他网卡驱动

int eth_init (bd_t *bd) : 初始化网络设备;

void eth_halt (void) : 关闭网络设备;

int eth_send (volatile void *packet,int len) : 发送数据包;

int eth_rx (void) : 接收数据包。

Makefile

在u-boot-1.0.0/Makefile中

at91rm9200dk_config : unconfig

./mkconfig $(@:_config=) arm at91rm9200 at91rm9200dk

1.8 编译u-boot

make at91rm9200_config

Configuring for at91rm9200 board...

make all

生成三个文件:u-boot.bin, u-boot, u-boot.srec

u-boot.bin is a raw binary image

u-boot is an image in ELF binary format

u-boot.srec is in Motorola S-Record format (objcopy -O srec -R.note -R.comment -S [inputfile] [outfile]

以上工作完成我们可以通过串口将u-boot.bin下载到主板的SDRAM中,它会自动执行, 并出现uboot>

这里我们可以通过串口把boot.bin, u-boot.bin.gz下载到主板,再用u-boot的提供的写flash功能分别

把boot.bin, u-boot.bin.gz写入到flash中,完成以上工作后,对主板跳线选择片外启动,

板子复位后会自动启动u-boot.

二.loader.bin, boot.bin, u-boot.bin代码执行流分析.

以上三个文件时at91rm9200启动所需要的三个bin,他们的实现代码并不难。

如果是你是采用at91rm9200的评估版,应该能得到其源码。

2.1 loader.bin 执行流程,这个文件主要在片内启动从串口下载代码时会用到

loader/entry.S init cpu

b main ---> crt0.S

--> copydata --> clearbss --> b boot

main.c --> boot -->

/*Get internel rom service address*/

/* Init of ROM services structure */

pAT91 = AT91C_ROM_BOOT_ADDRESS;

/* Xmodem Initialization */

--> pAT91->OpenSBuffer

--> pAT91->OpenSvcXmodem

/* System Timer initialization */

---> AT91F_AIC_ConfigureIt

/* Enable ST interrupt */

AT91F_AIC_EnableIt

AT91F_DBGU_Printk("XMODEM: Download U-BOOT ");

Jump.S

// Jump to Uboot BaseAddr exec

Jump((unsigned int)AT91C_UBOOT_BASE_ADDRESS)

2.2 boot.bin执行流程 该文件会在从片内启动时被下载到板子上,以后还会被烧写到片外Flash中,以便在片外启动时

用它来引导并解压u-boot.gz,并跳转到u-boot来执行。

boot/entry.S

b main --> crt0.S --> copydata --> clearbss --> b boot

T91F_DBGU_Printk(" ");

AT91F_DBGU_Printk("************************************** ");

AT91F_DBGU_Printk("** Welcome to at91rm9200 ** ");

AT91F_DBGU_Printk("************************************** ");

boot/misc.s /* unzip uboot.bin.gz */

----> decompress_image(SRC,DST,LEN) --> gunzip

//jump to ubootBaseAddr exec 这里跳转到解压u-boot.gz的地址处直接开始执行u-boot

asm("mov pc,%0" : : "r" (DST));

2.3 uboot.bin执行流程

u-boot/cpu/at91rm9200/start.S

start --->reset

---> copyex ---> cpu_init_crit

---> /* set up the stack */ --> start_armboot

u-boot/lib_arm/board.c

init_fnc_t *init_sequence[] = {

cpu_init, /* basic cpu dependent setup */

board_init, /* basic board dependent setup */

interrupt_init, /* set up exceptions */

env_init, /* initialize environment */

init_baudrate, /* initialze baudrate settings */

serial_init, /* serial communications setup */

console_init_f, /* stage 1 init of console */

display_banner, /* say that we are here */

dram_init, /* configure available RAM banks */

display_dram_config,

checkboard,

NULL,

};

---> start_armboot ---> call init_sequence

---> flash_init --> display_flash_config

---> nand_init ---> AT91F_DataflashInit

---> dataflash_print_info --> env_relocate

---> drv_vfd_init --> devices_init --> jumptable_init

---> console_init_r --> misc_init_r --> enable_interrupts

---> cs8900_get_enetaddr --> board_post_init -->

u-boot/common/main.c

for (;;)

{ /* shell parser */

main_loop () --> u_boot_hush_start --> readline

--> abortboot

-->printf("Hit any key to stop autoboot: %2d ", bootdelay);

}

以上是at91rm9200启动并进入u-boot的执行流分析。后面u-boot还会将uImage解压到特定的位置并开始执行内核代码。

三. 综述

总之, 不同厂商的出的Soc片子在启动方式大都提供片内和片外启动两种方式,一般都是在片内固化一段小程序

方便于程序开发而已,在其DataSheet文档中有详尽的描述。若是对at92rm9200有兴趣或玩过的朋友,可以与我共同探讨相互学习。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有