Linux下Nand Flash 驅動代碼分析

  隨着愈來愈多的平臺支持從Nand Flash 中啓動,掌握Nand Flash 的驅動編寫有着重要的現實意義,因爲內核已經完成了大部分的工做,實際工做中大部分工程師對Nand Flash 驅動只是簡單的修改。
   下面分析一下Nand Flash 的代碼流程:
   學習Nand Flash 以前,須要對塊設備中下面2點有個認識:
   1, gendisk: 描述塊設備實體(一整個Nand Flash 芯片)的結構體,整個塊設備的註冊過程都是圍繞gendisk 來開展的;
   2, add_disk(): 將一個分區信息(如:/dev/mtdblock3)註冊到內核列表中
 
   下面分析具體的驅動:
   1, s3c2410 nandflash 控制器初始化步驟
   s3c2410_nand_init(&s3c2410_nand_driver)
   ->driver_register->bus_add_driver()->driver_attach->bus_for_each_dev(_driver_attach)->driver_probe_device()->dev->probe()  /*最後這個函數實質是 s3c2410_nand_probe() */
 
   ->s3c2410_nand_probe()
   ->s3c24xx_nand_probe()
   ->s3c2410_nand_inithw()   /* 初始化nandflash 控制器 */
     ->s3c2410_nand_init_chip()  /* 初始化s3c2410 nandflash 驅動最底層的訪問控制函數 */
       ->chip->write_buf = s3c2410_nand_write_buf;
       ->chip->read_buf = s3c2410_nand_read_buf;
       ->chip->select_chip = s3c2410_nand_select_chip;
       ->chip->cmd_ctrl = s3c2410_nand_hwcontrol()
     ->nand_scan()
     ->s3c2410_nand_add_partition()
   ->add_mtd_device()
  
   將nandflash 的一個分區註冊成一個塊設備,並經過IO請求來訪問的步驟: /*塊設備驅動程序的註冊過程*/
   module_init(init_mtdblock)
   ->init_mtdblock()
   ->register_mtd_blktrans(&mtdblock_tr)
     ->register_blkdev()  /* 註冊爲塊設備 */
     ->blk_init_queue()   /* IO請求隊列初始化 */
     ->kernel_thread(mtd_blktrans_thread) /* 塊設備(nandflash)讀寫訪問io請求處理線程 */
     ->tr->add_mtd()
       mtdblock_add_mtd()
       ->add_mtd_blktrans_dev()
       ->alloc_disk()
       ->add_disk()   /* 初始化一個gendisk 結構體並註冊成一個disk */
         ->blk_register_region()
         ->register_disk()
         ->blk_register_queue()
 
   1, nandflash io 請求處理線程mtd_blktrans_thread()等在一個等待隊列上
   mtd_blktrans_thread()
   ->DECLARE_WAITQUEUE(wait,current);
   ->elv_next_request()  /* 檢查有沒有IO請求 */
   ->add_wait_queue(&tr->blkcore_priv->thread_wq)  /* 等在等待隊列上 */
   ->set_current_state(TASK_INTERRUPTIBLE)
   ->schedule();   /* 讓出cpu使用權 */
   ->    /* 等待,直到有IO請求到來被喚醒 */
   ->do_blktrans_request()
     ->blk_fs_request();
     ->   /* 檢查訪問的偏移量不能大於整個nandflash 的容量 */
     ->   /* 假設爲讀訪問: */
       ->tr->readsect()
         mtdblock_readsect()   /* mtd_block.c */
         ->do_cached_read()    /* mtd_block.c */
           ->mtd->read()
             nand_read()   /* nand_base.c */
             ->nand_do_read_ops()
               ->nand_read_page_raw()
                 ->s3c2410_nand_read_buf()  /* 經過s3c2410 nandflash控制器發命令讀取nandflash 內容*/  //s3c2410.c
 
     ->  /* 假設爲寫訪問 */
       ->tr->writesect()
         mtdblock_writesect()
   ->end_request()
 
   2, 當IO請求來時,喚醒線程 mtd_blktrans_thread()
   mtd_blktrans_request()
   ->wake_up(&tr->blkcore_priv->thread_wq)
 
   3, nandflash IO請求處理線程mtd_blktrans_thread()開始處理IO請求
   ->do_blktrans_request()
   ->/* 見上 */
 
從上面的代碼流程可見,Nand Flash 驅動做爲一個塊設備的典型案例,爲位於MTD的下層,其數據的讀寫經過mtd_blktrans_thread內核線程來處理IO請求。
相關文章
相關標籤/搜索