S3C2440移植uboot之支持NAND启动

S3C2440移植uboot之支持NAND启动上一节S3C2440移植uboot之新建单板_时钟_SDRAM_串口移植uboot初始化了时钟,配置了支持串口,这一节我们继续修改uboot支持NAND启动。

大家好,又见面了,我是你们的朋友全栈君。

  上一节S3C2440移植uboot之新建单板_时钟_SDRAM_串口移植uboot初始化了时钟,配置了支持串口,这一节我们继续修改uboot支持NAND启动。

移植Uboot其他文章链接:

S3C2440移植uboot之编译烧写uboot

S3C2440移植uboot之新建单板_时钟_SDRAM_串口

S3C2440移植uboot之启动过程概述

S3C2440移植uboot之支持NAND启动

S3C2440移植uboot之支持NORFLASH

S3C2440移植uboot之支持NANDFLASH操作

S3C2440移植uboot之支持DM9000

S3C2440移植uboot之裁剪和修改默认参数

S3C2440移植uboot之支持烧写yaffs映像及制作补丁

1.去掉 “-pie”选项

  参考之前uboot使用的start.S, init.c来修改uboot代码新的uboot链接地址位于0,且在arm-linux-ld时加了”-pie”选项, 使得u-boot.bin里多了"*(.rel*)", "*(.dynsym)",从而程序非常大,不利于从NAND启动(重定位之前的启动代码应该少于4K).
  所以接下来修改代码,并取消”-pie”选项.
  使用grep “-pie” * -nR找到:

arch/arm/config.mk:75:LDFLAGS_u-boot += -pie             // LDFLAGS: arm-linux-ld的参数

  所以屏蔽arch/arm/config.mk文件的”LDFLAGS_u-boot += -pie”这行即可
在这里插入图片描述

2.修改之前的init.c

  将以前写uboot里的init.c放入board/samsung/smdk2440目录, 并检查是否有同名函数名,若函数只在同文件使用,则添加static.并修改Makefile 增加对init.c的支持

vi board/samsung/smdk2440/Makefile 

在这里插入图片描述
  修改include/configs/smdk2440.h文件,将CONFIG_SYS_TEXT_BASE宏改为0x33f80000,也就是uboot重定位后的位置, 这里留了512K空间供给uboot重定位
修改完的代码如下所示



/* 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();
}


3.修改start.s重定位部分

  修改arch/arm/cpu/arm920t/start.S,更改重定位代码。由于nand启动时,2440未初始化之前只有前4K可读写,所以将重定位代码放在start.S的cpu_init_crit(初始化SDRAM)段后面。修改后代码如下

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
	bl	cpu_init_crit
#endif

	ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR) //等于0x30000f80
	bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
	
	bl nand_init_ll
	mov r0, #0       //r0->src
	//ldr r1, =_start
	ldr r1,_TEXT_BASE     //链接地址 _TEXT_BASE : 0x33f80000 0x34000000-0x33f80000=512k uboot 512k足以
	ldr r2,_bss_start_ofs		// _bss_start_ofs: __bss_start - _start (有效代码大小)

	bl copy_code_to_sdram
	bl clear_bss                         //清除bss段(参考自制uboot章节)
	ldr pc,=call_board_init_f            //绝对跳转,跳到SDRAM上执行


/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
	ldr	r0,=0x00000000
	bl	board_init_f

  上面的_TEXT_BASE,在start.S靠前处定义:
在这里插入图片描述
  由于它位于靠前处,保证了_TEXT_BASE存在前4k空间里,若直接使用ldr r1,=CONFIG_SYS_TEXT_BASE,编译器可能会将这个宏定义放在SDRAM上,则会出错。
  重定位写在前面了,所以我们还要删除start.S后面的u-boot-2012.04.01\arch\arm\lib\board.c中的 relocate_code重定位段,清除BSS段。同时在relocate_code(addr_sp, id, addr);后面增加return (unsigned int) id;,修改函数为unsigned int board_init_f(ulong bootflag)。

在这里插入图片描述
  同时注释掉board.c中如下的内容,固定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
	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

  start.s增加第二阶段启动代码

call_board_init_f:

	ldr	r0,=0x00000000
	bl	board_init_f

	/*unsigned int id 的值存在r0中,正好给board_init_r使用*/
	ldr r1, =_TEXT_BASE
	/*调用第二阶段代码*/
	bl	board_init_r

4.修改链接脚本

  把start.S, init.c(实现重定位), lowlevel.S(实现初始化SDRAM)等文件放在最前面

rm u-boot.lds
vi arch/arm/cpu/u-boot.lds

  添加以下字段:

 . = ALIGN(4);

    .text :

    { 
   

            __image_copy_start = .;

            CPUDIR/start.o (.text)              //CPUDIR为arch/arm/cpu/arm920t目录

            board/samsung/smdk2440/libsmdk2440.o (.text)  

            *(.text)

    }

  libsmdk2440.o是将smdk2440单板目录下的所有*.c,*S文件编译后,连接成一个库文件.

5.报错修改

  报错

board.c:259: error: conflicting types for 'board_init_f'
/work/system/u-boot-2012.04.01/include/common.h:276: error: previous declaration of 'board_init_f' was here
/work/system/u-boot-2012.04.01/config.mk:312: recipe for target 'board.o' failed

  根据指示修改u-boot-2012.04.01/include/common.h 276行如下
在这里插入图片描述
在这里插入图片描述
  报错

board/samsung/smdk2440/libsmdk2440.o: In function `clear_bss':
/work/system/u-boot-2012.04.01/board/samsung/smdk2440/init.c:77: undefined reference to `__bss_end_'
Makefile:472: recipe for target 'u-boot' failed

  根据指示修改u-boot-2012.04.01/board/samsung/smdk2440/init.c:77行如下
在这里插入图片描述

6.重新修改链接地址

  我们指定了 CONFIG_SYS_TEXT_BASE 0x33f80000 ,所以我们的uboot不能超过512k,0x33f80000这个是不包括bss段的全局变量的。查看start.s文件。
在这里插入图片描述
  在反汇编中搜索_bss_end_ofs,00094b40为整个代码段的大小(包括了bss段),转换为10进制609088,已经大于了512k,所以‬重新修改CONFIG_SYS_TEXT_BASE 0x33f00000 。预留uboot空间为0x34000000-0x33f00000=1M
在这里插入图片描述
  然后通过旧的uboot,将新的uboot烧写到nand中

usb 1 30000000                             //先下载到SDRAM上
nand erase 0  0x80000                      //擦除512kb,必须大于新的uboot
nand write 30000000   0  0x80000           //将SDRAM上的新uboot写入nand

查看u-boot.lds
在这里插入图片描述

在这里插入图片描述

  烧写后,如下图所示:
在这里插入图片描述
  nand启动便实现完成了,上面的Flash: *** failed *** 是属于uboot第二阶段函数board_init_r()里的代码,表示不支持nor flash,不能实现读,写,擦除等命令。
  下一节S3C2440移植uboot之支持NORFLASH我们将移植uboot支持我们的s3c2440。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/130787.html原文链接:https://javaforall.net

(0)
上一篇 2022年6月13日 下午1:16
下一篇 2022年6月13日 下午1:16


相关推荐

  • 运维架构体系

    运维架构体系 

    2022年7月17日
    24
  • eva0.4.1源码看看4

    eva0.4.1源码看看4

    2021年8月26日
    76
  • IntelliJ IDEA添加注释常用的快捷键[通俗易懂]

    IntelliJ IDEA添加注释常用的快捷键[通俗易懂]IDEA可以使用快捷键添加行注释Ctrl+/、块注释Ctrl+Shift+/,还可以快速生成类注释、方法注释等,下面就介绍这几种快捷键的用法.[1]行注释Ctrl+/首先你的光标要处于这一行,处于这行的哪个位置都可以,按Ctrl+/,就可以往行首添加"//",将该行注释掉。再次按Ctrl+/,可以去掉该行注释。[2]块注释Ctrl+Shift+/使用块注释需要先选中要注释的…

    2022年8月15日
    8
  • c语言面试知识点总结_c语言电话面试题

    c语言面试知识点总结_c语言电话面试题1、static和extern:1).在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。 2).一个被声明为静态的变量可以被模块内所用函数访问,但不能被其他文件函数访问。它是一个本地的全局变量。 3).在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用,这个函数被限制在声明它的模块的本地范围内使用。C++中的static  在C++中static还具有其它功能…

    2025年6月20日
    4
  • python中矩阵的转置_[转]Python中的矩阵转置[通俗易懂]

    python中矩阵的转置_[转]Python中的矩阵转置[通俗易懂]Python中的矩阵转置via需求:你需要转置一个二维数组,将行列互换.讨论:你需要确保该数组的行列数都是相同的.比如:arr=[[1,2,3],[4,5,6],[7,8,9],[10,11,12]]列表递推式提供了一个简便的矩阵转置的方法:print[[r[col]forrinarr]forcolinrange(len(arr[0]))][[1,4…

    2022年5月29日
    48
  • Java中SimpleDateFormat用法详解

    Java中SimpleDateFormat用法详解转自 http blog csdn net linbooooo198 article details java nbsp viewplain nbsp copypackage nbsp com bict util nbsp nbsp nbsp nbsp import nbsp java text SimpleDateFo nbsp nbsp import nbsp java util Date nbsp

    2026年3月26日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号