u-boot-2012.04.01移植到TQ2440(六):支持NAND FLASH启动
一、????支持NAND FLASH启动 新版u-boot在链接时加了“-pie”选项 -pie ?????????? Produce a position independentexecutable on targets which support it.?For predictable results,you must also specify the same set of optionsthat were used to generate code (-fpie,-fPIE,or model suboptions) when youspecify this option. 产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意 位置,都可以正确的执行。 最终u-boot.bin中多了这些段 .rel.dyn : { ???????? __rel_dyn_start = .; ???????? *(.rel*) ???????? __rel_dyn_end = .; ? } ? ? .dynsym : { ???????? __dynsym_start = .; ???????? *(.dynsym) ? } 从NOR FLASH把代码复制到SDRAM,程序的链接地址是0,访问全局变量、静态变量、调用函数时是使用基于0地址编译得到的地址,现在把程序复制到了SDRAM(0x3000000),需要修改代码,把原来的地址改为新地址。这样太复杂了,我还是使用老版本的方法。 去掉“-pie”选项,在u-boot源码搜索“-pie” root@zjh:/home/work/u-boot-2012.04.01#grep "-pie" . -nR ./doc/README.arm-relocation:3:Atarch level: add linker flag -pie ./arch/x86/config.mk:43:LDFLAGS_FINAL+= --gc-sections -pie ./arch/arm/config.mk:75:LDFLAGS_u-boot+= -pie 去除arch/arm/config.mk:75:LDFLAGS_u-boot += -pie中的“-pie” # needed for relocation ifndef CONFIG_NAND_SPL #LDFLAGS_u-boot +=-pie endif 修改配置文件includeconfigstq2440.h,给u-boot分配512KB #define CONFIG_SYS_TEXT_BASE 0x33f80000 增加文件boardtq2440nand_read_ll.c并修改相应的Makefile COBJS?? := tq2440.onand_read_ll.o Nand_read_ll.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)) ? static intisBootFromNorFlash(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; ? } } ? voidclear_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 #defineTWRPH0? 1 #defineTWRPH1? 0 ? /* 设置时序 */ ? NFCONF =(TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4); ? /* 使能NAND Flash控制器,初始化ECC,禁止片选 */ ? NFCONT =(1<<4)|(1<<1)|(1<<0);???? } ? static voidnand_select(void) { ? NFCONT &= ~(1<<1); } ? static voidnand_deselect(void) { ? NFCONT |= (1<<1);???? } ? static voidnand_cmd(unsigned char cmd) { ? volatile int i; ? NFCMMD = cmd; ? for (i = 0; i < 10; i++); } ? static voidnand_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 voidnand_wait_ready(void) { ? while (!(NFSTAT & 1)); } ? static unsignedchar nand_data(void) { ? return NFDATA; } ? voidnand_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(); } ? voidcopy_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_ll(); ???????? nand_read_ll((unsigned int)src,dest,len); ? } } 修改archarmcpuarm920tstart.S call_board_init_f: ??? ldr sp,=(CONFIG_SYS_INIT_SP_ADDR) ??? bic sp,sp,#7 /* 8-byte alignment for ABIcompliance */ ??? ldr r0,=0x00000000 ??? ldr r1,_TEXT_BASE ??? ldr r2,_bss_start_ofs ??? bl copy_code_to_sdram ??? bl clear_bss ??? ldr pc,= board_init_f? /* 跳转到SDRAM */ .globl second second: /* 调用第2阶段的代码 */ ?????? bl board_init_r 注释掉以下代码 #if 0 ?????? .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 ?????? beq?????? clear_bss????????? /* skip relocation */ ?????? mov????? r1,r6???????????????? /* r1 <- scratch forcopy_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.dynrelocations ?????? ?*/ ?????? ldr? r0,_TEXT_BASE??????????? /* r0 <- Text base */ ?????? sub?????? r9,r6,r0?????????? /* r9 <- relocation offset */ ?????? ldr? r10,_dynsym_start_ofs?? /* r10 <- sym tableofs */ ?????? add?????? r10,r10,r0???????????? /* r10 <- sym table in FLASH */ ?????? ldr? r2,_rel_dyn_start_ofs????? /* r2 <- reldyn 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,INFLASH! */ ?????? 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:str? r2,[r0]????????????? /*clear loop...????????????? ??? */ ?????? add?????? r0,#4 ?????? cmp????? r0,r1 ?????? bne?????? clbss_l ? ?????? bl coloured_LED_init ?????? bl red_led_on #endif #endif 修改archarmlibboard.c中的函数board_init_f //addr -=gd->mon_len; //addr &=~(4096 - 1); addr =CONFIG_SYS_TEXT_BASE; 注视最后的重定位,并跳转到刚才定义的second //relocate_code(addr_sp,id,addr); second(id,addr); 修改链接脚本archarmcpuu-boot.lds把start.o、nand_read_ll.o、lowlevel_init.o编译到前面4k CPUDIR/start.o (.text) board/tq2440/libtq2440.o(.text) 重新编译,烧到NAND FLASH TQ2440 # nand erase 040000;tftp 32000000 u-boot.bin;nand write 32000000 0 40000 ? NAND erase: device 0 offset0x0,size 0x40000 Erasing at 0x20000 -- 100%complete. OK dm9000 i/o: 0x20000000,id:0x90000a46 DM9000: running in 16 bitmode MAC: 00:0c:29:4d:e4:f4 Using dm9000 device TFTP from server172.28.12.60; our IP address is 172.28.12.10 Filename 'u-boot.bin'. Load address: 0x32000000 Loading: T ############### done Bytes transferred = 208508(32e7c hex) ? NAND write: device 0 offset0x0,size 0x40000 ?262144 bytes written: OK TQ2440 # 从NAND FLASH启动 U-Boot 2012.04.01 (Dec 312012 - 11:57:16) ? CPUID: 32440001 FCLK:????? 400 MHz HCLK:????? 100 MHz PCLK:?????? 50 MHz DRAM:? 64 MiB WARNING: Caches not enabled Flash: *** failed *** ### ERROR ### Please RESETthe board ### 由于从NAND启动,CPU检测不到NOR FLASH,具体代码如下archarmlibboard.c #if!defined(CONFIG_SYS_NO_FLASH) ? puts("Flash: "); ? ? flash_size = flash_init(); ? if (flash_size > 0) { # ifdefCONFIG_SYS_FLASH_CHECKSUM ???????? char *s = getenv("flashchecksum"); ? ???????? print_size(flash_size,""); ???????? /* ???????? ?* Compute and printflash CRC if flashchecksum is set to 'y' ???????? ?* ???????? ?* NOTE: Maybe weshould add some WATCHDOG_RESET()? XXX ???????? ?*/ ???????? if (s && (*s == 'y')) { ??????????????? printf("?CRC: %08X",crc32(0, ?????????????????????? (const unsigned char *) CONFIG_SYS_FLASH_BASE, ?????????????????????? flash_size)); ???????? } ???????? putc('n'); # else???? /* !CONFIG_SYS_FLASH_CHECKSUM */ ???????? print_size(flash_size,"n"); # endif /*CONFIG_SYS_FLASH_CHECKSUM */ ? } else { ???????? puts(failed); ???????? hang(); ? } #endif void hang(void) { ? puts("### ERROR ### Please RESET the board ###n"); ? for (;;); } 我们直接注释掉上面的hang(); # endif /*CONFIG_SYS_FLASH_CHECKSUM */ ? } else { ???????? puts(failed); ???????? //hang(); ? } #endif 重新编译,烧到NAND FLASH,从NAND启动 U-Boot 2012.04.01 (Dec 31 2012- 12:27:20) ? CPUID: 32440001 FCLK:????? 400 MHz HCLK:????? 100 MHz PCLK:?????? 50 MHz DRAM:? 64 MiB WARNING: Caches not enabled Flash: *** failed *** NAND:? 256 MiB 卡在这里,检查后发现修改start.S的时候调用第二阶段代码没有重新设置栈指针,做如下修改 board.c中的board_init_f函数 //relocate_code(addr_sp,addr); ? second(id,addr,addr_sp); start.S second: ? mov sp,r2 /*重新设置栈指针 */ /* 调用第2阶段的代码 */ ? bl board_init_r 重新编译,烧到NAND,从NAND启动 U-Boot 2012.04.01 (Dec 312012 - 12:31:58) ? CPUID: 32440001 FCLK:????? 400 MHz HCLK:????? 100 MHz PCLK:?????? 50 MHz DRAM:? 64 MiB WARNING: Caches not enabled Flash: *** failed *** NAND:? 256 MiB In:??? serial Out:?? serial Err:?? serial Net:?? dm9000 TQ2440 # (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |