资源描述
uboot-1.1.4在smdk2410上移植
———————————————————————————————— 作者:
———————————————————————————————— 日期:
17
个人收集整理 勿做商业用途
u—boot的移植
1。1 u-boot介绍
Uboot是德国DENX小组的开发用于多种嵌入式CPU的bootloader程序, UBoot不仅仅支持嵌入式Linux系统的引导,当前,它还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS嵌入式操作系统。UBoot除了支持PowerPC系列的处理器外,还能支持MIPS、 x86、ARM、NIOS、XScale等诸多常用系列的处理器。本文的代码取自于uboot1。1。4。
1。2 获取u-boot
从下面地址下载uboot的源代码.
http://
[uboot@localhost uboot]#tar xjvf uboot1.1.4.tar。bz2
[uboot@localhost uboot]#cd uboot1.1。4
1.3 u—boot体系结构
1。 目录树
.
|board
|common
|cpu
|disk
|doc
|drivers
|dtt
|examples
|fs
|include
|lib_
arm
|lib_
generic
|lib_
i386
|lib_
m68k
|lib_
microblaze
|lib_
mips
|lib_
nios
|lib_
nios2
|lib_
ppc
|net
|post
|rtc
`tools
2。 board:和一些已有开发板有关的文件. 每一个开发板都以一个子目录出现在当前目录中,比如说:SMDK2410,子目录中存放与开发板相关的配置文件。
3。 common:实现uboot命令行下支持的命令,每一条命令都对应一个文件.例如bootm命令对应就是cmd_bootm.c.
4。 cpu:与特定CPU架构相关目录,每一款Uboot下支持的CPU在该目录下对应一个子目录,比如有子目录arm920t等.
5。 disk:对磁盘的支持.
5。 doc:文档目录。Uboot有非常完善的文档,推荐大家参考阅读。
6。 drivers:Uboot支持的设备驱动程序都放在该目录,比如各种网卡、支持CFI的Flash、串口和USB等。
7. fs: 支持的文件系统,Uboot现在支持cramfs、fat、fdos、jffs2和registerfs.
8。 include:Uboot使用的头文件,还有对各种硬件平台支持的汇编文件,系统的配置文件和对文件系统支持的文件。该目录下configs目录有与开发板相关的配置头文件,如smdk2410.h。该目录下的asm目录有与CPU体系结构相关的头文件,asm对应的是asmarm.9. lib_xxxx: 与体系结构相关的库文件。如与ARM相关的库放在lib_arm中。
10。 net:与网络协议栈相关的代码,BOOTP协议、TFTP协议、RARP协议和NFS文件系统的实现。
11。 tools:生成Uboot的工具,如:mkimage, crc等等.
1.4 u-boot编译及配置
1.4。1 u—boot的Makefile分析
u-boot的Makefile从功能上可以分成两个部分。一部分是用来编译生成uboot。bin文件;另一部分是用来执行每种board相关的配置。下面以smdk2410为例来说明作了哪些配置。
$make smdk2410_config
在shell执行以上命令,对应于Makefile执行的命令是
smdk2410_config : unconfig
@。/mkconfig $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
首先执行如下命令,删除文件include/config。h include/config。mk board/*/config。tmp,后续会发现这些文件是如何建立的。
unconfig:
@rm —f include/config.h include/config.mk board/*/config。tmp
然后运行命令@。/mkconfig $(@:_config=) arm arm920t smdk2410 NULL s3c24x0,mkconfig是脚本文件,传入的参数$1至$6分别为:smdk2410 arm arm920t smdk2410 NULL s3c24x0,根据传入的参数执行如下命令
cd 。/include
rm –f asm
ln –s asm-arm asm
rm –f asm-arm/arch
ln –s arch—s3c24x0 asm-arm/arch
rm –f asm—arm/proc
ln –s proc-armv asm—arm/proc
生成文件config。mk,文件内容为:
ARCH = arm
CPU = arm920t
BOARD = smdk2410
SOC = s3c24x0
生成文件config.h,文件内容为:
/* Automatically generated - do not edit */
#include <configs/smdk2410.h〉
至此make smdk2410_config的命令全部执行完毕。配置完成与board相关的信息,下面就可以编译此board的u-boot。bin文件,执行如下命令:
$make CROSS_COMPILE=arm-linux-
Makefile的执行首先包含include include/config。mk文件,获取ARCH CPU BOARD VENDOR SOC的定义,然后根据宏的配置编译指定的文件,最终生成u-boot。bin文件,执行流程请自行分析。
1.4。2 u-boot.bin的生成
根据以上对于makefile的分析,u—boot。bin的生成分为两步。如下:
对于board进行配置: $make smdk2410_config
进行编译生成u—boot.bin: $make CROSS_COMPILE=arm—linux-
1。5 u—boot的启动过程及工作原理
1。5。1 启动模式介绍
大多数 Boot Loader 都包含两种不同的操作模式:”启动加载"模式和"下载”模式,这种区别仅对于开发人员才有意义.但从最终用户的角度看,Boot Loader 的作用就是用来加载操作系统,而并不存在所谓的启动加载模式与下载工作模式的区别。
启动加载(Boot loading)模式:这种模式也称为”自主”(Autonomous)模式。也即 Boot Loader 从目标机上的某个固态存储设备上将操作系统加载到 RAM 中运行,整个过程并没有用户的介入.这种模式是 BootLoader 的正常工作模式,因此在嵌入式产品发布的时侯,Boot Loader 显然必须工作在这种模式下。
下载(Downloading)模式:在这种模式下,目标机上的 Boot Loader 将通过串口连接或网络连接等通信手段从主机(Host)下载文件,比如:下载内核映像和根文件系统映像等。从主机下载的文件通常首先被 BootLoader 保存到目标机的 RAM 中,然后再被 BootLoader 写到目标机上的FLASH 类固态存储设备中.BootLoader 的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新也会使用 BootLoader 的这种工作模式。工作于这种模式下的 Boot Loader 通常都会向它的终端用户提供一个简单的命令行接口.
UBoot这样功能强大的 Boot Loader 同时支持这两种工作模式,而且允许用户在这两种工作模式之间进行切换。
大多数bootloader都分为阶段1(stage1)和阶段2(stage2)两大部分,uboot也不例外.依赖于CPU体系结构的代码(如CPU初始化代码等)通常都放在阶段1中且通常用汇编语言实现,而阶段2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。
1。5.2 阶段1介绍
uboot的stage1代码通常放在start。s文件中,它用汇编语言写成,其主要代码部分如下:
1。5.2。1 定义入口
由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。
1. board/smdk2410/uboot。lds: ENTRY(_start) ==〉 cpu/arm920t/start。o (.text)
2。 uboot在ram的代码区(TEXT_BASE = 0x33F80000)定义在board/smdk2410/config.mk
1.5。2。2 设置异常向量
.globl _start
_start: b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
当发生异常时,执行cpu/arm920t/interrupts.c中定义的中断处理函数
1。5.2。3 设置CPU 的模式为SVC 模式
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
1.5。2。4 关闭看门狗,禁掉所有中断,设置CPU 的频率
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
ldr r0, =pWTCON
mov r1, #0x0
str r1, [r0]
/*
* mask all IRQs by setting all bits in the INTMR — default
*/
mov r1, #0xffffffff
ldr r0, =INTMSK
str r1, [r0]
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */
1。5.2。5 与内存管理相关寄存器的设置,cp15协处理器,配置内存区控制寄存器
cpu_init_crit:
/*
* flush v4 I/D caches
*/
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* 失效I/D cache, 见S3C2410手册附录的2—16 */
mcr p15, 0, r0, c8, c7, 0 /* 失效TLB, 见S3C2410手册附录的2—18 */
/*
* disable MMU stuff and caches
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 /* 清除 bits 13, 9:8 (--V- -—RS)
* Bit 8: Disable System Protection
* Bit 7: Disable ROM Protection
* Bit 13: 异常向量表基地址: 0x0000 0000
*/
bic r0, r0, #0x00000087 /* 清除 bits 7, 2:0 (B——- —CAM)
* Bit 0: MMU disabled
* Bit 1: Alignment Fault checking disabled
* Bit 2: Data cache disabled
* Bit 7: 0 = Little-endian operation
*/
orr r0, r0, #0x00000002 @ set bit 2 (A) Align
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
mcr p15, 0, r0, c1, c0, 0
/*
* before relocating, we have to setup RAM timing
* because memory timing is board-dependend, you will
* find a lowlevel_init。S in your board directory.
*/
mov ip, lr
bl lowlevel_init /*寄存器的具体值的设置需要对总线周期及
外围芯片非常熟悉, 根据所采用的内存芯片确定*/
mov lr, ip
mov pc, lr
1。5。2。6 把u-boot。lds定义的text段,rodata段,data段,got段,__u_boot_cmd_start段搬移到ram区
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate: /* relocate U—Boot to RAM */
adr r0, _start /* r0 〈— current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc during debug */
beq stack_setup
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 〈- size of armboot */
add r2, r0, r2 /* r2 <— source end address */
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
1。5.2.7 建立stack空间
stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* leave 3 words for abort—stack */
1.5.2。8 bss段清0
clear_bss:
ldr r0, _bss_start /* find start of bss segment */
ldr r1, _bss_end /* stop here */
mov r2, #0x00000000 /* clear */
clbss_l:str r2, [r0] /* clear loop.。. */
add r0, r0, #4
cmp r0, r1
ble clbss_l
1.5。2。9 进入C 代码部分
ldr pc, _start_armboot
_start_armboot: 。word start_armboot
1。5.3 阶段2的C语言代码部分
lib_arm/board。c中的start_armboot是C语言开始的函数,也是整个启动代码中C语言的主函数,同时还是整个
uboot(armboot)的主函数,该函数主要完成如下操作:
1。5.3.1 调用一系列的初始化函数
1。 指定初始函数表:
init_fnc_t *init_sequence[] = {
cpu_init, /* cpu的基本设置 */
board_init, /* 开发板的基本初始化 */
interrupt_init, /* 初始化中断 */
env_init, /* 初始化环境变量 */
init_baudrate, /* 初始化波特率 */
serial_init, /* 串口通讯初始化 */
console_init_f, /* 控制台初始化第一阶段 */
display_banner, /* 通知代码已经运行到该处 */
dram_init, /* 配制可用的内存区 */
display_dram_config,
#if defined(CONFIG_VCMA9) || defined (CONFIG_CMC_PU2)
checkboard,
#endif
NULL,
};
执行初始化函数的代码如下:
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
2. 配置可用的Flash区
flash_init ()
3. 初始化内存分配函数
mem_malloc_init()
4。 nand flash初始化
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
puts ("NAND:");
nand_init(); /* 初始化 NAND */
5. 初始化环境变量
env_relocate ();
6. 外围设备初始化
devices_init()
7. I2C总线初始化
i2c_init();
8. LCD初始化
drv_lcd_init();
9。 VIDEO初始化
drv_video_init();
10。 键盘初始化
drv_keyboard_init();
11。 系统初始化
drv_system_init();
1.5.3.2 初始化网络设备
初始化相关网络设备,填写IP、MAC地址等。
1。5。3.3 进入主UBOOT 命令行
进入命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。
for (;;) {
main_loop (); /* 在common/main。c */
}
1。6 u—boot命令使用说明
1。6.1 命令配置
1.6。2 命令帮助获取
通过help可以获得当前开发板的UBOOT中支持的命令。
# help
? - alias for 'help’
autoscr - run script from memory
base — print or set address offset
bdinfo - print Board Info structure
boot — boot default, i。e., run ’bootcmd'
bootd - boot default, i.e., run 'bootcmd’
bootelf — Boot from an ELF image in memory
bootm — boot application image from memory
bootp — boot image via network using BootP/TFTP protocol
bootvx - Boot vxWorks from an ELF image
cmp — memory compare
coninfo - print console devices and information
cp — memory copy
crc32 - checksum calculation
date — get/set/reset date & time
dcache — enable or disable data cache
echo — echo args to console
erase - erase FLASH memory
flinfo - print FLASH memory information
go — start application at address 'addr'
help — print online help
icache - enable or disable instruction cache
iminfo — print header information for application image
imls — list all images found in flash
itest - return true/false on integer compare
loadb — load binary file over serial line (kermit mode)
loads - load S-Record file over serial line
loop — infinite loop on address range
md — memory display
mm — memory modify (auto—incrementing)
mtest - simple RAM test
mw - memory write (fill)
nand - NAND sub—system
nboot — boot from NAND device
nfs - boot image via network using NFS protocol
nm - memory modify (constant address)
ping — send ICMP ECHO_REQUEST to network host
printenv — print environment variables
protect — enable or disable FLASH write protection
rarpboot — boot image via network using RARP/TFTP protocol
reset - Perform RESET of the CPU
run - run commands in an environment variable
saveenv — save environment variables to persistent storage
setenv - set environment variables
sleep — delay execution for some time
tftpboot — boot image via network using TFTP protocol
version — print monitor version
1.6。3 命令使用说明
l askenv(F)
在标准输入(stdin)获得环境变量。
l autoscr
从内存(Memory)运行教本.(注意,从下载地址开始,例如我们的开发板是从0x30008000处开始运
行)。
# autoscr 0x30008000
## Executing script at 30008000
l base
打印或者设置当前指令与下载地址的地址偏移。
l bdinfo
打印开发板信息
# bdinfo
—arch_number = 0x000000C1 (CPU体系结构号)
-env_t = 0x00000000 (环境变量)
-boot_params = 0x30000100 (启动引导参数)
-DRAM bank = 0x00000000 (内存区)
-—> start = 0x30000000 (SDRAM起始地址)
-—〉 size = 0x04000000 (SDRAM大小)
-ethaddr = 01:23:45:67:89:AB (以太网地址)
-ip_addr = 192。168.1。5 (IP地址)
—baudrate = 115200 bps (波特率)
l bootp
通过网络使用Bootp或者TFTP协议引导境像文件。
# help bootp
bootp [loadAddress] [bootfilename]
l bootelf
默认从0x30008000引导elf格式的文件(vmlinux)
# help bootelf
bootelf [address] — load address of ELF image。
l bootd(=boot)
引导的默认命令,即运行U-BOOT中在“include/configs/smdk2410.h” 中设置的“bootcmd” 中
的命令.如下:
#define CONFIG_BOOTCOMMAND ”tftp 0x30008000 uImage; bootm 0x30008000";
在命令下做如下试验:
# set bootcmd printenv
# boot
bootdelay=3
baudrate=115200
ethaddr=01:23:45:67:89:ab
# bootd
bootdelay=3
baudrate=115200
ethaddr=01:23:45:67:89:ab
l tftp(tftpboot)
即将内核镜像文件从PC中下载到SDRAM的指定地址,然后通过bootm来引导内核,前提是所用PC要安装设
置tftp服务。
下载信息:
# tftp 0x30008000 zImage
TFTP from server 10.0。0。1; our IP address is 10。0。0.110
Filename ’zImage’。
Load address: 0x30008000
Loading: #################################################################
#################################################################
#################################################
done
Bytes transferred = 913880 (df1d8 hex)
l bootm
内核的入口地址开始引导内核。
# bootm 0x30008000
## Booting image at 30008000 。。.
Starting kernel 。。。
Uncompressing
Linux...。。.。。。。。。.。。。。..。..。...。.。。.。....。.。。.。。.。.。。。。。。.。...。。.。.。。。。....
done, 。
l go
直接跳转到可执行文件的入口地址,执行可执行文件.
# go 0x30008000
## Starting application at 0x30008000 ...
l cmp
对输入的两段内存地址进行比较。
# cmp 0x30008000 0x30008040 64
word at 0x30008000 (0xe321f0d3) != word at 0x30008040 (0xc022020c)
Total of 0 words were the same
# cmp 0x30008000 0x30008000 64
Total of 100 words were the same
l coninfo
打印所有控制设备和信息,例如
-List of available devices:
—serial 80000003 SIO stdin stdout stderr
l cp
内存拷贝,cp 源地址 目的地址 拷贝大小(字节)
# help cp
cp [.b, 。w, 。l] source target count
ANE2410 # cp 0x30008000 0x3000f000 64
l date
获得/设置/重设日期和时间
# date
Date: 2006—6—6 (Tuesday) Time: 06:06:06
l erase(F)
擦除FLASH MEMORY, 由于该ARM板没有Nor Flash, 所有不支持该命令。
# help erase
erase start end
— erase FLASH from addr ’start' to addr 'end’
erase start +len
— erase FLASH from addr 'start' to the end of sect w/addr ’start'+'len'-1
erase N:SF[-SL]
- erase sectors SF-SL in FLASH bank # N
erase bank N
— erase FLASH bank # N
erase all
— erase all FLASH banks
l flinfo(F)
打印Nor Flash信息, 由于该ARM板没有Nor Flash, 所有不支持该命令.
l iminfo
打印和校验内核镜像头, 内核的起始地址由CFG_LOAD_ADDR指定:
#define CFG_LOAD_ADDR 0x30008000 /* default load address */
该宏在include/configs/zte2410。h中定义。
# iminfo
## Checking Image at 30008000 。.。
Image Name: Linux-2。6。14.1
Created: 2006-06-28 7:43:01 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1047080 Bytes = 1022.5 kB
Load Address: 30008000
Entry Point: 30008040
Verifying Checksum ... OK
l loadb
从串口下载二进制文件
# loadb
## Ready for binary (kermit) download to 0x30008000 at 115200 bps...
## Total Size = 0x00000000 = 0 Bytes
## Start Addr = 0x30008000
l md
显示指定内存地址中的内容
# md 0
00000000: ea000012 e59ff014 e59ff014 e59ff014 .。。。....。.。...。。
00000010: e59ff014 e59ff014 e59ff014 e59ff014 .。.。....。.。..。.。
00000020: 33f80220 33f80280 33f802e0 33f80340 。。3..。3。。.3@。.3
00000030: 33f803a0 33f80400 33f80460 deadbeef ..。3.。.3`。.3.。..
00000040: 33f80000 33f80000 33f9c0b4 33fa019c 。。.3.。.3。..3..。3
00000050: e10f0000 e3c0001f e38000d3 e129f000 ...。..。。..。...)。
00000060: e3a00453 e3a01000 e5801000 e3e01000 S...。.。。.。.。。。。.
00000070: e59f0444 e5801000 e59f1440 e59f0440 D。..。...@.。.@。.。
00000080: e5801000 e59f043c e3a01003 e5801000 。。。。<。。...。。。...
00000090: eb000051 e24f009c e51f1060 e1500001 Q。.。。.O.`。。。。。P。
000000a0: 0a000007 e51f2068 e51f3068 e0432002 .。。。h 。。h0。。。 C。
000000b0: e0802002 e8b007f8 e8a107f8 e1500002 。 ..。。.。。。...。P。
000000c0: dafffffb e51f008c e2400803 e
展开阅读全文