1. 程式人生 > >NandFlash操作詳解(二)

NandFlash操作詳解(二)

NandFlash讀操作:

         NandFlash的讀取分為頁讀和隨機讀。頁讀每次讀取一個page,從page的第一個資料開始讀。其實也就是列號(偏移地址)為0,只提供頁地址。

隨機讀能讀取到一個page裡面的某個儲存單元,但是需要提供行地址和列地址。

         頁讀和隨機讀的區別只是在於是否提供列號(偏移地址)。

開啟NandFlash的晶片手冊,找到讀時序圖


根據時序圖可以看出,NandFlash的讀取先要傳送00h的命令,然後傳送地址(兩個週期的列地址,三個週期的行地址),傳送30h命令,傳送完0x30後,R/B訊號會呈現忙的狀態,就是說開始處理之前請求的這些命令去了。所以在R/B訊號為低時要等待R/B出現高電平。

然後就可以讀取資料了。在以上這些步驟之前呢,還需要先選擇片選和對R/B訊號做清除,然後在最後讀取完資料後還要取消選擇NandFlash晶片。

在2440手冊中可以看到這個暫存器,它便是控制片選的:


接著是清除R/B訊號,當RnB訊號也就是R/B訊號從低跳變成高的時候,我們就認為前面的指令正確執行可以獲取資料了,而當RnB從低跳變到高時,下面這個暫存器中的[2]位會自動置位,而我們的清除工作也是對這一位操作:需要注意這個暫存器是8位的,所以定義地址時要寫成char*


然後向下面這個暫存器中寫入命令:這也是一個8位暫存器


向下面這個暫存器中傳送地址(8位暫存器):



可以在時序圖中清晰的看到需要傳送兩次列地址,如果是頁讀的訪問方式,列地址便無效了,列地址直接寫0x00。隨機訪問方式的話需要寫入兩次列地址資訊。傳送地址資訊比較容易暈頭,舉例說明:

寫入5次地址,前兩次為列地址(頁內偏移),後三次為行地址(相當於頁號)。

如寫入十進位制地址8000,則需要寫入的頁號為:8000/2048(每頁大小)=3.9頁,所以寫入第3頁,在第三頁業內偏移為:8000-3*2048=1856。

程式表示為:

void nand_addr(unsigned char addr)

{

        NFADDR = addr;

}

void nand_send_addr(unsigned int addr)

{

unsigned int page   = addr / 2048;

    unsigned int colunm = addr & (2048 - 1);//這一句和colunm =addr%2048等效

    /* 這兩個地址表示從頁內哪裡開始 */

    nand_addr(colunm & 0xff);

    nand_addr((colunm >> 8) & 0xff);

      /* 下面三個地址表示哪一頁 */

    nand_addr(page & 0xff);

    nand_addr((page >> 8) & 0xff);

            nand_addr((page >> 16) & 0xff);

}

或者:

不要以為跟著手冊的寫入順序應該這樣寫:

                  nand_addr(addr & 0xff);         /* a0~a7 */

                 nand_addr((addr >> 8) & 0x1f);    /* 程式的角度: a8~a11*/

                 nand_addr((addr >> 12) & 0xff);   /* 程式的角度:a12~a19 */

                 nand_addr((addr >> 20) & 0xff);   /* 程式的角度:a20~a27*/

                 nand_addr((addr >> 28) & 0xff);   /* 程式的角度:a28 */

其實應該這樣寫:

        nand_addr(addr & 0xff);             /* a0~a7 */

        nand_addr((addr >> 8) & 0x7);        /* 程式的角度: a8~a11 */

a0-a7共8位加上a8-a10三位總共11位,2的11次方就是一頁2048的大小!如果1頁為4096位元組,傳送的兩次列地址可能就是a0-a7,a8-a11了(沒使用過每page4096位元組的NandFlash)。

        nand_addr((addr >> 11) & 0xff);       /* 程式的角度:a12~a19 */

        nand_addr((addr >> 19) & 0xff);       /* 程式的角度:a20~a27 */

        nand_addr((addr >> 27) & 0xff);       /* 程式的角度: a28    */

從時序圖中也可以看出,傳送了0x30命令後便需要去等待RnB訊號由低向高的跳變。而檢測的暫存器也是前面做清除的那個暫存器NFSTAT,也是第[2]位。

等待完成後便可以從NFDATA暫存器中讀取到資料了。NFDATA也是一個8位暫存器。


如果想要連續讀取某個地址後連續的n個位元組,只需要反覆讀取NFDATA暫存器即可。

連續讀取1000個位元組:

         for(i=0;i<1000;i++)                                                                                                                                                                                                                                              

         {

            buff[i] = NFDATA;     

         }

取得資料後,取消片選,整個讀取功能便實現了

總結一下NandFlash的讀操作步驟:

1、  選中nandflash晶片

2、  清除RnB

3、  傳送命令0x00

4、  傳送列地址

5、  傳送行地址

6、  傳送命令0x30

7、  等待RnB

8、  讀取資料

9、  取消選中nandflash晶片

程式碼實現(讀取一頁):

void NF_PageRead(unsigned long addr,unsigned char* buff)

{

         int i;

         int col = addr % 2048;                                                                                                                                                                                                                                          

int page = addr / 2048;

         //選中nandflash晶片

         select_chip();

         //清除RnB

         clear_RnB();

         //傳送命令0x00

         send_cmd(0x00);

         send_addr(col & 0xff);

         send_addr((col >> 8) & 0xff);

         send_addr(page & 0xff);

         send_addr((page >> 8) & 0xff);

         send_addr((page >> 16) & 0xff);

         //傳送命令0x30

         send_cmd(0x30);

         //等待RnB

         wait_RnB();

         //讀取資料

         for(i=0;i<2048;i++)

         {

            buff[i] = NFDATA;    

         }

         //取消選中nandflash晶片

         deselect_chip();

}

NandFlash寫操作:

         NandFlash的寫操作之前需要先對NandFlash進行擦除工作,於是手冊中找到擦除時序:


可以在NandFlash手冊的Features中看到,NandFlash的擦除是按照頁所在的塊一整塊來擦除的。根據時序可以得到擦除的步驟為:

1、  選中flash晶片

2、  清除RnB

3、  傳送命令0x60

4、  傳送行地址

5、  傳送命令D0

6、  等待RnB

7、  傳送命令0x70

8、  讀取擦除結果

9、  取消選中flash晶片

程式碼實現:

int NF_Erase(unsigned long addr)                                                                                                                                                                                                                           

{

         int ret;

         unsigned int page = addr/2048;

  //選中flash晶片

         select_chip();

         //清除RnB

         clear_RnB();

         //傳送命令0x60

         send_cmd(0x60);

         //傳送行地址

         send_addr(page&0xff);

         send_addr((page>>8)&0xff);

         send_addr((page>>16)&0xff);

         //傳送命令D0

         send_cmd(0xD0);

         //等待RnB

         wait_RnB();

         //傳送命令0x70

         send_cmd(0x70);

         //讀取擦除結果

         ret = NFDATA;

         //取消選中flash晶片

         deselect_chip();

         return ret;

}

擦除後就可以執行寫操作,寫入的時序為:


根據時序圖,我們可以得到寫入資料的流程:

1、  選中Flash晶片(NandFlash晶片操作都需要先片選)

2、  清除RnB(既然要檢視RnB的跳變自然要先清除)

3、  傳送命令0x80

4、  傳送2個列地址

5、  傳送3個行地址

6、  傳送資料(往資料暫存器中寫),跟讀操作一樣,需要連續寫的話直接重複往NFDATA寫入就行,不需要其他操作。

7、  傳送命令0x10

8、  等待RnB

9、  傳送命令0x70

10、             讀取寫入結果(在資料暫存器中讀,沒錯,傳送資料也是往資料暫存器中寫的)

11、             關閉片選(NandFlash操作都需要先選擇Flash在關閉Flash)

程式碼實現:

int NF_WritePage(unsigned long addr,unsigned char *buff)                                                                                                                                                                              

{

         unsigned int i,ret = 0,page,col;

         col = addr % 2048;

         page = addr /2048;

         //選中nandflash

         select_chip();

         //清除RnB

         clear_RnB();

         //傳送0x80命令

         send_cmd(0x80);

         //傳送2個列地址

         /* 這種寫法ok

         send_addr(col & 0xff);

         send_addr((col >> 8) & 0xff);

         send_addr(page & 0xff);

         send_addr((page >> 8) & 0xff);

         send_addr((page >> 16) & 0xff);

         */

         send_addr(addr & 0xff);         // a0~a7

         send_addr((addr >> 8) & 0x7);   // 以程式角度看 a8~a10

         send_addr((addr >> 11) & 0xff); // 以程式角度看 a12~a19

         send_addr((addr >> 19) & 0xff); // 以程式角度看 a20~a27

         send_addr((addr >> 27) & 0xff); // 以程式角度看 a28   

/*     This’s wrong 移位錯誤

         send_addr(addr & 0xff);         // a0~a7

         send_addr((addr >> 8) & 0x7);   // 以程式角度看 a8~a10

         send_addr((addr >> 12) & 0xff); // 以程式角度看 a12~a19

         send_addr((addr >> 20) & 0xff); // 以程式角度看 a20~a27

         send_addr((addr >> 28) & 0xff); // 以程式角度看 a28   

*/

         //傳送資料

         for(i=0;i<2048;i++)

         {

            NFDATA = buff[i];    

         }

         //傳送0x10命令

         send_cmd(0x10);

         //等待RnB

         wait_RnB();

         //傳送0x70命令

         send_cmd(0x70);

         //讀取寫入結果

         ret = NFDATA;

         //關閉nandflash

         deselect_chip();

          return ret;

  }

當然還可以對NandFlash進行讀取ID的操作,這個工作根據時序圖仿造讀寫操作就可以實現了,在裸機中用得比較少我就不寫了。


下一節NandFlash操作詳解(三)

相關推薦

NandFlash操作

NandFlash讀操作:          NandFlash的讀取分為頁讀和隨機讀。頁讀每次讀取一個page,從page的第一個資料開始讀。其實也就是列號(偏移地址)為0,只提供頁地址。 隨機讀能讀取到一個page裡面的某個儲存單元,但是需要提供行地址和列地址。    

C# 檔案操作FileInfo類

本篇讓我們一起看一下FileInfo類如何使用。     FileInfo類  提供了與File類相同的功能,不同的是FileInfo提供的都是成員方法   1、讀檔案 1 2 3 4 //摘要:建立只讀 System.IO.FileStrea

NandFlash操作

NandFlash的分類:          根據物理結構上的區別,NandFlash主要分為以下兩種:                    SLC(SingleLevel Cell):單層式儲存                    MLC(MultiLevel Cel

Nginx操作

ive nal set gen local pcr 大小寫 cpu 目錄結構 一、前言二、Nginx安裝三、Nginx的配置文件詳解四、nginx配置之http段五、其他模塊六、實驗一、前言http://www.nginx.cn/doc/ nginx安裝等各個操作界面介紹

adb命令——手機缺失sqlite3時操作資料庫的多種解決方案

在android應用開發無處不在SQLite資料庫的身影。那麼在開發中怎麼使用adb命令操作資料庫的功能呢?下面我們將完整的介紹與資料庫操作相關的命令集及當手機缺少sqlite3的時候的多種解決方案。1.當手機缺失sqlite3時,如何操作資料庫先來看看手機缺失sqlite3

java.util包——Connection接口

操作 相同 元素 叠代 cat roo soft true nbsp Connection接口介紹   Connection接口是java集合的root接口,沒有實現類,只有子接口和實現子接口的各種容器。主要用來表示java集合這一大的抽象概念。   Connection接

C++ 模板

創建 規則 error ++ 例如 public err iostream () 四、類模板的默認模板類型形參   1、可以為類模板的類型形參提供默認值,但不能為函數模板的類型形參提供默認值。函數模板和類模板都可以為模板的非類型形參提供默認值。   2、類模板的類型形

mybatis ------入門實例基於XML

ssi 開發模式 文件中 Coding import 拼接 upd baidu actor   通過上一小節,mybatis 和 jdbc 的區別:http://www.cnblogs.com/ysocean/p/7271600.html,我們對 mybatis有了一個大致

Spring------IOC控制反轉

tsp name 調試 的人 好的 turn 同時 eth 時機   我相信提到 Spring,很多人會脫口而出IOC(控制反轉)、DI(依賴註入)、AOP等等概念,這些概念也是面試官經常問到的知識點。那麽這篇博客我們就來詳細的講解 IOC控制反轉。   ps:本篇博客源

.Net AppDomain

onf urn attach msdn 允許 cut isolation cal pst AppDomain 類 表示應用程序域,它是一個應用程序在其中執行的獨立環境。 此類不能被繼承。 命名空間: System程序集: mscorlib(位於 mscorlib.

Ansible

latest load 遠程 即使 centos fine oct syn srv Ansible系列命令 Ansible系列命令有如下: ansible:這個命令是日常工作中使用率非常高的命令之一,主要用於臨時一次性操作; ansible-doc:是Ansible模塊文

Zookeeper:Zookeeper安裝

zookeeper安裝安裝環境:CentOS 7 內存1GBJDK版本:1.8.0_112為JDK配置如下環境變量:編輯/etc/profile.d/jdk.sh#!/bin/bash JAVA_HOME=/usr/local/jdk1.8.0_112 export PATH=$JAVA_HOME/bi

dns

dns 子域授權 主從架構 bind 轉發區域 bind view dns的另外一種實現方式:dnsmasq較為簡單請自行理解一.主從架構 二.子域授權 三.轉發區域 四.bind中的安全相關配置 五.bind view視圖一.主從架構從s擁有和主s一樣的解析庫 註意:從服務器是

Linux防火墻

iptables netfilter linux防火墻詳解 nat dnat 一、iptables命令基本語法 二、iptables語法進階 三、iptables顯示擴展 四、iptables簡單案例 五、iptables之forward 六、iptables之NAT一、iptables命

Redis

redis sentinal redis集群 redis主從 redis事務 一、redis認證二、redis事務三、Connection&server相關命令四、Redis的發布與訂閱//充當mq的功能五、Redis持久化六、redis復制七、master-slave實現八、se

05-Linux中DNS

相關 proc gen lin 四種方法 .... rate 我的網站 四種 接“04-Linux中DNS詳解(一)” 六、在Linux上測試域名解析1、先檢查DNS是否設置正確 cat /etc/resolv.conf [resolv.conf] # Generate

LAMP

cgi www perl gre tar.gz emd init.d .html product 編譯安裝LAMP一、安裝mariadb二、安裝httpd三、php編譯四、apache的代理指令五、其他LAMP結合的方式 c---httpd[modules]

RGB格式--索引格式

存儲 簡介 以及 關於 需要 色彩 顏色 針對 表現 本節針對RGB索引格式做簡單介紹,這些格式是比較老的格式,比較節省空間,在計算機發展的初期存儲的成本還是很高的,但是表現的色彩很有限,而隨著存儲成本的不斷降低,以及用戶越來越高的視覺體驗需求,這些格式也就基本被拋棄,不再

編碼原理---變換編碼

mar 關於 詳解 tex 描述 原理 學習 編碼原理 watermark 本篇介紹編碼原理中的變換編碼。 一、變換的目的和作用: 變換編碼的作用是將空間域描述的圖像信號變換到頻率域,然後對變換後的系數進行編碼處理。一般來說,圖像在空間上具有較強的相關性,變換到頻率

Android進階筆記:AIDL內部實現

ucc == 筆記 null stack 直接 android 最好 public 接著上一篇分析的aidl的流程解析。知道了aidl主要就是利用Ibinder來實現跨進程通信的。既然是通過對Binder各種方法的封裝,那也可以不使用aidl自己通過Binder來實現跨進