Linux MTD層的研究(Nandflash)

來源:互聯網
上載者:User

花了點時間學習Linux MTD層,下面簡單總結一下!

以下是MTD層的結構圖


      MTD層實現了檔案系統與Flash之間的橋樑,下面就粗略說明字元型MTD驅動與下層驅動的關係。

分析對象:/drivers/mtdchar.c 字元型mtd裝置

字元裝置中定義了mtd_fops字元類的檔案指標操作函數,完成字元裝置讀寫與開啟等功能。

1. static int mtd_open(struct inode *inode, struct file *file)
{
    int minor = iminor(inode);
    int devnum = minor >> 1;
    int ret = 0;
    struct mtd_info *mtd;
    struct mtd_file_info *mfi;
   ........
    mtd = get_mtd_device(NULL, devnum);    //在原始裝置層實現, mtd/mtdcore.c檔案中被EXPORTS_SYMBOL
    ........
} /* mtd_open */

/*====================

get_mtd_device在原始裝置層中被實現,原始裝置層中維護了一個struct mtd_info *mtd_table[MAX_MTD_DEVICES],用來儲存註冊mtd的裝置列表。該檔案中(該層)實現了如下的函數對外Export_Symbol:

EXPORT_SYMBOL_GPL(add_mtd_device);     
//用於硬體驅動層調用,註冊到原始裝置層,調用路徑為:s3c24xx_nand_probe()(/drivers/mtd/nand/s3c2410.c) --> add_one_partition(mtdpart.c) --> add_mtd_device()(mtdcore.c)
EXPORT_SYMBOL_GPL(del_mtd_device);    //用法與上面差不多
EXPORT_SYMBOL_GPL(get_mtd_device);    //得到table裡面的具體mtd裝置(mtd_info),該結構裡有read等函數;該函數主要為mtd字元裝置層調用
EXPORT_SYMBOL_GPL(get_mtd_device_nm);   //通過名字得到mtd裝置(mtd_info)
EXPORT_SYMBOL_GPL(put_mtd_device);           //釋放
EXPORT_SYMBOL_GPL(register_mtd_user);    //註冊mtd_user;mtd原始層維護了一個mtd_notifiers鏈表,用於提供上層向下層註冊 struct mtd_notifier {void (*add)(struct mtd_info *mtd); void (*remove)(struct mtd_info *mtd);struct list_head
list; }
EXPORT_SYMBOL_GPL(unregister_mtd_user);
EXPORT_SYMBOL_GPL(default_mtd_writev);


2. 字元裝置mtdchar.c中的


static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos)
{
   

。。。。。

           ret = mtd->read(mtd, *ppos, len, &retlen, kbuf);
。。。。。
    return total_retlen;
} /* mtd_read */


 通過調用mtd原始層struct mtd_info *mtd_table[MAX_MTD_DEVICES]中對應的mtd_info中的封裝的read方法實現讀寫。

那麼該read方法是怎麼實現的呢?在/drivers/mtd/nand下有個nand_base.c中,公開了一些函數,在s3c2440.c中被調用

EXPORT_SYMBOL_GPL(nand_scan);
EXPORT_SYMBOL_GPL(nand_scan_ident);
EXPORT_SYMBOL_GPL(nand_scan_tail);
EXPORT_SYMBOL_GPL(nand_release);

其中nand_scan函數中完成了Mtd_info的read等函數的賦值:

    /* Fill in remaining MTD driver data */
    mtd->type = MTD_NANDFLASH;
    mtd->flags = MTD_CAP_NANDFLASH;
    mtd->erase = nand_erase;
    mtd->point = NULL;
    mtd->unpoint = NULL;
    mtd->read = nand_read;
    mtd->write = nand_write;
    mtd->read_oob = nand_read_oob;
    mtd->write_oob = nand_write_oob;
    mtd->sync = nand_sync;
    mtd->lock = NULL;
    mtd->unlock = NULL;
    mtd->suspend = nand_suspend;
    mtd->resume = nand_resume;
    mtd->block_isbad = nand_block_isbad;
    mtd->block_markbad = nand_block_markbad;

這些函數的功能,使得硬體驅動層struct nand_chip中的相關read函數與之關聯起來。

3. /driver/mtd/nand/s3c2410.c實現了與硬體相關的驅動程式:

該驅動是platform類型的驅動,其裝置的註冊在/arch/arm/plat-s3c24xx/common-smdk.c中:

static struct mtd_partition smdk_default_nand_part[]
將源結構體刪除,或者注釋掉,修改為以下形式
static struct mtd_partition smdk_default_nand_part[] = {
                [0] = {
                                .name                = "Boot",
                                .size                = 0x00100000,
                                .offset = 0
                },
                [1] = {
                                .name                = "MyApp",
                                .size                = 0x003c0000,
                                .offset = 0x00140000,
                },
                [2] = {
                                .name                = "Kernel",
                                .size                = 0x00300000,
                                .offset = 0x00500000,
                },
                [3] = {
                                .name                = "fs_yaffs",
                                .size                = 0x03c00000,                  //30M
                                .offset = 0x00800000,
                },                
                [4] = {
                                .name                = "WINCE",
                                .size                = 0x03c00000,
                                .offset = 0x04400000,
                }
};    //該配置針對的是 FL2440中的nandflash分區劃分。common-smdk中smdk_machine_init調用了platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));函數,實現了平台裝置的註冊,這些裝置還包括看門狗,LCD等等。。。根據Platform的特點,在/drivers/mtd/nand/s3c2410.c中實現驅動的註冊就行了,下面這個函數會在platform類型的驅動被核心自動調用。該函數取出上面結構的資訊,分配給驅動儲存空間,nand_chip
初始化,以及調用mtd原始驅動提供的函數完成Mtd裝置的增加(s3c24xx_nand_probe()(/drivers/mtd/nand/s3c2410.c) --> add_one_partition(mtdpart.c) --> add_mtd_device()(mtdcore.c))。

static int s3c24xx_nand_probe(struct platform_device *pdev,
                  enum s3c_cpu_type cpu_type)
{
    struct s3c2410_platform_nand *plat = to_nand_plat(pdev);

   。。。。。。


4. 對於一個Soc晶片來說,之需要實現與硬體相關的驅動層的結構體(nand_chip),mtd原始裝置層與mtd字元裝置,快裝置系統核心已經實現了,

nand_chip結構體為:

struct nand_chip {
 

   void __iomem* IO_ADDR_R;
    void __iomem* IO_ADDR_W;

    uint8_t (* read_byte) ( struct mtd_info * mtd) ;
    u16 ( *read_word) ( struct mtd_info * mtd) ;
    void ( *write_buf) ( struct mtd_info * mtd, const uint8_t * buf, int len);
    void ( *read_buf) ( struct mtd_info * mtd, uint8_t * buf, int len) ;
    int ( *verify_buf) ( struct mtd_info * mtd, const uint8_t * buf, int len);
    void ( *select_chip) ( struct mtd_info * mtd, int chip) ;
    int ( *block_bad) ( struct mtd_info * mtd, loff_t ofs, int getchip);
    int ( *block_markbad) ( struct mtd_info * mtd, loff_t ofs) ;
    void ( *cmd_ctrl) ( struct mtd_info * mtd, int dat, unsigned int ctrl);
    int ( *dev_ready) ( struct mtd_info * mtd) ;
    void ( *cmdfunc) ( struct mtd_info * mtd, unsigned command, int column, intpage_addr) ;
    int ( *waitfunc) ( struct mtd_info * mtd, struct nand_chip * this );
    void ( *erase_cmd) ( struct mtd_info * mtd, int page) ;
    int ( *scan_bbt) ( struct mtd_info * mtd) ;
    int ( *errstat) ( struct mtd_info * mtd, struct nand_chip * this , intstate, int status, int page) ;
    int ( *write_page) ( struct mtd_info * mtd, struct nand_chip * chip, constuint8_t * buf, int page, int cached, int raw) ;

    ……

    structnand_ecc_ctrl ecc;

    ……
}

    要想些SOC類型的Nandflash驅動可以重點研究/drivers/mtd/nand/s3c2410.c,仿造其來實現。注意:這裡可以調用的函數常常有/drivers/mtd/mtdcore.c,/dirvers/mtd/mtdpart.c , /driver/mtd/nand/nand_base.c中匯出的供下層使用的函數(kernel 2.6.28),另外,/drivers/mtd/chips中主要為Norflash驅動的實現,還沒來得及研究,後續在寫。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.