u-boot-1.1.4在yl2410上的移植过程

ARM 76浏览

一、u-boot-1.1.4在yl2410上的移植过程:
1. 例行准备
3.2.1 修改Makefile
[uboot@localhost uboot]#vi Makefile
#为crane2410建立编译项
yl2410_config : unconfig
@./mkconfig $(@:_config=) arm arm920t yl2410 NULL s3c24x0
各项的意思如下:
arm: CPU的架构(ARCH)
arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录。
yl2410: 开发板的型号(BOARD),对应于board/yl2410目录。
NULL: 开发者/或经销商(vender)。
s3c24x0: 片上系统(SOC)。
3.2.2 在board子目录中建立yl2410
#cp rf board/smdk2410 board/yl2410
#cd board/yl2410
#mv smdk2410.c yl2410.c
3.2.3 在include/configs/中建立配置头文件
#cd ../..
#cp include/configs/smdk2410.h include/configs/yl2410.h
3.2.4 指定交叉编译工具的路径
#vi ~/.bashrc
export PATH=/usr/local/arm/2.95.3/bin:$PATH
3.2.5 测试编译能否成功
#make yl2410_config /*产生include/config.mk*/
#make

1. 在make的过程中,出现:cc1: invalid option `abi=apcs-gnu'
解决方法:
出错的文件是/cpu/s3c44b0/下的config.mk:将
PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu)
改成:
PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,$(call cc-option,-mabi=apcs-gnu),)

2. 修改了第一个错误后,继续make,出现了如下的报错:
make[1]: *** No rule to make target `hello_world.srec', needed by `all'.  Stop.
make[1]: Leaving directory `/home/mort/src/targa/u-boot/u-boot-TOT/examples'
make: *** [examples] Error 2
解决方法:
修改examples/Makefile
把126行和129行改为:
     %.srec: %.o
     %.bin: %.o
继续make

3. 出现 crane2410.a needed by smdk2410.o
解决方法:
修改board/crane2410/Makefile
将28行的
OBJS    := smdk2410.o flash.o
改为
OBJS    := crane2410.o flash.o
继续make获得u-boot

4. 初步调试,主要是在sdram上调试要打开CONFIG_SKIP_LOWLEVEL_INIT
即可看到打印信息

5. 读写NorFlash(SST39VF1601)
在include/configs/yl2410.h添加
#ifdef CONFIG_SST_39VF1601
#define PHYS_FLASH_SIZE  0x00200000 /* 2MB */
#define CFG_MAX_FLASH_SECT (35) /* max number of sectors on one chip */
#define CFG_ENV_ADDR  (CFG_FLASH_BASE + 0x1F0000) /* addr of environment */
#endif
修改board/yl2410/flash.c 参考board/dave/common/flash.c
#elif defined(CONFIG_SST_39VF1601)
   (SST_MANUFACT & FLASH_VENDMASK) |
   (SST_ID_xF1601 & FLASH_TYPEMASK);
在int flash_erase (flash_info_t * info, int s_first, int s_last)
#if defined(CONFIG_SST_39VF1601) /* Ali + */
   *addr = CMD_ERASE_BLOCK;
#else
   *addr = CMD_ERASE_CONFIRM;
#endif
在volatile static int write_hword (flash_info_t * info, ulong dest, ushort data)
#if defined(CONFIG_SST_39VF1601) /* Ali + */
 MEM_FLASH_ADDR1 = CMD_PROGRAM;
#else
 MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;
 *addr = CMD_PROGRAM;
#endif
即可正确操作flash,其中monitor_flash_len(_bss_start - _armboot_start)和环境参数保存区是受保护的,标示为(RO)

6. 从norflash启动
打开选项CONFIG_S3C2410_NOR_BOOT
编译生成u-boot.bin
Loadb 0x32000000 115200 (set baud rate to 115200,download u-boot to 0x32000000 by Kermit protocol)
Cp.b 0x32000000 0 0x20000 (u-boot write to norflash)
重启,OK

7. 如要看到调试信息
在include/configs/yl2410.h添加
#define DEBUG

8. 打ping命令时,输出“*** ERROR: `ethaddr' not set”,板上网卡CS8900本身没有固化MAC地址,自己在include/configs/yl2410.h设定一个,或者运行时设定环境参数,接下来使用ping和tftp都正常

9. 支持nandflash读写
在include/configs/yl2410.h添加CFG_CMD_NAND
编译,在cmd_nand.c产生很多错误,原因是yl2410根本就没有nandflash的驱动支持,如:
NAND_DISABLE_CE()
NAND_ENABLE_CE()
NAND_WAIT_READY()
WRITE_NAND_COMMAND()
WRITE_NAND_COMMANDW()
WRITE_NAND_ADDRESS()
WRITE_NAND()
这些函数的实现都很简单,参考at91rm9200dk.h,对nand的驱动支持全部添加在include/configs/yl2410.h
加载运行,nand write 0x32000000 0x20000 0x200 (向nand flash写512字节),报错,nand_write_page : Failed write verify, 应该是sector(page)没擦除,nand erase 0x20000 0x200,出错,提示边界没对齐,查得资料获知,erase单位是一个block(16k),program单位是一个sector(512B),按要求先擦除后写入,正确

10. 支持nandflash启动
在cpu/arm920t/start.S添加对nandflash重定位的支持,在board/yl2410/nand_boot.c添加对nandflash的初始化和读取操作,在nandflash启动时被start.s调用,注意nand_boot.c的所有代码以及被调用的代码不能超出4k,因为按nandflash启动模式,开始只有4k的运行空间。
编译获得u-boot.bin
Tftp 0x32000000 u-boot.bin (load u-boot.bin to 0x32000000)
Nand erase 0 0x20000 (erase nandflash first 128k)
Nand write 0x32000000 0 0x20000 (write u-boot.bin to nandflash)
设置跳线到nandflash启动模式,重启即可

二、流程图
 

 
三、答疑
1. 关于入口地址
在board/yl2410/u-boot.lds:
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
 . = 0x00000000;

 . = ALIGN(4);
 .text      :
 {
   cpu/arm920t/start.o (.text)
   *(.text)
 }

}
_start的入口地址为0x00000000,为何编译出来的代码。链接地址是从0x33f80000(TEXT_BASE)开始的?
答:
lds文件中的起始地址为0x00000000是不起作用的,由链接参数替代的。见u-boot-1.1.4/config.mk,L145:LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)

2. 关于ADR的编译原理
adr r0, _start  /* r0 <- current position of code   */
_start在flash运行是0,在sdram运行是0x33f80000
答:
伪指令:ADR;ADRL;ALIGN;DCx;EQUx;OPT
ADR:小范围的地址读取伪指令.ADR 指令将基于PC 相对偏移的地址值读取到寄存器中.
在汇编编译源程序时,ADR 伪指令被编译器替换成一条合适的指令.通常,编译器用一条
ADD 指令或SUB 指令来实现该ADR 伪指令的功能,若不能用一条指令实现,则产生错误,
编译失败.
所以adr r0, _start,实际产生的汇编是sub      r0,pc,#0x9c ; #0x33f80000

3. 关于nandflash启动
如何保证nandflash启动模式下,启动代码定位在前4k
一个是直接在start.s用汇编写nandflash的初始化和重定位代码,或者用C写nandflash启动代码nand_boot.c,进而修改编辑board/yl2410/u-boot.lds
在 *(.text) 之前添加board/yl2410/nand_boot.o (.text)(当然,运气好的话,不用也可以)
为了避免代码运行超出4k,nand_boot.c不能调用其它库函数,不能引用数据段(.data)的数据,因为*(.data)在*(.text)之后,超出了4k。
注意:在修改cpu/arm920t/start.S, nandflash启动模式不能引用_TEXT_BASE,因为
_TEXT_BASE:
 .word TEXT_BASE
放于数据段,超出了4k的限制,可以用立即数或者宏定义替代。

4. nandflash启动模式下保存环境变量
u-boot启动后,出现“Warning - bad CRC, using default environment”,没有正确的环境变量。
查看S3C2410的数据手册,在图表“S3C2410A Memory Map after Reset”中显示,如果“Using NAND flash for boot ROM”,bank 0(128M)仅映射到片内的4k sram,所以同时位于bank 0的norflash无效,这时候的环境变量只能保存于nandflash,修改include/configs/yl2410.h相关的宏定义,重新烧入到nandflash,启动后,输入“saveenv”即可。