TQ2440 u-boot-2012.04.01移植二支持NAND启动
继?u-boot-2012.04.01移植一串口正常输出,继续修改代码支持单板NAND启动。最后直接用NOR Flash里的u-boot烧写自己移植的u-boot到NAND,方便电脑没有并口或手上没有openjtag,照样能移植u-boot,当然有openjtag更方便。
开发环境: 搭建开发环境详见ubuntu 10.04.4开发环境配置。 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.04.01/ 看到生成的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.04.01$ grep "-pie" * -nR 2.参考以前update写的start.S init.c修改代码 在arch/arm/cpu/arm920t/start.S112:增加 .globl base_sp 在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) 在arch/arm/cpu/arm920t/start.S:226行增加如下代码 /*unsigned int id */ 用自己的重定位代码,去掉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,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,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,LSR #4 /* r1 <- symbol index in .dynsym */ add r1,r1 /* r1 <- address of symbol in table */ ldr r1,[r1,#4] /* r1 <- symbol value */ add r1,r9 /* r1 <- relocated sym addr */ b fixnext fixrel: /* relative fix: increase location by offset */ ldr r1,[r0] add r1,r9 fixnext: str r1,[r0] add 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,r4 add 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,#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 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(); }同时修改该目录下的在Makfile,board/samsung/TQ2440/Makefile: 28:?COBJS:= TQ2440.o init.o? 其中lowlevel_init.S定义_TEXT_BASE: ? ??.word CONFIG_SYS_TEXT_BASE,是u-boot的重定位地址,搜索定义在TQ2440.h42: //#define CONFIG_SYS_TEXT_BASE 0x0 同时修改include/common.h 276: void?board_init_f? (ulong) __attribute__ ((noreturn)); 改为unsigned int?board_init_f? (ulong); arch/arm/lib/board.c265:增加extern ulong base_sp;//**add arch/arm/lib/board.c373:修改如下 //addr -= gd->mon_len; arch/arm/lib/board.c439:修改如下 base_sp = addr_sp;//**add 代码部分修改的差不多了,接下来还要修改链接脚本,确保重定位之前的代码编译在最前面 在arch/arm/cpu/u-boot.lds 38:增加如下 board/samsung/TQ2440/libTQ2440.o(.text) 3.重新配置、编译 change@change:~/Si/TQ2440/u-boot-2012.04.01$ make distclean ok编译通过,看看现在的u-boot.bin多大 change@change:~/Si/TQ2440/u-boot-2012.04.01$ ls u-boot.bin -l 4.烧写、测试 记住这里是烧到NAND,我用NOR Flash里的u-boot烧写,拨到NOR Flash启动,设置串口 115200 8 n 1
CPUID: 32440001 In:??? serial NAND erase: device 0 offset 0x0,size 0x80000 NAND write: device 0 offset 0x0,size 0x80000 单板断电,拨到NAND启动,上电串口输出: CPUID: 32440001 启动了,但卡在NOR Flash,NAND启动没检测到NOR Flash 就hang()这是正常的。这里修改一下不然它卡住,直接输出0 arch/arm/lib/board.c530:修改如下: ??puts("0 KBnr"); 修改后再次编译,应该就没问题了。发现还会卡在NET,暂时不支持网卡,先这样屏蔽arch/arm/lib/board.c:619//eth_initialize(gd->bd);同时将TQ2440.h131: #define CONFIG_SYS_PROMPT?"SMDK2410 # "改为#define CONFIG_SYS_PROMPT?"TQ2440 # " change@change:~/Si/TQ2440/u-boot-2012.04.01$ make distclean change@change:~/Si/TQ2440/u-boot-2012.04.01$ cp u-boot.bin /home/change/work/tftpboot/ OK编译通过,单板拨到NOR Flash启动,串口设置115200 8 n 1上电 U-Boot 2012.04.01 (Oct 25 2012 - 22:47:25) CPUID: 32440001 In:??? serial NAND erase: device 0 offset 0x0,size 0x80000 NAND write: device 0 offset 0x0,size 0x80000 烧写刚刚移植的u-boot.bin到NAND,现在单板断电,拨到NAND启动,串口115200 8 n 1上电
CPUID: 32440001 In:??? serial 这样NAND启动基本正常了,还需要完善,支持更多的功能。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |