(基于MPC8377E)SylixOS的 nandflash驱动开发笔记

版权声明:本文为博主原创文章,转载请写明来源。 https://blog.csdn.net/hahajinbu/article/details/80628453

1.前言

    本文档旨为移植Powerpc平台的nandflash到SylixOS的开发者提供理解帮助。因笔者也不是专业的嵌入式驱动开发工程师,因此可能存在纰漏,如有纰漏请以芯片手册以及SylixOS驱动开发手册为准。

本篇驱动开发笔记离不开北京翼辉信息公司的何鑫工程师、张鹏程工程师、焦进星工程师、徐贵洲工程师的大力帮助和支持,在此对他们表示极大感谢。

2.相关的nandflash硬件描述

    本文针对的是MPC8377E开发板,nandflash的型号是K9F2G08U0C。其具体的型号参数为:页大小为2KB,块大小为64页/128KB,总共数据区容量为2048块/256MB。如图1所示。

图1 所使用的nandflash型号参数

    根据前人资料显示:nand的地址编排精确到字节,但是实际读写却只能精确到页,并且每次写之前都需要擦除nand,擦除的单位是块。nand读写时地址传递是通过IO线发送的,因为地址有30位((2K+64)*64*2048=2^28B,其中A0-A11是2KB页内地址,也就是所谓的列地址)而IO只有8位,所以需要多个cycle(循环)才能发送完毕。一般的nand都是4cycle或者5cycle发送地址。

3.SylixOS下的nandflash开发通用框架

3.1 nandflash驱动整体框架

         SylixOS的nandflash驱动整体框架如图2所示。

                                                                

图2 nand驱动整体框架

    SylixOS通过yaff2文件系统将nandflash设备看做mtd设备,通过mtd驱动里面的nandflash操作结构体中的nandflash操作函数指针指向的具体函数来操控nandflash硬件设备。具体来说,需要在Bsp中的框架参考bspmini2440中编写对应的三个文件,如图3所示:

图3 编写的文件示意图

其中, k9f2g08.c是调用MTD提供的函数挂载nand的信息,并将其挂载到yaffs2文件系统下,并完成分区设置。mpc837x_nand.c函数实现nand控制器硬件的初始化。nand.c是将初始化好并封装成了一块mtd设备的nand的这个事儿通知给上层。

         具体的来说,实际的驱动函数的完成的nand的初始化函数调用流程如图4:

图4 nandflash驱动函数大致调用关系

综上,完成nandflash驱动需要完成的文件为:

         1)nand.h/nand.c  ///用来将nand封装成mtd设备,对接base的mtd接口,基本上可以照抄bspmini2440的函数(如果按照mini2440的驱动框架来会多一个nand_init_chip,如果按照uboot框架来则为图上的框架)

         2)k9f2g08.h/k9f2g08.c   ////调用MTD提供的函数读取nand的信息,并挂载到yaffs2文件系统下,并设置相应的分区,也比较好抄,本驱动中的开发基本上照抄了bspmini2440的k9f1g08.c

         3)mpc837x_nand.h/mpc837x_nand.c /////完成具体的硬件(主要是nandflash控制器的eLBC寄存器初始化,并填充具体的mtd操作函数,可以类比于bspmini2440中的s3c24xx_nand.c,其中的函数主要应该参考开发板相关的uboot函数(在本例中主要参考的文件是uboot的drivers/mtd/nand/fsl_elbc/nand.c)。

3.2nandflash驱动编写完成后续步骤

在完成nandflash的硬件相关驱动层开发后,我们还需要完成的步骤:

1.需要修改的地方:bspInit里面添加调用nand_init()/mtdDevCreateEx("/n");

2.在bspinit.c的halDevInit函数中添加yaffsDevCreate("/yaffs2")实际创建yaffs2设备;

2.使用symlink在启动的时候的软连接部分修改软连接,在yaffs2/n0创建默认使用的文件夹并设置软连接 (halStdDirInit函数中);

3.3 建议的nandflash驱动编写步骤

编写bspInit函数调用所需的nand_init(),在nand_init()中调用自定义的测试函数,分别完成以下测试:

1.     测试初始化函数,看能否打印nandflash的大小等信息

2.     测试操作读写相关的寄存器的函数,使用寄存器操作完成基本读写操作,应该先测试写入操作,即先测试设置写入地址、写入数据、写入命令的的寄存器操作能否成功,再测试读入操作,能够从刚才的地址中正确读入写入的数据。

3.     测试其他函数。

4.     完成真正的函数编写和mtd结构体的nand_chip结构体中的函数指针赋值。

5.     在编写的过程中,尽量参考uboot驱动,因为uboot开始能够使用说明uboot中的驱动至少是可用的,在功能能满足需求的时候,寄存器的赋值等尽量保持uboot的初始化不变,另外也可多参考linux内核中的相关驱动。

4.MPC837x的平台相关驱动笔记

         PS.水平有限,外部连线笔者确实没太看懂,具体的如果有误请参考芯片手册的10.2节的External Signal Descriptions。主要看的还是寄存器部分,所以可能这一节会出现一些错误。不建议放到驱动开发手册中。

4.1 MPC837x的硬件及nandflash控制机制

笔者使用的是实验室采购的北京智心胜达科技有限公司的MPC8377 EVB V22开发板(这个公司的官网已经打不开了,所以无法寻求技术支持了,但是文档还是给的比较充分的),使用的是采用MPC8377E嵌入式处理器,提供了16 MB片外Nor Flash(S29GL128M90TAIR1)和256 MB的8位片外Nand Flash(K9F2G08U0C),同时提供硬件ECC支持(uboot中初始化了硬件ECC校验,因此在本次驱动编写中也保持一致)。

由于uboot和操作系统固化在了norflash中并且可以正常启动SylixOS,只是因为没有yaffs2文件系统所以无法使用256M的nandflash,因此需要自己编写nandflash驱动。

MPC8377E通过加强本地总线控制器(eLBC),为存储设备提供了通用片选机制(GPCM)、用户编程机制(UPM)、Flash 控制机制(FCM)3种接口,对于nandflash的控制采用FCM机制。

4.2 FCM机制相关重要寄存器

         FCM的设备(在本次驱动中主要是nandflash)需要配置eLBC的本地窗口基址寄存器(LBLAWBARx)和本地窗口属性寄存器(LBLAWARx)进行本地内存映射。其中,LAWARn定义了2个域,第0位是en使能位代表是否使能此窗口,第26~31位是SIZE域。eLBC的存储控制单元提供了8个Bank,每个Bank对应一对32位的基址寄存器BRn和选项寄存器ORn寄存器。FCM模式下,BRn定义了相应片选存储器块的起始地址、位宽、读写保护方式、校验与否以及设备指派访问方式。ORn定义相应的地址掩码(高16位)、FCM模式的所有参数及NAND Flash芯片时序设置。当系统发出对FCM设备的访问请求时,eLBC通过(BRx[BA]&ORx[AM])的值比较来进行地址解码,将控制信号交与FCM。

         因为在Uboot里面已经定义过相关地址寄存器并进行了赋值了,对这块地址映射的原理不是很清楚(并不知道为什么基址是该地址而且windows大小是32KB),所以在这里就保证跟Uboot一致即可。在Uboot里面找到相关定义如图5所示:

图5 Uboot中关于nandflash的LAW定义及赋值

    从上图,我们知道nandflash的FCM的访问基址应该是0Xe280000,因为这个相当于是个虚拟地址,所以要在相应的bspMap.h进行映射,映射大小笔者觉得应该大于windows的size(32K)应该就可以,根据翼辉工程师的建议映射了128K。

    同时,eLBC通过传输错误状态寄存器(LTESR)、传输错误状态检测使能寄存器(LTEDR)、传输错误中断使能寄存器(LTESR)、传输错误状态特征寄存器(LTESR)提供对FCM传输模式的数据检测、状态监测。当硬件加电时,用户需要对上述寄存器进行初始化这些寄存器的配置。几乎所有的这些寄存器的初始化参考代码都可以在uboot里面找到。

4.3 MPC837x的FCM特点及控制机制

                    

图6 FCM buffer的相关描述

    如图6所示,如果笔者理解没问题的话,FCM内部集成8 KB大小的数据缓冲RAM,该RAM完全模拟一块NAND Flash的页结构,用本驱动中的k9f2g08u0c的nandflash来说,其一页的大小是2KB,所以这8KB的区域被划分成2个区,每个区大小4KB,第0号区对应偶数页号的页,第1号区对应奇数号页(不过这里说的后面是重复的FCM buffer我没太看懂,是说的是不止一个8KB的缓冲区,还是说把这8KB的缓冲区复制了多份?如果是前者,为啥前面说的是只有一个共享的8KB缓冲区?如果是后者,这么做的设计意义何在?)。每个区中的4KB又划成两个区域,前2KB就是一页的数据区,后2KB的前64B缓存的是OOB区域,剩下的1984B区域作为保留区。

实际操作nandflash的时候,是通过将相应指令按顺序写入FIR,FCM执行时按照FIR内部指令顺序将命令、地址和数据按时序发送到NAND Flash对应基址或读取数据到RAM中。

         整个MPC8377E的FCM的控制流程,根据手册以及笔者大概理解,总结如下:

1.      根据需要操作的根据需要发出的命令、地址,初始化FCM下的命令寄存器(FCR)、块地址寄存器(FBAR)和页列地址寄存器(FPAR);配置指令寄存器FIR;当写操作时,将准备写入Nand页的数据,写入页号对应FCM buffer中。

2.      设置(读,写)字节长度寄存器(FBCR),当FBCR置为0且ECC功能开启时,硬件ECC单元会生成该页的校验数据,存放在FCM RAM模拟页的OOB区(不确定,猜测),并在真正写入的时候一起写入nandflash的oob中。

3.      设置模式寄存器FMR操作位(FMR[op])去写保护,发送控制信号;写特殊操作启动寄存器(LSOR),选择片选,触发执行信号;FCM按FIR中的指令序列,依据ORn中的时钟周期参数向NAND Flash发出命令、地址和数据信号。

4.      等待错误状态寄存器指令执行状态位中断信号(LTESR[cc]),判断并处理执行状态;然后写1复位错误状态寄存器(LTESR)、写0复位传输错误状态特征寄存器(LTEATR)。

5.      从页号对应RAM地址空间读取数据;(写操作时)重复上述步骤执行读取NAND Flash状态命令,判断写过程完成。

4.4 结构体需要完成的函数

    几乎所有的操作函数,都可以照着Uboot填写完成,所以也没有遇到什么问题,除了需要修改等待操作完成的for循环轮询语句,其他几乎没有什么需要修改的地方。

             

图7 需要填写的结构体中的函数指针

    为什么是这些函数,是需要从nand_base里面的nand_scan_ident函数(这个函数在mini2440中是调用的nand_scan,nand_scan函数中再调用nand_scan_ident和nand_scan_tail函数)中看的,nand_scan_ident函数中调用了nand_set_defaults设置nand操作的默认函数,如图8所示,如果没有填写对应的函数,则会调用默认的nand操作函数,有些调用的默认函数中又会调用没有定义的cmd->ctrl函数,所以为了不让调用出问题,结构体中用不到的函数(例如select_chip)必须被定义且赋值给函数指针,这些函数可以定义为空函数。或者,就像bspmini2440中的那样,必须定义并赋值给cmd->ctrl指针。

总得来说,这次虽然靠抄uboot完成了nandflash驱动,但是目前还有很多地方一知半解甚至完全不明白,目前还有一些不懂的地方主要有:

1. mtd具体是怎么调用nandflash的这些函数的,尤其是nandflash写入是怎么调用的(即FCM buffer的运作机制还不太明白,具体是怎么从FCM buffer写入到nandflash中的不清楚)。

2. static struct nand_ecclayout fsl_elbc_oob_lp_eccm1 为什么设置是

 

static struct nand_ecclayout fsl_elbc_oob_lp_eccm1 = {

.eccbytes = 12, ///每512B产生一个ECC,每个ECC 3B,所以一页一共4x3=12B的ECC,至于位置为什么是这些我也不知道

.eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58},

};

.oobfree = { {1, 7}, {11, 13}, {27, 13}, {43, 13}, {59, 5} },

3. 现在判断nandflash的命令执行是否完毕是靠的for循环,这是典型的轮询方式,应该是有适用于nandflash读写的中断方式的,还不知道怎么实现。

参考文章:

https://blog.csdn.net/u012561935/article/details/78314692

https://blog.csdn.net/u012561935/article/details/78318991

https://blog.csdn.net/u012561935/article/details/78342118

https://blog.csdn.net/u012561935/article/details/78318991

http://blog.163.com/liuqiang_mail@126/blog/static/10996887520126413925138/

https://blog.csdn.net/qingfengtsing/article/details/7399404

https://blog.csdn.net/qingfengtsing/article/details/18703161

SylixOS驱动开发手册和应用开发手册

猜你喜欢

转载自blog.csdn.net/hahajinbu/article/details/80628453