文章目录
1、之前编译时出现的错误
之前由于nand部分报错,直接注释了 u-boot-2012.04.01\include\configs\smdk2440.h
中的#define CONFIG_CMD_NAND
。现在我们去掉注释,重新编译。
报错如下:
这是由于我们没有定义CONFIG_S3C2410
这个宏导致的:
可以看到下面有2440的NAND结构体
2、复制s3c2410_nand.c,修改宏定义支持SC32440
所以我们可以拷贝一份s3c2410_nand.c
给2440,使用2410的NandFlash位于drivers/mtd/nand/s3c2410_nand.c
,首先复制s3c2410_nand.c
,改为s3c2440_nand.c
:
并修改drivers/mtd/nand/Makefile
,如下图所示:
在上一节分析过CONFIG_NAND_S3C2410
宏,位于include/configs/smdk2440.h
:
如上图所示,其中CONFIG_CMD_NAND
宏表示uboot是否支持nand,在上节里我们把它屏蔽了,接下来便取消屏蔽CONFIG_CMD_NAND
宏。
继续添加对CONFIG_NAND_S3C2440
宏的支持,将:
/*
* NAND configuration
*/
#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
/*
* File system
*/
修改为:
/*
* NAND configuration
*/
#ifdef CONFIG_CMD_NAND
#ifdef CONFIG_S3C2410
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#else // CONFIG_S3C2440
#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
/*
* File system
*/
其中CONFIG_S3C2410
没有定义,而CONFIG_S3C2440
定义了:
由于smdk2410.h
中定义的是CONFIG_S3C2410
,而smdk2440.h
中定义的是CONFIG_S3C2440
,所以便会根据上面的#ifdef
来动态定义宏。
分析nand
的初始化过程:nand_init()
如下:
nand_init
nand_init_chip
board_nand_init //单板相关的初始化
设置nand_chip结构体, 提供底层的操作函数(即发命令、发地址、读数据等等)
nand_scan //识别nand flash
nand_scan_ident
nand_set_defaults
chip->select_chip = nand_select_chip; //选中芯片
chip->cmdfunc = nand_command; //发出读复位命令
chip->read_byte = busw ? nand_read_byte16 : nand_read_byte; //读数据
nand_get_flash_type
chip->select_chip
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
nand_command()//即可发命令,也可发列地址(页内地址)、行地址(哪一页)
chip->cmd_ctrl
s3c2440_hwcontrol
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
*maf_id = chip->read_byte(mtd);
*dev_id = chip->read_byte(mtd);
3、修改s3c2440_nand.c 中的NFCONF,NFCONT,支持S3C2440
往下看代码发现原来的NFCONF
设置并不能匹配我们的2440,将s3c2440_nand.c
中改为如下:
其中:
2440的NFCONF的15位是保留的:
所以注释掉这部分代码:
2410 NFCONF的其他位设置也不匹配我们的2440:
2440NFCONF 时序参数设置:
s3c2440_hwcontrol
函数中使能选中:
对照2440手册修改为支持2440的:
修改为:
int board_nand_init(struct nand_chip *nand) {
。。。
。。。
#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);
/* initialize nand_chip data structure */
nand->IO_ADDR_R = (void *)&nand_reg->nfdata;
nand->IO_ADDR_W = (void *)&nand_reg->nfdata;
nand->select_chip = s3c2440_nand_select;
/* read_buf and write_buf are default */
/* read_byte and write_byte are default */
。。。
。。。
4、修改s3c2440_hwcontrol区分命令和地址
/* ctrl : 表示做什么, 选中芯片/取消选中, 发命令还是发地址
* dat : 命令值或地址值
*/
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);
}
}
5、添加选中芯片函数
修改board_nand_init
函数中的`选中芯片函数:
nand->select_chip = NULL; //设置CE ;
改为:
nand->select_chip = s3c2440_select_chip; //设置CE ;
选中芯片函数s3c2440_select_chip
如下:
static void s3c2440_nand_select(struct mtd_info *mtd, int chipnr)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand();
switch (chipnr) {
case -1: /* 取消选中 */
nand->nfcont |= (1<<1);
break;
case 0: /* 选中 */
nand->nfcont &= ~(1<<1);
break;
default:
BUG();
}
}
编译烧写如下图所示,可以看到已支持Nand Flash:
试验nand是否能读写,烧写到nand flash:
nand erase 0 2000 //擦除
mw.b 30000000 0x55 2000 //向30000000 写入0x55,长度为2000
nand write 30000000 0 2000 //将0x55写入nand,
nand dump 0 2000 //打印
如下图所示,可以看到读写nand都没问题:
开发版设置为nand
启动,重新上电。完成支持nand
即可发现nand启动
时不支持读取nor flash
,此时nor flash
为0。