五一就要劳动,写点代码与大家分享哈哈。继 u-boot-2012.10移植一串口正常输出,继续修改代码支持单板NAND启动。最后直接用NOR Flash里的u-boot烧写自己移植的u-boot到NAND,方便电脑没有并口或手上没有openjtag,照样能移植u-boot,当然有openjtag更方便。
开发环境:
系统:ubuntu 10.04.4
单板:tq2440
NAND FLASH:K9F1216U0A 256MB
NOR Flash:AM29LV160A 2MB
SDRAM:HY57V561620 x2 64MB
NET:DM9000AEP
编译器:arm-2009q3-67-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
搭建开发环境详见ubuntu 10.04.4开发环境配置。
目标:
1.支持NOR Flash启动,串口正常输出
2.支持NAND启动
3.支持DM9000网卡
4.添加u-boot菜单
5.裁剪u-boot及制作补丁
NOR Flash是内存接口,能直接运行程序,但是NAND Flash地址线都没有,是不能直接跑程序的。熟悉三星片子的人都知道s3c2440 NAND启动时,CPU会自动从NAND Flash读取前4KB到SRAM,同时把这段片内SRAM映射到nGCS0片选空间即0x0000 0000。而ARM架构的CPU第一条指令是从0地址开始执行的。相当于片内SRAM充当一个载体,把NAND前4KB映射到0地址,CPU开始执行NAND前4KB内容。
change@change:~$ cd Si/TQ2440/u-boot-2012.10/
change@change:~/Si/TQ2440/u-boot-2012.10$ ls u-boot.bin -l
-rw-r--r-- 1 change change 368508 2013-04-30 21:49 u-boot.bin
change@change:~/Si/TQ2440/u-boot-2012.10$
看到生成的u-boot.bin有360KB左右,这个放在NOR Flash里能直接启动,但是不利于NAND启动。u-boot运行后,不管是NNAD还是NOR Flash启动,都会进行重定位,即把代码拷到内存运行,就像PC机一样程序都是在内存运行的。那么支持NAND启动的u-boot,重定位之前代码必须小于4KB,才能跑起来。分析现在较新的u-boot源码(以后在另外文章分析),代码连接时加-pie选项,重定位成位置无关代码,搞的很高级,不利于像S3C2440这样片内SRAM十分有限的SOC跑。这里修改重定位代码,支持NAND启动。
1.去掉-pie选项,不需要附加“*(.rel*)”、“*(.dynsm)”等信息
change@change:~/Si/TQ2440/u-boot-2012.10$ grep "\-pie" * -nR
arch/x86/config.mk:43:LDFLAGS_FINAL += --gc-sections -pie
arch/arm/config.mk:88:LDFLAGS_u-boot += -pie
doc/README.arm-relocation:3:At arch level: add linker flag -pie
change@change:~/Si/TQ2440/u-boot-2012.10$ vim arch/arm/config.mk
去掉88行LDFLAGS_u-boot += -pie
2.参考以前update写的start.S init.c修改代码
在arch/arm/cpu/arm920t/start.S:205行增加如下代码
- ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)/*sp =30000f80*/
- bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
- bl nand_init_ll
- mov r0, #0
- //ldr r1, =_start
- ldr r1, _TEXT_BASE
- //dr r2, =__bss_start
- //sub r2, r2, r1
- ldr r2, _bss_start_ofs
- bl copy_code_to_sdram
- bl clear_bss
- ldr pc, =call_board_init_f
arch/arm/cpu/arm920t/start.S221:注释掉下面2行
//ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
//bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
在arch/arm/cpu/arm920t/start.S:226行增加如下代码
/*unsigned int id */
ldr r1, _TEXT_BASE//*link addres
ldr sp, base_sp
bl board_init_r//*the second step
用自己的重定位代码,去掉u-boot自带的arch/arm/cpu/arm920t/start.S 231:
- /*------------------------------------------------------------------------------*/
- /*
- * void relocate_code (addr_sp, gd, addr_moni)
- *
- * This "function" does not return, instead it continues in RAM
- * after relocating the monitor code.
- *
- */
- .globl relocate_code
- relocate_code:
- mov r4, r0 /* save addr_sp */
- mov r5, r1 /* save addr of gd */
- mov r6, r2 /* save addr of destination */
- /* Set up the stack */
- stack_setup:
- mov sp, r4
- adr r0, _start
- cmp r0, r6
- moveq r9, #0 /* no relocation. relocation offset(r9) = 0 */
- beq clear_bss /* skip relocation */
- mov r1, r6 /* r1 <- scratch for copy_loop */
- ldr r3, _bss_start_ofs
- add r2, r0, r3 /* r2 <- source end address */
- copy_loop:
- ldmia r0!, {r9-r10} /* copy from source address [r0] */
- stmia r1!, {r9-r10} /* copy to target address [r1] */
- cmp r0, r2 /* until source end address [r2] */
- blo copy_loop
- #ifndef CONFIG_SPL_BUILD
- /*
- * fix .rel.dyn relocations
- */
- ldr r0, _TEXT_BASE /* r0 <- Text base */
- sub r9, r6, r0 /* r9 <- relocation offset */
- ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */
- add r10, r10, r0 /* r10 <- sym table in FLASH */
- ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */
- add r2, r2, r0 /* r2 <- rel dyn start in FLASH */
- ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */
- add r3, r3, r0 /* r3 <- rel dyn end in FLASH */
- fixloop:
- ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */
- add r0, r0, r9 /* r0 <- location to fix up in RAM */
- ldr r1, [r2, #4]
- and r7, r1, #0xff
- cmp r7, #23 /* relative fixup? */
- beq fixrel
- cmp r7, #2 /* absolute fixup? */
- beq fixabs
- /* ignore unknown type of fixup */
- b fixnext
- fixabs:
- /* absolute fix: set location to (offset) symbol value */
- mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */
- add r1, r10, r1 /* r1 <- address of symbol in table */
- ldr r1, [r1, #4] /* r1 <- symbol value */
- add r1, r1, r9 /* r1 <- relocated sym addr */
- b fixnext
- fixrel:
- /* relative fix: increase location by offset */
- ldr r1, [r0]
- add r1, r1, r9
- fixnext:
- str r1, [r0]
- add r2, r2, #8 /* each rel.dyn entry is 8 bytes */
- cmp r2, r3
- blo fixloop
- #endif
- clear_bss:
- #ifndef CONFIG_SPL_BUILD
- ldr r0, _bss_start_ofs
- ldr r1, _bss_end_ofs
- mov r4, r6 /* reloc addr */
- add r0, r0, r4
- add r1, r1, r4
- mov r2, #0x00000000 /* clear */
- clbss_l:cmp r0, r1 /* clear loop... */
- bhs clbss_e /* if reached end of bss, exit */
- str r2, [r0]
- add r0, r0, #4
- b clbss_l
- clbss_e:
- bl coloured_LED_init
- bl red_led_on
- #endif
接着在board/samsung/TQ2440/目录下增加init.c文件,board/samsung/TQ2440/init.c:
- /* NAND FLASH控制器 */
- #define NFCONF (*((volatile unsigned long *)0x4E000000))
- #define NFCONT (*((volatile unsigned long *)0x4E000004))
- #define NFCMMD (*((volatile unsigned char *)0x4E000008))
- #define NFADDR (*((volatile unsigned char *)0x4E00000C))
- #define NFDATA (*((volatile unsigned char *)0x4E000010))
- #define NFSTAT (*((volatile unsigned char *)0x4E000020))
- /* GPIO */
- #define GPHCON (*(volatile unsigned long *)0x56000070)
- #define GPHUP (*(volatile unsigned long *)0x56000078)
- /* UART registers*/
- #define ULCON0 (*(volatile unsigned long *)0x50000000)
- #define UCON0 (*(volatile unsigned long *)0x50000004)
- #define UFCON0 (*(volatile unsigned long *)0x50000008)
- #define UMCON0 (*(volatile unsigned long *)0x5000000c)
- #define UTRSTAT0 (*(volatile unsigned long *)0x50000010)
- #define UTXH0 (*(volatile unsigned char *)0x50000020)
- #define URXH0 (*(volatile unsigned char *)0x50000024)
- #define UBRDIV0 (*(volatile unsigned long *)0x50000028)
- #define TXD0READY (1<<2)
- void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len);
- static int isBootFromNorFlash(void)
- {
- volatile int *p = (volatile int *)0;
- int val;
- val = *p;
- *p = 0x12345678;
- if (*p == 0x12345678)
- {
- /* 写成功, 是nand启动 */
- *p = val;
- return 0;
- }
- else
- {
- /* NOR不能像内存一样写 */
- return 1;
- }
- }
- void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)
- {
- int i = 0;
- /* 如果是NOR启动 */
- if (isBootFromNorFlash())
- {
- while (i < len)
- {
- dest[i] = src[i];
- i++;
- }
- }
- else
- {
- //nand_init();
- nand_read_ll((unsigned int)src, dest, len);
- }
- }
- void clear_bss(void)
- {
- extern int __bss_start, __bss_end__;
- int *p = &__bss_start;
- for (; p < &__bss_end__; p++)
- *p = 0;
- }
- void nand_init_ll(void)
- {
- #define TACLS 0
- #define TWRPH0 1
- #define TWRPH1 0
- /* 设置时序 */
- NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
- /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
- NFCONT = (1<<4)|(1<<1)|(1<<0);
- }
- static void nand_select(void)
- {
- NFCONT &= ~(1<<1);
- }
- static void nand_deselect(void)
- {
- NFCONT |= (1<<1);
- }
- static void nand_cmd(unsigned char cmd)
- {
- volatile int i;
- NFCMMD = cmd;
- for (i = 0; i < 10; i++);
- }
- static void nand_addr(unsigned int addr)
- {
- unsigned int col = addr % 2048;
- unsigned int page = addr / 2048;
- volatile int i;
- NFADDR = col & 0xff;
- for (i = 0; i < 10; i++);
- NFADDR = (col >> 8) & 0xff;
- for (i = 0; i < 10; i++);
- NFADDR = page & 0xff;
- for (i = 0; i < 10; i++);
- NFADDR = (page >> 8) & 0xff;
- for (i = 0; i < 10; i++);
- NFADDR = (page >> 16) & 0xff;
- for (i = 0; i < 10; i++);
- }
- static void nand_wait_ready(void)
- {
- while (!(NFSTAT & 1));
- }
- static unsigned char nand_data(void)
- {
- return NFDATA;
- }
- void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len)
- {
- int col = addr % 2048;
- int i = 0;
- /* 1. 选中 */
- nand_select();
- while (i < len)
- {
- /* 2. 发出读命令00h */
- nand_cmd(0x00);
- /* 3. 发出地址(分5步发出) */
- nand_addr(addr);
- /* 4. 发出读命令30h */
- nand_cmd(0x30);
- /* 5. 判断状态 */
- nand_wait_ready();
- /* 6. 读数据 */
- for (; (col < 2048) && (i < len); col++)
- {
- buf[i] = nand_data();
- i++;
- addr++;
- }
- col = 0;
- }
- /* 7. 取消选中 */
- nand_deselect();
- }
COBJS := smdk2410.o 改为 COBJS:= smdk2410.o init.o
其中lowlevel_init.S定义_TEXT_BASE: .word CONFIG_SYS_TEXT_BASE,是u-boot的重定位地址,搜索定义在TQ2440.h42:
//#define CONFIG_SYS_TEXT_BASE 0x0
#define CONFIG_SYS_TEXT_BASE 0x33f80000
arch/arm/lib/board.c274:增加extern ulong base_sp;//**add
arch/arm/lib/board.c448:修改如下
: base_sp = addr_sp;//**add
//relocate_code(addr_sp, id, addr);
return (unsigned int) id;// add it
arch/arm/lib/board.c382:修改如下
//addr -= gd->mon_len;
//addr &= ~(4096 - 1);
addr = _TEXT_BASE;//**add return sp to start.s
代码部分修改的差不多了,接下来还要修改链接脚本,确保重定位之前的代码编译在最前面
在arch/arm/cpu/u-boot.lds 38:增加如下
board/samsung/TQ2440/libTQ2440.o(.text)
3.重新配置、编译
change@change:~/Si/TQ2440/u-boot-2012.10$ make distclean
change@change:~/Si/TQ2440/u-boot-2012.10$ make TQ2440 CROSSS_COMPILE=arm-none-linux-gnueabi-
/bin/bash: arm-linux-gcc: command not found
make[1]: *** [lib/asm-offsets.s] Error 127
make[1]: Leaving directory `/home/change/Si/TQ2440/u-boot-2012.10'
make: *** [TQ2440] Error 2
老出现这个问题,我都指定编译器arm-none-linux-gnueabi- ,还是报/bin/bash: arm-linux-gcc: command not found,算啦换回arm-linux-gcc-4.3.2,并设置为默认交叉编译链,其它不变
change@change:~/Si/TQ2440/u-boot-2012.10$ make distclean
change@change:~/Si/TQ2440/u-boot-2012.10$ make TQ2440_config
Configuring for TQ2440 board...
change@change:~/Si/TQ2440/u-boot-2012.10$ make
start.S:228: Error: internal_relocation (type: OFFSET_IMM) not fixed up
make[1]: *** [start.o] Error 1
make[1]: Leaving directory `/home/change/Si/TQ2440/u-boot-2012.10/arch/arm/cpu/arm920t'
make: *** [arch/arm/cpu/arm920t/start.o] Error 2
有错误,说start.S:228有错误,打开忘记定义了,修改如下arch/arm/cpu/arm920t/start.S112:增加
.globl base_sp
base_sp:
.long 0
change@change:~/Si/TQ2440/u-boot-2012.10$ make
ok问题解决,编译通过,看看现在的u-boot.bin多大
change@change:~/Si/TQ2440/u-boot-2012.10$ la u-boot.bin -l
-rwxr-xr-x 1 change change 344336 2013-05-01 16:43 u-boot.bin
change@change:~/Si/TQ2440/u-boot-2012.10$ cp u-boot.bin /home/change/work/tftpboot/
4.烧写、测试
记住这里是烧到NAND,我用NOR Flash里的u-boot烧写,拨到NOR Flash启动,设置串口 115200 8 n 1
U-Boot 2012.04.01 (Oct 25 2012 - 22:47:25)
CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz
PCLK: 50 MHz
DRAM: 64 MiB
WARNING: Caches not enabled
Flash: 0 KB
NAND: 256 MiB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: dm9000
Hit any key to stop autoboot: 0
SMDK2410 # set ipaddr 172.16.1.111
SMDK2410 # set gatewayip 172.16.1.1
SMDK2410 # set serverip 172.16.1.132
SMDK2410 # tftp 0x32000000 u-boot.bin
dm9000 i/o: 0x20000000, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 00:0c:29:4d:e4:f4
could not establish link
Using dm9000 device
TFTP from server 172.16.1.132; our IP address is 172.16.1.111
Filename 'u-boot.bin'.
Load address: 0x32000000
Loading: ########################
done
Bytes transferred = 344336 (54110 hex)
SMDK2410 # nand erase 0 0x80000
NAND erase: device 0 offset 0x0, size 0x80000
Erasing at 0x60000 -- 100% complete.
OK
SMDK2410 # nand write 0x32000000 0 0x80000
NAND write: device 0 offset 0x0, size 0x80000
524288 bytes written: OK
SMDK2410 #
单板断电,设为NAND启动,串口输出如下:
U-Boot 2012.10 (May 01 2013 - 17:20:57)
CPUID: 32440001
FCLK: 405.600 MHz
HCLK: 101.400 MHz
PCLK: 50.700 MHz
DRAM: 64 MiB
接着就卡死了,很奇怪的问题,先写到这吧,既然串口都有输出了,应该问题不大,下次再调调看。
发现问题了这个时钟不是配置的,有问题,先解决时钟问题。在board/samsung/tq2440/smdk2410.c去掉对时钟MPLL的配置76:
/* to reduce PLL lock time, adjust the LOCKTIME register */
//writel(0xFFFFFF, &clk_power->locktime);
/* configure MPLL */
//writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV,
// &clk_power->mpllcon);
同时增加打印语句。arch/arm/lib/board.c 447:增加
puts("board_init_f over!\n");
再次编译,烧写输出如下:
U-Boot 2012.10 (May 02 2013 - 15:12:15)
CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz
PCLK: 50 MHz
DRAM: 64 MiB
board_init_f over!
并且反复重启,时钟是正常了,还是有问题。细细看代码,调用u-boot第二阶段代码,需要出入参数id,但我们id是从board_init_f返回的,犯了个低级错误
arch/arm/lib/board.c 268:将void board_init_f(ulong bootflag)修改unsigned int board_init_f(ulong bootflag)
同时修改include/common.h 314:
void board_init_f (ulong) __attribute__ ((noreturn));
改为unsigned int board_init_f (ulong);
修改后编译OK,烧进去还是有问题,我再多加些打印语句试试。貌似问题有点怪了,加了打印语句发现bl board_init_r就没跳转过去,貌似运行完 board_init_f就卡死了。很郁闷,立即换成u-boot-2012.04.01移植一遍又没问题。再分析吧,哪位知道指点哈啊
http://blog.csdn.net/u010216127/article/details/8871525