U-boot-2014.04移植到MINI2440(8) nand flash 读写支持移植

时间:2022-10-14 17:12:45

上一篇帖子分析了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.cs3c2440_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寄存器有关位如下:

U-boot-2014.04移植到MINI2440(8) nand flash 读写支持移植

       上图中给出了三个值的取值范围,对应寄存器的位,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:

U-boot-2014.04移植到MINI2440(8) nand flash 读写支持移植

也就是初始化了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读写移植结束,如有不正确的地方,还请指出,大家共同进步。