赞
踩
重新编译烧写,串口输出错误信息:
Flash:*** failed ***
### ERROR ### Please RESET the board
这个错误下一节再解决,这一节先为u-boot提供nand flash启动的支持
前面分析uboot时提到链接时加上-pie选项会生成位置无关码,将变量、函数的地址保存起来,以便于在uboot重定位代码时使用,这样虽然可以不指定程序的链接地址,但会导致程序增大,超过4k,不易使用nand启动,并且重定位代码复杂
修改办法:
1、修改Makefile去掉链接命令中的-pie选项
通过下面命令找到-pie的位置在arch/arm/config.mk的75行
grep “\-pie” * -nR
注释掉arch/arm/config.mk的75行
#LDFLAGS_u-boot += -pie
2、添加nand支持
①、修改board/samsung/smdk2440/Makefile
- //COBJS := smdk2410.o
- COBJS := smdk2410.o init.o
②、在board/samsung/smdk2440中新增一个文件init.c,提供nand flash的操作函数、启动flash类型的判断、代码重定位函数等等
- /* 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))
-
- //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)
- {
- *p = val;
- return 0;
- }
-
- return 1;
- }
-
- void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)
- {
- int i = 0;
-
- if (isBootFromNorFlash())
- {
- while (i < len)
- {
- dest[i] = src[i];
- i++;
- }
- }
- else
- {
- nand_read((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);
- 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;
-
- nand_select();
-
- while (i < len)
- {
- nand_cmd(0x00);
-
- nand_addr(addr);
-
- nand_cmd(0x30);
-
- nand_wait_ready();
-
- for (; (col < 2048) && (i < len); col++)
- {
- buf[i] = nand_data();
- i++;
- addr++;
- }
-
- col = 0;
- }
-
- nand_deselect();
- }
③、修改arch/arm/lib/board.c
修改board_init_f的返回值类型为unsigned int,并且对应修改其声明的返回值,注意要去掉__attribute__ ((noreturn)),声明位于include/common.h
在board_init_f函数中
Ⅰ、将
- addr -= gd->mon_len;
- addr &= ~(4096 - 1);
替换为
addr = _TEXT_BASE;
指定一个固定的链接地址(u-boot在SDRAM上的起始地址)
Ⅱ、在函数头部添加一行,引用外部变量,变量等下会定义在start.S中,用于存放栈指针
extern ulong base_sp;
Ⅲ、在函数末尾
将
relocate_code(addr_sp, id, addr);
替换为
- base_sp = addr_sp;
- return id;
保存栈指针,返回参数地址
④、修改arch/arm/cpu/arm920t/start.S,使用新的重定位、清除bss段代码,栈也需要重新设置
Ⅰ、
源代码:
- call_board_init_f:
- ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
- bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
- ldr r0,=0x00000000
- bl board_init_f
修改后:
- ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
- bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
-
- bl nand_init_ll
-
- mov r0, #0
- ldr r1, _TEXT_BASE
- ldr r2, _bss_start_ofs
- bl copy_code_to_sdram
- bl clear_bss
-
- ldr pc, =call_board_init_f
-
- call_board_init_f:
- ldr r0,=0x00000000
- bl board_init_f
- /*board_init_f返回值存于r0,用于传入board_init_r*/
- ldr r1, _TEXT_BASE
- ldr sp, base_sp
- bl board_init_r
-
- .globl base_sp
- base_sp:
- .long 0
为了让代码跳转到重定位后的位置,需要用绝对跳转指令ldr pc, =call_board_init_f(如果使用相对跳转指令bl,无法跳到SDRAM),跳转到SDRAM后即可使用相对跳转指令bl调用子程序
Ⅱ、删除这段重定位相关代码
- .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 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:str r2, [r0] /* clear loop... */
- add r0, r0, #4
- cmp r0, r1
- bne clbss_l
-
- bl coloured_LED_init
- bl red_led_on
- #endif
3、修改链接地址
修改include/configs/smdk2440.h
- //#define CONFIG_SYS_TEXT_BASE 0
- #define CONFIG_SYS_TEXT_BASE 0x33F00000
4、修改链接脚本,将重定位前所用到的文件放在最前面
通过下面命令找到链接脚本位置arch/arm/cpu
find -name *.lds | grep arm
修改链接脚本
源代码
- .text :
- {
- __image_copy_start = .;
- CPUDIR/start.o (.text)
- *(.text)
- }
修改后
- .text :
- {
- __image_copy_start = .;
- CPUDIR/start.o (.text)
- board/samsung/smdk2440/libsmdk2440.o (.text)
- *(.text)
- }
重新编译烧写后即支持nand flash启动
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。