Linux NAND FLASH驅動程序分析(mini2440)
一、Linux-MTD Subsystem介紹
FLASH在嵌入式系統中是必不可少的,它是bootloader、linux內核和文件系統的最佳載體。在Linux內核中引入了MTD子系統爲NOR FLASH和NAND FLASH設備提供統一的接口,從而使得FLASH驅動的設計大爲簡化。
在引入MTD後Linux系統中FLASH設備驅動可分爲四層,如圖:
1. 硬件驅動層
FLASH硬件驅動層負責FLASH硬件設備的讀、寫、擦出,LINUX MTD設備的NOR FLASH驅動位於/driver/mtd/chips子目錄下,NAND FLASH驅動則位於/driver/mtd/nand子目錄下。
特定硬件層負責完成特定硬件的讀寫,例如2440的/driver/mtd/nand/s3c2410.c
通用驅動爲所有nand的通用部分,實現nand設備發現,通用讀寫等./driver/mtd/nand/nand_base.c
2. MTD原始設備層:MTD原始設備層由兩部分構成,一部分是MTD原始設備的通用代碼(mtdcore.c、mtdpart.c),另一部分是各個 特定的FLASH的數據,例如分區。
3. MTD設備層:基於MTD原始設備,LINUX系統可以定義出MTD的塊設備(主設備號31)和字符設備(設備號90),構成設備層。MTD字符設備在mtdchar.c實現,MTD塊設備在mtdblock.c實現。
4. 設備節點:通過mknod在/dev子目錄下建立MTD字符設備節點(主設備號爲90)和塊設備節點(主設備號爲31),用戶通過訪問此設備節點即可訪問MTD字符設備和塊設備。
也可通過下圖理解:
從上圖可以看出,MTD設備層與原始設備層打交道。通過分析源代碼我們可以知道當上層要求對FLASH進行讀寫時,它會像設備層發出請求,設備層的讀寫函數會調用原始設備層中的讀寫函數,即mtd_info結構體(mtd原始設備層中描述設備的專用結構體)中的讀寫函數,而mtd_info中的函數會調用nand_chip(nand硬件驅動層中描述設備的結構體,其中包含了針對特定設備的基本參數和設備操作函數)中的讀寫函數。所以一個flash硬件驅動程序時的步驟大致如下:
1. 如果FLASH要分區,則定義mtd_partition數組,將FLASH分區信息記錄其中。
mtd_partition friendly_arm_default_nand_part[],arch/arm/plat-s3c24xx/common-friendly-arm.c
2. 在模塊加載時爲每一個chip(主分區)分配mtd_info和nand_chip的內存,根據目標板nand 控制器的特殊情況初始化nand_chip中的實現對FLASH操作的成員函數,如hwcontrol()、dev_ready()、read_byte()、write_byte()等。填充mtd_info,並將其priv成員指向nand_chip。 driver/mtd/nand/s3c2410/c
3. 以mtd_info爲參數調用nand_scan()函數探測NAND FLASH的存在。nand_scan()函數會從FLASH芯片中讀取其參數,填充相應nand_chip成員。 driver/mtd/nand/nand_base/c
nand_scan()分爲兩步,首先是nand_scan_ident(),主要完成flashID的讀取等,然後是nand_scan_tail(),主要完成chip結構體中未初始化函數的默認賦值,以及壞塊的掃描。
4. 如果要分區,則以mtd_info和mtd_partition爲參數調用add_mtd_partions(),添加分區信息。在這個函數裏面會爲每一個分區分配一個mtd_info結構體填充,並註冊。
二、nand flash驅動程序實例分析
我們以2.6.29內核中mini2440的nand flash驅動程序爲例來分析一下這個過程,這裏的flash驅動被寫成了platform驅動的形式。我們下面分析其過程:
1. 註冊nand flash設備
nand flash分區:
nand控制器資源
2.註冊nand flash driver
當platform_driver驅動被加載時或者是當platform_device被註冊時,總線驅動程序
會查找與設備匹配的驅動程序,找到時設備驅動程序的probe函數會被調用,下面我們來分析一下在我們驅動程序中的probe函數
probe的具體調用流程見 Linux NAND FLASH驅動代碼分析