1. 程式人生 > >學習uboot前奏之hardware-nand flash[s3c2440]

學習uboot前奏之hardware-nand flash[s3c2440]

好久沒有更新博文了,最近確實懶惰了,哎,不說了。開始今天的學習吧,今天讓我們來學習下嵌入式開發中不可缺少的模組-NAND FLASH。

FLASH主要分為兩類: NAND FLASH 和NOR FLASH

兩者的主要區別和適用場合如下

引數 NAND NOR
容量 1-32MB NAND:16-512MB 甚至更大
XIP 不可以 可以直接在其上執行程式碼
介面 IO介面 RAM介面
訪問方法 順序訪問 隨機訪問
可靠性 比較低,位反轉比較常見 比較高
可擦寫次數 10000-100000 100000-1000000
主要用途 儲存資料和程式碼 儲存程式碼

總結下的話就是NOR FLASH可以支援XIP,可靠性高,但是讀寫速度相對於NAND FLASH來說慢一些
NAND 不支援XIP,但是它的價效比比較高,但是也有一個比較嚴重的問題就是發生位翻轉的概率比較大,因此NAND FLASH 在使用的時候都配備軟體的ECC或者硬體的ECC。

在本人接觸的有限的產品中,NAND FLASH用的比較多,功能類似PC的硬體,本文以三星公司生產的K9F1208U0M為例進行介紹NAND FLASH

K9F1208U0M的主要引腳如下:
這裡寫圖片描述

對於NAND FLASH訪問的命令、地址、資料都是通過I/O輸入/輸出,這種形式減少了
晶片的引腳個數,並使得系統很容易升級到更大的容量。

寫入命令、地址或者資料時,都需要將WE#、CE#、訊號同時拉低。資料在WE#訊號的
上升沿被NAND FLASH鎖存;命令鎖存訊號CLE、地址鎖存訊號ALE用來分辨、鎖存命令命令或者地址

地址序列
這裡寫圖片描述

K9F1208U0M一頁大小為528位元組,而列地址A0~A7可以定址的範圍是256位元組,所以必須輔以其他手段才能完全定址這528位元組。將一頁分為A、B、C、三個區;A區為0~255位元組,B區為256~511位元組,C區為512~527位元組。訪問某頁,需要選定特定的區,這成為“使地址指標指向特定的區”。通過三個命令實現:命令00h讓地址指標指向A區、命令01h讓地址指標指向B區、命令50h讓地址指標指向C區。命令00h和50h會使得訪問FLASH的地址指標一直從A區或C區開始,除非發出了其他的修改地址的命令。命令01h的效果只能維持一次,當前的讀、寫、擦除、復位或者上電操作完成後,地址指標重新指向A區。寫A區或C區的資料時,必須在發出命令80h之前發出00h或者50h;寫B區的資料,發出命令01h後必須緊接就發出命令80h

下面講下NAND FLASH的讀寫操作次序:

  1. 設定NFCONF(對於S3C2440還要設定NFCONT)暫存器,配置NAND Flash
  2. 向NFCMD暫存器寫入命令,命令字參考具體的FLASH手冊
  3. 向NFADDR暫存器寫入地址
  4. 讀/寫資料:通過暫存器NFSTAT檢測NAND Flash的狀態,在啟動某個操作後,應該檢測R/nB訊號以確定該操作是否完成、成功

舉個讀操作的例子:

  1. 設定NFCONF,NFCONT
    NFCONF=0x300(TACLS=0,TWRPH0=3,TWRPH1=0)
 設定NFCONT暫存器如下,表示使能NAND FlASH控制器、禁止控制引腳訊號nFCE、初始化ECC
    NFCONT = (1<<4)|(1<<1)|(1<<0)

2.在第一次操作NAND Flash前,通常復位一下NAND flash

    NFCONT &= ~(1<<1) (發出片選訊號)
    NFCMD = 0xff      (reset訊號)

然後迴圈查詢NFSTAT位0,直到它等於1。
最後禁止片選訊號,在實際使用NAND Flash時再使能

    NFCONT |= 0X2

3.發出讀命令
先使能NAND Flash,然後發出讀命令

    NFCONT &= ~(1<<1)(發出片選訊號)
    NFCMD   = 0 (讀命令)

4 發出地址訊號
在上面的表中列舉出了地址的操作步驟和對應的以及對應的地址線,地址線A8不需要直接設定由A8設定,當讀命令為0時,A8=0;當讀命令為1時,A8=0,具體地址設定如下。

    NFADDR =  addr & 0xff
    NFADDR = (addr>>9)&0xff
    NFADDR =  (addr>>17)&0xff
    NFADDR =  (addr>>25)&0xff

5 迴圈查詢NFSTAT位0,直到它等於1,這時就能讀取資料了
6 連續讀NFDATA既存器512次,得到一頁資料
7 最後,禁止 NAND Flash的片選訊號

下面以實際程式碼講解NAND Flash操作。nand實驗的原始檔為head.s、init.c和main.c。程式的功能是將點燈的程式放在NAND flash地址4096後,當程式啟動後通過NAND flash控制器將它們讀出來執行。
連線指令碼nand.lds把所有的源程式分為兩部分,nand.lds程式碼如下:

SECTIONS
{ 
  firtst    0x00000000 : { head.o init.o nand.o}
  second    0x30000000 : AT(4096) { main.o }
} 

其中連結指令碼的第二行表示head.o、init.o、nand、這3個檔案的執行地址為0,它們在生成的映像檔案中的偏移地址也為0(從0開始存放)

第3行表示main.o,它在生成的映像檔案中的偏移地址為4096

下面開始分析原始碼head.s

.text
.global _start
_start:

@函數disable_watch_dog, memsetup, init_nand, nand_read_ll在init.c中定義

            ldr     sp, =4096               @設置堆疊 
            bl      disable_watch_dog       @關WATCH DOG
            bl      memsetup                @初始化SDRAM
            bl      nand_init               @初始化NAND Flash

@將NAND Flash中地址4096開始的1024位元組程式碼(main.c編譯得到)複製到SDRAM中

                                        @nand_read_ll函式需要3個引數:
            ldr     r0,     =0x30000000 @1. 目標地址=0x30000000,這是SDRAM的起始地址
            mov     r1,     #4096       @2. 源地址=4096,連線的時候,main.c中的程式碼在NAND Flash地址4096處
            mov     r2,     #2048       @3. 複製長度= 2048(bytes)
            bl      nand_read           @調用C函式nand_read

            ldr     sp, =0x34000000     @設置棧
            ldr     lr, =halt_loop      @設置返回地址
            ldr     pc, =main           @b指令和bl指令只能前後跳轉32M的範圍,所以這裡使用向pc賦值的方法進行跳轉
halt_loop:
            b       halt_loop

head.S中呼叫init.c中的函式來管WATCH DOG、初始化SDRAM;呼叫nand.c中函式來初始化NAND Flash,然後將main.c中的程式碼從NAND Flash地址4096開始處複製到SDRAM中,最後跳到main.c中的main函式繼續執行。

下面再仔細分析nand_read函式

/* 讀函式 */
void nand_read(unsigned char *buf, unsigned long start_addr, int size)
{
    int i, j;

    if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
        return ;    /* 地址或長度不對齊 */
    }

    /* 選中晶片 */
    nand_select_chip();

    for(i=start_addr; i < (start_addr + size);) 
    {
      /* 發出READ0命令 */
      write_cmd(0);

      /* Write Address */
      write_addr(i);

      wait_idle();


      for(j=0; j < NAND_SECTOR_SIZE; j++, i++) 
      {

          *buf = read_data();
          buf++;
      }
    }

    /* 取消片選訊號 */
    nand_deselect_chip();

    return ;
}

函式功能為從NAND flash中將起始地址為start_addr開始的size大小的資料拷貝到buf對應的地址處。從上面的程式可以看出讀Flash資料的過程如下:

  1. 選擇晶片
  2. 發出讀命令
  3. 發出地址
  4. 等待資料就緒
  5. 讀取資料
  6. 結束後,取消片選訊號

好的,本節到此為止了