一、 支持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
修改配置文件include\configs\tq2440.h,给u-boot分配512KB
#define CONFIG_SYS_TEXT_BASE 0x33f80000
增加文件board\tq2440\nand_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);
}
}
修改arch\arm\cpu\arm920t\start.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, 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
#endif
修改arch\arm\lib\board.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);
修改链接脚本arch\arm\cpu\u-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,具体代码如下arch\arm\lib\board.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, id,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 #