NAND FLASH驱动框架以及程序实现

发布时间:2024-08-19  

1、NAND FLASH的硬件连接:

实验用的NAND FLASH芯片为K9F2G08U0C,它是三星公司的存储芯片,它的大小为256M。它的接线图如下所示:

它的每个引脚的分别为LDATA0-LDATA7为数据引脚、CLE为发送命令使能引脚、ALE为发送地址使能引脚、CE为芯片使能引脚、WE为写使能引脚、WP为写保护引脚、R/B为芯片是否繁忙的状态指示引脚,如下图所示:

 

2、NAND FLASH的操作:

根据NAND FLASH的芯片手册可以知道需要操作NAND FLASH一般的流程是发出命令、发出地址、发出数据/读数据,下面依次分析。

a、发命令,对于NAND FLASH芯片来说需要1、选中芯片(CE为低电平);2、CLE设为高电平、ALE设为低电平;3、在DATA0-DATA7上输出命令数据;4、在WE上发出一个上升沿的信号。这样命令数据就会被写入命令的命令寄存器。而对于S3C2440来说,只要简单的令NFCMD寄存器为命令值S3C2440的NAND控制器就可以完成1-4的操作。

 

b、发地址,对于NAND FLASH芯片来说需要1、选中芯片(CE为低电平);2、ALE设为高电平、CLE设为低电平;3、在DATA0-DATA7上输出地址数据;4、在WE上发出一个上升沿的信号。这样地址数据就会被写入地址寄存器。分析图中可知需要5个字节的地址。而对于S3C2440来说,只要简单的令NFADDR寄存器为地址值S3C2440的NAND控制器就可以完成1-4的操作。

 

c、发数据/读数据,对于NAND FLASH芯片来说需要1、选中芯片(CE为低电平);2、ALE设为低电平、CLE设为低电平;3、在DATA0-DATA7上输出数据或读入数据;4、在WE上发出一个上升沿的信号,这样数据就会被写入、在RE上发出一个上升沿信号,这样数据就会被读出。而对于S3C2440来说,只要简单的令NFDATA寄存器为数据值或读NFDATA寄存器,S3C2440的NAND控制器就可以完成1-4的操作。

 

 

3、读NAND FLASH数据:

从图中可以看出要读FLASH某个地址的数据需要先发出0x00命令、在发出5字节地址、接着发出0x30命令,过一会等R/B信号不忙之后就可以连续的在RE信号的上升沿时读出数据了。

4、读芯片的ID

读芯片的ID很简单,只要先写入0x90命令,再接着写入0x00地址。接着就可以读出连续的5个字节的芯片ID了,对于K9F2G08U0C,它的芯片ID是EC DA 10 15 44,如下图:

 

5、NAND FLASH的驱动框架,对与NAND FLASH这个设备,LINUX已经给我们分好了框架,它将稳定的协议层等都做在一个层里面,而将与硬件相关的做在另外一个层里面,而我们写驱动只要更改与硬件相关的方面就可以了。框架如下:

下面从LINUX的启动信息可以得到“S3C24XX NAND Driver”字样,在内核源码中搜索它,可以在driversmtdnands3c2410.c文件中得到以下的一些调用层次关系:


s3c2410_nand_init

    s3c2440_nand_probe

        s3c2410_nand_inithw

        s3c2410_nand_init_chip

        nand_scan    // driversmtdnandnand_base.c 根据nand_chip的底层操作函数构造mtd_info

            nand_scan_ident

                nand_set_defaults

                    if (!chip->select_chip)

                        chip->select_chip = nand_select_chip;/*  默认值不适用 */


                    if (chip->cmdfunc == NULL)

                        chip->cmdfunc = nand_command;

                    if (chip->waitfunc == NULL)

                        chip->waitfunc = nand_wait;

                nand_get_flash_type

                    chip->select_chip(mtd, 0);

                    chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);

                    *maf_id = chip->read_byte(mtd)

                    dev_id = chip->read_byte(mtd);

            nand_scan_tail

                mtd->erase = nand_erase

                mtd->read = nand_read;

                mtd->write = nand_write;

        

        s3c2410_nand_add_partition

            add_mtd_device

                list_for_each(this, &mtd_notifiers) { // 问. mtd_notifiers在哪里设置

                                   // 答. drivers/mtd/mtd_blkdevs.c,mtdchar.c调用register_mtd_user

                        struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);

                        not->add(mtd);

                        // mtd_notify_add 和 blktrans_notify_add

                        先看字符设备mtd_notify_add

                            class_device_create

                            class_device_create

                        再看块设备blktrans_notify_add

                            list_for_each(this, &blktrans_majors) { // 问. blktrans_majors在哪设置

                                                   //  答. driversmtdmdblock.c或mdblock_ro.c调用register_mtd_blktrans      //注册队列     

                                struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);


                                tr->add_mtd(tr, mtd);

                                    mtdblock_add_mtd

                                        add_mtd_blktrans_dev

                                            alloc_disk

                                            set_capacity

                                            gd->queue = tr->blkcore_priv->rq;//blk_init_queue(mtd_blktrans_request, &tr->blkcore_priv->queue

                                            add_disk

                            }

                    }


接着搜索“end_request”这个块设备驱动程序的通用函数来找到NAND FLASH块设备的请求函数,在driversmtdmtd_blkdevs.c 文件中搜多到了它。通过这个文件可以看到块设备的通用框架的流程:


mtd_blktrans_ops->blkcore_priv-rq

gd->queue = tr->blkcore_priv->rq;

    struct mtd_blktrans_ops *tr = new->tr;

        int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)

            add_mtd_blktrans_dev(dev);

                mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)

                    static void blktrans_notify_add(struct mtd_info *mtd)

                        static void blktrans_notify_add(struct mtd_info *mtd)

                        {

                            struct list_head *this;


                            if (mtd->type == MTD_ABSENT)

                            return;


                            list_for_each(this, &blktrans_majors) {

                            struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);


                            tr->add_mtd(tr, mtd);

                        }

                            list_for_each(this, &mtd_notifiers) {//从头到尾访问mtd_notifiers链表

                                                              struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);

                                not->add(mtd);//调用mtd_notifier结构体的add函数

                            }

                                add_mtd_device(struct mtd_info *mtd)

                                    

                                    add_mtd_partitions(s3c_mtd, s3c_nand_parts, 4);

                


读函数mtd_blktrans_ops->readsect

写函数mtd_blktrans_ops->writesect


首先NAND FLASH驱动框架也是采用驱动分层分离的方法


最终分析下来,NAND FLASH驱动框架涉及到的文件有:driversmtdmtdcore.c 、driversmtdmtd_blkdevs.c、driversmtdmdblock.c、driversmtdnandnand_base.c、driversmtdnands3c2410.c等


最终分析出读函数为mtd_blktrans_ops->readsect;写函数为mtd_blktrans_ops->writesect。最终定位到mtd->read与mtd->write,而这两个函数又可以定位到nand_read、nand_write;接着向下定位可以定位到nand_chip->select_chip、nand_chip->cmd_ctrl、nand_chip->IO_ADDR_R、nand_chip->IO_ADDR_W、nand_chip->dev_ready等等。


6、NAND FLASH的驱动程序的编写、测试


在第5部分最后已经分析到了需要我们提供的几个函数和参数,下面直接贴出代码:


/* 参考

 * S3c2410.c   (driversmtdnand)     

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>