三、移植 u-boot-2012.04.01 之 支持NAND启动
需要进行修改和添加的文件:
1、添加的文件:init.c 包含NAND Flash 的相关配置
board/samsung/smdk2440目录, 修改Makefile
2、需要修改的文件:
a、去掉-pie选项,修改arch/arm/config.mk
b、start.S
c、smdk2440.h
d、common.h
e、board.c
f、arch/arm/cpu/u-boot.lds
1、添加的文件:init.c
init.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))
/* GPIO */
#define GPHCON (*(volatile unsigned long *)0x56000070)
#define GPHUP (*(volatile unsigned long *)0x56000078)
/* UART registers*/
#define ULCON0 (*(volatile unsigned long *)0x50000000)
#define UCON0 (*(volatile unsigned long *)0x50000004)
#define UFCON0 (*(volatile unsigned long *)0x50000008)
#define UMCON0 (*(volatile unsigned long *)0x5000000c)
#define UTRSTAT0 (*(volatile unsigned long *)0x50000010)
#define UTXH0 (*(volatile unsigned char *)0x50000020)
#define URXH0 (*(volatile unsigned char *)0x50000024)
#define UBRDIV0 (*(volatile unsigned long *)0x50000028)
#define TXD0READY (1<<2)
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)
{
/* 写成功, 是nand启动 */
*p = val;
return 0;
}
else
{
/* NOR不能像内存一样写 */
return 1;
}
}
void copy_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();
nand_read_ll((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);
/* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
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;
/* 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();
}
同时在 board/samsung/smdk2440目录, 修改Makefile
Makefile:28: COBJS:= smdk2440.o init.o
2、需要修改的文件:
a、去掉-pie选项,不需要附加“*(.rel*)”、“*(.dynsm)”等信息
命令:grep "\-pie" * -nR
arch/x86/config.mk:43:LDFLAGS_FINAL += --gc-sections -pie
arch/arm/config.mk:75:LDFLAGS_u-boot += -pie
doc/README.arm-relocation:3:At arch level: add linker flag -pie
然后输入命令: vim arch/arm/config.mk
去掉/config.mk去掉75行LDFLAGS_u-boot += -pie
b、修改start.S 参考以前写的start.S 修改代码
前一篇我们对u-boot 进行了时钟、SDRAM 以及串口的相关设定;这一篇的目的是要让u-boot 支持NAND 启动。
在进行是时钟设定之后需要对重定向的代码进行修改:
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
/* 重定位 : 把bootloader本身的代码从flash复制到它的链接地址去 */
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, = board_init_f
/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr r0,=0x00000000
bl board_init_f
ldr r1, _TEXT_BASE
bl board_init_r
同时对将CONFIG_SYS_TEXT_BASE修改为0x33f80000
自己写了重定位,就去掉它写的重定位函数
注释掉掉board.c中board_init_f中//relocate_code(addr_sp, id, addr);
删掉start.S中下面不需要的代码
- /*------------------------------------------------------------------------------*/
- /*
- * void relocate_code (addr_sp, gd, addr_moni)
- *
- * This "function" does not return, instead it continues in RAM
- * after relocating the monitor code.
- *
- */
- .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
- moveq r9, #0 /* no relocation. relocation offset(r9) = 0 */
- 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:cmp r0, r1 /* clear loop... */
- bhs clbss_e /* if reached end of bss, exit */
- str r2, [r0]
- add r0, r0, #4
- b clbss_l
- clbss_e:
- bl coloured_LED_init
- bl red_led_on
- #endif
c、smdk2440.h
上一篇我们在 smdk2440.h 定义了CONFIG_S3C2440 并且注释了CONFIG_S3C2410
注释了 #define CONFIG_CMD_NAND
前面我们已经对smdk2440.h 的#define CONFIG_SYS_TEXT_BASE 进行了修改
还需要修改的:
注释掉 #define CONFIG_YAFFS2,解决nand_info 没有定义的错误。
d、common.h
修改include/common.h 276:
void board_init_f (ulong) __attribute__ ((noreturn));
改为unsigned int board_init_f (ulong);
e、board.c
259:将void board_init_f(ulong bootflag)
修改为 unsigned int board_init_f(ulong bootflag)
372:修改如下
//addr -= gd->mon_len;
//addr &= ~(4096 - 1);
addr = _TEXT_BASE;//**add return sp to start.s
439:修改如下
//relocate_code(addr_sp, id, addr);
return (unsigned int) id;// add it
f、arch/arm/cpu/u-boot.lds
修改链接脚本,确保重定位之前的代码编译在最前面
在arch/arm/cpu/u-boot.lds 38:增加如下
board/samsung/smdk2440/libsmdk2440.o (.text)
3、重新配置、编译
make distclean
make smdk2440_config
make
4、烧写、测试
记住这里是烧到NAND,我用NOR Flash里的u-boot烧写,拨到NOR Flash启动,设置串口 115200 8 n 1
CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz
PCLK: 50 MHz
DRAM: 64 MiB
WARNING: Caches not enabled