1. 程式人生 > >如何正確nandflash的塊地址和頁地址

如何正確nandflash的塊地址和頁地址

結論

  • 塊地址 從1開始,其範圍位於1~2048(以2Gb nandflash為例)
  • 頁地址 從0到63, 其範圍位於0~63(以2Gb nandflash為例)

背景

對於初次接觸nandflash的新手而言,不管是做裸機的驅動還是複雜的Linux下的nand驅動,能看懂nandflash的資料手冊中給出的時序圖,已經是不錯的,但要想正確的去實現功能,恐怕是還是有一道攔路虎的,當然,弄懂了,就一紙老虎,這老虎就是我們要說的 nandflash操作中的塊地址跟頁地址的正確設定。

塊地址

nandflash中有塊和頁的概念,常見的表述如,

nandflash的大小=塊總數x每塊的頁總數x每頁的大小

這裡的塊大小和頁大小,均會在相應的資料手冊中查到,那麼,我們關係的擦除、讀寫

這幾個重要的操作而言,其中的塊地址該如何計算而來?

比如說,我們常在控制檯上用nand erase addr size,而這個命令通常是直接傳入addr,我們怎麼從addr中解析出塊地址呢?下面給出一份正確的實現程式碼

int addr = 0x0ffc0000 ; 
int block_addr = 0;
int page_size = 2048;
int page_count_per_block= 64;

block_addr = addr/(page_size*page_count_per_block) ;    //小問號認為按照這句命令的理解:塊地址就是塊數,                                                        //求得塊的數量就是塊的地址,這個數量是一個塊的總數量,
//塊總數量等於塊的最大數,並且把最大塊數定為塊地址, //這與我們平常理解的定義地址一般是最小數(值)有些不 //同,這一點要注意這一點。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

有的時候,我們看網上有的人說,nandflash的塊地址等於頁地址,其實這句話說的是有前提條件的,那就是第0塊第0頁的時候滿足這個說法,其他的一概不滿足

頁地址

還是用上面的nand erase addr size,而這個命令通常是直接傳入addr,我們怎麼從addr中解析出頁地址呢?下面給出一份正確的實現程式碼

int addr = 0x0ffc0000 ; 
int block_addr = 0;
int page_size = 2048;
int page_addr = 0;

page_addr = addr/page_size; //小問號同樣認為,此語句可以理解為頁地址就是在給定Nand的某個地址後,求得頁的數量就是
                            //頁的地址,這個數量是一個頁的總數量,總數量等於頁的最大數,並且把最大頁數定為頁地址,                            //這與我們平常理解的定義地址一般是最小數(值)有些不同,要注意這一點。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

有的時候,我們看網上有的人說,nandflash的塊地址等於頁地址,其實這句話說的是有前提條件的,那就是第0塊第0頁的時候滿足這個說法,其他的一概不滿足

實現nandflash的擦除

給出的已知條件為要擦除的地址,以及大小,要去實現擦除的虛擬碼 
- 頁大小page_size 
- 每塊的頁總數page_count_per_block

int nand_erase_one_block(int addr, int size)
{
    int page_addr = 0;

    page_addr = addr/(page_size);

    虛擬碼:
    reset_nand();
    write_erase_cmd();
    write_addr(page_addr&0xff);
    write_addr(page_addr>>8&0xff);
    write_addr(page_addr>>16&0xff); 
    write_erase_cmd();

    wait_dev_ready();
    check_nand_erase_stat();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

有人或許會很好奇,你這寫法為什麼跟我在資料手冊上看到的不一樣,資料手冊明明跟這不一樣,而且你這種寫法如何對得上資料手冊中的地址週期值呢?我們不妨先解決這個疑問,用資料手冊上的地址週期寫法來實現一組程式碼,我們就按照下面的5個地址週期的資料手冊寫法來實現一組: 
5個地址週期圖

因為我們都知道,在擦除程式時,只需要寫三個行地址(為啥?因為資料手冊的擦除時序圖要求的,不會的看下面這張圖) 
nand erase時序圖

int nand_erase_one_block(int addr, int size)
{
    int block_addr = 0;

    block_addr = addr/(page_size*page_count_per_block);

    虛擬碼:
    reset_nand();
    write_erase_cmd();
    write_addr((block_addr << 6) & 0xff);//按照5個地址週期值,我們來填充資料
    write_addr((block_addr >> 2) & 0xff);
    write_addr((block_addr >> 10) & 0x01); 
    write_erase_cmd();

    wait_dev_ready();
    check_nand_erase_stat();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

以上這兩種實現方法其實大同小異,第一種方法是用page_addr來實現的,而第二種方法是用block_addr的方法實現的,這兩種方法實現其實是一模一樣的,並沒有什麼差別。(小問號認為這裡為何出現了頁擦除和塊擦除兩種方法?,老師不是講擦除只能是塊擦除嗎?)