u-boot移植--4、对于NAND FLASH的支持
来源:互联网 发布:curl windows 64 下载 编辑:程序博客网 时间:2024/05/16 08:54
常常说自己是老年人记忆,因为看过的东西很快就忘。秉承着看自己写的东西肯定要比看别人写东西要好理解的原则。写下这个系列的u-boot移植,同时也加深自己的理解。其实到现在网上大神很多,给出了很多的解决方案。我也以他们为参考。与之不同我会加上一些我自己对某些地方的理解来进行处理。希望对大家有帮助。
开发板:天嵌TQ2440
u-boot:u-boot-1.1.6
手里的开发板是天嵌的TQ2440,看的书是韦东山老师的《嵌入式Linux开发完全手册》,有些许不同的地方,增加了移植困得,当应该也更加深自己的理解。
NAND FLASH型号:K9F2G08U0A
对于NAND FLASH,我们需要了解如下的信息。K9F2G08UXA 是一个具有128K页,2048块,每一块64页,每一页具有(2K+64)byte,2K是主区,64是信息区域,每一块是(128K+4K)byte的空间。所有的操作都是通过一个8位的IO实现。对每一页的访问通过列地址进行访问,2K空间一共需要11个位宽,因此列访问需要两次,第一次前8位,
第二次前4位,后4位为0。行地址和列地址是分开访问的。页访问通过行地址实现,一共128K,则需要17位位宽,这样8位IO口需要三次才能访问完全,前两次的8位,后一次的1位,其他位都必须为0。因此K9F2G08UXA 的地址是5次地址方式。这才导致了5个周期输入。实质上存储空间不止256M。具体的操作的方式是通过一些命令实现的,因此需要熟悉命令,才能实现控制。我们以一张图来看看NAND FLASH的构架。
首先我们在include/configs/TQ2440.h文件中的CONFIG_COMMANDS中增加CFG_CMD_NAND的命令,如下所示。
#define CONFIG_COMMANDS \ (CONFIG_CMD_DFL | \ CFG_CMD_CACHE | \ CFG_CMD_NAND | \ CFG_CMD_REGINFO | \ CFG_CMD_DATE | \ CFG_CMD_PING | \ CFG_CMD_ELF)
定义的CFG_CMD_NAND实际上就相当于u-boot对nand支持的总开关,定义之后u-boot对于NAND的应用就被打开了。我们先编译一下,看看现在是什么状态。make all,发现了如下的报错信息。
/work/system/u-boot-1.1.6/include/linux/mtd/nand.h:412: error: `NAND_MAX_CHIPS' undeclared here (not in a function)nand.c:35: error: `CFG_MAX_NAND_DEVICE' undeclared here (not in a function)nand.c:38: error: `CFG_NAND_BASE' undeclared here (not in a function)nand.c:35: error: storage size of `nand_info' isn't knownnand.c:37: error: storage size of `nand_chip' isn't knownnand.c:38: error: storage size of `base_address' isn't knownnand.c:37: warning: 'nand_chip' defined but not usednand.c:38: warning: 'base_address' defined but not used
可以看到实际上虽然我们打开了对于NAND FLASH的支持,但是我们并没有添加NAND的信息,这样NAND肯定是有意见的。我们没有定义这三个宏定义,也缺少一些基本信息。那么我们首先在include/configs/TQ2440.h中添加三个宏定义信息。如下所示
/*----------------------------------------------------------------------- * NAND FLASH environment organization */#define CFG_NAND_BASE 0x4E000000 /* define the base address */#define CFG_MAX_NAND_DEVICE 1 /* the count of device */#define NAND_MAX_CHIPS 1 /* every device is consist of 1 chip */可以看到我们定义的CFG_NAND_BASE是使用S3C2410_NAND_BASE来定义的,这是因为S3C2440的NAND控制器首地址是与S3C2410相同的,另外定义CFG_NAND_BASE实际上就是指的S3C2440的NAND控制器的所有寄存器的首地址。所以这里定义的CFG_NAND_BASE即为S3C2410_NAND_BASE所代表的0x4E000000.
对于u-boot来说,他的启动分两个阶段,第一阶段的文件为cpu/arm920t/start.s和board/TQ2440/low_level_init.s文件,前者是和平台相关的,后者是和开发板相关的。第二阶段是从lib_arm/board.c中的start_armboot函数开始的,如下图所示
在start_armboot函数中flash_init完成之后,如果定了的nand则会初始化nand,函数为nand_init(),nand_init()是drivers/nand/nand.c文件中函数,在nand_init()中又调用了同文件中的nand_init_chip();,然后nand_init_chip()又调用同文件中的board_nand_init()函数,可以看到这个函数也在nand.c文件中,只不过只有个名字,没有被实现。我们需要自己来实现这个函数。
在编写nand_init_chip()之前我们应该知道s3c2410和s3c2440还是有差异存在。这其中就包括了nand控制寄存器的差异。在s3c2410中,nand控制寄存器地址范围为0x4E000000到0x4E000014(6个32位寄存器)。而在s3c2440在nand控制寄存器地址范围为0x4E000000到0x4E00003C(12个32位寄存器)。s3c2410的寄存器的定义是在include/S3c24x0.h中定义的(S3c2410.h包含这个头文件),代码中寄存器的定义是按照2410的寄存器定义的,因为s3c2440的nand控制器的寄存器更多一些,我们新建一个S3C2440_NAND结构体来定义我们要用的关于S3C2440的寄存器。具体添加什么寄存器,及对应顺序可以去s3c2440的数据手册里去查。添加完成后的两个片子的nand控制器寄存器结构体如下所示。
/* NAND FLASH (see S3C2410 manual chapter 6) */typedef struct {S3C24X0_REG32NFCONF;S3C24X0_REG32NFCMD;S3C24X0_REG32NFADDR;S3C24X0_REG32NFDATA;S3C24X0_REG32NFSTAT;S3C24X0_REG32NFECC;} /*__attribute__((__packed__))*/ S3C2410_NAND;/* NAND FLASH (see S3C2440) */typedef struct {S3C24X0_REG32NFCONF;S3C24X0_REG32NFCONT;S3C24X0_REG32NFCMD;S3C24X0_REG32NFADDR;S3C24X0_REG32NFDATA; S3C24X0_REG32NFMECCD0; S3C24X0_REG32NFMECCD1; S3C24X0_REG32NFSECCD; S3C24X0_REG32NFSTAT; S3C24X0_REG32NFESTAT0; S3C24X0_REG32NFESTAT1; S3C24X0_REG32NFMECC0; S3C24X0_REG32NFMECC1; S3C24X0_REG32NFSECC; S3C24X0_REG32NFSBLK; S3C24X0_REG32NFEBLK;} /*__attribute__((__packed__))*/ S3C2440_NAND;
好接下来我们只要实现board_nand_init()函数就好了。为了能够更好地层次化处理我们代码我们在单独编写一个s3c2440_nand.c文件来单独实现一个s3c2440_nand_init()函数以及其他几个用到的函数。这样我们就可以直接在drivers/nand/nand.c中用board_nand_init()直接调用函数s3c2440_nand_init函数就可以了。
首先为了更好地编写s3c2440_nand.c文件,我们在include/s3c2410.h中添加对于获取nand地址的函数,即仿照S3C2410_GetBase_NAND函数定义实现一个函数名为S3C2410_GetBase_NAND的函数来获取地址,如下所示
static inline S3C2410_NAND * const S3C2410_GetBase_NAND(void){return (S3C2410_NAND * const)S3C2410_NAND_BASE;}static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void){return (S3C2440_NAND * const)S3C2440_NAND_BASE;}
这里的S3C2440_NAND_BASE我们需要在前面的宏定义添加一下,这个地址是芯片寄存器已经定义好的。宏定义如下所示
#define S3C2440_NAND_BASE 0x4E000000
(这里需要说明一下,这里定义的S3C2440_NAND_BASE地址和我们之前定义的CFG_NAND_BASE一样都指向了S3C2440片子的NAND控制器寄存器的首地址。)
然后编写的s3c2440_nand.c文件代码为(s3c2440_nand.c的文件路径是/cpu/arm920t/s3c24x0/s3c2440_nand.c)
/* * Nand flash interface of s3c2410/s3c2440, by www.100ask.net * Changed from drivers/mtd/nand/s3c2410.c of kernel 2.6.13 */#include <common.h>#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)#include <s3c2410.h>#include <nand.h>DECLARE_GLOBAL_DATA_PTR;#define S3C2440_NFSTAT_READY (1<<0)#define S3C2440_NFCONT_nFCE (1<<1)/* select chip, for s3c2440 */static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chip){ S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND(); if (chip == -1) { s3c2440nand->NFCONT |= S3C2440_NFCONT_nFCE; } else { s3c2440nand->NFCONT &= ~S3C2440_NFCONT_nFCE; }}/* command and control functions */static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd){ S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND(); struct nand_chip *chip = mtd->priv; switch (cmd) { case NAND_CTL_SETNCE: case NAND_CTL_CLRNCE: printf("%s: called for NCE\n", __FUNCTION__); break; case NAND_CTL_SETCLE: chip->IO_ADDR_W = (void *)&s3c2440nand->NFCMD; break; case NAND_CTL_SETALE: chip->IO_ADDR_W = (void *)&s3c2440nand->NFADDR; break; /* NAND_CTL_CLRCLE: */ /* NAND_CTL_CLRALE: */ default: chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA; break; }}/* s3c2440_nand_devready() * * returns 0 if the nand is busy, 1 if it is ready */static int s3c2440_nand_devready(struct mtd_info *mtd){ S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND(); return (s3c2440nand->NFSTAT & S3C2440_NFSTAT_READY);}/* * Nand flash hardware initialization: * Set the timing, enable NAND flash controller */static void s3c2440_nand_inithw(void){ S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();#define TACLS 0#define TWRPH0 4#define TWRPH1 2 /* Set flash memory timing */ s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4); /* Initialize ECC, enable chip select, NAND flash controller enable */ s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0);}/* * Called by drivers/nand/nand.c, initialize the interface of nand flash */void s3c2440_nand_init(struct nand_chip *chip){ S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND(); s3c2440_nand_inithw(); chip->IO_ADDR_R = (void *)&s3c2440nand->NFDATA; chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA; chip->hwcontrol = s3c2440_nand_hwcontrol; chip->dev_ready = s3c2440_nand_devready; chip->select_chip = s3c2440_nand_select_chip; chip->options = 0; chip->eccmode = NAND_ECC_SOFT;}#endif(这段代码是直接由韦东山老师的代码改的)
(详细的研究下这段代码的作用,多研究http://blog.csdn.net/ying_seven/article/details/6888923)
接着修改drivers/nand/nand.c文件在其中建立函数board_nand_init(),其代码为
void board_nand_init(struct nand_chip *nand){ s3c2440_nand_init(nand);}
最后修改将s3c2440_nand.c文件加入到编译链中,就可以了。修改cpu/arm920t/s3c24x0/Makefile文件
修改前:
COBJS= i2c.o interrupts.o serial.o speed.o \ usb_ohci.o
修改后:
COBJS= i2c.o interrupts.o serial.o speed.o \ usb_ohci.o s3c2440_nand.o
这样就大功告成了,我们编译一下make all,然后编译通过,就可以了
最后说一下关于nand中的调用关系实际上是比较复杂,也比较完善的。我这里并没有提及这些东西,因为我也不是搞的很清楚,本博文的移植实际上也只是皮毛的移植。如果想深入了解,这里有一篇好博文大家可以去看。我自己也深受其益。http://blog.csdn.net/ying_seven/article/details/6888923
参考文献:1、《嵌入式linux开发完全手册》、韦东山
2、http://blog.csdn.NET/zhaocj (这位博主下面的u-boot系列)
3、http://blog.csdn.net/ying_seven/article/details/6888923
- u-boot移植--4、对于NAND FLASH的支持
- u-boot:从NOR FLASH启动并支持NAND FLASH读写的移植
- 基于TQ2440的u-boot 1.1.6移植(二)(支持nor flash nand flash )
- TQ2440 u-boot-2012.04.01移植四支持NAND Flash
- U-boot-2010.09移植(六)NAND Flash启动支持
- u-boot移植之支持 NAND FLASH 学习笔记
- u-boot移植(四)使支持NAND FLASH
- u-boot-2011.03在mini2440/micro2440上的移植(五)——支持Nand Flash
- fl2440的U-boot-2010.09移植(六)NAND Flash启动支持
- 用mini2440开发板学习韦东山毕业班移植最新的u-boot支持nand flash
- u-boot移植后的 nand flash命令
- 移植u-boot-2011.03到S3C2440(utu2440)的方法与步骤###7.NAND FLASH部分移植和支持NAND FLASH启动和读写
- U-Boot移植——Nand Flash
- U-boot移植 (v2012.04.1 S3C2440平台) (三) Nor flash Nand flash 驱动支持
- U-boot-2014.04移植到MINI2440(8) nand flash 读写支持移植
- 移植u-boot-2012.04----支持nand启动
- u-boot-2011.03在mini2440/micro2440上的移植(七)——支持Nand Flash启动
- u-boot-2009.08在飞凌OK2440/FL2440上的移植(四)——让u-boot支持nand flash识别与操作
- [Machine Learning][Linear Regression]Feature Scaling
- 多线程编程-线程同步方式介绍(二)
- 如何代表与JAXB空元素空值?(jaxb中引用@XmlNullPolicy仍然不能显示空节点)
- Hadoop学习之HDFS读流程
- MyEclipse中的常用快捷键
- u-boot移植--4、对于NAND FLASH的支持
- ldap学习笔记 1
- python使用pymongo访问MongoDB的基本操作,以及CSV文件导出
- 从论文中寻找知识、思路、最新研究成果
- 1037. 在霍格沃茨找零钱(20)
- java.io.IOException: Cannot create directory /app/hadoop-2.4.1/tmp/dfs/name/current
- 欢迎使用CSDN-markdown编辑器
- ZooKeeper数据模型与层次命名空间
- 写在入学第一日