移植笔记-:从Nand flash启动的uboot
uboot移植与源码分析总结(6)-Nand驱动

uboot移植与源码分析总结(6)-Nand驱动uboot移植与源码分析总结(6)-Nand驱动2013-06-29 11:32:17分享:有关nand flash的特性描述,可以见我之前写的这篇文章《NandFlash结构与分析》。
从功能上来说,nand flash与norflash 并无太大差异,主要区别在于操作接口和方式。
Nand基于非sram总线接口,使用nand接口,所以一般需要mcu具有nand控制器才可与其连接。
在读取时,以页为单位;擦除和写入时,以块为单位。
将nand视作一个MTD设备uboot将nand视作一个mtd设备,所以使用mtd机制对nand 设备进行管理。
单个nand设备用nand_info_t来描述。
而nand_info_t实际上就是mtd结构。
最多支持的nand设备数CONFIG_SYS_MAX_NAND_DEVICE可由开发者自行配置。
不过一般目标板上只有一块Nand设备,所以取值通常为1。
但是仅使用mtd结构来描述不够,因为MTD只是一个通用的存储描述结构,而Nand设备特定的某些属性,如ECC布局等不能简单的添加到mtd结构中。
所以,uboot定义了nand_chip结构。
int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);void (*select_chip)(struct mtd_info *mtd, int chip);int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);int (*init_size)(struct mtd_info *mtd, struct nand_chip *this, u8 *id_data);int (*dev_ready)(struct mtd_info *mtd);void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column,int page_addr);int(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);void (*erase_cmd)(struct mtd_info *mtd, int page);int (*scan_bbt)(struct mtd_info *mtd);int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state,int status, int page);int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,const uint8_t *buf, int page, int cached, int raw);int chip_delay;unsigned int options;int page_shift;int phys_erase_shift;int bbt_erase_shift;int chip_shift;int numchips;uint64_t chipsize;然后,分配了CONFIG_SYS_MAX_NAND_DEVICE个nand_chip 结构。
移植笔记-:从Nand_flash启动的uboot

到目前为此,这个版本的uboot已经加进了Nand驱动,可以使用Nand命令对nandflash进行读写。
但是还不能从Nand启动,只可以从Norflash启动或用tftp下载到sdram中然后go到该地址使用。
原因是目前移植的uboot还没有实现s3c2410支持的从Nand Flash启动机制需要的自拷贝功能。
下面介绍移植可以从Nand flash启动的uboot。
关于这里的Nand Boot概念,如果分析过vivi源码,明白vivi是如何从Nand跳转到sdram中继续执行以及copy_myself原理的话,再理解这里就比较简单了。
其实我们这里使uboot支持从nand启动的原理正是移植vivi里的copy_myself机制。
关于s3c2410从Nand Flash启动的原理可以查阅其他相关资料,不懂的话也没关系,不影响移植过程。
当然,我们的最终目的是编译一个可以直接烧录到nand中启动的uboot。
既然已经到这一步了,要实现nand启动已经很容易了。
只需要添加几行代码,大部分从vivi拷贝,只需修改少许地方。
过程如下:1.在board/smdk2410加入NAND Flash读函数,建立nand_read.c文件,加入如下内容(copy from vivi):(在vivi源码下的arch\s3c2410\nand_read.c)#include<config.h>#define __REGb(x)(*(volatile unsigned char*)(x))#define __REGi(x)(*(volatile unsigned int*)(x))#define NF_BASE 0x4e000000#define NFCONF __REGi(NF_BASE + 0x0)#define NFCMD __REGb(NF_BASE + 0x4)#define NFADDR __REGb(NF_BASE + 0x8)#define NFDATA __REGb(NF_BASE + 0xc)#define NFSTAT __REGb(NF_BASE + 0x10)#define BUSY 1inline void wait_idle(void){int i;while(!(NFSTAT & BUSY))for(i=0; i<10; i++);}#define NAND_SECTOR_SIZE 512#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)/* low level nand read function */intnand_read_ll(unsigned char*buf,unsigned long start_addr,int size) {int i, j;if((start_addr & NAND_BLOCK_MASK)||(size & NAND_BLOCK_MASK)) {return-1;/* invalid alignment */}/* chip Enable */NFCONF &=~0x800;for(i=0; i<10; i++);for(i=start_addr; i <(start_addr + size);){/* READ0 */NFCMD = 0;/* Write Address */NFADDR = i & 0xff;NFADDR =(i >> 9)& 0xff;NFADDR =(i >> 17)& 0xff;NFADDR =(i >> 25)& 0xff;wait_idle();for(j=0; j < NAND_SECTOR_SIZE; j++, i++){*buf =(NFDATA & 0xff);buf++;}}/* chip Disable */NFCONF |= 0x800;/* chip disable */return 0;}2.修改cpu/arm920t/start.S文件(copy from vivi)(在vivi源码下的arch\s3c2410\Head.s。
移植笔记从Norflash启动的uboot

移植笔记从Norflash启动的uboot uboot移植记录之一uboot整个移植过程我们可以分为三个阶段:一,移植可以从Nor flash启动的uboot这个阶段是移植一个最简单的uboot,可以烧在Nor flash内运行.二,移植支持Nand flash驱动的uboot加入Nand flash驱动的支持,可以在uboot命令行下操作Nand flash.但还未能从Nand flash启动,只能在Nor flash内运行.三,移植可以从Nor flash启动的uboot可以烧录在Nand flash,并设置从Nand flash启动运行uboot.分三个阶段进行移植,可以对整个uboot的移植过程及原理更加清晰明了,同时降低了发现问题时解决问题的困难度和解决范围.首先介绍移植可以从Nor flash启动的uboot. 这个阶段相对简单一点,是移植一个最简单的uboot,可以烧在Nor flash内运行.不需要修改太多的东西。
步骤如下: 测试一下默认的smdk2410_config配置能否在你的板子上正常运行 1.编译uboot1.1.4#make smdk2410_config#make ARCH=arm注:编译针对arm的平台时,uboot默认使用arm-linux-gcc编译,若交叉编译器名字不一样,需要自行在Makefile里修改。
会出现两个错误.错误信息一:cc1: Invalid option `abi=apcs-gnu'make[1]: *** [hello_world.o] Error 1make[1]: Leaving directory `/root/u-boot-1.1.4/examples'make: *** [examples] Error 2解决办法:出错的文件是/cpu/arm920t/下的config.mk:将PLATform_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) 改成: PLATform_CPPFLAGS +=$(call cc-option,-mapcs-32,$(callcc-option,-mabi=apcs-gnu,))错误信息二:make[1]: *** No rule to make target `hello_world.srec', needed by`all'. Stop. make[1]: Leaving directory `/work/src/u-boot-1.1.4/examples' 解决方法:打开 examples/Makefile把example文件夹下的Makefile中的第126行%.srec: % 改成 %.srec: %.o第129行的%.bin: % 改成 %.bin: %.o2.若编译成功,则会在uboot源码下产生u-boot.bin文件。
u_boot移植(五)之分析uboot源码中nand flash操作

u_boot移植(五)之分析uboot源码中nand flash操作一、OneNand 和Nand Flash我们已经能从Nand Flash启动了,启动之后,大家会看到如下效果:可以看出,我们的uboot默认使用的是OneNand。
需要注意的是我们的FSC100上面是没有OneNand的,有的是K9F2G08U0B型号的NAND FLASH。
前面我们了解过Nor Flash 和Nand Flash,那OneNand Flash又是什么呢?二、uboot 源码中Nand Flash部分代码分析我们从Nand Flash初始化看起,打开lib_arm/board.c文件,为了紧抓主线,以下代码只列举出了主线代码。
可以看出,我们可以通过CONFIG_CMD_NAND和CONFIG_CMD_ONENAND两个宏来选择NAND FLASH初始化还是 ONENAND FLASH初始化。
uboot 中默认定义了宏CONFIG_CMD_ONENAND,所以选择的是ONENAND FLASH初始化。
我们的FSC100上面使用的是NAND FLASH,所以我们要定义CONFIG_CMD_NAND宏,取消CONFIG_CMD_ONENAND宏的定义。
嗯!先做个记录:修改include/configs/fsc100.h,定义宏CONFIG_CMD_NAND,取消宏CONFIG_CMD_ONENAND。
好了,接下我们看看nand_init()函数时如何实现的。
看以看出,这段代码调用根据CONFIG_SYS_MAX_NAND_DEVICE宏[默认没有定义]的值来决定系统中Nand Flash设备的个数。
接着调用nand_init_chip()函数完成Nand Flash初始化,然后计算出每块Nand Flash的大小。
最终会输出Nand Flash总的容量。
嗯!做个记录:修改include/configs/fsc100.h,定义宏CONFIG_SYS_MAX_NAND_DEVICE,值为1没有看明白的地方是给nand_init_chip()函数传递的参数,接下来我们来看看他们是如何定义的。
u(boot中NANDflash的MTD驱动移植)-

u(boot中NANDflash的MTD驱动移植)-u-bootu-boot中的“与非”闪存的MTD驱动程序迁移移植了linux中的MTD 驱动程序源代码,以支持“与非”闪存擦除、刻录写入和读取驱动程序内存技术设备内存技术设备是Linux的一个子系统,用于访问闪存设备MTD的主要目的是简化新存储设备的驱动,并提供通用接口功能。
MTD驱动可以支持CFI接口的非闪存驱动和非闪存驱动。
众所周知,“与非”闪存的访问接口不像“非”闪存那样提供标准的CFI访问接口,但“与非”闪存制造商已经对不同品牌和型号的“与非”闪存芯片的访问接口制定了一些常规规定,如命令字、地址序列、命令序列、坏块标记位置、oob区域格式等。
值得注意的是,在工艺方面有两种类型的“与非”闪存:MLC和SLCMLC和SLC属于两种不同类型的NAND闪存SLC的全称是单级单元,即单级单元闪存,而MLC的全称是多级单元,即多级单元闪存。
它们的区别在于,SLC的每个单元只能存储一位数据,而MLC 的每个单元只能存储两位数据,MLC的数据密度是SLC的两倍。
就页容量而言,还有两种类型的与非:大页与非闪存(例如HY27UF082G2B)和小页与非闪存(例如K9F1G08U0A)这两种类型在页面容量、命令序列、地址序列、页面内访问和坏块识别方面非常不同,并且遵循不同的约定,因此在移植驱动程序时应该特别注意。
在下,以大页面NAND flash: HY27UF082G2B为例,介绍NAND flash 的一些基本情况,然后介绍MTD驱动程序的基本结构和流程分析。
最后,介绍了在u-boot中迁移MTD驱动程序的详细步骤:3 .4 . 1)nandflash的一些基本信息fl2400开发板上的NAND Flash芯片型号是现代HY27UF082G2B。
英特尔于1988年首次开发了或非闪存技术。
它最重要的特点是支持片上执行,彻底改变了EPROM和EEPROM主宰非易失性闪存世界的局面。
UBOOT移植(NANDFLASH的支持)——初步移植(二)

UBOOT移植(NANDFLASH的支持)——初步移植(二)NAND FLASH初始化入口函数(arch/arm/lib/board.c)这里需要定义CONFIG_CMD_NAND这个宏才行,在配置头文件中已经包含进去了,没问题。
nand_init()函数(drivers/mtd/nand/nand.c)这个函数里面使用两个宏参数进行控制CONFIG_SYS_MAX_NAND_DEVICE和CONFIG_SYS_NAND_SELECT_DEVICE,前者已经在配置头文件中进行了描述,后者由于对应的是有多个NAND设备存在的情况,这里就忽略了。
nand_init_chip()函数(drivers/mtd/nand/nand.c)这个函数需要配置三个宏参数,除了CONFIG_RELOC_FIXUP_WORKS其余都定义了。
没有定义的那个宏给出的描述是“Relocation to SDRAM works on all XXX boards”意思是重置到SDRAM工作在所有XXX板子上。
UBOOT中大部分ARM板子上都没有定义这个宏,SMDK2410也没有定义这个宏,这里也就选择不定义。
这个函数函数还需要三个参数,这三个参数在开头进行了定义。
nand_info_t nand_info[CONFIG_SYS_MAX_NAND_DEVICE];static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE];static ulong base_address[CONFIG_SYS_MAX_NAND_DEVICE] =CONFIG_SYS_NAND_BASE_LIST;宏CONFIG_SYS_NAND_BASE_LIST采用默认的配置。
#ifndef CONFIG_SYS_NAND_BASE_LIST#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }#endif上述所有参数在配置头文件中都有定义。
Nand Flash启动模式下的Uboot移植
好 的移 植 性 和 可 读 性 , 在 阶 段 2中 通 常 用 C代 码 来 实 现 。 关于 C P U 的初始化文 件一般放 在第一 阶段 , 其 对 应 的 文 件 目录 为 c p u / a r m9 2 0 t / s t a r t . S , 主 要 实 现 一 些 寄 存 器 的
映射图 、 将 系统 的 软 硬环 境 带 到 一 个 合适 的状 态 , 为 最 终 的
内核调 试 做 好 准 备 。Ub o o t 是在 p p c b o o t 以 及 AR Mb o o t 的 基础上 发展 而来 的较 为 通用 的 B o o t I o a d e r , 不 仅 仅 支 持
工程与应 用, 2 O 1 1 ( 3 4 ) . ( 责任编辑 : 孙 娟)
[ 6 ] 邓金 华 , 蒋浩 , 邝达 , 等. 用 擂 台赛 排 挤 算 法 构 造 多 目标 最 优 解 集 的
M oGA Ba s e d On g - Do mi n a t e d M e t h o d f o r kna p s a c k pr o b l e ms
s 3 c 2 4 4 0 A 平 台上 如 何 实现 Na n d F l a s h启 动 模 式 下 的 Ub o o t 移 植 进 行 了介 绍 。 具 体 操 作 和 编 译 在 f e d o r a 9操 作 系 统
和 a r m— l i n u x - g c c 4 . 3 . 2交 叉 编 译 下 完 成 。
硬 件 设 备 的初 始 化 函数 来 完 成 本 阶 段 要 使 用 到 的 硬 件 设
中 的 No r f l a s h。但 No r f l a s h存 储 器 的价 格 比较 昂 贵且 存
Nand Flash启动模式下的Uboot移植
Nand Flash启动模式下的Uboot移植
杨素秋
【期刊名称】《软件导刊》
【年(卷),期】2013(020)003
【摘要】BootLoader移植是嵌入式系统开发中的一个重要环节,而Uboot是一个支持多处理器多操作系统较为通用的BootLoader。
分析了Uboot的启动过程,并对s3c2440A如何支持驱动代码在外部NandFlash上的执行,以及在
s3c2440A平台上如何实现NandFlash启动模式下的Uboot移植进行了介绍。
具体操作和编译在fedora9操作系统和arm—linux-gcc4.3.2交叉编译下完成。
【总页数】4页(P33-36)
【作者】杨素秋
【作者单位】常州信息职业技术学院,江苏常州213164
【正文语种】中文
【中图分类】TP301
【相关文献】
1.基于S3C2440 Nand Flash启动模式的研究 [J], 韩金利
2.季底效应6月下旬主流NAND Flash颗粒合约价小跌约1%~6% [J],
3.VxWorks环境下NandFlash驱动程序设计研究 [J], 冉鹏;陈向
4.Nand Flash启动模式下的Uboot移植 [J], 杨素秋
5.嵌入式Linux下NAND flash上根文件系统的构建 [J], 程建
因版权原因,仅展示原文概要,查看原文内容请购买。
uboot学习与移植笔记整理
Part1:remap.remap比较简单,和MMU的功能可以看做是等价的,只是一般remap地址估定为0x0 ,网上有个帖子叫<<ARM remap与重定位摘抄>>专门讲了它对remap的理解,对remap的作用是这样讲的: 当ARM处理器上电或者Reset之后,处理器从0x0取指。
因此,必须保证系统上电时,0x0处有指令可以执行。
所以,上电的时候,0x0地址处必定是ROM或者Flash(NOR)。
但是,为了加快启动的速度,也方便可以更改异常向量表,加快中断响应速度,往往把异常向量表映射到更快、更宽(32bit/16bit)的RAM中。
但是异常向量表的开始地址是由ARM架构决定的,必须位于0x0处,因此,必须把RAM映射到0x0。
文中提到了ARM处理器remap的三种情况,如下1)如果处理器有专门的寄存器可以完成Remap。
那么Remap是通过Remap寄存器的相应bit置1完成的。
如Atmel AT91xx2)如果处理器没有专门的寄存器,但是memory的bank控制寄存器可以用来配置bank的起始地址,那么只要把RAM的起始地址编程为0x0,也可以完成remap。
如samsung s3c4510 .3)如果上面两种机制都没有,那么Remap就不要做了。
因为处理器实现决定了SDRAM对应的bank地址是不能改变的。
如Samsung S3c2410.不过我的看法有点稍微不一样,如果上面两种机制都没有,那么Remap就不要做了,它给的典型例子是Samsung S3c2410 ,2410虽然sdram对应的bank地址不能改变,但它有MMU功能, MMU可以起到remap的作用,常用的最典型的应该是例子Samsung S3c44b0,它既没有mmu,又SDRAM对应地址有没办法改变.顺便补充下除了4510可以改变每个bank的地址,还有华邦的w90P740(arm7),呵呵,我现在用的U就是这款U,可以把bank的地址随意的设置.2.relocate .relocate (地址重定位),个人觉得这个是boot里面最麻烦也是最核心的部分,刚开始看boot代码的时候,它简直是我的噩梦,不知道大家分析boot的源码流程是否这样,也可能我大学不是计算机的,没学过编译原理(现在也没看过)对链接和加载一无所知,有两个星期非常痛苦,就是不懂人家boot里面的链接脚本为什么要那样写.网上关于uboot的帖子很多,但对链接加载这块,始终写的不详细,不知道是不是太过于基础了,高手都不愿意讲,最后自己找资料,发现其实一切痛苦的根源都是对链接和加载不太清楚造成的,但个人感觉boot除了初始化以外就是搬运程序,如何搬运?为什么要那样搬运都需要对硬件板的地址分布很清楚?而这些都是链接决定的,所以非弄清楚不可!1.我们为什么需要relocate ? 经济方面,(nandflash和norflash 每兆价格相差悬殊),把boot代码放在norflash里面(为什么不放在nandflash里面,因为nandflash读需要驱动支持,norflash可以直接访问),boot通常很小,只需要占用几十k的空间,所以只需要很小的norflash芯片,这样很便宜,而把应用程序通常很大,所以用价格低廉nandflash来储存,实际应用,通过执行boot程序,把nandflash里面代码和数据搬运到内存中来执行,这样比程序直接放在norflash里执行,可以.另外还有运行速度方面的差别,程序在norflash里执行的速度远远小于在sdram中执行的速度,为了追求更高的速度,也需要relocate,让程序在sdram里面执行.2.关于加载域(VMA)和运行域(LMA)(加载域和运行域,加载域是程序代码在ROM、FLASH中的排列次序及地址安排,运行域是程序运行时代码在SRAM、SDRAM中地址安排;存储代码时按照加载域存放在FLASH中,运行时再从FLASH中取出代码到RAM运行域运行,一段代码的加载域和存储域可以不同),杜春雷在它那本经典的<<arm体系结构与编程>>一书专门有一章来讲加载域和运行域不一致的情况,但我当初接触了它的这些加载域和运行域后,看uboot的lds ,uboot的lds没有设置LMA,只是设置了VMA,为此我疑惑很久.直到耐心的看了那本链接器和加载器的书才豁然明白( /viewthread.php?tid=817770 ),任何一个链接器和加载器的基本工作都非常简单: 将更抽象的名字与更底层的名字绑定起来,好让程序员使用更抽象的名字编写代码,链接器的就是把源文件进行符号解析,把解析出来的符号和地址的进行绑定,把全局变量,函数,标号等等这些符合和地址绑定起来.3.boot上电后开始能够正确执行还有个很重要的原因,是要保证boot在系统加电或复位后最初执行的代码是跟地址无关的,(即在代码搬运前所执行的代码是与地址无关),地址无关即地址无关代码生成的这个映象文件可以被放在内存中的任何一个地址上运行。
u_boot移植(四)之nand flash启动
u_boot移植(四)之nand flash启动通过前面几节的介绍,我们了解了DDR2内存的初始化,K9F2G08U0B Nand Flash的操作。
接下来,是时候将我们的uboot烧写到Nand Flash,然后从Nand Flash启动了。
在正式干活之前,我们先来了解一下S5PC100的启动流程。
一、S5PC100 启动流程通过上面英文的解释,我们可以知道:(1)S5PC100在上电的时候,可以选择从Nand Flash 、OneNand 、SD 卡、USB进行启动。
我们这里选择从Nand Flash进行启动。
(2)S5PC100上电的时候,首先运行的是它内部ROM中程序。
这段程序会自动拷贝Nand Flash前16KB数据到S5PC100内部的SRAM中,接下来跳到内部的SRAM中执行。
我们如果想将我们的uboot能从NAND FLASH启动,就必须把它烧写到Nand Flash的启始位置。
这样以一上电的时候,S5PC100内部ROM中的程序会将我们uboot的前16KB代码拷贝到其内部的SRAM中执行。
嗯,这样我们就可以执行uboot的第一阶段代码了。
通过前面我们对NAND FLASH启动流程的分析,我想大家应该知道,uboot第一阶段干的主要事情有三个:(1)初始化DRAM(2)拷贝Nand Flash上的uboot到DRAM中(3)跳到DRAM中执行Nand Flash的第二阶段下面,我画了一幅图,对上面的过程做了简单的一个总结,帮助大家更好的理解,uboot是如何从Nand Flash启动的?好了,接下来我们就来修改uboot源码,让它支持从nand flash启动。
二、修改uboot源码,支持从nand flash启动这里主要修改的是u_boot的第一阶段,我想通过前面对uboot的启动流程分析,大家应该很熟悉uboot的第一阶段了。
好,开始干活吧!我们回顾一下,第一阶段设计到主要文件:需要关心的文件我已经在上图中标识出来了,接下来我们来看一下每个文件,确认需要修改的地方。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
到目前为此,这个版本的uboot已经加进了Nand驱动,可以使用Nand命令对nandflash进行读写。
但是还不能从Nand启动,只可以从Norflash启动或用tftp下载到sdram中然后go到该地址使用。
原因是目前移植的uboot还没有实现s3c2410支持的从Nand Flash启动机制需要的自拷贝功能。
下面介绍移植可以从Nand flash启动的uboot。
关于这里的Nand Boot概念,如果分析过vivi源码,明白vivi是如何从Nand跳转到sdram中继续执行以及copy_myself原理的话,再理解这里就比较简单了。
其实我们这里使uboot支持从nand启动的原理正是移植vivi里的copy_myself机制。
关于s3c2410从Nand Flash启动的原理可以查阅其他相关资料,不懂的话也没关系,不影响移植过程。
当然,我们的最终目的是编译一个可以直接烧录到nand中启动的uboot。
既然已经到这一步了,要实现nand启动已经很容易了。
只需要添加几行代码,大部分从vivi拷贝,只需修改少许地方。
过程如下:1.在board/smdk2410加入NAND Flash读函数,建立nand_read.c文件,加入如下内容(copy from vivi):(在vivi源码下的arch\s3c2410\nand_read.c)#include<config.h>#define __REGb(x)(*(volatile unsigned char*)(x))#define __REGi(x)(*(volatile unsigned int*)(x))#define NF_BASE 0x4e000000#define NFCONF __REGi(NF_BASE + 0x0)#define NFCMD __REGb(NF_BASE + 0x4)#define NFADDR __REGb(NF_BASE + 0x8)#define NFDATA __REGb(NF_BASE + 0xc)#define NFSTAT __REGb(NF_BASE + 0x10)#define BUSY 1inline void wait_idle(void){int i;while(!(NFSTAT & BUSY))for(i=0; i<10; i++);}#define NAND_SECTOR_SIZE 512#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)/* low level nand read function */intnand_read_ll(unsigned char*buf,unsigned long start_addr,int size) {int i, j;if((start_addr & NAND_BLOCK_MASK)||(size & NAND_BLOCK_MASK)) {return-1;/* invalid alignment */}/* chip Enable */NFCONF &=~0x800;for(i=0; i<10; i++);for(i=start_addr; i <(start_addr + size);){/* READ0 */NFCMD = 0;/* Write Address */NFADDR = i & 0xff;NFADDR =(i >> 9)& 0xff;NFADDR =(i >> 17)& 0xff;NFADDR =(i >> 25)& 0xff;wait_idle();for(j=0; j < NAND_SECTOR_SIZE; j++, i++){*buf =(NFDATA & 0xff);buf++;}}/* chip Disable */NFCONF |= 0x800;/* chip disable */return 0;}2.修改cpu/arm920t/start.S文件(copy from vivi)(在vivi源码下的arch\s3c2410\Head.s。
只不过要注意的是完全拷贝过来后需修改两个地方,下面我已经修改好,并且标了出来)在ldr pc, _start_armboot之前加入:在_start_armboot: .word start_armboot之后加入:#ifdef CONFIG_S3C2410_NAND_BOOTcopy_myself:mov r10, lr@ reset NANDmov r1,#NAND_CTL_BASEldr r2,=0xf830 @ initial valuestr r2,[r1,#oNFCONF]ldr r2,[r1,#oNFCONF]bic r2, r2,#0x800 @ enable chipstr r2,[r1,#oNFCONF]mov r2,#0xff @ RESET commandstrb r2,[r1,#oNFCMD]mov r3,#0 @ wait1:add r3, r3,#0x1cmp r3,#0xablt 1b2:ldr r2,[r1,#oNFSTAT] @ wait readytst r2,#0x1beq 2bldr r2,[r1,#oNFCONF]orr r2, r2,#0x800 @ disable chipstr r2,[r1,#oNFCONF]@ get read to call C functions (for nand_read())ldr sp, DW_STACK_START @ setup stack pointermov fp,#0 @ no previous frame, so fp=0@ copy vivi to RAMldr r0,=UBOOT_RAM_BASE //replace VIVI_RAM_BASE with UBOOT_RAM_BASEmov r1,#0x0mov r2,#0x20000bl nand_read_lltst r0,#0x0beq ok_nand_read#ifdef CONFIG_DEBUG_LLbad_nand_read:ldr r0, STR_FAILldr r1, SerBasebl PrintWord1:b 1b @ infinite loop#endifok_nand_read:#ifdef CONFIG_DEBUG_LLldr r0, STR_OKldr r1, SerBasebl PrintWord#endif@ verifymov r0,#0ldr r1,=UBOOT_RAM_BASE //replace 0x33f00000 with UBOOT_RAM_BASEmov r2,#0x400 @ 4 bytes * 1024 = 4K-bytesgo_next:ldr r3,[r0],#4ldr r4,[r1],#4teq r3, r4bne notmatchsubs r2, r2,#4beq done_nand_readbne go_nextnotmatch:#ifdef CONFIG_DEBUG_LLsub r0, r0,#4ldr r1, SerBasebl PrintHexWordldr r0, STR_FAILldr r1, SerBasebl PrintWord#endif1:b 1bdone_nand_read:#ifdef CONFIG_DEBUG_LLldr r0, STR_OKldr r1, SerBasebl PrintWord#endifmov pc, r10@ clear memory@ r0: start address@ r1: lengthmem_clear:mov r2,#0mov r3, r2mov r4, r2mov r5, r2mov r6, r2mov r7, r2mov r8, r2mov r9, r2clear_loop:stmia {r2-r9}subs r1, r1,#(8 * 4)bne clear_loopmov pc, lr#endif @ CONFIG_S3C2410_NAND_BOOT在文件的最后加入:.align 2DW_STACK_START:.word STACK_BASE+STACK_SIZE-4注:UBOOT_RAM_BASE即uboot从nand启动时将自身拷贝到sdram中的地址,换句话说就是uboot在sdram 中运行的地址。
这个地址会在smdk2410中定义。
3.修改include/configs/smdk2410.h文件添加如下内容:4.修改board/smdk2410/Makefile为OBJS := smdk2410.o flash.o nand_read.o注:此处的目的是把新添加的nand_read.c编译进uboot,若不添加编译时会提示找不到nand_read_ll函数错误。
5.最后将新编译好的带Nand boot功能的uboot.bin烧录到Nand flash中这里同样不需要烧录工具(sjflash),使用上篇文章已实现的nand驱动提供的命令对nand flash烧写即可。
步骤如下:1)将新编译好的uboot.bin下载到sdram中地址0x30000000处2)help一下查看nand命令帮助发现nand read/write命令使用很简单,addr为内存地址,off为偏移地址,size为数据大小。
要注意的是写nand 前必须先擦除。
3)檫除Nand flash前128KB:4)将sdram中的uboot烧录到Nand Flash 0块位置:6.重起开发板,设置好跳线从nand flash启动。
之前一直用的从nor flash启动,这把终于可以从nand flash启动啦,激动ing!启动信息如下:测试了一下,可以正常使用!到此,uboot移植记录系列完成了!注:这边有个小插曲。
uboot从nand启动时老是卡在"*** Warning - bad CRC, using default environment"这里,并且显示"NAND: 0 MB"。
解决这个问题花了好长时间,最后发现竟然是编译器问题,这里我的板子需要把编译器改为crosstool 2.95.3编译,而不是3.3.2。
编译后再烧到板子上跑"NAND: 0 MB"的问题就消失了。