u-boot-2012.04.01移植(六)提供nand flash启动支持

重新编译烧写,串口输出错误信息:

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启动

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值