uboot移植参考说明:
http://blog.chinaaet.com/detail/17764.html
该移植有部分移植参考互联网资源,如有侵权,请与我联系。大部分为自己原创,如有转载请注明出处,该技术仅供学习交流,不可商用。------小盒子 于哈尔滨2008年12月13日整理
1 U-Boot简介
U-Boot,全称Universal Boot Loader,是遵循GPL条款的开放源码项目。从FADSROM、8xxROM、PPCBOOT逐步发展演化而来。其源码目录、编译形式与Linux内核很相似,事实上,不少U-Boot源码就是相应的Linux内核源程序的简化,尤其是一些设备的驱动程序,这从U-Boot源码的注释中能体现这一点。但是U-Boot不仅仅支持嵌入式Linux系统的引导,当前,它还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS嵌入式操作系统。其目前要支持的目标操作系统是OpenBSD, NetBSD, FreeBSD,4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR, VxWorks, LynxOS, pSOS, QNX, RTEMS, ARTOS。这是U-Boot中Universal的一层含义,另外一层含义则是U-Boot除了支持PowerPC系列的处理器外,还能支持MIPS、 x86、ARM、NIOS、XScale等诸多常用系列的处理器。这两个特点正是U-Boot项目的开发目标,即支持尽可能多的嵌入式处理器和嵌入式操作系统。就目前来看,U-Boot对PowerPC系列处理器支持最为丰富,对Linux的支持最完善。其它系列的处理器和操作系统基本是在2002年11 月PPCBOOT改名为U-Boot后逐步扩充的。从PPCBOOT向U-Boot的顺利过渡,很大程度上归功于U-Boot的维护人德国DENX软件工程中心Wolfgang Denk[以下简称W.D]本人精湛专业水平和持着不懈的努力。当前,U-Boot项目正在他的领军之下,众多有志于开放源码BOOT LOADER移植工作的嵌入式开发人员正如火如荼地将各个不同系列嵌入式处理器的移植工作不断展开和深入,以支持更多的嵌入式操作系统的装载与引导。
选择U-Boot的理由:
① 开放源码;
② 支持多种嵌入式操作系统内核,如Linux、NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS;
③ 支持多个处理器系列,如PowerPC、ARM、x86、MIPS、XScale;
④ 较高的可靠性和稳定性;
④ 较高的可靠性和稳定性;
⑤ 高度灵活的功能设置,适合U-Boot调试、操作系统不同引导要求、产品发布等;
⑥ 丰富的设备驱动源码,如串口、以太网、SDRAM、FLASH、LCD、NVRAM、EEPROM、RTC、键盘等;
⑦ 较为丰富的开发调试文档与强大的网络技术支持;
2 U-Boot主要目录结构
board 目标板相关文件,主要包含SDRAM、FLASH驱动;
common 独立于处理器体系结构的通用代码,如内存大小探测与故障检测;
cpu 与处理器相关的文件。如mpc8xx子目录下含串口、网口、LCD驱动及中断初始化等文件;
driver 通用设备驱动,如CFI FLASH驱动(目前对INTEL FLASH支持较好)
doc U-Boot的说明文档;
examples可在U-Boot下运行的示例程序;如hello_world.c,timer.c;
include U-Boot头文件;尤其configs子目录下与目标板相关的配置头文件是移植过程中经常要修改的文件;
lib_xxx 处理器体系相关的文件,如lib_ppc, lib_arm目录分别包含与PowerPC、ARM体系结构相关的文件;
net 与网络功能相关的文件目录,如bootp,nfs,tftp;
post 上电自检文件目录。尚有待于进一步完善;
rtc RTC驱动程序;
tools 用于创建U-Boot S-RECORD和BIN镜像文件的工具;
3 U-Boot支持的主要功能
U-Boot可支持的主要功能列表
系统引导 支持NFS挂载、RAMDISK(压缩或非压缩)形式的根文件系统
支持NFS挂载、从FLASH中引导压缩或非压缩系统内核;
基本辅助功能强大的操作系统接口功能;可灵活设置、传递多个关键参数给操作系统,适合系统在不同开发阶段的调试要求与产品发布,尤其对Linux支持最为强劲;
支持目标板环境参数多种存储方式,如FLASH、NVRAM、EEPROM;
CRC32校验,可校验FLASH中内核、RAMDISK镜像文件是否完好;
设备驱动串口、SDRAM、FLASH、以太网、LCD、NVRAM、EEPROM、键盘、USB、PCMCIA、PCI、RTC等驱动支持;
上电自检功能 SDRAM、FLASH大小自动检测;SDRAM故障检测;CPU型号;
特殊功能 XIP内核引导;
好了废话就少说了,直接进入主题
1.下载最新版本的u-boot:
ftp://ftp.denx.de/pub/u-boot/
u-boot 手册:http://www.denx.de/wiki/DULG/Manual
2.安装编译工具cross-3.3.2.tar.bz2
#tar –xjvf cross-3.3.2.tar.bz2
将解压缩的文件夹3.3.2 copy到/usr/local/arm/下
3.修改文件脚本文件
#cd /etc
#vim bashrc
在文件最后添加以下语句
PATH=/usr/local/arm/3.3.2/bin:”${PATH}”
保存退出
退出当前用户重新登陆即可
查看是否修改成功
#echo $PATH
或
修改uboot的Makefile文件,详细修改参考第5小结
4.在linux下面解压缩uboot
#tar –xjvf u-boot-1.1.4.tar.bz2 //解压缩
5.修改Makefile文件
#cd u-boot-1.1.4
#vi Makefile
ifeq ($(ARCH),arm)
CROSS_COMPILE := /usr/local/arm/3.3.2/bin/arm-linux-
endif
如果你修改了此处就不需要执行第三节的设置了。
5.首先随便找一个SOC芯片编译一下
make distclean
make smdk2410_config
make
看看是否能通过。如果这里你都编译不过,你就别继续往下看了,还是检查你的交叉编译器或是源码吧。。。。。。
uboot移植参考说明:
该移植有部分移植参考互联网资源,如有侵权,请与我联系。大部分为自己原创,如有转载请注明出处,该技术仅供学习交流,不可商用。------小盒子 于哈尔滨2008年12月22日整理
6. 打开board文件夹新建一个处理器文件名
Ex:mkdir hyt24x0
分别从SDMK2410下拷贝以下几个文件到该目录
config.mk \ flash.c \ lowlevel_init.S \ Makefile \ u-boot.lds \ smdk2410.c
并修改以上几个文件,以适合你的系统
重新命名smdk2410.c
#mv smdk2410.c hyt24x0.c
并修改Makefile文件
OBJS := hyt24x0.o flash.o
SOBJS := lowlevel_init.o
7. 其实board这里要修改的不多,先跳过flash部分吧,我们来看一下cpu设置部分吧。u-boot-1.1.4里面已经加入了对s3c24x0的支持,让我们来看一下cpu/arm920t/s3c24x0里面的部分吧。
i2c.c \ interrupts.c \ serial.c \ speed.c \ usb_ohci,c \ usb_ohci.h \ Makefile
这几个文件,不用解释这几个文件就应该知道它们都是做什么用的了。
8.添加头文件
cd u-boot-1.1.4/include/configs
cp smdk2410.h ../configs/hyt24x0.h
并添加相应的内容,稍后介绍该文件。『这里不影响后面的编译』
9.回到u-boot-1.1.4主目录修改Makefile文件
在1508行左右添加如下代码:
smdk2410_config : unconfig
@./mkconfig $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
hyt24x0_config■:■unconfig
■@./mkconfig $(@:_config=) arm arm920t hyt24x0 NULL s3c24x0
注意:■为一个TAB,不可以是空格,也不是紫方块;否则make时会出错
arm: CPU的架构(ARCH)
arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录。
hyt24x0: 开发板的型号(BOARD),对应于board/ hyt24x0目录。
NULL: 开发者/或经销商(vender)。
s3c24x0: 片上系统(SOC)。
uboot移植参考说明:
该移植有部分移植参考互联网资源,如有侵权,请与我联系。大部分为自己原创,如有转载请注明出处,该技术仅供学习交流,不可商用。------小盒子 于哈尔滨2009年03月10日整理
这里介绍一下有关编译器的问题,如果你使用的交叉编译器版本不是3.4.1,你可以跳过此节。注意使用3.3.2版本的也需要看一下,后面有一个小地方需要修改一下。
如果你使用的是3.4.1在编译u-boot的时候大多数人会遇到以下这样的错误,这个时候你别紧张,这里给你提供了一个好的解决办法:
rm-linux-ld:ERROR:usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/libgcc.a(_udivdi3.oS) uses hardware FP, whereas u-boot uses software FP
arm-linux-ld:failed to merge target specific data of file /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/libgcc.a(_udivdi3.oS)
arm-linux-ld: ERROR: /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/libgcc.a(_clz.oS) uses hardware FP, whereas u-boot uses software FP
arm-linux-ld: failed to merge target specific data of file /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/libgcc.a(_clz.oS)
make: *** [u-boot] Error 1
解决的办法:
找到/u-boot-1.1.4/cpu/arm920t/config.mk文件
该文件内容如下所示:
PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \
-msoft-float
PLATFORM_CPPFLAGS += -march=armv4
# =========================================================================
#
# Supply options according to compiler version
#
# =========================================================================
PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu)
PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,))
修改该文件:
PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \
# -msoft-float
PLATFORM_CPPFLAGS += -march=armv4
# =========================================================================
#
# Supply options according to compiler version
#
# =========================================================================
PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32)#,-mabi=apcs-gnu)
PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,))
请注意紫色部分的修改!
问题是编译链接器3.4.1用的是hardware FP,而u-boot 使用的是 software FP 也可以使用2.95或者3.3.2版本可解决这个问题。
如果使用3.3.2编译器编译出错的话
编译错误:error: invalid option `abi=apcs-gnu'
出错原因:
指示编译器不支持选项 -mabi=apcs-gnu
出错的文件是/cpu/arm920t/下的config.mk
函数cc-option用于检查编译器是否支持给定的选项
在PLATform_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu)中
apcs:指的是 ARM 过程调用标准
apcs-32和apcs-gnu是APCS 标准中的两个版本。
在上边脚本中cc-option首先检查是否支持apcs-32标准,如果不支持的话就使用apcs-gnu标准,而3.3.2 arm-linux-gcc也不支持apcs-gnu标准,所以出错。而PLATform_CPPFLAGS +=$(call cc-option,-mapcs-32,$(call cc-option,-mabi=apcs-gnu,))
脚本中如果给定的两个标准都不支持的话就不指定了。
如果你用的是3.3.2版本你可以按照我的修改
PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32)#,-mabi=apcs-gnu)
PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,))
11.修改cpu/arm920t/start.S文件
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
#if defined(CONFIG_S3C2400)
# define pWTCON 0x15300000
# define INTMSK 0x14400008
# define CLKDIVN 0x14800014
#else
# define pWTCON 0x53000000
# define INTMSK 0x4A000008
# define INTSUBMSK 0x4A00001C
# define CLKDIVN 0x4C000014
#endif
……
修改中断禁止部分:
# if defined(CONFIG_S3C2410)
ldr r1, =0x7ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
#if defined(CONFIG_S3C2440)
ldr r1, =0x7fff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
……
修改时钟:
#if defined(CONFIG_S3C2440)
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#else
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#endif
#endif
……
从FLASH启动改成从NAND FLASH启动
#if defined(CONFIG_S3C2440)
ldr r0,=0x4e000038;
ldr r1,=0x0
str r1,[r0]
ldr r1,=0xffffff
str r1,[r0,#4]
adr r0,_start
ldr r1,_TEXT_BASE
cmp r0,r1
beq stack_setup
bl copy_nand_to_sdram
@bl stack_setup
#endif
#if defined(CONFIG_S3C2410)
adr r0,_start
ldr r1,_TEXT_BASE
cmp r0,r1
beq stack_setup
bl copy_nand_to_sdram
#endif
禁止从FLASH启动
#ifdef CONFIG_AT91RM9200
#define CONFIG_SKIP_RELOCATE_UBOOT
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:
adr r0, _start
ldr r1, _TEXT_BASE
cmp r0, r1
beq stack_setup
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2
@add r2, r0, r2
ldr r2,=0x20000
copy_loop:
ldmia r0!, {r3-r10}
stmia r1!, {r3-r10}
cmp r0, r2
ble copy_loop
#endif
#endif
为了测试方便,在uboot启动第一个阶段后,用LED闪烁做指示
bl led_test
ldr pc, _start_armboot
这里说明一下led_test是一段汇编程序(也可以是你写的C程序),根据板子具体的情况自己去写这段程序。
从NAND FLASH到SDRAM
#if defined(CONFIG_S3C2440)
copy_nand_to_sdram:
mov r10,lr
ldr sp,DW_STACK_START
mov fp,#0x0
bl nand_reset
ldr r0,_TEXT_BASE
mov r1,#0x0
mov r2,#0x20000
bl nand_read_ll
tst r0,#0x0
beq ok_nand_read
ok_nand_read:
mov r0,#0x0
ldr r1,_TEXT_BASE
mov r2,#0x400
go_next:
ldr r3,[r0],#4
ldr r4,[r1],#4
teq r3,r4
bne notmatch
subs r2,r2,#0x4
beq done_nand_read
bne go_next
notmatch:
1:
b 1b
done_nand_read:
mov pc,r10
#endif
#if defined(CONFIG_S3C2410)
copy_nand_to_sdram:
mov r10,lr
ldr sp,DW_STACK_START
mov fp,#0x0
bl nand_reset
ldr r0,_TEXT_BASE
mov r1,#0x0
mov r2,#0x20000
bl nand_read_ll
tst r0,#0x0
beq ok_nand_read
ok_nand_read:
mov r0,#0x0
ldr r1,_TEXT_BASE
mov r2,#0x400
go_next:
ldr r3,[r0],#4
ldr r4,[r1],#4
teq r3,r4
bne notmatch
subs r2,r2,#0x4
beq done_nand_read
bne go_next
notmatch:
1:
b 1b
done_nand_read:
mov pc,r10
#endif
DW_STACK_START:
.word 0x33f08000
12.在board/hyt24x0/文件夹下新建一个.c文件<read_nand.c>
文件内容如下:
#include <common.h>
#include <s3c2410.h>
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define NF_BASE 0x4e000000
#if defined(CONFIG_S3C2440)
#define NFCONF __REGi(NF_BASE + 0x0)
#define NFCONT __REGi(NF_BASE + 0x4)
#define NFCMD __REGb(NF_BASE + 0x8)
#define NFADDR __REGb(NF_BASE + 0xC)
#define NFDATA __REGb(NF_BASE + 0x10)
#define NFSTAT __REGb(NF_BASE + 0x20)
//#define GPDAT __REGi(GPIO_CTL_BASE+oGPIO_F+oGPIO_DAT)
#define NAND_CHIP_ENABLE (NFCONT &= ~(1<<1))
#define NAND_CHIP_DISABLE (NFCONT |= (1<<1))
#define NAND_CLEAR_RB (NFSTAT |= (1<<2))
#define NAND_DETECT_RB { while(! (NFSTAT&(1<<0)) );}
#define BUSY 4
#define NAND_SECTOR_SIZE 512
#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)
void nand_reset(void)
{
int i;
NFCONF=(7<<12)|(7<<8)|(7<<4);
NFCONT=(0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
NAND_CHIP_ENABLE;
NFCMD = 0xff;
for(i=0;i<10;i++)
;
NAND_DETECT_RB;
NAND_CHIP_DISABLE;
}
int nand_read_ll(unsigned char *buf,unsigned long start_addr,int size)
{
int i,j;
NAND_CHIP_ENABLE;
for(i=0;i<10;i++)
;
i=start_addr;
while(i<start_addr+size)
{
NFCMD=0;
NFADDR=i&0xff;
NFADDR=(i>>9)&0xff;
NFADDR=(i>>17)&0xff;
NFADDR=(i>>25)&0xff;
NAND_DETECT_RB;
for(j=0;j<NAND_SECTOR_SIZE;i++,j++)
{
*buf=(NFDATA & 0xff);
buf++;
}
}
NAND_CHIP_DISABLE;
return 0;
}
#endif //CONFIG_S3C2440
#if defined(CONFIG_S3C2410)
#define NFCONF __REGi(NF_BASE + 0x0)
#define NFCMD __REGb(NF_BASE + 0x4)
#define NFADDR __REGb(NF_BASE + 0x8)
#define NFDATA __REGb(NF_BASE + 0xc)
#define NFSTAT __REGb(NF_BASE + 0x10)
#define BUSY 1
#define NAND_SECTOR_SIZE 512
#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)
inline void wait_idle(void) {
int i;
while(!(NFSTAT & BUSY))
for(i=0; i<10; i++);
}
void nand_reset(void)
{
int i;
NFCONF = (1<<15)|(1<<12)|(1<<11)|(7<<8)|(7<<4)|(7);
NFCONF &= ~0x800;
NFCMD = 0xff;
for(i=0;i<10;i++)
;
wait_idle();
NFCONF |= 0x800;
}
int
nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
{
int i, j;
// Remove by heyunhuan at 20081008
NFCONF &= ~0x800;
for(i=0; i<10; i++);
for(i=start_addr; i < (start_addr + size);) {
NFCMD = 0;
NFADDR = i & 0xff;
NFADDR = (i >> 9) & 0xff;
NFADDR = (i >> 17) & 0xff;
NFADDR = (i >> 25) & 0xff;
wait_idle();
for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
*buf = (NFDATA & 0xff);
buf++;
}
}
NFCONF |= 0x800;
return 0;
}
#endif //CONFIG_S3C2410
添加完后保存并退出。同时修改在目录下面的Makefile文件
OBJS := hyt24x0.o flash.o read_nand.o
SOBJS := lowlevel_init.o