李洋 Michael Collier
摘要:隨著全球電視數(shù)字廣播的發(fā)展,數(shù)字電視已然成為市場(chǎng)的主流,集成模擬和數(shù)字電視信源解碼和高端后處理能力的SOC核心處理器芯片具有廣闊的市場(chǎng)前景。NAND Flash作為一種大容量的存儲(chǔ)設(shè)備,滿足了數(shù)字電視嵌入式系統(tǒng)對(duì)功耗、體積、成本及抗震性的苛刻要求,因而得到了廣泛的應(yīng)用。該論文主要探討NAND Flash設(shè)備在數(shù)字電視中的工作原理以及基于Linux系統(tǒng)框架下的NAND Flash驅(qū)動(dòng)程序的設(shè)計(jì)與實(shí)現(xiàn)。
關(guān)鍵詞:數(shù)字電視;嵌入式系統(tǒng);NAND Flash;驅(qū)動(dòng)開發(fā);Linux
中圖分類號(hào):TP316文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):1009-3044(2012)01-0070-04
Design and Implementation of NAND Flash Driver in Digital TV
LI Yang,Michael Collier
(College of Information and Electrical Engineering, Shandong University of Science and Technology, Qingdao 266590, China)
Abstract: With the global development of digital broadcasting, digital television has become the mainstream of market, SOC processor chips integrated analog and digital TV source decoder and high capabilities of post-processing has broad market prospects. As a kind of large-capacity storage devices, NAND Flash meets the harsh requirements of power, size, cost and resistance to shock by embedded system, which has been widely used. This paper probes into the principles of the NAND Flash devices in DTV and the design and implementation of NAND Flash driver based on the framework of Linux.
Key words: digital TV; embedded system; NAND Flash; driver development; Linux
在嵌入式系統(tǒng)開發(fā)過(guò)程中,大容量存儲(chǔ)器模塊的設(shè)計(jì)已經(jīng)成了不可或缺的重要方面。數(shù)字電視SOC芯片的NAND Flash支持由兩部分組成[1]:NAND Flash控制器和NAND Flash存儲(chǔ)芯片(H27U1G8F2B)。當(dāng)要訪問(wèn)NAND Flash中的數(shù)據(jù)時(shí),必須通過(guò)NAND Flash控制器發(fā)送命令才能完成,因此開發(fā)一個(gè)高效的NAND Flash控制器的驅(qū)動(dòng)程序顯得尤其重要。
1 NAND Flash工作原理
1.1 NAND Flash組織結(jié)構(gòu)
該數(shù)字電視系統(tǒng)采用的NAND Flash型號(hào)為K9F1G08U0B,整個(gè)芯片分為1024個(gè)塊(block),塊是擦除的基本單位。每個(gè)塊又分為64頁(yè)(page),每個(gè)頁(yè)包含2112字節(jié)的容量,其中2K字節(jié)用于存放數(shù)據(jù),64個(gè)字節(jié)用來(lái)存放ECC校驗(yàn)信息及其他額外數(shù)據(jù)。用戶數(shù)據(jù)存儲(chǔ)區(qū)總?cè)萘繛?28MB,額外數(shù)據(jù)區(qū)總?cè)萘繛?MB。NAND Flash以頁(yè)為單位讀寫數(shù)據(jù),而以塊為單位擦除數(shù)據(jù)[2]。NAND Flash的存儲(chǔ)結(jié)構(gòu)如圖1所示。
圖1 Nand Flash存儲(chǔ)結(jié)構(gòu)圖
1.2 NAND Flash尋址方式
按照上述的組織方式可以形成三類地址:
Column Address:列地址
Page Address:頁(yè)地址
Block Address:塊地址
表1 NAND Flash尋址方式表
A0 ~A11是列地址,共12位以保證能尋址到2112的頁(yè)容量;A12~A17是頁(yè)地址,共6位,保證能尋址到每個(gè)塊中的64個(gè)頁(yè);A18~A27是塊地址,共10位,用來(lái)尋址1024個(gè)塊。由于地址只能在I/O[7:0]上傳遞,因此,必須采用移位的方式進(jìn)行。整個(gè)地址傳遞過(guò)程需要如下4步才能完成,稱為4-step addressing。
第1步是傳遞列地址的前8位,也就是A[0:7],不需移位即可傳遞到I/O[0:7]上;第2步是將NAND_ADDR右移8位,將列地址的后4位A[8:11]傳到I/O[0:7]上;第3步將NAND_ADDR再右移8位,將頁(yè)地址跟塊地址的前兩位放到I/O[0:7]上;
第4步將NAND_ADDR繼續(xù)右移8位,將塊地址的最后8位放到I/O[0:7]上。
1.3 NAND Flash操作方式
1)擦除操作:
擦除操作時(shí)以塊為單位進(jìn)行的,擦除的啟動(dòng)指令為60h,隨后的2個(gè)時(shí)鐘周期是塊地址。其中只有A17到A27是有效的,而A12到A17是可以忽略的。塊地址之后是擦除確認(rèn)指令D0h,用來(lái)開始內(nèi)部的擦除操作。器件檢測(cè)到擦除確認(rèn)命令后,在/WE的上升沿啟動(dòng)內(nèi)部寫控制器,開始執(zhí)行擦除和擦除校驗(yàn)。內(nèi)部擦除操作完成后,應(yīng)該檢測(cè)寫狀態(tài)位(I/O 0),從而了解擦除操作是否成功完成。
2)寫操作:
寫入操作以頁(yè)為單位。寫入之前必須在擦除之后,否則寫入時(shí)將會(huì)出現(xiàn)錯(cuò)誤。頁(yè)寫入周期中包括以下步驟:
寫入串行數(shù)據(jù)輸入指令80h。然后寫入4個(gè)字節(jié)的地址,最后串行寫入數(shù)據(jù)。串行寫入的數(shù)據(jù)最多為2112B。串行數(shù)據(jù)寫入完成后,需要寫入“頁(yè)寫入確認(rèn)”指令10h,這條指令將初始化器件內(nèi)部寫入操作。10h寫入之后,NAND Flash的內(nèi)部寫控制器將自動(dòng)執(zhí)行內(nèi)部寫入和校驗(yàn)中必要的算法和時(shí)序,系統(tǒng)可以通過(guò)檢測(cè)R/B的輸出,或讀狀態(tài)寄存器的狀態(tài)位I/O 0來(lái)判斷內(nèi)部寫入是否結(jié)束。
2 NAND Flash控制器
該NAND Flash控制器的讀寫擦除都是來(lái)自AMBA APB總線的請(qǐng)求。NAND Flash控制器的主要功能是把來(lái)自于AMBA APB總線的請(qǐng)求轉(zhuǎn)化為標(biāo)準(zhǔn)的NAND Flash的命令序列。
因?yàn)镹AND Flash的普通的數(shù)字讀寫都是以頁(yè)為基礎(chǔ)的,所以在NAND Flash控制器中使用了一個(gè)2K的數(shù)據(jù)緩存buffer。
對(duì)于數(shù)據(jù)路徑的設(shè)計(jì),因?yàn)镹AND Flash的輸入輸出總線是一個(gè)命令形式的串行總線,地址和數(shù)據(jù)復(fù)用一條總線,所以設(shè)計(jì)中有必要引入一個(gè)多路器。另外,為了提高系統(tǒng)的可靠性,數(shù)據(jù)通路中引入了可選的ECC功能。
3 NAND Flash驅(qū)動(dòng)程序設(shè)計(jì)
3.1 LINUX MTD驅(qū)動(dòng)框架
NAND Flash作為boot loader、內(nèi)核與文件系統(tǒng)的最佳載體,是嵌入式系統(tǒng)中必不可少的一個(gè)外設(shè)。Linux內(nèi)核引入了MTD內(nèi)存技術(shù)設(shè)備子系統(tǒng)來(lái)為NAND Flash、NOR Flash等存儲(chǔ)設(shè)備提供統(tǒng)一的接口,從而使Flash驅(qū)動(dòng)的設(shè)計(jì)大大簡(jiǎn)化。引入MTD框架后,NAND Flash設(shè)備驅(qū)動(dòng)可以分為如圖3幾層。
圖3 NAND Flash驅(qū)動(dòng)程序分層結(jié)構(gòu)
1)硬件驅(qū)動(dòng)層
NAND Flash硬件驅(qū)動(dòng)層負(fù)責(zé)FLASH硬件設(shè)備的讀、寫、擦除,Linux MTD設(shè)備的NAND Flash驅(qū)動(dòng)則位于/driver/mtd/nand子目錄下。
2) MTD原始設(shè)備層:
MTD原始設(shè)備層由兩部分構(gòu)成,一部分是MTD原始設(shè)備的通用代碼(mtdcore.c、mtdpart.c),另一部分是各個(gè)特定的FLASH的數(shù)據(jù),例如分區(qū)等。
3) MTD設(shè)備層:
基于MTD原始設(shè)備,Linux系統(tǒng)可以定義出MTD的塊設(shè)備(主設(shè)備號(hào)31)和字符設(shè)備(設(shè)備號(hào)90),構(gòu)成設(shè)備層。MTD字符設(shè)備在mtdchar.c實(shí)現(xiàn),MTD塊設(shè)備在mtdblock.c實(shí)現(xiàn)。
4)設(shè)備節(jié)點(diǎn):
通過(guò)mknod命令在dev子目錄下建立MTD字符設(shè)備節(jié)點(diǎn)(主設(shè)備號(hào)為90)和塊設(shè)備節(jié)點(diǎn)(主設(shè)備號(hào)為31),用戶通過(guò)訪問(wèn)該設(shè)備節(jié)點(diǎn)即可訪問(wèn)MTD字符設(shè)備和塊設(shè)備。
3.2 NAND Flash平臺(tái)驅(qū)動(dòng)結(jié)構(gòu)體
NAND Flash平臺(tái)驅(qū)動(dòng)結(jié)構(gòu)體定義如下:
static struct platform_driver hiview_nand_driver = {.probe= hiview_nand_probe,
.remove= hiview_nand_remove,
.suspend = hiview_nand_suspend,.resume= hiview_nand_resume,.driver= {
.name = "hiview-nand",.owner = THIS_MODULE,},}; 1) hiview_nand_probe函數(shù)是驅(qū)動(dòng)真正開始工作的部分,主要作用是初始化硬件、掃描設(shè)備、分配相應(yīng)的資源等[3]。這部分代碼根據(jù)具體的NAND Flash器件有關(guān),必須自己去實(shí)現(xiàn)。
2) hiview_nand_remove函數(shù)與函數(shù)hiview_nand_probe相對(duì)應(yīng),主要完成NAND Flash的反初始化工作,包括釋放系統(tǒng)資源及關(guān)閉硬件時(shí)鐘等。
3) suspend和resume主要用于電源管理的相關(guān)操作,在沒(méi)有電源管理的系統(tǒng)中放個(gè)空函數(shù)即可。
3.3 NAND Flash底層操作函數(shù)實(shí)現(xiàn)
通過(guò)平臺(tái)驅(qū)動(dòng)中的hiview_nand_probe函數(shù)注冊(cè)之后,相應(yīng)的函數(shù)都掛載完畢,初始化工作也已經(jīng)做完,此時(shí)NAND Flash便可以工作了[4]。上層在訪問(wèn)NAND Flash的時(shí)候,通過(guò)MTD,一層一層向下調(diào)用,最終調(diào)用到底層的操作函數(shù)。
1) hiview_nand_write_buf和hiview_nand_read_buf:
這是兩個(gè)最基本的操作函數(shù),其功能就是往NAND Flash控制器的FIFO中讀寫數(shù)據(jù)。比如要讀取一頁(yè)的數(shù)據(jù),那么在發(fā)送完相關(guān)的讀命令和等待時(shí)間之后,就會(huì)調(diào)用到你底層的read_buf,去NAND Flash的FIFO中,一點(diǎn)點(diǎn)把所需要的數(shù)據(jù)讀取出來(lái),放到內(nèi)存的緩存中去。寫操作也是類似,將我們內(nèi)存中的數(shù)據(jù),寫到NAND Flash的FIFO中去。
2) hiview_nand_devready:
NAND Flash的一些操作,比如讀1頁(yè)數(shù)據(jù),寫入1頁(yè)數(shù)據(jù),擦除1個(gè)塊,都需要一定的時(shí)間,在命令發(fā)送完成后,就是硬件開始忙著工作的時(shí)候了,而硬件什么時(shí)候完成。這些操作,就是通過(guò)這個(gè)函數(shù)去檢查狀態(tài)的。具體實(shí)現(xiàn)都是去讀硬件的一個(gè)狀態(tài)寄存器,其中某一位是否是1,對(duì)應(yīng)著是處于“就緒”還是“忙”狀態(tài)。
3) hiview_nand_enable_hwecc:
在硬件支持的前提下,前面設(shè)置了硬件ECC的話,要實(shí)現(xiàn)這個(gè)函數(shù),用于每次在讀寫操作前,通過(guò)設(shè)置對(duì)應(yīng)的硬件寄存器的某些位,使得啟用硬件ECC,這樣在讀寫操作完成后,就可以去讀取硬件校驗(yàn)產(chǎn)生出來(lái)的ECC數(shù)值了。
4) hiview_nand_correct_data:
當(dāng)實(shí)際操作過(guò)程中,讀取出來(lái)的數(shù)據(jù)所對(duì)應(yīng)的硬件或軟件計(jì)算出來(lái)的ECC和從OOB中讀出來(lái)的ECC不一樣的時(shí)候,就是說(shuō)明數(shù)據(jù)有誤了,就需要調(diào)用此函數(shù)去糾正錯(cuò)誤[5]。對(duì)于常見的ECC算法來(lái)說(shuō),可以發(fā)現(xiàn)2位,糾正1位。更復(fù)雜的情況和更加注重?cái)?shù)據(jù)安全的情況下,一般是需要另外實(shí)現(xiàn)更高效和檢錯(cuò)和糾錯(cuò)能力更強(qiáng)的ECC算法。
4結(jié)束語(yǔ)
在驅(qū)動(dòng)開發(fā)結(jié)束之后,將此驅(qū)動(dòng)程序編譯成模塊,并整合到要移植的Linux系統(tǒng)中。經(jīng)過(guò)系統(tǒng)的整機(jī)調(diào)試,此NAND Flash驅(qū)動(dòng)功能完整,性能穩(wěn)定,能夠很好的支持YAFFS2文件系統(tǒng),很好地滿足了設(shè)計(jì)需求。參考文獻(xiàn):
[1]宋寶華.Linux設(shè)備驅(qū)動(dòng)開發(fā)詳解[M].北京:人民郵電出版社,2008.
[2]漢澤西,呂飛.大容量NAND Flash在嵌入式系統(tǒng)中的應(yīng)用[J].石油儀器,2006 (2):62-66
[3] Love R. Linux內(nèi)核設(shè)計(jì)與實(shí)現(xiàn)[M].陳莉君,譯.北京:機(jī)械工業(yè)出版社,2006.
[4]徐君明,陳振林,郭天杰.嵌入式硬件設(shè)計(jì)[M].北京:中國(guó)電力出版社,2007.
[5] Bovetd,Cesati M.深入理解LINUX內(nèi)核[M].陳莉君,張瓊生,張宏偉,譯.3版.北京:中國(guó)電力出版社,2007.