移植U-Boot手记【转】
2007-02-03 17:21:05
一直想弄弄u-boot,却一直没时间弄。现在终于放假了,准备趁此清闲机会好好研究研究bootloader,于是从昨天开始往s3c2410板子上移植uboot,目前可以实现uboot在Nand Flash上的启动,擦写NF和引导Linux内核还没整明白。
一开始准备上sourceforge下的,不知怎么回事,就是上不去,于是改去www.denx.de上下载个最新版本的u-boot 1.2.0。下来之后在/usr/src中tar jxvf u-boot-1.2.0.tar.bz2解压缩了,进入代码目录,然后把board/smdk2410目录给cp成board/py2410,这个 py2410是我给自己板子起的名字,其他名字也可以,无特定要求。然后cd board/py2410,把里面的smdk2410.c改名称py2410.c(要与板子名称一致)。并且把 include/configs/smdk2410.h给cp成include/configs/py2410.h。最后退到源代码目录的根处,把 Makefile里面加上:
py2410_config: unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t py2410 NULL s3c24x0
并找到
ifeq($(ARCH), arm)
CROSS_COMPILE = arm-linux
在这里修改交叉编译工具的路径。这里有个问题,第一次我使用的是2.95.3的arm-linux-gcc,编译了一下不好使,说是一个什么符号不识别。然后我就改用了3.3.2版本的工具,然后问题解决。因为在网上搜帖子看到的大部份人编译uboot 1.1.3用的是2.95.3,难道1.2.0的时候不好使了?所以比较疑惑,有时间再研究一下这个地方。
做好以上工作之后就可以build一下了
make py2410_config
make all
一阵编译之后,没有问题,生成了u-boot.bin等文件,但是这个如果现在就下载到板子上用,那基本上是不好使的,所以接下来就开始修改一些参数,添加一些代码,使其能正常工作。
上网搜索了一下uboot移植的帖子,以下这个比较不错,很详细:
这个帖子说的是移植到arm7上的,可以参考一下移植过程以及了解一下uboot工作的方式
http://www.icwin.net/ShowArtitle.ASP?art_id=6598&cat_id=16
所谓修改参数主要是指修改在include/configs/py2410.h中定义的一些宏,这个文件里定义了像CPU频率,网卡地址,SDRAM的某些设置也都在这里。主要修改如下:
/*cs8900网卡的设置*/
#define CONFIG_DRIVER_CS8900 1 //使用cs8900的驱动
#define CS8900_BASE 0x19000300 //网卡的地址,如要变动,则需查阅板子的手册
#define CS8900BUS16 1
/*设置波特率*/
#define CONFIG_BAUDRATE 115200
下面是选择要编译的命令,这些命令是在uboot启动之后可以在提示符下使用的,具体含义README中有详细说明,需要指出的是,ping的功能得自己手动加上去,CONFIG_CMD_DEL中没有ping,将这里修改如下:
#define CONFIG_COMMANDS
(CONFIG_CMD_DFL |
CFG_CMD_CACHE |
/*CFG_CMD_NAND | */
/*CFG_CMD_EEPROM |*/
/*CFG_CMD_I2C |*/
/*CFG_CMD_USB |*/
CFG_CMD_PING |
CFG_CMD_REGINFO |
CFG_CMD_DATE |
CFG_CMD_ELF)
这里关于nand的命令先没加上,因为擦写nand的功能还没搞明白
下面是关于网络的一些环境变量的设置(这些变量都可以在uboot起来之后重新修改):
#define CONFIG_BOOTDELAY 5
#define CONFIG_BOOTARGS "root=/dev/mtdblock2 loadramfs=0 devfs=mount mem=64M init=/linuxrc console=ttyS0,115200"
#define CONFIG_ETHADDR 00:00:C0:FF:EE:08
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 10.0.0.110
#define CONFIG_SERVERIP 10.0.0.100
有关于网卡mac地址,ip地址,以及tftp服务器的ip的设置,还有linux内核启动的参数等
接下来非常重要,使关于SDRAM的设置:
#define CONFIG_NR_DRAM_BANKS 1
#define PHYS_SDRAM_1 0x30000000 //SDRAM的开始地址
#define PHYS_SDRAM_1_SIZE 0x04000000 //SDRAM的大小,这里是64MB
py2410.h中基本修改这些就可以了,然后打开board/py2410/lowlevel_init.S文件:
按照板子上的实际情况的分配来修改以下寄存器的值。我是按照原来板子上给的bootloader中的设置修改的:
#define BWSCON 0x48000000 //这个是SFR区中控制SDRAM的寄存器的基址
/* BWSCON */
#define DW8 (0x0)
#define DW16 (0x1)
#define DW32 (0x2)
#define WAIT (0x1<<2)
#define UBLB (0x1<<3)
#define B1_BWSCON (DW32)
#define B2_BWSCON (DW16)
#define B3_BWSCON (DW16 + WAIT + UBLB)
#define B4_BWSCON (DW16)
#define B5_BWSCON (DW16)
#define B6_BWSCON (DW32)
#define B7_BWSCON (DW32)
/* BANK0CON */
#if 0
#define B0_Tacs 0x0 /* 0clk */
#define B0_Tcos 0x0 /* 0clk */
#define B0_Tacc 0x7 /* 14clk */
#define B0_Tcoh 0x0 /* 0clk */
#define B0_Tah 0x0 /* 0clk */
#define B0_Tacp 0x0
#define B0_PMC 0x0 /* normal */
#endif
#define B0_Tacs 0x3 /* 0clk */
#define B0_Tcos 0x3 /* 0clk */
#define B0_Tacc 0x7 /* 14clk */
#define B0_Tcoh 0x3 /* 0clk */
#define B0_Tah 0x3 /* 0clk */
#define B0_Tacp 0x1
#define B0_PMC 0x0 /* normal */
/* BANK1CON */
#define B1_Tacs 0x3 /* 0clk */
#define B1_Tcos 0x3 /* 0clk */
#define B1_Tacc 0x7 /* 14clk */
#define B1_Tcoh 0x3 /* 0clk */
#define B1_Tah 0x3 /* 0clk */
#define B1_Tacp 0x3
#define B1_PMC 0x0
#define B2_Tacs 0x0
#define B2_Tcos 0x0
#define B2_Tacc 0x7
#define B2_Tcoh 0x0
#define B2_Tah 0x0
#define B2_Tacp 0x0
#define B2_PMC 0x0
#define B3_Tacs 0x0 /* 0clk */
#define B3_Tcos 0x0 /* 4clk */
#define B3_Tacc 0x7 /* 14clk */
#define B3_Tcoh 0x0 /* 1clk */
#define B3_Tah 0x0 /* 0clk */
#define B3_Tacp 0x0 /* 6clk */
#define B3_PMC 0x0 /* normal */
#define B4_Tacs 0x0 /* 0clk */
#define B4_Tcos 0x0 /* 0clk */
#define B4_Tacc 0x7 /* 14clk */
#define B4_Tcoh 0x0 /* 0clk */
#define B4_Tah 0x0 /* 0clk */
#define B4_Tacp 0x0
#define B4_PMC 0x0 /* normal */
#define B5_Tacs 0x0 /* 0clk */
#define B5_Tcos 0x0 /* 0clk */
#define B5_Tacc 0x7 /* 14clk */
#define B5_Tcoh 0x0 /* 0clk */
#define B5_Tah 0x0 /* 0clk */
#define B5_Tacp 0x0
#define B5_PMC 0x0 /* normal */
#define B6_MT 0x3 /* SDRAM */
#define B6_Trcd 0x1
#define B6_SCAN 0x1 /* 9bit */
#define B7_MT 0x3 /* SDRAM */
#define B7_Trcd 0x1 /* 3clk */
#define B7_SCAN 0x1 /* 9bit */
/* REFRESH parameter */
#define REFEN 0x1 /* Refresh enable */
#define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */
#define Trp 0x0 /* 2clk */
#define Trc 0x3 /* 7clk */
#define Tchr 0x2 /* 3clk */
#define REFCNT 1113 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */
/**************************************/
别的基本不用动了,然后重新编译uboot:
make distclean
make py2410_config
make all
把生成的u-boot.bin通过原来板子上厂家给的bootloader下载到内存中去,然后用原来的bootloader运行u-boot.bin,这时应该可以看到串口上输出的信息了:
U-Boot 1.2.0 (Feb 2 2007 – 00:49:08)
DRAM: 64 MB
Flash: 512 kB
*** Warning – bad CRC, using default environment
In: serial
Out: serial
Err: serial
PY2410 #
然后ping一下tftp服务器(事先要准备好tftp server,这里地址是10.0.0.100)
PY2410 #ping 10.0.0.100
host 10.0.0.100 is alive
PY2410 #
说明网络功能ok,试着下载一个zImage,然后用go运行一下,结果内核解压缩之后就停在那里了,可能是文件系统没load进去?目前还没解决引导的问题。
至此,uboot已经可以在ram中跑了,下面弄nand flash boot,好把它给烧到flash中去
上网再搜索一番,发现了一篇相当不错的文章:
http://blog.csdn.net/bekars/archive/2006/05/06/710888.aspx
照着文章开始修改u-boot,主要修改如下:
1)先在board/py2410目录下新建一个nand_read.c,内容如下:
#include <config.h>
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define NF_BASE 0x4e000000
#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
inline void wait_idle(void) {
int i;
while(!(NFSTAT & BUSY))
for(i=0; i<10; i++);
}
#define NAND_SECTOR_SIZE 512
#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE – 1)
/* low level nand read function */
int
nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
{
int i, j;
if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
return -1; /* invalid alignment */
}
/* chip Enable */
NFCONF &= ~0x800;
for(i=0; i<10; i++);
for(i=start_addr; i < (start_addr + size);) {
/* READ0 */
NFCMD = 0;
/* Write Address */
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++;
}
}
/* chip Disable */
NFCONF |= 0x800; /* chip disable */
return 0;
}
2)修改board/py2410下的Makefile,要不没法编译:
OBJS := py2410.o flash.o nand_read.o
3)在cpu/arm920t/start.S的
ldr pc, _start_armboot前加入
#ifdef CONFIG_S3C2410_NAND_BOOT
bl copy_myself
@ jump to ram
ldr r1, =on_the_ram
add pc, r1, #0
nop
nop
1: b 1b @ infinite loop
on_the_ram:
#endif
然后在最后加上:
#ifdef CONFIG_S3C2410_NAND_BOOT
copy_myself:
mov r10, lr
@ reset NAND
mov r1, #NAND_CTL_BASE
ldr r2, =0xf830 @ initial value
str r2, [r1, #oNFCONF]
ldr r2, [r1, #oNFCONF]
bic r2, r2, #0x800 @ enable chip
str r2, [r1, #oNFCONF]
mov r2, #0xff @ RESET command
strb r2, [r1, #oNFCMD]
mov r3, #0 @ wait
1:add r3, r3, #0x1
cmp r3, #0xa
blt 1b
2:ldr r2, [r1, #oNFSTAT] @ wait ready
tst r2, #0x1
beq 2b
ldr r2, [r1, #oNFCONF]
orr r2, r2, #0x800 @ disable chip
str r2, [r1, #oNFCONF]
@ get read to call C functions (for nand_read())
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
@ copy vivi to RAM
ldr r0, =UBOOT_RAM_BASE
mov r1, #0x0
mov r2, #0x20000
bl nand_read_ll
tst r0, #0x0
beq ok_nand_read
#ifdef CONFIG_DEBUG_LL
bad_nand_read:
ldr r0, STR_FAIL
ldr r1, SerBase
bl PrintWord
1:b 1b @ infinite loop
#endif
ok_nand_read:
#ifdef CONFIG_DEBUG_LL
ldr r0, STR_OK
ldr r1, SerBase
bl PrintWord
#endif
@ verify
mov r0, #0
ldr r1, =UBOOT_RAM_BASE
mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes
go_next:
ldr r3, [r0], #4
ldr r4, [r1], #4
teq r3, r4
bne notmatch
subs r2, r2, #4
beq done_nand_read
bne go_next
notmatch:
#ifdef CONFIG_DEBUG_LL
sub r0, r0, #4
ldr r1, SerBase
bl PrintHexWord
ldr r0, STR_FAIL
ldr r1, SerBase
bl PrintWord
#endif
1:b 1b
done_nand_read:
#ifdef CONFIG_DEBUG_LL
ldr r0, STR_OK
ldr r1, SerBase
bl PrintWord
#endif
mov pc, r10
@ clear memory
@ r0: start address
@ r1: length
mem_clear:
mov r2, #0
mov r3, r2
mov r4, r2
mov r5, r2
mov r6, r2
mov r7, r2
mov r8, r2
mov r9, r2
clear_loop:
stmia r0!, {r2-r9}
subs r1, r1, #(8 * 4)
bne clear_loop
mov pc, lr
#endif @ CONFIG_S3C2410_NAND_BOOT
.align 2
DW_STACK_START:
.word STACK_BASE+STACK_SIZE-4
这几段的意思是说uboot把自己copy到SDRAM中,然后在ram中执行_start_armboot开始的程序
4)最后一步,在include/configs/py2410.h中加上:
/*
* Nandflash Boot
*/
#define CONFIG_S3C2410_NAND_BOOT 1
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x8000
#define UBOOT_RAM_BASE 0x33f80000
/* NAND Flash Controller */
#define NAND_CTL_BASE 0x4E000000
#define bINT_CTL(Nb) __REG(INT_CTL_BASE + (Nb))
/* Offset */
#define oNFCONF 0x00
#define oNFCMD 0x04
#define oNFADDR 0x08
#define oNFDATA 0x0c
#define oNFSTAT 0x10
#define oNFECC 0x14
这是定义了SFR区中和Nand Flash控制器相关的寄存器地址,具体参加芯片手册
最后重新编译u-boot:
make distclean
make py2410_config
make all
把生成的u-boot.bin烧写到板子上Nand Flash的0x0处,reset开发板,就可以看到启动信息了。
目前只进行到这里,还有u-boot读写flash的功能以及bootloader最重要的引导操作系统的功能还没整出来,网上的资料很多都是1.1.x版本的uboot,与1.2.0版本有些不同,比如在说擦写falsh的问题时,不少人指出uboot里的nand_init函数没有实现,需要自己添加,但是在1.2.0版本的uboot中是存在这个函数的(drivers/nand/nand.c里,这个版本比1.1.x多了个nand目录),总之看来区别还是不少,具体情况准备明天去denx.de看看文档再说。
PS:我用的是优龙的板子,他们给的jtag小板的并口接头外面居然多了一个铁圈,还有两边的那种可以拧进去螺丝的螺丝,好像是准备让别的母口的头插进来似的,于是没辙,只能拿钳子把螺丝给卸了,现在并口插头上就是25根“针头”,插在笔记本后面晃晃荡荡的
转载请注明:在路上 » 移植U-Boot手记