重新编译烧写,串口输出错误信息:
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启动