加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

nandflash驱动分析 针对K9GAG08U0D uboot1.1.6(下)

发布时间:2020-12-15 07:11:56 所属栏目:百科 来源:网络整理
导读:Nandfalsh 移植 1. 在 cpu/s3c64xx/s3c6410/ 下新建 nand.c 2. 在 nand.c 上添加 board_nand_init() 实现 nand_chip 的初始化功能 3. 添加初始化函数 4. 在 include/configs/smdk6410.h 上定义相关宏 完成上述移植后,实际上启动后的 uboot 中的 nand 命令是

Nandfalsh移植

1.cpu/s3c64xx/s3c6410/下新建nand.c

2.nand.c上添加board_nand_init()实现nand_chip的初始化功能

3.添加初始化函数

4.include/configs/smdk6410.h上定义相关宏

完成上述移植后,实际上启动后的uboot中的nand命令是通过include/nand.h实现的


------------------------------------------------------------------------------------------------------------------------------------分割线---------------------------------------------------------------------------------------------




在这前先定义nand的一些硬件地址

在S3C6410.C中

/*
?* Nand flash controller
?*/
#define ELFIN_NAND_BASE?? ??? ?0x70200000

#define NFCONF_OFFSET?????????? 0x00
#define NFCONT_OFFSET?????????? 0x04
#define NFCMMD_OFFSET?????????? 0x08
#define NFADDR_OFFSET?????????? 0x0c
#define NFDATA_OFFSET?? ??? ?0x10
#define NFMECCDATA0_OFFSET????? 0x14
#define NFMECCDATA1_OFFSET????? 0x18
#define NFSECCDATA0_OFFSET????? 0x1c
#define NFSBLK_OFFSET?????????? 0x20
#define NFEBLK_OFFSET?????????? 0x24
#define NFSTAT_OFFSET?????????? 0x28
#define NFESTAT0_OFFSET???????? 0x2c
#define NFESTAT1_OFFSET???????? 0x30
#define NFMECC0_OFFSET????????? 0x34
#define NFMECC1_OFFSET????????? 0x38
#define NFSECC_OFFSET?????????? 0x3c
#define NFMLCBITPT_OFFSET?????? 0x40
#define NF8ECCERR0_OFFSET?? ?0x44
#define NF8ECCERR1_OFFSET?? ?0x48
#define NF8ECCERR2_OFFSET?? ?0x4c
#define NFM8ECC0_OFFSET?? ??? ?0x50
#define NFM8ECC1_OFFSET?? ??? ?0x54
#define NFM8ECC2_OFFSET?? ??? ?0x58
#define NFM8ECC3_OFFSET?? ??? ?0x5c
#define NFMLC8BITPT0_OFFSET?? ?0x60
#define NFMLC8BITPT1_OFFSET?? ?0x64

#define NFCONF?? ??? ??? ?(ELFIN_NAND_BASE+NFCONF_OFFSET)
#define NFCONT?? ??? ??? ?(ELFIN_NAND_BASE+NFCONT_OFFSET)
#define NFCMMD?? ??? ??? ?(ELFIN_NAND_BASE+NFCMMD_OFFSET)
#define NFADDR????????? ??? ?(ELFIN_NAND_BASE+NFADDR_OFFSET)
#define NFDATA???????? ??? ?(ELFIN_NAND_BASE+NFDATA_OFFSET)
#define NFMECCDATA0??? ??? ?(ELFIN_NAND_BASE+NFMECCDATA0_OFFSET)
#define NFMECCDATA1??? ??? ?(ELFIN_NAND_BASE+NFMECCDATA1_OFFSET)
#define NFSECCDATA0???? ??? ?(ELFIN_NAND_BASE+NFSECCDATA0_OFFSET)
#define NFSBLK???????? ??? ?(ELFIN_NAND_BASE+NFSBLK_OFFSET)
#define NFEBLK????????? ??? ?(ELFIN_NAND_BASE+NFEBLK_OFFSET)
#define NFSTAT????????? ??? ?(ELFIN_NAND_BASE+NFSTAT_OFFSET)
#define NFESTAT0??????? ??? ?(ELFIN_NAND_BASE+NFESTAT0_OFFSET)
#define NFESTAT1??????? ??? ?(ELFIN_NAND_BASE+NFESTAT1_OFFSET)
#define NFMECC0???????? ??? ?(ELFIN_NAND_BASE+NFMECC0_OFFSET)
#define NFMECC1???????? ??? ?(ELFIN_NAND_BASE+NFMECC1_OFFSET)
#define NFSECC????????? ??? ?(ELFIN_NAND_BASE+NFSECC_OFFSET)
#define NFMLCBITPT????????? ??? ?(ELFIN_NAND_BASE+NFMLCBITPT_OFFSET)
#define NF8ECCERR0?? ??? ?(ELFIN_NAND_BASE+NF8ECCERR0_OFFSET)
#define NF8ECCERR1?? ??? ?(ELFIN_NAND_BASE+NF8ECCERR1_OFFSET)
#define NF8ECCERR2?? ??? ?(ELFIN_NAND_BASE+NF8ECCERR2_OFFSET)
#define NFM8ECC0?? ??? ?(ELFIN_NAND_BASE+NFM8ECC0_OFFSET)
#define NFM8ECC1?? ??? ?(ELFIN_NAND_BASE+NFM8ECC1_OFFSET)
#define NFM8ECC2?? ??? ?(ELFIN_NAND_BASE+NFM8ECC2_OFFSET)
#define NFM8ECC3?? ??? ?(ELFIN_NAND_BASE+NFM8ECC3_OFFSET)
#define NFMLC8BITPT0?? ??? ?(ELFIN_NAND_BASE+NFMLC8BITPT0_OFFSET)
#define NFMLC8BITPT1?? ??? ?(ELFIN_NAND_BASE+NFMLC8BITPT1_OFFSET)

#define NFCONF_REG?? ??? ?__REG(ELFIN_NAND_BASE+NFCONF_OFFSET)
#define NFCONT_REG?? ??? ?__REG(ELFIN_NAND_BASE+NFCONT_OFFSET)
#define NFCMD_REG?? ??? ?__REG(ELFIN_NAND_BASE+NFCMMD_OFFSET)
#define NFADDR_REG????????? ??? ?__REG(ELFIN_NAND_BASE+NFADDR_OFFSET)
#define NFDATA_REG???????? ??? ?__REG(ELFIN_NAND_BASE+NFDATA_OFFSET)
#define NFDATA8_REG???????? ??? ?__REGb(ELFIN_NAND_BASE+NFDATA_OFFSET)
#define NFMECCDATA0_REG??? ??? ?__REG(ELFIN_NAND_BASE+NFMECCDATA0_OFFSET)
#define NFMECCDATA1_REG??? ??? ?__REG(ELFIN_NAND_BASE+NFMECCDATA1_OFFSET)
#define NFSECCDATA0_REG???? ??? ?__REG(ELFIN_NAND_BASE+NFSECCDATA0_OFFSET)
#define NFSBLK_REG???????? ??? ?__REG(ELFIN_NAND_BASE+NFSBLK_OFFSET)
#define NFEBLK_REG????????? ??? ?__REG(ELFIN_NAND_BASE+NFEBLK_OFFSET)
#define NFSTAT_REG????????? ??? ?__REG(ELFIN_NAND_BASE+NFSTAT_OFFSET)
#define NFESTAT0_REG??????? ??? ?__REG(ELFIN_NAND_BASE+NFESTAT0_OFFSET)
#define NFESTAT1_REG??????? ??? ?__REG(ELFIN_NAND_BASE+NFESTAT1_OFFSET)
#define NFMECC0_REG???????? ??? ?__REG(ELFIN_NAND_BASE+NFMECC0_OFFSET)
#define NFMECC1_REG???????? ??? ?__REG(ELFIN_NAND_BASE+NFMECC1_OFFSET)
#define NFSECC_REG????????? ??? ?__REG(ELFIN_NAND_BASE+NFSECC_OFFSET)
#define NFMLCBITPT_REG??????? ??? ?__REG(ELFIN_NAND_BASE+NFMLCBITPT_OFFSET)

#define NFCONF_ECC_MLC?? ??? ?(1<<24)

#define NFCONF_ECC_1BIT?? ??? ?(0<<23)
#define NFCONF_ECC_4BIT?? ??? ?(2<<23)
#define NFCONF_ECC_8BIT?? ??? ?(1<<23)

#define NFCONT_ECC_ENC?? ??? ?(1<<18)
#define NFCONT_WP?? ??? ?(1<<16)
#define NFCONT_MECCLOCK?? ??? ?(1<<7)
#define NFCONT_SECCLOCK?? ??? ?(1<<6)
#define NFCONT_INITMECC?? ??? ?(1<<5)
#define NFCONT_INITSECC?? ??? ?(1<<4)
#define NFCONT_INITECC?? ??? ?(NFCONT_INITMECC | NFCONT_INITSECC)
#define NFCONT_CS_ALT?? ??? ?(1<<1)
#define NFCONT_CS?? ??? ?(1<<1)
#define NFSTAT_ECCENCDONE?? ?(1<<7)
#define NFSTAT_ECCDECDONE?? ?(1<<6)
#define NFSTAT_RnB?? ??? ?(1<<0)
#define NFESTAT0_ECCBUSY?? ?(1<<31)

在nand.h中对比芯片手册,添加修改必要的命令

Nand基本指令:

/*

*Standard NAND flash commands

*/

#defineNAND_CMD_READ0 0

#defineNAND_CMD_READ1 1

#defineNAND_CMD_RNDOUT 5

#defineNAND_CMD_PAGEPROG 0x10

#defineNAND_CMD_READOOB 0x50

#defineNAND_CMD_ERASE1 0x60

#defineNAND_CMD_STATUS 0x70

#defineNAND_CMD_STATUS_MULTI 0x71

#defineNAND_CMD_SEQIN 0x80

#defineNAND_CMD_RNDIN 0x85

#defineNAND_CMD_READID 0x90

#defineNAND_CMD_ERASE2 0xd0

#defineNAND_CMD_RESET 0xff

/*Extended commands for large page devices */

#defineNAND_CMD_READSTART 0x30

#defineNAND_CMD_RNDOUTSTART 0xE0

#defineNAND_CMD_CACHEDPROG 0x15

/*Extended commands for AG-AND device */

*Note: the command for NAND_CMD_DEPLETE1 is really 0x00 but

* there is no way to distinguish that from NAND_CMD_READ0

* until the remaining sequence of commands has been completed

* so add a high order bit and mask it off in the command.

#defineNAND_CMD_DEPLETE1 0x100

#defineNAND_CMD_DEPLETE2 0x38

#defineNAND_CMD_STATUS_ERROR 0x72

/*multi-bank error status (banks 0-3) */

#defineNAND_CMD_STATUS_ERROR0 0x73

#defineNAND_CMD_STATUS_ERROR1 0x74

#defineNAND_CMD_STATUS_ERROR2 0x75

#defineNAND_CMD_STATUS_ERROR3 0x76

#defineNAND_CMD_STATUS_RESET 0x7f

#defineNAND_CMD_STATUS_CLEAR 0xff



nand.c文件

voidboard_nand_init(struct nand_chip *nand)



s3c_nand_hwcontrol函数


staticvoid s3c_nand_hwcontrol(struct mtd_info *mtd,int dat,unsigned intctrl)


s3c_nand_device_ready函数


staticint s3c_nand_device_ready(struct mtd_info *mtdinfo)




@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

深入分析

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

U-BOOTNand命令支持
u-boot1.1.6nand_legacy
驱动提供了u-bootnand相关命令的一个轻量级的实现,但好象可扩展性不足。本文主要分析u-boot1.16/drivers/nand文档夹下的源码。
.关键数据结构
1.structmtd_info

该结构在 include linux mtd Mtd.h 中定义,字段比较多,有很多还是函数指针,他是 MTD 设备操作的通用接口,这个结构中有一个比较重要的成员 void*priv priv 被声明成 void 指针,在下文的分析中会知道 priv 实际上指向了 nand_chip 结构。

2.structnand_chip

该结构在includelinuxmtdNand.h中定义,从名字上看就知道u-boot用他来描述NandFlash芯片的结构,比如他定义了页地址的偏移,页地址的位掩码等。structnand_chip不用我们手动的初始化,而是由另外一个结构,structnand_flash_dev在程式中动态的初始化。
3.structnand_flash_dev

该结构的定义有两处地方分别是
include/linux/mtd/nand_legacy.h
nand_legacy模块使用
include/linux/mtd/nand.hu-boot通用nand架构使用
特别是在移植的时候要小心把两者混淆。我们先来看看2中该结构的定义
structnand_flash_dev {
char *name;
int id;
unsigned longpagesize;
unsigned long chipsize;
unsigned longerasesize;
unsigned long options;
};
name : Nand Flash
名称
id: u-boot
内部id编号
chipsize:
MB为单位的芯片大小
erasesize:
擦除块的大小
options:
一些选项,比较重要的是Flash的数据位宽

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

nand.c

structnand_info_t nand_info[ CFG_MAX_NAND_DEVICE ]

#defineCFG_MAX_NAND_DEVICE 1smdk6410.h中定义板子的NandFlash芯片的数量


structnand_flash_dev nand_flash_ids[] = { …};
driversnandnand_ids.c中定义,可以找到适合自己的nandflash描述

{"NAND2GiB 3,3V 8-bit",0xD5,4096,2048,512*1024,LP_OPTIONS},

含义为Name.ID code,pagesize,chipsize in MegaByte,eraseblock size,options


.nandflash初始化流程图


1.nand_initnand.c

nand_init在被board.c调用

#if(CONFIG_COMMANDS & CFG_CMD_NAND)

voidnand_init (void);

#endif

u-bootNand的主函数

nand_init的主要功能是对CFG_MAX_NAND_DEVICENand设备进行初始化(调用nand_init_chip,nand/nand.c

voidnand_init(void)

{

inti;

unsignedint size = 0;

for(i = 0; i < CFG_MAX_NAND_DEVICE; i++) {

nand_init_chip(&nand_info[i],&nand_chip[i],base_address[i]);

size+= nand_info[i].size;

if(nand_curr_device == -1)

nand_curr_device= i;

}

#ifdefFORLINX_DEBUG

printf("NandFlashSize is %lu MB ",size / (1024 * 1024));

#else

printf("%luMB ",SimSun">#endif

#ifdefined(CFG_NAND_FLASH_BBT)

printf("(FlashBased BBT Enabled)");

printf("n");

#ifdefCFG_NAND_SELECT_DEVICE

/*

* Select the chip in the board/cpu specific driver

*/

board_nand_select_device(nand_info[nand_curr_device].priv,nand_curr_device);

}

累加NandFlash的总大小。在nand_init结束时,能够配置是否执行board_nand_select_device,选择Nand芯片。
2.nand_init_chip
driversnandnand.c
staticvoid nand_init_chip
structmtd_info *mtd,struct nand_chip *nand,ulong base_addr )调用各个研发板提供的board_nand_init函数(board\\.c)让研发板获得初始化NandFlash芯片的机会。调用nand_scan



staticvoid nand_init_chip(struct mtd_info *mtd,

ulong base_addr)

{

mtd->priv= nand;



nand->IO_ADDR_R= nand->IO_ADDR_W = (void __iomem *)base_addr;

board_nand_init(nand);



//printf("nand_init_chip!n");

if(nand_scan(mtd,1) == 0) {

if(!mtd->name)

mtd->name= (char *)default_nand_name;

}else

mtd->name= NULL;

}
3.nand_scan
nand_base.c

intnand_scan(struct mtd_info *mtd,int maxchips)

intret;

ret= nand_scan_ident(mtd,maxchips);

if(!ret)

ret= nand_scan_tail(mtd);

returnret;

}
这是u-boot初始化nand设备的核心函数。他主要完成以下工作

1)初始化nand_chip的函数指针,这些函数一般在.c中定义。


structnand_chip *this = mtd->priv
....
if( this-> cmdfunc ==NULL )
this->cmdfunc = nand_command;

2)使用上面注册的函数指针,读取NandFlash的设备,并且在上文提到的nand_flash_ids[]中找是否有匹配项,若找到匹配的项,则初始化nand_chipmtd_info,他们的初始化代码老长的一段,一般没什么问题。

.Nand Flash操作

read操作来说,调用流程如下

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读