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。

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

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/130786.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • finalize方法_final与finalize区别

    finalize方法_final与finalize区别当对象没有引用指向时,虚拟机会按照一定的垃圾回收机制算法来调用finalize方法将该对象回收,并不是只要没有引用对象就会被回收。因此,可以调用System.gc()方法来主动调用垃圾回收机制,但也并不能保证一定能成功。在调用时,程序并不会阻塞在此处,而是会继续向下执行。默认的object类中的finalize方法是不作其余处理的。可以重写finalize方法来实现自己想要的资源释放操作,比如数据库连接等。…

  • KindEditor富文本编辑器 items配置项 对照表「建议收藏」

    KindEditor富文本编辑器 items配置项 对照表「建议收藏」source:’HTML代码’, undo:’后退(Ctrl+Z)’, redo:’前进(Ctrl+Y)’, cut:’剪切(Ctrl+X)’, copy:’复制(Ctrl+C)’, paste:’粘贴(Ctrl+V)’, plainpaste:’粘贴为无格式文本’, wordpaste:’从Word粘贴’, selectall:

  • Macbook air/pro m1 恢复出厂设置小记

    Macbook air/pro m1 恢复出厂设置小记今日手抽,想恢复下出厂,看了官方教程https://support.apple.com/zh-cn/HT211983够,按照说明一步一步进行,然鹅~在正确抹掉2遍开始选择重装bigsur时发现无法找到硬盘。经摸索,解决方法:再次重启进去恢复模式,选择磁盘工具,点击显示所有卷宗,这时发现硬盘处于非格式化状态,因而无法被安装程序识别,(点击+号新建afps分区时会提示无效的arg,无法新建分区)应选择抹除,来重新抹盘,即可解决问题。返回到恢复界面,就能发现硬盘并正常重装。注:这个问题用u盘进行引导安装时也一

  • python3 zipfile模块_Python ZipFile模块详解[通俗易懂]

    python3 zipfile模块_Python ZipFile模块详解[通俗易懂]Pythonzipfile模块用来做zip格式编码的压缩和解压缩的,zipfile里有两个非常重要的class,分别是ZipFile和ZipInfo,在绝大多数的情况下,我们只需要使用这两个class就可以了。ZipFile是主要的类,用来创建和读取zip文件而ZipInfo是存储的zip文件的每个文件的信息的。比如要读取一个Pythonzipfile模块,这里假设filename是一个…

  • HttpServletRequest

    HttpServletRequest代表的是我们的响应对象HttpServletRequest概述service方法中的request的类型是ServletRequest,而doGet/doPost方法的request的类型是Htt

发表回复

您的电子邮箱地址不会被公开。

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