以TC58NVG2S3ETA00 為例:
下面是它的一些實體參數:
圖一

圖二
圖三
圖四
圖五
圖6-0
圖6-1
說明一下,在圖6-1中中間的那個布局表可以看做是實際的NandFlash一頁資料的布局,其中Data區域用于存放有效的資料,也就是我們可以通過類似read、write、pread、pwrite可以通路的區域,那每頁中的64位元組的OOB區域是無法通過前面的幾個函數通路的,他們會自動跳過OOB區域,通路OOB區域需要借助特殊的指令。
簡單說明一下:Data A(512B)對應的ECC校驗碼存放在ECC for Data A(4 byte)中,OOB A (8byte) 對應的ECC校驗碼存放在緊接着的下一個ECC for Data A(4 byte)中,雖然用4位元組存放ECC,但是對于本例,ECC隻占3個位元組。在實際使用中如果解決方案中用不到OOB A/B/C/D,可以不用管他們對應的ECC,隻需要關心Data區域對應的ECC。如果使能了硬體ECC,硬體會自動把計算生成的ECC寫到OOB中。讀NandFlash需要按頁讀,即一次讀一頁;寫NandFlash需要按頁寫,即每次寫一頁;擦除NandFlash需要按塊擦,即每次要擦除一塊。
對與NandFlash等塊裝置的通路操作,mtd-utils工具集中提供了非常好的支援(可以到http://www.linux-mtd.infradead.org/進行了解),要使用mtd-utils工具集首先需要搞到mtd-utils的源碼,并且使用目标裝置上的交叉工具編譯鍊進行編譯,具體方法可以參考:,其中介紹了如何生成可以再目标闆上運作的mtd-utils工具。關于mtd-utils工具的使用可以參考其中介紹了mtd-utils中常用的工具。
我們可以參考mtd-utils中工具的實作,進而完成在自己的應用程式中實作對NandFlash的操作。常用的指令如下:
#define MEMGETINFO _IOR('M', 1, struct mtd_info_user)
#define MEMERASE _IOW('M', 2, struct erase_info_user)
#define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf)
#define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf)
#define MEMLOCK _IOW('M', 5, struct erase_info_user)
#define MEMUNLOCK _IOW('M', 6, struct erase_info_user)
#define MEMGETREGIONCOUNT _IOR('M', 7, int)
#define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user)
#define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo)
#define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo)
#define MEMGETBADBLOCK _IOW('M', 11, __kernel_loff_t)
#define MEMSETBADBLOCK _IOW('M', 12, __kernel_loff_t)
#define OTPSELECT _IOR('M', 13, int)
#define OTPGETREGIONCOUNT _IOW('M', 14, int)
#define OTPGETREGIONINFO _IOW('M', 15, struct otp_info)
#define OTPLOCK _IOR('M', 16, struct otp_info)
#define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout_user)
#define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats)
#define MTDFILEMODE _IO('M', 19)
#define MEMERASE64 _IOW('M', 20, struct erase_info_user64)
#define MEMWRITEOOB64 _IOWR('M', 21, struct mtd_oob_buf64)
#define MEMREADOOB64 _IOWR('M', 22, struct mtd_oob_buf64)
#define MEMISLOCKED _IOR('M', 23, struct erase_info_user)
打開裝置
這裡需要注意的是,打開的裝置結點是/dev/mtd?,而不是/dec/mtdblock?,原因可以參考:其中介紹了mtd與mtdblock的差別。
fd = open ("/dev/mtd0", O_SYNC | O_RDWR);
擷取裝置資訊
#include <linux/types.h>
structmtd_info_user {
__u8 type;
__u32 flags;
__u32 size; // Total size of the MTD
The below two fields are obsolete and broken, do not use them * (TODO: remove at some point) */
ioctl(fd, MEMGETINFO,&mtd) ;
其中type可以用來區分是NorFlash還是NandFlash。
擦除NandFlash
寫NandFlash
這裡分為寫資料區和寫OOB區
寫資料區,對于本例一次要寫一頁,也就是2KB,寫OOB區,對于本例可以操作的隻有32位元組,剩下的32位元組用于存放ECC。
對于寫NandFlash,有的裝置支援一次性把data和oob一塊寫進去。代碼如下:
#define MEMEWRITEPAGE _IOWR('M', 23, struct mtd_epage_buf)
#define MAX_PAGE_SIZE 8192
#define MAX_OOB_SIZE 512
/*
* Buffer array used for writing data
*/
unsigned char writebuf[MAX_PAGE_SIZE];
char oobbuf[MAX_OOB_SIZE];
讀OOB
讀OOB跟寫OOB類似,隻不過使用的指令是MEMREADOOB。
以上隻是本人在工作中遇到的,僅供參考。