U-boot-2014.04移植到MINI2440(8) nand flash 读写支持移植
上一篇帖子分析了nand flash,这篇帖子开始移植u-boot对nand flash的读写支持,进入正题。 ?????? 一.修改mini2440.h ?????? 之前再初步移植的时候注释掉了nand的相关部分,这里再打开,在mini2440.h的第96行: ?????? #define CONFIG_CMD_NAND ?????? 既然打开了nand的配置,就需要在nand configuration里面做配置,在mini2440.h里面只有s3c2410的,这里需要进行添加,在第187行,红色字体为添加进去的部分: /* ?*NAND configuration ?*/ #ifdef CONFIG_CMD_NAND #ifdef CONFIG_S3C2440 #define CONFIG_NAND_S3C2440 #defineCONFIG_SYS_S3C2440_NAND_HWECC #else #define CONFIG_NAND_S3C2410 #define CONFIG_SYS_S3C2410_NAND_HWECC #endif #define CONFIG_SYS_MAX_NAND_DEVICE?? 1 #define CONFIG_SYS_NAND_BASE??????????? 0x4E000000 #endif ?????? ?????? 二.拷贝s3c2410_nand.c为s3c2440_nand.c ?????? 由于支持了2410的nand的读写,所以只需要以其为蓝本,将其拷贝再做修改就可以了。这里进入目录:/drivers/mtd/nand/下,执行 cp s3c2410_nand.c s3c2440_nand.c. 然后使用vim打开s3c2440_nand.c,这里面配置都是2410的,我们执行命令: :%s/2410/2440 这样会将该文件下的所有2410替换成2440,关于vim字符替换的命令格式可以自行网上查阅。 ?????? ?????? 三.修改/drivers/mtd/nand/下Makefile ?????? 第55行: obj-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o ?????? 是说如果定义了CONFIG_NAND_S3C2410那么久将s3c2410_nand编译进去,这里我们在下面一行添加2440的: ?????? obj-$(CONFIG_NAND_S3C2440) +=s3c2440_nand.o ? ?????? 四.修改drivers/mtd/nand/s3c2440_nand.c ?????? 因为我们只是把2410的蓝本拷贝过来,现在要根据2440和具体的nand型号做修改,这里首先修改的是时序,第19行: #define S3C2440_NFCONF_TACLS(x)??? ((x)<<8) #define S3C2440_NFCONF_TWRPH0(x)?? ((x)<<4) #define S3C2440_NFCONF_TWRPH1(x)?? ((x)<<0) ?????? 这里的三个参数TACLS,TWRPH0,TWRPH1是在读写nand的时候需要配置的三个时序参数,这里可以对照s3c2440和nand的datasheet,对照网上别人的分析总结如下: TACLS:CLE/ALE有效到nWE有效之间的持续时间。 TWRPH0:CLE/ALE的持续时间。 ?????? TWRPH1:表示CLE/ALE的维持时间(hold?time)。 ?????? 同时看到s3c2440的datasheet的NFCONF寄存器有关位如下: ?????? 上图中给出了三个值的取值范围,对应寄存器的位,12,8,4以及持续时间的计算方法,HCLK一般是100MHZ,所以我们需要进行修改: ?????? #define S3C2440_NFCONF_TACLS(x)??? ((x)<<12) #define S3C2440_NFCONF_TWRPH0(x)?? ((x)<<8) #define S3C2440_NFCONF_TWRPH1(x)?? ((x)<<4) ?????? 下面第123行: #ifdefined(CONFIG_S3C24XX_CUSTOM_NAND_TIMING) ?????? tacls? = CONFIG_S3C24XX_TACLS; ?????? twrph0= CONFIG_S3C24XX_TWRPH0; ?????? twrph1=? CONFIG_S3C24XX_TWRPH1; #else ?????? tacls= 4; ?????? twrph0= 8; ?????? twrph1= 8; #endif ?????? 这里我们没有定义CONFIG_S3C24XX_CUSTOM_NAND_TIMING,所以会执行下面的参数,这三个参数等于多少,网上有很多,我没有一一去试过,这里暂且用一组0.1,1,修改如下: ?????? #ifdefined(CONFIG_S3C24XX_CUSTOM_NAND_TIMING) ?????? tacls?= CONFIG_S3C24XX_TACLS; ?????? twrph0 = CONFIG_S3C24XX_TWRPH0; ?????? twrph1 =?CONFIG_S3C24XX_TWRPH1; #else ?????? tacls= 0; ?????? twrph0= 1; ?????? twrph1= 0; #endif ?????? 在下面第133行: ?????? cfg = S3C2440_NFCONF_EN; ?????? cfg |= S3C2440_NFCONF_TACLS(tacls - 1); ?????? cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1); ?????? cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1); ?????? writel(cfg,&nand_reg->nfconf); ?????? 我们将这部分修改如下: ?????? //cfg =S3C2440_NFCONF_EN; ?????? cfg |= S3C2440_NFCONF_TACLS(tacls); ?????? cfg |= S3C2440_NFCONF_TWRPH0(twrph0); ?????? cfg |= S3C2440_NFCONF_TWRPH1(twrph1); ?????? writel(cfg,&nand_reg->nfconf); ?????? writel((1<<4)|(1<<1)|(1<<0),&nand_reg->nfcont); ?????? 这部分cfg这一段后面的第一个writel主要是将刚才设置的tacls,twrph0,twrph1赋给了NFCONF,这里&nand_reg指的是代表nand flash寄存器的结构体, writel使用方法复习下就是往内存映射的I/O空间上写数据: ?????? void?writel?(unsigned?char?data?,?unsigned?short?addr?)。 下面一个writel这里的(1<<4)|(1<<1)|(1<<0)意思是往nandflash的NFCONT寄存器的第0,1,4位分别置一,这里查看datasheet: 也就是初始化了ECC,禁止片选,以及使能了NandFlash控制器。 ?????? 接着,修改s3c2440_hwcontrol函数,第48行: ?????? if (ctrl & NAND_CTRL_CHANGE) { ????????????? ulong IO_ADDR_W = (ulong)nand; ? ????????????? if (!(ctrl & NAND_CLE)) ???????????????????? IO_ADDR_W |=S3C2440_ADDR_NCLE; ????????????? if (!(ctrl & NAND_ALE)) ???????????????????? IO_ADDR_W |=S3C2440_ADDR_NALE; /*判断是命令还是地址,从而决定IO_ADDR_W的指向。*/ ????????????? if(cmd==NAND_CMD_NONE) ???????????????????? { ??????????????????????????? IO_ADDR_W=&nand->nfdata; ??????????????????????????? } ? ????????????? chip->IO_ADDR_W = (void*)IO_ADDR_W; ? ????????????? if (ctrl & NAND_NCE) ???????????????????? writel(readl(&nand->nfcont)& ~(1<<1), ???????????????????? ?????? &nand->nfcont); ????????????? else ???????????????????? writel(readl(&nand->nfcont)| (1<<1), ???????????????????? ?????? &nand->nfcont);???????????????? //控制片选 ?????? } ?????? 修改部分已经用红色字体标注出来了,以上修改还是因为2410和2440的寄存器不同,并且他们的偏移也不一样。 ????????????? if(cmd==NAND_CMD_NONE) ???????????????????? { ??????????????????????????? IO_ADDR_W=&nand->nfdata; ???????????????????? } ?????? 这部分代码主要是针对后面我们使用nand write写入数据失败的问题,具体是由于我们上一次是写的命令寄存器,但是下一次直接写数据,但是我们的IO_ADDR_W 还是指向的命令寄存器,所以这里如果判断我们写入的不是命令,就直接指向我们的数据寄存器NFDATA,这样我们就可以成功的使用nandwrite命令了。s3c2440_hwcontrol这个函数主要是命令控制函数,下面还是针对偏移不同做出的修改,在第23行: ?????? #define S3C2440_ADDR_NALE 4 #define S3C2440_ADDR_NCLE 8 ?????? 修改成如下: ?????? #define S3C2440_ADDR_NALE 8 #define S3C2440_ADDR_NCLE 12 #define S3C2440_NFCONF_nFCE (1<<1) ?????? 同时注释掉第18行://#define S3C2440_NFCONF_nFCE??????? (1<<11) 到这里我们的s3c2440_nand.c文件修改结束。 ? ?????? 五.修改drivers/mtd/nand/nand_base.c ?????? 在第207行,在nand_select_chip函数里面,修改第207行,如下: ?????? ?????? case0: ????????????? chip->cmd_ctrl(mtd,NAND_CMD_NONE,NAND_CTRL_CLE| NAND_CTRL_CHANGE); ????????????? break; ?????? ?????? 六.编译测试 ?????? make distclen ?????? makemini2440_config ?????? make ?????? 对生成的u-boot.bin,chmod 777 u-boot.bin ?????? 拷贝到tftp目录下cp u-boot.bin /tftpboot ?????? 从nor flash启动开发板,执行: tftp 0x30008000 u-boot.bin ?????? go 0x30008000 ?????? 出现以下信息: U-Boot 2014.04 (Sep 02 2015 - 08:47:58) ? CPUID: 32440001 FCLK:?????400 MHz HCLK:?????100 MHz PCLK:??????50 MHz DRAM:?64 MiB WARNING: Caches not enabled Flash: 2 MiB NAND:? 256 MiB *** Warning - bad CRC,using defaultenvironment ? In:???serial Out:??serial Err:??serial Net:??dm9000 MINI2440 Deep_l_zh # ?????? 可以看到红色字体说明已经识别到了我们的nand,下面对读写进行测试: ?????? MINI2440 Deep_l_zh # nand write0x30008000 0 0xff NAND write: device 0 offset 0x0,size 0xff 255 bytes written: OK ?????? 这暂时说明读是没有问题的,接下来往里面写: ?????? MINI2440 Deep_l_zh # nand read 0x320000000 0xff NAND read: device 0 offset 0x0,size 0xff NAND read from offset 0 failed -74 ????? 0bytes read: ERROR ?????? 出现错误了。。。 ? ?????? 七.nand read错误解决办法 ?????? 网上查找资料说是根据校验码-74,是ecc校验的问题,具体修改方法比较复杂,这里我修改了一下时序参数。 tacls = 3; ?????? twrph0 = 3; ?????? twrph1 = 2; ?????? 然后在读写之前进行nand erase操作,这个很重要,可以读出如下信息: ?????? MINI2440 Deep_l_zh # nand read 0x300080000 0xff ? NAND read: device 0 offset 0x0,size 0xff ????? 255bytes read: OK ?????? 可以看出来是读出来了,接着进行读写数据对比测试: ?????? MINI2440 Deep_l_zh # nand write 0x30008000 0 0xff NAND write: device 0 offset 0x0,size 0xff ?255 bytes written: OK MINI2440 Deep_l_zh # nand read 0x32000000 0 0xff NAND read: device 0 offset 0x0,size 0xff ?255 bytes read: OK MINI2440 Deep_l_zh # cmp.b 0x30008000 0x32000000 0xff Total of 255 byte(s) were thesame ?????? 完全一样,说明我们读写都成功了。至此,nand flash读写移植结束,如有不正确的地方,还请指出,大家共同进步。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |