硬件平台:tq2440
开发环境:Ubuntu-3.11
u-boot版本:2014.10
本文允许转载,请注明出处:http://blog.csdn.net/fulinus
为实现nand flash启动,最好的方法是使用u-boot自身提供的SPL方式,就是借助另一个相对独立的u-boot-spl.bin执行文件,将u-boot.bin拷贝到SDRAM中去,再运行u-boot.bin。这样一来u-boot就可以再次重定向。我们这里首先尝试用一个老方法。
1、首先关闭“位置无关”的编译选项,在arch/arm/config.mk文件中,注释“pie”:
# needed for relocation # LDFLAGS_u-boot += -pie
2、修改基地址,在include/configs/tq2440.h配置文件中,修改CONFIG_SYS_TEXT_BASE:
#define CONFIG_SYS_TEXT_BASE 0x33F80000
/* NAND FLASH控制器 */ #define NFCONF (*((volatile unsigned long *)0x4E000000)) #define NFCONT (*((volatile unsigned long *)0x4E000004)) #define NFCMMD (*((volatile unsigned long *)0x4E000008)) #define NFADDR (*((volatile unsigned long *)0x4E00000C)) #define NFDATA (*((volatile unsigned long *)0x4E000010)) #define NFSTAT (*((volatile unsigned long *)0x4E000020)) static int is_boot_from_norflash(void) { int val; volatile int *p = (volatile int *)0; val = *p; *p = 0x12345678; if(*p == 0x12345678){ /* 写成功,是nand flash启动 */ *p = val; return 0; }else{ /* Nor flash 不能像内存一样写 */ return 1; } } void nand_init_ll(void) { #define TACLS 0 #define TWRPH0 1 #define TWRPH1 0 /* 设置时序 */ NFCONT = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4); /* 使能Nand flash 控制器,初始化ECC, 禁止片选 */ NFCONT = (1<<4)|(1<<1)|(1<<0); } void clear_bss(void) { extern int __bss_start, __bss_end; int *p = &__bss_start; for(; p < &__bss_end; p++){ *p = 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) { volatile int i; unsigned int col = addr % 2048; unsigned int page = addr / 2048; 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; } static void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len) { int i = 0; int col = addr % 2048; /* 1.选中 */ nand_select(); while(i < len) { /* 2.发出读命令:00h */ nand_cmd(0x00); /* 3.发出地址指令 */ 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(); } void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len) { int i = 0; /* 如果是Nor flash 启动 */ if(is_boot_from_norflash()){ while(i < len){ dest[i] = src[i]; i++; } }else{ nand_init_ll(); nand_read_ll((unsigned int)src, dest, len); } }
obj-y := tq2440.o + obj-y += nand_read_ll.o obj-y += lowlevel_init.o
ENTRY(_main)
/*
* Set up initial C runtime environment and call board_init_f(0).
*/
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
ldr sp, =(CONFIG_SPL_STACK)
#else
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
#endif
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
mov r2, sp
sub sp, sp, #GD_SIZE /* allocate one GD above SP */
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
mov r9, sp /* GD is above SP */
#if 1
__TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE
mov r0, #0
ldr r1, __TEXT_BASE
ldr r2, __TEXT_BASE
ldr r3, =__bss_end
sub r2, r3, r2
bl copy_code_to_sdram
bl clear_bss
ldr pc, =call_board_init_f
call_board_init_f:
mov r0, #0
bl board_init_f
ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
sub r9, r9, #GD_SIZE /* new GD is below bd */
ldr r1, __TEXT_BASE
bl board_init_r
#else
mov r1, sp
mov r0, #0
clr_gd:
cmp r1, r2 /* while not at end of GD */
strlo r0, [r1] /* clear 32-bit GD word */
addlo r1, r1, #4 /* move to next */
blo clr_gd
#if defined(CONFIG_SYS_MALLOC_F_LEN) && !defined(CONFIG_SPL_BUILD)
sub sp, sp, #CONFIG_SYS_MALLOC_F_LEN
str sp, [r9, #GD_MALLOC_BASE]
#endif
/* mov r0, #0 not needed due to above code */
bl board_init_f
#if ! defined(CONFIG_SPL_BUILD)
/*
* Set up intermediate environment (new sp and gd) and call
* relocate_code(addr_moni). Trick here is that we'll return
* 'here' but relocated.
*/
ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
sub r9, r9, #GD_SIZE /* new GD is below bd */
adr lr, here
ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */
add lr, lr, r0
ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
b relocate_code
here:
/* Set up final (full) environment */
bl c_runtime_cpu_setup /* we still call old routine here */
ldr r0, =__bss_start /* this is auto-relocated! */
ldr r1, =__bss_end /* this is auto-relocated! */
mov r2, #0x00000000 /* prepare zero to clear BSS */
clbss_l:cmp r0, r1 /* while not at end of BSS */
strlo r2, [r0] /* clear 32-bit BSS word */
addlo r0, r0, #4 /* move to next */
blo clbss_l
bl coloured_LED_init
bl red_led_on
/* call board_init_r(gd_t *id, ulong dest_addr) */
mov r0, r9 /* gd_t */
ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */
/* call board_init_r */
ldr pc, =board_init_r /* this is auto-relocated! */
/* we should not return here. */
#endif
#endif
ENDPROC(_main)
6、修改arch/arm/lib/board.c 文件中的board_init_f函数:
//void board_init_f(ulong bootflag)
unsigned int board_init_f(ulong bootflag)
。。。
//addr -= gd->mon_len;
//addr &= ~(4096 - 1);
addr = CONFIG_SYS_TEXT_BASE;
。。。
memcpy(id, (void *)gd, sizeof(gd_t));
return (unsigned int)id;
}
7、同时修改include/common.h头文件中board_init_f函数的声明:
//void board_init_f(ulong);
unsigned int board_init_f(ulong);
8、修改连接脚本arch/arm/cpu/u-boot.lds文件,将nand_read_ll.c文件放在前4K字节中:
.text :
{
*(.__image_copy_start)
*(.vectors)
CPUDIR/start.o (.text*)
board/samsung/tq2440/lowlevel_init.o(.text*)
board/samsung/tq2440/nand_read_ll.o(.text*)
*(.text*)
}
9、修改arch/arm/config.mk文件,将checkarmreloc功能注释掉:
# ALL-y += checkarmreloc
10、编译
不成功,感觉这个方法很牵强,换一种;
明天继续;