JZ2440 第8章 NAND Flash

本章目標 

瞭解NAND Flash 芯片的接口
掌握通過NAND Flash控制器訪問NAND Flash的方法

8.1 NAND Flash介紹和NAND Flash控制器使用

    NAND Flash在嵌入式系統中的地位與PC上的硬盤類似,用於保存系統運行所需的操
作系統、應用程序、用戶數據、運行過程中產生的各類數據。與內存掉電數據丟失不同,
NAND Flash中的數據在掉電後仍可永久保存。

8.1.1 Flash介紹

    常用的Flash類型由NOR Flash和NAND Flash兩種。兩者的主要差別如表8.1所示。


    NOR Flash支持XIP,即代碼可以直接在NOR Flash上執行,無需複製到內存中。這是
由於NOR Flash的接口與RAM完全相同,可以隨機訪問任意地址的數據。在NOR Flash
上進行讀操作的效率非常高,但擦除和寫操作的效率很低;另外,NOR Flash的容量一般
比較小。NAND Flash進行擦除和寫操作的效率更高,而且容量更大。一般而言,NOR 
Flash用於存儲程序,NAND Flash用於存儲數據。基於NAND Flash的設備通常也要搭配
NOR Flash以存儲程序。
    Flash存儲器件由擦除單元(也稱爲塊)組成,當要寫某個塊時,需要確保這個塊已經被
擦除。NOR Flash的塊大小範圍爲64KB~128KB;NAND Flash的塊大小範圍爲8KB~64KB,
擦寫一個NOR Flash塊需要4s,而擦寫一個NAND Flash塊僅需2ms。NOR Flahs的塊太大,
不僅增加了擦寫時間,對於給定的寫操作,NOR Flash也需要更多的擦除操作——特別是一
些小文件,比如一個文件只有1KB,但是爲了保存它,確需要擦除大小爲64KB~128KB的
NOR Flash塊。
    NOR Flash的接口與RAM完全相同,可以隨意訪問任意地址的數據,而NAND Flahs的接口
僅僅包含幾個I/O引腳,需要串行地訪問。NAND Flash一般以512字節爲單位進行讀寫。這使得
NOR Flash適合於運行程序,而NAND Flash更適合於存儲數據。
    容量相同的情況下,NAND Flash的體積更小,對於空間有嚴格要求的系統,NAND Flash
可以節省更多空間。市場上NOR Flash的容量通常爲1MB~4MB(也有32MB的NOR Flash),
NAND Flash的容量爲8MB~512MB。容量的差別也使得NOR Flash多用於存儲程序,NAND 
Flash多用於存儲數據。
    對於Flash存儲器件的可靠性需要考慮3點:位反轉、壞塊和可擦除次數。所有Flash器件
都遭遇位反轉的問題:由於Flash固有的電器特性,在讀寫數據過程中,偶然會產生一位或幾位
數據錯誤(這種概率很低),而NAND Flash出現的概率遠大於NOR Flash。當位反轉發生在關鍵的
代碼、數據上時,有可能導致系統崩潰。當僅僅是報告位反轉,重新讀取即可;如果確實發生了
位反轉,則必須有相應的錯誤檢測/恢復措施。在 NAND Flash上發生位反轉的概率更高,推薦使用
EDC/ECC進行錯誤檢測和恢復。NAND Flash上面會有壞塊隨機分佈,在使用前需要將壞塊檢測
出來,確保它們不再使用,否則會使產品含有嚴重的故障NAND Flash每塊的可擦除次數通常在
10 0000次,是NOR Flash的10倍。另外,因爲NAND Flash的塊大小通常是NOR Flash的1/8,
所以NAND Flash的壽命遠遠超過NOR Flash。
    嵌入式Linux對NOR、NAND Flash的軟件支持都很成熟。在NOR Flash上常用jffs2文件系統,
而在NAND Flash上常用yaffs文件系統。在更底層,有MTD驅動程序實現對它們的讀、寫、擦除
操作,它也實現了EDC/ECC校驗。

8.1.2 NAND Flash的物理結構

    NAND Flash K9F1208U0M爲例,這款芯片時三星公司生產的容量爲64MB的NAND Flash,
常用於手持式設備等消費類電子。它的封裝及外部引腳如圖8.7所示:

     K9F1208U0M的功能結構圖如圖8.2所示。

     K9F1208U0M的內部結構分爲10個功能部件
    ① X-Buffers Latche & Decoders:用於行地址;
    ② Y-Buffers Latche & Decoders:用於列地址;
    ③ Command Register:用於命令字;
    ④ Control Logic & High Voltage Generator:控制邏輯及產生Flash所需高壓;
    ⑤ Nand Flash Array:存儲部件。
    ⑥ Page Register & S/A:頁寄存器,當讀、寫某頁時,會將數據先讀入\寫入此寄存器,大小爲528字節;
    ⑦ Y-Gating;
    ⑧ I/O Buffers & Latches;
    ⑨ Global Buffers;
    ⑩ Output Driver。
    NAND Flash存儲單元組織結構如圖8.3所示。

     K9F1208U0M容量爲528Mbit,分爲131072行(頁)、528列;每頁大小爲512字節,外加
16字節的額外空間,這16字節額外空間的列地址爲512~527。
    命令、地址、數據都通過8個I/O口輸入/輸出,這種形式減少了芯片的引腳個數,並使得
系統很容易升級到更大的容量。寫入命令、地址或數據時,都需要將WE#、CE#信號同時
拉低。數據在WE#信號的上升沿被NAND Flash鎖存:命令鎖存信號CLE、地址鎖存信號
ALE用來分辨、鎖存命令或地址。K9F1208U0M的64MB存儲空間需要26位地址,因此以
字節爲單位訪問Flash時需要4個地址序列:列地址、行地址的低位部分、行地址的高位部分。
讀寫頁在發出命令後,需要4個地址序列,而擦除塊在發出擦除命令後僅需要3個地址序列。

8.1.3 NAND Flash訪問方法

1.硬件連接
    NAND Flash與S3C2410/S3C2440的硬件連接如圖8.4所示。

    NAND Flash與S3C2410/S3C2440的連線比較少:8個I/O引腳(IO0~IO7)、5個使能
信號(nWE、ALE、CLE、nCE、nRE)、1個狀態引腳(RDY/B)、1個寫保護引腳(nWP)。
地址、數據和命令都是在這些使能信號的配合下,通過8個I/O引腳傳輸。寫地址、數據、
命令時,nCE、nWE信號必須爲低電平,它們在nWE信號的上升沿被鎖存。命令鎖存使
能信號CLE和地址鎖存信號ALE用來區分I/O引腳上傳輸的是命令還是地址。
2.命令字及操作方法
    操作NAND Flash時,先傳輸命令,然後傳輸地址,最後讀寫數據,期間要檢查Flash
的狀態。對於K9F1208U0M,它的容量爲64MB,需要一個26位的地址。發出命令後,後
面要緊跟着4個地址序列。比如讀Flash時,發出讀命令和4個地址序列後,後續的讀操作就
可以得到這個地址及其後續地址的數據。相應的命令字和地址序列如表8.2、8.3所示。
 
    K9F1208U0M一頁大小爲528字節,而列地址A0~A7可以尋址的範圍是256字節,所
以必須輔以其他手段才能完全尋址這528字節。將一頁分爲A、B、C三個區:A區爲0~255
字節,B區爲256~511字節,C區爲512~527字節。訪問某頁時,需要選定特定的區,這
稱爲“使地址指針指向特定的區”。這通過3個命令來實現:
    命令00h讓地址指針指向A區、命令01h讓地址指針指向B區、命令50h讓地址指針指向C區。
    命令00h和50h會使得訪問Flash的地址指針一直從A區或C區開始,除非發出了其他的修改
地址指針的命令。
    命令01h的效果只能維持一次,當前的讀、寫、擦除、復位或者上電操作完成後,地址指針
重新指向A區。
    寫A區或C區數據時,必須在發出命令80h之前發出命令00h或者50h;
    寫B區數據時,發出命令01h後必須緊接着發出命令80h。
    圖8.5形象地表示了K9F1208U0M的這個特性。

     下面逐個講解表8.2的命令字。
    (1)Read1:命令字爲00h或01h。
    如圖8.5所示,發出命令00h或者01h後,就選定了讀操作從A區還是B區開始。從表8.3
可知,列地址A0~A7可以尋址的範圍是256字節,命令00h和01h使得可以在512字節大小
的頁內任意尋址——這相當於A8被命令00h設爲0,而被命令01h設爲1。
    發出命令字後,依照表8.3發出4個地址序列,然後就可以檢測R/nB引腳以確定Flash
是否準備好。如果準備好了,就可以發起讀操作依次讀入數據。
    (2)Read2:命令字爲50h。
    與Read1類似,不過讀取的是C區數據,操作序列爲:發出命令字50h、發出4個地址
序列、等待R/nB引腳爲高,最後讀取數據。不同的是,地址序列中A0~A3用於設定C區
(大小爲16字節)要讀取的起始地址,A4~A7被忽略。
    (3)ReadID:命令字位90h。
    發出命令字90h,發出4個地址序列(都設爲0),然後就可以連續讀入5個數據,分別
表示:廠商代碼(對於SAMSUNG公司爲Ech)、設備代碼(對於K9F1208U0M爲76h)、保
留的字節(對於K9F1208U0M爲A5h)、多層操作代碼(C0h表示支持多層操作)。
    (4)Reset:命令字位FFh。
    發出命令字FFh即可復位NAND Flash芯片。如果芯片正處於讀、寫、擦除狀態,復位
命令會終止這些命令。
    (5)Page Program(True):命令字分兩段,80h和10h。
    它的操作序列如圖8.6所示。

     NAND Flash的寫操作一般是以頁爲單位的,但是可以只寫一頁中的一部分。發出命令
字80h後,緊接着是4個地址序列,然後向Flash發送數據(最大可以達到528字節),然後發
出命令字10h啓動寫操作,此時Flash內部會自動完成寫、校驗操作。一旦發出命令字10h
後,就可以通過讀狀態命令70h獲知當前操作是否完成、是否成功。
    (6)Page Program(Dummy):命令字分兩階段,80h和11h。
    NAND Flash K9F1208U0M分爲4個128Mbit的存儲層(plane),每個存儲層包含1024個
block和528字節的寄存器。這使得可以同時寫多個頁(page)或者同時擦除多個塊(block)。
塊的地址經過精心安排,可以在4個連續的塊內同時進行寫或者擦除操作。
    如圖8.7所示位K9F1208U0M的塊組織圖。

    命令Page Program(Dummy)正是在這種結構下對命令Page Program(True)的擴展,後
者僅能對一頁進行寫操作,前者可以同時寫4頁。命令Page Program(Dummy)的操作序列
如圖8.8所示。

     發出命令字80h、4個地址序列及最多528字節的數據之後,發出命令字11h(11h稱
“Dummy Page Program command”,相對地,10h稱爲“True Page Program command”);
接着對相鄰層(plane)上的頁進行同樣的操作;僅在第4頁的最後使用10h替代11h,這樣
即可啓動Flash內部的寫操作。此時可以通過命令71h獲知這些操作是否完成、是否成功。
    (7)Copy-Back Program(True):命令字分3階段,00h、8Ah、10h。
    此命令用於將一頁複製到同一層(plane)內的另一頁,它省略了讀出源數據、將數據重新
載入Flash,這使得效率大爲提高。此命令有兩個限制:源頁、目的頁必須在同一層(plane)
中,並且源地址、目的地址的A14、A15必須相同。
    操作序列如圖8.9所示。

    首先發出命令Read1(00h)、4個源地址序列,此時源頁的528字節數據很快就被全部
內部寄存器中;
    接着發出命令字8Ah(Page-Copy Data-input command),隨之發出4個目的地址序列;
    最後發出命令字10h啓動對目的頁的寫操作。
    此後,可以使用命令70h來查看此操作是否完成、是否成功。
    (8)Copy-Back Program(Dummy):命令字分3階段,03h、8Ah、11h。
    與命令Page Program(Dummy)類似,Copy-Back Program(Dummy)可以同時啓動對多
達4個連續plane內的Copy-Back Program操作。操作序列如圖8.10所示。

    從圖8.10 可知,首先發出命令字00h、源頁地址,這使得源頁的528字節數據被讀入
所在plane的寄存器;對於隨後的其他plane的源頁,發出命令字03h和相應的源頁地址
將數據讀入該plane的寄存器;按照前述說明讀出最多4頁的數據到寄存器後,發出命令
字8Ah、目的地址、命令字11h,在發出最後一頁的地址後,用10h代替11h以啓動寫操作。
    (9)Block Erase:命令字分3階段,60h、D0h。
    此命令用於擦除NAND Flash塊(block,大小爲16KB)。發出命令字60h之後,發出block
地址——僅需要3個地址序列(請參考表8.3,僅需要發出2、3、4 cycle所示地址),並且
A9~A13被忽略。操作序列如圖8.11所示。


     (10)Multi-Plane Block Erase:60h——60h D0h
    此命令用於同時擦除不同的plane中的塊。發出命令字60h之後,緊接着發出block地址
序列,如此最多可以發出4個block地址,最後發出命令字D0h啓動擦除操作。操作序列如
圖8.12所示。


     (11)讀狀態命令有以下兩種:
    ① Read Status:命令字位70h;
    ② Read Multi-Plane Status:命令字位71h。
    Flash中有狀態寄存器,發出命令字70h或者71h之後,啓動讀操作即可讀入此寄存器。
狀態寄存器中各位的含義如表8.4所示。

    

 8.1.4 S3C2410/S3C2440 NAND Flash控制器介紹

    NAND Flash控制器提供幾個寄存器來簡單對NAND Flash的操作。比如要發出讀命令時,
只需要向NFCMD寄存器中寫入0即可,NAND Flash控制器會自動發出各種控制信號。
1.操作方法概述
    訪問NAND Flash時需要先發出命令,然後發出地址序列,最後讀寫數據;需要使用各個
使能信號來分辨是命令、地址還是數據。S3C2410的NAND Flash控制器提供了NFCONF、
NFCMD、NFADDR、NFDATA、NFSTAT和NFECC等6個寄存器來簡化這些操作。S3C2440
的NAND Flash控制器則提供了NFCONF、NFCONT、NFCMMD、NFADDR、NFDATA、
NFSTAT和其他與ECC有關的寄存器。對NAND Flash控制器的操作,S3C2410/S3C2440
有一點不同:有些寄存器的地址不一樣,有些寄存器的內容不一樣,這在示例程序中會體現
出來。
    NAND Flash的讀寫操作次序如下:
    ① 設置NFCONF(對於S3C2410,還要設置NFCONT)寄存器,配置NAND Flash;
    ② 向NFCMD寄存器寫入命令,這些命令字可參考表8.2;
    ③ 向NFADDR寄存器寫入地址;
    ④ 讀寫數據:通過寄存器NFSTAT檢測NAND Flash的狀態,在啓動某個操作後,應該檢
測R/nB信號以確定該操作是否完成,是否成功。
2.寄存器介紹
    下面講解這些寄存器的功能及具體用法。
(1)NFCONF:NAND Flash配置寄存器。
    這個寄存器在S3C2410、S3C2440上功能有所不同。
    ① S3C2410的NFCONF寄存器。
    被用來使能/禁止NAND Flash控制器、使能/禁止控制引腳信號nFCE、初始化ECC、設
置NAND Flash的時序參數等。
    TACLS、TWRPH0和TWRPH1這3個參數控制的是NAND Flash信號線CLE/ALE與寫控
制信號nWE的時序關係,如圖8.13所示。

    ② S3C2440的NFCONF寄存器。
    被用來設置NAND Flash的時序參數TACLS、TWRPH0、TWRPH1,設置數據尾款;還
有一些只讀位,用來指示是否支持其他大小頁(比如一頁大小爲256/512/1024/2048字節)。
    它沒有實現S3C2410的NFCONF寄存器的控制功能,這些功能在S3C2440的NFCONT
寄存器裏實現。
(2)NFCONT:NAND Flash控制寄存器,S3C2410沒有這個寄存器。
    被用來使能/禁止NAND Flash控制器、使能/禁止控制引腳信號nFCE、初始化ECC。它
還有其他功能,在一般的應用中用不到,比如鎖定NAND Flash。
(3)NFCMD:NAND Flash命令寄存器。
    對於不同信號的Flash,操作命令一般不一樣。對於本開發板使用的K9F1208U0M,請參
考表8.2.
(4)NFADDR:NAND Flash地址寄存器
    當寫這個寄存器時,它將對Flash發出地址信號。
(5)NFDATA:NAND Flash數據寄存器。
    只用到低8位,讀、寫此寄存器將啓動對NAND Flash的讀、寫數據操作。
(6)NFSTAT:NAND Flash狀態寄存器。
    只用到位0,0:busy;1:ready。

8.2 NAND Flash 控制器操作實例:讀Flash

    本實例講述如何讀取NAND Flash,擦除、寫Flash的操作與讀Flash類似,讀者可以
自行編寫程序。

8.2.1 讀NAND Flash的步驟

    下面講述如何從NAND Flash中讀出數據,假設讀地址爲addr。
1.設置NFCONF(對於S3C2440,還要設置NFCONT)
(1)對於S3C2420。
    在本章實例中設爲0x9830——使能NAND Flash控制器、初始化ECC、NAND Flash片
選信號nFCE = 1(inactive,真正使用時再讓它等於0),設置TACLS = 0,TWRPH0 = 3,
TWRPH1= 0。這些時序參數的含義爲:TACLS = 1個HCLK時鐘,TWRPH0 = 4個HCLK
時鐘,TWRPH1 = 1個HCLK時鐘。
    K9F1208U0M的時間特性如下:
    CLE setup Time = 0 ns,CLE Hold Time = 10ns,
    ALE setup Time = 0 ns,ALE Hold Time = 10ns,
    WE Pulse Width = 25ns
    參考圖8.13,可以計算:即使在HCLK = 100MHz的情況下,
        TACLS + TWRPH0 + TWRPH1 = 6/100us = 60ns ,
也是可以滿足NAND Flash K9F1208U0M的時序要求的。
(2)對於S3C2440。
    時間參數也設爲:TACLS = 0,TWRPH0 = 3,TWRPH1= 0.NFCONF寄存器的值如下:
    NFCONF = 0x300
    NFCONT寄存器的取值如下,表示使能NAND Flash控制器、禁止控制引腳信號nFCE、
初始化ECC。
    NFCONT = (1 << 4) | (1 << 1) | (1 << 0)
2.在第一次操作NAND Flash前,通常復位一下NAND Flash
(1)對於S3C2410。
    NFCONF &= ~(1 << 11)    (發出片選信號)
    NFCMD     = 0xff             (reset命令)
     然後循環查詢NFSTAT的位0,直到它等於1。
    最後禁止片選信號,在實際使用NAND Flash時再使能。
    NFCONF |= (1 << 11)        (禁止NAND Flash)
(2)對於S3C2440。
    NFCONT &= ~(1 << 1)      (發出片選信號)
    NFCMD     = 0xff             (reset命令)
    然後循環查詢NFSTAT位0,知道它等於1。
    最後禁止片選信號,在實際使用NAND Flash時再使能。
    NFCONT |= 0x2                (禁止NAND Flash)
3.發出讀命令
    先使能NAND Flash,然後發出讀命令。
(1)對於S3C2410。
    NFCONF &= ~(1 << 11)    (發出片選信號)
    NFCMD     = 0                (讀命令)
(2)對於S3C2440。
    NFCONT &= ~(1 << 1)       (發出片選信號)
    NFCMD     = 0                  (讀命令)
4.發出地址信號
    這步請注意,表8.3列出了在地址操作的4個步驟對應的地址線,沒有用到A8(它由讀命令
設置,當讀命令位0時,A8 = 0;當爲1時,A8 = 1),如下所示:
1
NFADDR = addr & 0xff
2
NFADDR = (addr >> 9) & 0xff    (左移9位,不是8位)
3
NFADDR = (addr >> 17) & 0xff    (左移17位,不是16位)
4
NFADDR = (addr >> 25) & 0xff    (左移25位,不是24位) 
5.循環查詢NFSTAT位0,直到它等於1,這時可以讀取數據了
6.連續讀NFDATA寄存器512次,得到一頁數據(512字節)
    循環執行第3、4、5、6這4個步驟,直到讀出所要求的所有數據。
7.最後,禁止NAND Flash的片選信號
(1)對於S3C2410。
    NFCONF |= (1 << 11) 
(2)對於S3C2440。
    NFCONT |= (1 << 1)

8.2.2 代碼詳解

    實驗代碼在/work/hardware/nand目錄下,源文件爲head.S、init.c和main.c。本實例的目的
是把一部分代碼存放在NAND Flash地址4096之後,當程序啓動後通過NAND Flash控制器將
它們讀出來、執行。以前的代碼都小於4096字節,開發板啓動後它們被自動複製進
“Steppingstone”中。
    連接腳本nand.lds把它們分爲兩部分,nand.lds代碼如下:
1
SECTIONS{
2
    first    0x00000000:{head.o init.o nand.o}
3
    second   0x30000000:AT(4096){main.o}
4
}
    第2行表示head.o、init.o、nand.o這3個文件的運行地址爲0,它們在生成的映像文件中
的偏移地址也爲0(從0開始存放)。
    第3行表示main.o的運行地址爲0x30000000,它在生成的映像文件中的偏移地址爲4096。
    head.S調用init.c中的函數來關看門狗、初始化SDRAM;
        調用nand.c中的函數來初始化NAND Flash,
        然後將main.c中的代碼從NAND Flash地址4096開始複製到SDRAM中;
        最後跳到main.c中的main函數繼續執行。
    由於S3C2410、S3C2440的NAND Flash控制器並非完全一樣,這個程序要能分辨出是
S3C2410還是S3C2440,然後使用不同的函數進行處理。
    讀取GSTATUS1寄存器,如果它的值爲0x3241 0000或0x3241 0002,就表示處理器是
S3C2410,否則是S3C2440。
    nand.c向外引出兩個函數:初始化NAND Flash的nand_init函數、將數據從NAND Flash
讀到SDRAM的nand_read函數。
1.nand_init函數分析
代碼如下:
1
/*初始化NAND Flash*/
2
void nand_init(void)
3
{
4
    #define TACLS     0
5
    #define TWRPH0    3
6
    #define TWRPH1    0
7
    
8
    /*判斷S3C2410還是S3C2440*/
9
    if((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
10
    {
11
        nand_chip.nand_reset          = s3c2410_nand_reset;
12
        nand_chip.wait_idle           = s3c2410_wait_idle;
13
        nand_chip.nand_select_chip    = s3c2410_nand_select_chip;
14
        nand_chip.nand_deselect_chip  = s3c2410_nand_deselect_chip;
15
        nand_chip.write_cmd           = s3c2410_write_cmd;
16
        nand_chip.read_data           = s3c2410_read_data;
17
        
18
        /*使能NAND Flash控制器,初始化ECC,禁止片選,設置時序*/
19
        s3c2410nand->NFCONF = (1 << 15) | (1 << 12) | (1 << 11) | (TACLS << 8) | (TWRPH0 << 4) | (TWRPH1);
20
    }
21
    else
22
    {
23
        nand_chip.nand_reset          = s3c2440_nand_reset;
24
        nand_chip.wait_idle           = s3c2440_wait_idle;
25
        nand_chip.nand_select_chip    = s3c2440_nand_select_chip;
26
        nand_chip.nand_deselect_chip  = s3c2440_nand_deselect_chip;
27
        nand_chip.write_cmd           = s3c2440_write_cmd;
28
        nand_chip.read_data           = s3c2440_read_data;
29
        
30
        /*設置時序*/
31
        s3c2440nand->NFCONF = (TACLS << 12) | (TWRPH0 << 8) | (TWRPH1 << 4);
32
        /*使能NAND Flash控制器,初始化ECC,禁止片選*/
33
        s3c2440nand->NFCONF = (1 << 4) | (1 << 1) | (1 << 0);
34
    }
35
    
36
    /*復位NAND Flash*/
37
    nand_reset();
38
}
2.nand_read函數分析
    它的原型如下,表示從NAND Flash位置start addr開始,將數據複製到SDRAM地址
buf處,共複製size字節。
1
void nand_read(unsigned char *buf, unsigned long start_addr, int size)
代碼如下:
1
void nand_read(unsigned char *buf, unsigned long start_addr, int size)
2
{
3
    int i, j;
4
    
5
    if((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)){
6
        return;    /*地址或長度不對齊*/
7
    }
8
    
9
    /*選中芯片*/
10
    nand_select_chip();
11
    
12
    for(i = start_addr; i < (start_addr + size) ; ){
13
        /*發出READ0命令*/
14
        write_cmd(0);
15
        
16
        /*Write Address*/
17
        write_addr(i);
18
        wait_idle();
19
        
20
        for(j = 0; j < NAND_SECTOR_SIZE; j++, i++){
21
            *buf = read_data();
22
            buf++;
23
        }
24
    }
25
    
26
    /*取消片選信號*/
27
    nand_deselect_chip();
28
    
29
    return;
30
}
    可以看到,讀取NAND Flash的操作分爲6步:
    ① 選擇芯片;
    ② 發出讀命令;
    ③ 發出地址;
    ④ 等待數據就緒;
    ⑤ 讀取數據;
    ⑥ 結束後,取消片選信號。
    流程圖如圖8.14所示。

     爲了更形象地瞭解程序執行時代碼複製、程序執行位置,請參考圖8.15。



附:代碼:
鏈接: https://pan.baidu.com/s/1kV24a9L 密碼: tfab

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章