
一、获得U-Boot源码
我们的光盘中提供了直接从U-Boot的官方网站下载的源代码,版本是1.3.2.,放在src目录下。将u-boot-1.3.2.tar.bz2拷贝了工作目录下,解压源码包:
[root@vm-dev 2410-s]# pwd
/root/2410-s
[root@vm-dev 2410-s]# cp /mnt/hgfs/e/u-boot-1.3.2.tar.bz2 ./
[root@vm-dev 2410-s]# tar jxvf u-boot-1.3.2.tar.bz2
[root@vm-dev 2410-s]# cd u-boot.1.3.2
二、建立板级支持包
在board目录下,每一块开发板都有一个对应的目录,因此我们需要为我们的开发板建立一个目录,名字叫做up2410,并创建相应的文件:
[root@vm-dev u-boot-1.3.2]# cd board/
[root@vm-dev board]# mkdir up2410
[root@vm-dev board]# cp smdk2410/* up2410
[root@vm-dev board]# cd ../
上面的步骤中,我们把smdk2410目录下的所有文件都拷贝到了我们的up2410目录下,因为我们的开发板和smdk2410开发板的配置差不多。
每个开发板都有一个自己的配置文件,如smdk2410开发板的配置文件为include/configs/smdk2410.h,我们也需要为我们的开发板建立自己的配置文件。可以直接从smdk2410开发板的配置文件中修改而来。因此我们先把smdk2410的配置文件复制到我们开发板的配置文件当中:
[root@vm-dev u-boot-1.3.2]# cp include/configs/smdk2410.h include/configs/up2410.h
然后,修改Makefile,使得可以配置我们的开发板:
[root@vm-dev u-boot-1.3.2]# vi Makefile
在Makefile中找到下面两行:
smdk2400_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2400 NULL s3c24x0
紧接这这两行添加如下两行:
up2410_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t up2410 NULL s3c24x0
注意第二行开始部分的空白是按TAB键获得的!红色的部分显示了不同处!
这样,我们自己的板级支持包就建好了。
三、添加代码,支持从Nand Flash启动
由于我们的开发板上没有Nor Flash,只能从Nand Flash启动。而U-Boot默认不支持从Nand Flash启动,所以需要我们自己添加代码来实现从Nand Flash启动。
1、 修改start.S文件
位于cpu/arm920t/目录下的start.S文件是开发板上电后运行的第一段代码,需要在这个文件中添加内容,以支持从Nand Flash启动。
[root@vm-dev u-boot-1.3.2]# vi cpu/arm920t/start.S
首先,删掉start.S中的第181行和201行的下面内容:
#ifdef CONFIG_AT91RM9200
...............................................................
#endif
如果有这两句,这两句之间的内容将不会被编译。而我们的开发板需要执行这些内容。然后,找到这一行:
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
在紧接这这行的下面添加下面几行:
#ifdef CONFIG_S3C2410_NAND_BOOT
bl copy_myself
#else
再找到
ble copy_loop
在它的下面添加一行:
#endif
做这些工作就是要完成一个简单的功能:如果我们定义了CONFIG_S3C2410_NAND_BOOT这个宏,那么就执行copy_myself这个子程序,否则就执行#else下面的程序。copy_myself这个子程序的功能就是把U-Boot自身的代码从Nand Flash拷贝到SDRAM中,需要我们自己实现,U-Boot自身并没有为我们实现。
我们把copy_myself也添加在start.S文件中。找到下面的一行:
_start_armboot: .word start_armboot
在这一行的下面添加如下的内容:
/*
*************************************************************************
*
* copy u-boot to ram
*
*************************************************************************
*/
#ifdef CONFIG_S3C2410_NAND_BOOT
copy_myself:
mov r10, lr @save return address to r10
ldr sp, DW_STACK_START
mov fp, #0
bl NF_Init
ldr r0, =UBOOT_RAM_BASE
mov r1, #0x0
mov r2, #0x30000
bl nand_read_whole
tst r0, #0x0
beq ok_nand_read
1: b 1b
ok_nand_read:
mov r0, #0x00000000
ldr r1, =UBOOT_RAM_BASE
mov r2, #0x400
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:
1: b 1b
done_nand_read:
mov pc, r10
#endif
DW_STACK_START:
.word STACK_BASE+STACK_SIZE-4
上面是copy_myself的实现代码,添加完成以后,U-Boot启动时就会执行我们的这段代码,将U-Boot的内容从Flash中拷贝到SDRAM中。
这样,start.S这个文件就修改完成了,保存刚才的修改。
2、 添加nand.c文件
在copy_mysel这段程序中,我们调用了nand_read_whole子程序。这个程序是用C程序实现的,我们新建一个文件,board/up2410/nand.c,在这个文件中实现它:
#include #include #include #define TACLS 0 #define TWRPH0 3 #define TWRPH1 0 #define U32 unsigned int extern unsigned long nand_probe(unsigned long physadr); static void NF_Reset(void) { int i; NF_nFCE_L(); NF_CMD(0xFF); for(i=0;i<10;i++); NF_WAITRB(); NF_nFCE_H(); } void NF_Init(void) { rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); NF_Reset(); } int nand_read_whole(unsigned char *buf, unsigned long start_addr, int size) { int i, j; if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) return 1; NF_nFCE_L(); for(i=0; i<10; i++); i = start_addr; while(i < start_addr + size) { rNFCMD = 0; rNFADDR = i & 0xff; rNFADDR = (i >> 9) & 0xff; rNFADDR = (i >> 17) & 0xff; rNFADDR = (i >> 25) & 0xff; NF_WAITRB(); for(j=0; j < NAND_SECTOR_SIZE; j++, i++) { *buf = (rNFDATA & 0xff); buf++; } } NF_nFCE_H(); return 0; } 上面就是nand.c文件的全部内容。为了使编译的时候能把这个文件编译进去,需要修改相应的Makefile: [root@vm-dev u-boot-1.3.2]# vi board/up2410/Makefile 找到这一行: COBJS := smdk2410.o flash.o 把这行的内容改为下面这行: COBJS := smdk2410.o flash.o nand.o 即在行尾加上了nand.o,这样,编译的时候就会把nand.c编译进去,并进行链接。 3、 修改up2410.h 前面提到,up2410.h是开发板的配置文件。关于nand.c中用到的一些宏或者其他需要定义的,我们都放在up2410.h中。注意,这里只介绍和从Nand启动相关的配置,因为up2410.h中还有很多其他配置,将在后面介绍! [root@vm-dev u-boot-1.3.2]# vi include/configs/up2410.h 光标移动到文件的末尾,在文件的最后一个#endif的前面添加如下内容: #define CONFIG_S3C2410_NAND_BOOT 1 #define STACK_BASE 0x33f00000 #define STACK_SIZE 0x8000 #define UBOOT_RAM_BASE 0x33f80000 #define CFG_NAND_BASE 0x4E000000 #define CFG_MAX_NAND_DEVICE 1 #define SECTORSIZE 512 #define NAND_SECTOR_SIZE SECTORSIZE #define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1) #define ADDR_COLUMN 1 #define ADDR_PAGE 2 #define ADDR_COLUMN_PAGE 3 #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 #define NAND_MAX_CHIPS 1 #define WRITE_NAND_COMMAND(d, adr) do {rNFCMD = d;} while(0) #define WRITE_NAND_ADDRESS(d, adr) do {rNFADDR = d;} while(0) #define WRITE_NAND(d, adr) do {rNFDATA = d;} while(0) #define READ_NAND(adr) (rNFDATA) #define NAND_WAIT_READY(nand) {while(!(rNFSTAT&(1<<0)));} #define NAND_DISABLE_CE(nand) {rNFCONF |= (1<<11);} #define NAND_ENABLE_CE(nand) {rNFCONF &= ~(1<<11);} #define NAND_CTL_CLRALE(nandptr) #define NAND_CTL_SETALE(nandptr) #define NAND_CTL_CLRCLE(nandptr) #define NAND_CTL_SETCLE(nandptr) #define CONFIG_MTD_NAND_VERIFY_WRITE 1 #define rNFCONF (*(volatile unsigned int *)0x4e000000) #define rNFCMD (*(volatile unsigned char *)0x4e000004) #define rNFADDR (*(volatile unsigned char *)0x4e000008) #define rNFDATA (*(volatile unsigned char *)0x4e00000c) #define rNFSTAT (*(volatile unsigned int *)0x4e000010) #define rNFECC (*(volatile unsigned int *)0x4e000014) #define rNFECC0 (*(volatile unsigned char *)0x4e000014) #define rNFECC1 (*(volatile unsigned char *)0x4e000015) #define rNFECC2 (*(volatile unsigned char *)0x4e000016) #define NF_CMD(cmd) {rNFCMD=cmd;} #define NF_ADDR(addr) {rNFADDR=addr;} #define NF_nFCE_L() {rNFCONF&=~(1<<11);} #define NF_nFCE_H() {rNFCONF|=(1<<11);} #define NF_RSTECC() {rNFCONF|=(1<<12);} #define NF_RDDATA() (rNFDATA) #define NF_WRDATA(data) {rNFDATA=data;} #define NF_WAITRB() {while(!(rNFSTAT&(1<<0)));} 这样,关于从Nand启动的修改就做完了。保存文件。 三、开发板的配置 前面已经提到,up2410.h是我们的开发板的配置文件,许多重要的内容都需要在这个文件中进行配置。 1、 网卡配置 Smdk2410开发板上用的是CS00网卡,而我们的开发板上使用的是AX88796网卡,因此网卡的配置需要修改。找到下面三行: #define CONFIG_DRIVER_CS00 1 /* we have a CS00 on-board */ #define CS00_BASE 0x19000300 #define CS00_BUS16 1 /* the Linux driver does accesses as shorts */ 注释掉这三行,在这三行下面添加下面的两行: #define CONFIG_DRIVER_NE2000 1 #define CONFIG_DRIVER_NE2000_BASE (0x10000000+0x200) 这样定义主要是因为U-Boot中并没有专门为AX88796网卡实现驱动,但是AX88796网卡和NE2000网卡是寄存器兼容的,因此,可以使用NE2000网卡的驱动。但是需要一定的修改,我们将在后面介绍。 2、 添加命令 U-Boot中提供了丰富的命令,smdk2410开发板配置了一部分命令,我们为我们的开发板增加一些命令。找到下面的几行: #define CONFIG_CMD_CACHE #define CONFIG_CMD_DATE #define CONFIG_CMD_ELF 在其下面添加下面几行: #define CONFIG_CMD_REGINFO #define CONFIG_CMD_NAND #define CONFIG_CMD_PING #define CONFIG_CMD_DLF #define CONFIG_CMD_ENV #define CONFIG_CMD_NET 这样就添加了一些我们需要的命令。 3、 修改环境变量 环境变量是U-Boot运行时或者传递给内核的重要参数,需要正确设置。找到下面的一行: #define CONFIG_BOOTDELAY 3 /*#define CONFIG_BOOTARGS "root=ramfs devfs=mount console=ttySA0,9600" */ /*#define CONFIG_ETHADDR 08:00:3e:26:0a:5b */ #define CONFIG_NETMASK 255.255.255.0 #define CONFIG_IPADDR 10.0.0.110 #define CONFIG_SERVERIP 10.0.0.1 /*#define CONFIG_BOOTFILE "elinos-lart" */ /*#define CONFIG_BOOTCOMMAND "tftp; bootm" */ #if defined(CONFIG_CMD_KGDB) 注意上面的#if defined(CONFIG_CMD_KGDB)处,需要做的修改都在这之前进行修改。修改后的代码如下: #define CONFIG_BOOTDELAY 3 #define CONFIG_BOOTARGS "root=/dev/mtdblock3 init=/linuxrc console=ttySAC0,115200" #define CONFIG_ETHADDR 08:00:3e:26:0a:5b #define CONFIG_NETMASK 255.255.255.0 #define CONFIG_IPADDR 192.168.1.131 #define CONFIG_SERVERIP 192.168.1.132 #define CONFIG_BOOTFILE "uImage" #define CONFIG_BOOTCOMMAND "tftp; bootm" #define CONFIG_CMDLINE_TAG 1 #define CONFIG_SETUP_MEMORY_TAGS 1 #define CONFIG_INITRD_TAG 1 #if defined(CONFIG_CMD_KGDB) 上面添加的环境变量在U-Boot启动时作为U-Boot的默认环境变量,如果不执行saveenv命令,则这些变量只存在于SDRAM中;执行saveenv命令后,这些便量会保存到Flash中,下次上电,在从Flash中把它读出来,作为环境变量使用。 4、 修改命令提示符 找到下面一行: #define CFG_PROMPT "SMDK2410 # " /* Monitor Command Prompt */ 修改为: #define CFG_PROMPT "[UP-2410-S #]" 这样,U-Boot的命令提示符就是[UP-2410-S #]。这样做只是为了使用的时候知道我们使用的是UP-2410-S开发板上Bootloader,当然不改的话,也没有什么影响。 5、 修改默认下载地址 找到下面的一行: #define CFG_LOAD_ADDR 0x33000000 /* default load address */ 这个变量定义的是在使用串口或者网卡下载文件到SDRAM时,如果不指定下载地址,则下载到这个宏指定的默认地址。我们用下面的两行来替代: #define CFG_LOAD_ADDR 0x30008000 #define CFG_TFTP_LOAD_ADDR 0x30008000 6、 修改环境变量在Flash中的存储地址 找到下面的两行: #define CFG_ENV_IS_IN_FLASH 1 #define CFG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */ 上面的定义说明环境变量是存在Flash中。我们的板子上只有Nand Flash,因此环境变量只能存在Nand Flash中。因此,注释掉上面的两行,用下面的几行代替: #define CFG_ENV_IS_IN_NAND 1 #define CFG_ENV_SIZE 0x4000 #define CFG_ENV_OFFSET (0x80000-0x4000) 表示环境变量存储在Nand Flash中,大小为16KB,起始地址是0.5M往下的16KB地址处。这样的话,U-Boot占用的Flash地址是前0.5M,对U-Boot来说,已经足够了。 到这里,配置文件的修改就完成了。 四、修改网卡驱动 前面提到,我们的开发板上是AX88796网卡。该网卡使用NE2000网卡的驱动,但是U-Boot中的 NE2000网卡驱动是使用的8位数据接口,而我们的开发板上的AX88796网卡和CPU之间是通过16位的数据接口连接的,需要做一定的修改。 由于网卡驱动需要修改的地方比较多,在这个文档里就不在详细说明了.我们直接给出修改后的驱动文件,位于光盘的src目录下。共三个文件:ne2000.c、ne2000.h和8390.h.把这三个拷贝到u-boot源代码目录下的drivers/net下,替换掉U-Boot自身的驱动文件。 [root@vm-dev u-boot-1.3.2]# cp /mnt/hgfs/e/ne2000.c drivers/net/ cp:是否覆盖‘drivers/net/ne2000.c’? y [root@vm-dev u-boot-1.3.2]# cp /mnt/hgfs/e/ne2000.h drivers/net/ cp:是否覆盖‘drivers/net/ne2000.h’? y [root@vm-dev u-boot-1.3.2]# cp /mnt/hgfs/e/8390.h drivers/net/ cp:是否覆盖‘drivers/net/8390.h’? y [root@vm-dev u-boot-1.3.2]# 五、编译U-Boot 首先运行如下命令配置U-Boot: [root@vm-dev u-boot-1.3.2]# make up2410_config Configuring for up2410 board... [root@vm-dev u-boot-1.3.2]# 然后运行make命令编译: [root@vm-dev u-boot-1.3.2]# make 编译完成后,会在U-Boot的源代码目录下生成u-boot.bin文件。这个文件就是我们需要的二进制文件。 六、烧写U-Boot 将编译得到的u-boot.bin拷贝到XP的D盘下,将我们光盘中的sjf2410-s.exe文件也拷贝到D盘下。连接好开发板的电源、JTAG下载线,打开开发板的电源。在电脑桌面的左下角点击开始,找到运行: Beijing Universal Pioneering Technology Co.,LTD. 在打开的菜单中输入cmd,并回车: 这样将会打开一个DOS对话框。在打开的DOS对话框中进入D盘: Microsoft Windows XP [版本 5.1.2600] (C) 版权所有 1985-2001 Microsoft Corp. C:\\Documents and Settings\\Administrator>D: D:\\> 这样就进入了D盘,运行如下命令进行烧写: D:\\>sjf2410-s.exe /f:u-boot.bin 这样就会启动烧写程序。在烧写程序中需要我们做一些选择,要分别输入三次0,然后才开始真正的烧写,烧写完毕后,输入2推出程序。如下面的内容: D:\\>sjf2410-s.exe /f:u-boot.bin +------------------------------------+ | SEC JTAG FLASH(SJF) v 0.7 | | (S3C2410X & SMDK2410 B/D) | | PROVIDED BY KENT 20050628 | | **************** | +------------------------------------+ Usage: SJF /f: > S3C2410X(ID=0x0032409d) is detected. [SJF Main Menu] 0:K9S1208 prog 1:K9F2808 prog 2:28F128J3A prog 3:AM29LV800 Prog 4:Memory Rd/Wr 5:Exit Select the function to test:0 [K9S1208 NAND Flash JTAG Programmer] K9S1208 is detected. ID=0xec76 0:K9S1208 Program 1:K9S1208 Pr BlkPage 2:Exit Select the function to test :0 [SMC(K9S1208V0M) NAND Flash Writing Program] Source size:0h~21237h Available target block number: 0~4095 Input target block number:0 target start block number =0 target size (0x4000*n) =0x24000 STATUS:Epppppppppppppppppppppppppppppppp Epppppppppppppppppppppppppppppppp Epppppppppppppppppppppppppppppppp Epppppppppppppppppppppppppppppppp Epppppppppppppppppppppppppppppppp Epppppppppppppppppppppppppppppppp Epppppppppppppppppppppppppppppppp Epppppppppppppppppppppppppppppppp Epppppppppppppppppppppppppppppppp 0:K9S1208 Program 1:K9S1208 Pr BlkPage 2:Exit Select the function to test :2 D:\\> 七、测试U-Boot 现在U-Boot已经烧写到开发板上了,可以启动开发板检测是否烧写好。连接好开发板和主机之间的串口、网口,断开开发板的JTAG下载线,启动开发板。如果烧写成功,会在串口终端上出现如下内容: U-Boot 1.3.2 (Dec 5 2008 - 10:35:38) DRAM: MB Flash: 512 kB NAND: MiB *** Warning - bad CRC or NAND, using default environment In: serial Out: serial Err: serial Hit any key to stop autoboot: 0 [UP-2410-S #] 注意上面内容中红色的部分,主要是因为我们没有把环境变脸写入Flash。运行如下命令将环境变量写入Flash中: [UP-2410-S #]saveenv Saving Environment to NAND... Erasing Nand...Writing to Nand... done [UP-2410-S #] 运行printenv查看环境变量: [UP-2410-S #]printenv bootargs=root=/dev/mtdblock3 init=/linuxrc console=ttySAC0,115200 bootcmd=tftp; bootm bootdelay=3 baudrate=115200 ethaddr=08:00:3e:26:0a:5b ipaddr=192.168.1.131 serverip=192.168.1.132 netmask=255.255.255.0 bootfile="uImage" stdin=serial stdout=serial stderr=serial Environment size: 265/16380 bytes [UP-2410-S #] 可以看到我们在up2410.h中定义的环境变量都正确地保存下来了。然后检测网络功能: [UP-2410-S #]ping 192.168.1.135 NE2000 - eeprom ESA: 08:00:3e:26:0a:5b host 192.168.1.135 is alive [UP-2410-S #] 返回host 192.168.1.135 is alive,说明网卡已经通了。 另外,还可以运行help命令来查看U-Boot提供的命令及其作用: [UP-2410-S #]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 loady - load binary file over serial line (ymodem mode) 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 reginfo - print register information 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 [UP-2410-S #] 可以尝试运行U-Boot的命令,对所移植的U-Boot进行测试。
