一、将配置文件中的nand命令打开:
shanl@shanl-Aspire-4740:~/Boot/u-boot-2012.04.01_nandsupportTest$ vi include/configs/shanl2440.h
#define CONFIG_CMD_BSP
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_ELF
#define CONFIG_CMD_NAND
#define CONFIG_CMD_PING
#define CONFIG_CMD_REGINFO
#define CONFIG_CMD_USB
二、编译出现下面的错误:
s3c2410_nand.c: In function 's3c2410_hwcontrol':
s3c2410_nand.c:57: warning: implicit declaration of function 's3c2410_get_base_nand'
s3c2410_nand.c:57: warning: initialization makes pointer from integer without a cast
s3c2410_nand.c:72: error: dereferencing pointer to incomplete type
s3c2410_nand.c:72: error: dereferencing pointer to incomplete type
s3c2410_nand.c:75: error: dereferencing pointer to incomplete type
s3c2410_nand.c:75: error: dereferencing pointer to incomplete type
s3c2410_nand.c: In function 's3c2410_dev_ready':
s3c2410_nand.c:85: warning: initialization makes pointer from integer without a cast
s3c2410_nand.c:87: error: dereferencing pointer to incomplete type
s3c2410_nand.c: In function 'board_nand_init':
s3c2410_nand.c:129: warning: initialization makes pointer from integer without a cast
s3c2410_nand.c:150: error: dereferencing pointer to incomplete type
s3c2410_nand.c:153: error: dereferencing pointer to incomplete type
s3c2410_nand.c:154: error: dereferencing pointer to incomplete type
make[1]: *** [s3c2410_nand.o] 错误 1
make[1]:正在离开目录 `/home/shanl/Boot/u-boot-2012.04.01/drivers/mtd/nand'
解决:
做一份2440单板相关的s3c2440_nand.c文件
配置文件(shanl2440.h)修改:
将:
#ifdef CONFIG_CMD_NAND
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE 0x4E000000
#endif
修改为:
#ifdef CONFIG_CMD_NAND
#ifdef CONFIG_S3C2410
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#else
#define CONFIG_NAND_S3C2440
#define CONFIG_SYS_S3C2440_NAND_HWECC
#endif
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE 0x4E000000
#endif
加入2440的单板文件:
shanl@shanl-Aspire-4740:~/Boot/nandsupport$ cp drivers/mtd/nand/s3c2410_nand.c drivers/mtd/nand/s3c2440_nand.c
Makefile的修改:
shanl@shanl-Aspire-4740:~/Boot/nandsupport$ vi drivers/mtd/nand/Makefile
COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o
COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o
COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o
都设置好后回头看下编译错误:
将s3c2440_nand.c中的所有的关于2410的文件全部改为2440的函数名
s3c2410_nand -> s3c2440_nand
s3c2410_get_base_nand -> s3c2440_get_base_nand
s3c2410_hwcontrol -> s3c2440_hwcontrol
s3c2410_dev_ready -> s3c2440_dev_ready
重新编译就不会报错了
3.下面要修改代码来让nandflash支持2440
重初始化nandflash的代码开始分析(archarmlibBoard.c):
nand_init
nand_init_chip
board_nand_init(这个就是上面我们做的2440的单板相关文件driversmtdnandS3c2440_nand.c中的函数)
nand_scan
nand_scan_ident
nand_set_defaults
chip->cmdfunc = nand_command;
nand_get_flash_type//获取nandflash的相关信息
chip->select_chip(mtd,0);
chip->cmdfunc(mtd,NAND_CMD_RESET,-1,-1);//nand_command
chip->cmdfunc(mtd,NAND_CMD_READID,0x00,-1);
*maf_id = chip->read_byte(mtd);
*dev_id = chip->read_byte(mtd);
nand_register
从nand_command的实现看既可以发命令又可以发地址,最终调用到chip->cmd_ctrl(mtd,command,ctrl);来进行相关的操作。也就是s3c2440_hwcontrol
board_nand_init的修改:
设置时序
将:
cfg = S3C2410_NFCONF_EN;
cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
writel(cfg,&nand_reg->nfconf);
修改为:
#if 0
cfg = S3C2410_NFCONF_EN;
cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
#endif?
/* 设置时序 */
cfg = ((tacls-1)<<12)|((twrph0-1)<<8)|((twrph1-1)<<4);
writel(cfg,&nand_reg->nfconf);
/* 使能NAND Flash控制器,初始化ECC,禁止片选 */
writel((1<<4)|(1<<1)|(1<<0),&nand_reg->nfcont);
设置片选函数:
将
nand->select_chip = NULL;
修改为:
nand->select_chip = s3c2440_nand_select_chip;
(函数的实现可以参考: driversmtdnandNand_base.c中的chip->select_chip = nand_select_chip;)
加入实现:
static void s3c2440_nand_select_chip(struct mtd_info *mtd,int chipnr)
{
? ?struct s3c2440_nand *nand_reg = s3c2440_get_base_nand();
? ?switch (chipnr) {
? ? ? case -1: // 取消片选
? ? ? ? ?nand_reg->nfcont |= (1<<1);
? ? ? ? ?break;
? ? ?case 0: // 选中片选
? ? ? ? ?nand_reg->nfcont &= ~(1<<1);
? ? ? ? ?break;
? ? ?default:
? ? ? ? BUG();
? ? }
}
发送地址命令函数s3c2440_hwcontrol的修改:
将:
static void s3c2440_hwcontrol(struct mtd_info *mtd,int cmd,unsigned int ctrl)
{
struct nand_chip *chip = mtd->priv;
struct s3c2440_nand *nand = s3c2440_get_base_nand();
debug("hwcontrol(): 0x%02x 0x%02xn",cmd,ctrl);
if (ctrl & NAND_CTRL_CHANGE) {
ulong IO_ADDR_W = (ulong)nand;
if (!(ctrl & NAND_CLE))
IO_ADDR_W |= S3C2410_ADDR_NCLE;
if (!(ctrl & NAND_ALE))
IO_ADDR_W |= S3C2410_ADDR_NALE;
chip->IO_ADDR_W = (void *)IO_ADDR_W;
if (ctrl & NAND_NCE) //选中芯片
writel(readl(&nand->nfconf) & ~S3C2410_NFCONF_nFCE,
? ? ? &nand->nfconf);
else
writel(readl(&nand->nfconf) | S3C2410_NFCONF_nFCE,
? ? ? &nand->nfconf);
}
if (cmd != NAND_CMD_NONE)
writeb(cmd,chip->IO_ADDR_W);
}
修改为:
static void s3c2440_hwcontrol(struct mtd_info *mtd,int dat,unsigned int ctrl)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand();
if(ctrl & NAND_CLE){//发命令
writeb(dat,&nand->nfcmd);
}
else if(ctrl & NAND_ALE)
{//发地址
writeb(dat,&nand->nfaddr);
}
}
烧写到开发板,出现到如下打印即NANDFLASH的读写操作完成:
![](http://img50.lidatong.com.cn//uploads/allimg/c20201215/52f8d75b043a2f2c076b5769324bcd8d.gif)
代码地址:uboot支持nand读写
uboot中的nandflash的结构:
nand协议层 :知道发什么,发送一些序列
单板相关层 :知道怎么发,比如:
1.选中/取消选中
2.发命令
3.发地址
4.R/W数据
5.判断状态
nand_init的具体分析,可以参考nand_init分析