如何正確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個地址週期的資料手冊寫法來實現一組:
因為我們都知道,在擦除程式時,只需要寫三個行地址(為啥?因為資料手冊的擦除時序圖要求的,不會的看下面這張圖)
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的方法實現的,這兩種方法實現其實是一模一樣的,並沒有什麼差別。(小問號認為這裡為何出現了頁擦除和塊擦除兩種方法?,老師不是講擦除只能是塊擦除嗎?)