TQ210 —— NandFlash
生活随笔
收集整理的這篇文章主要介紹了
TQ210 —— NandFlash
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
TQ210 —— nandflash
? ? TQ210 開發板板載一片 1Gbyte 的 NAND FLASH——K9K8G08U0B,通過查詢K9K8G08U0B 芯片手冊可以得到如下信息:(理論知識不再介紹)
K9K8G08U0B : (1G + 32M) x 8bit 總大小
Data Register : (2K + 64) x 8bit 數據寄存器
Page Program : (2K + 64)Byte 頁編程
Block Erase : (128K + 4K)Byte 塊擦除
Page Read: (2K + 64)Byte 頁讀
?
我們需要按上面這個地址周期表來發地址。
對NFDATA 寄存器的定義(參考 S5PV210 芯片手冊 4.3.1.1 8-bit NAND Flash Memory Interface) ??
?#define NFDATA (*(volatile unsigned char *)0xB0E00010)
NFCONF 寄存器中 3 個時間參數稍微比計算的值大些(大 1 就可以),否則會出現讀寫不穩定
下面幾種操作流程中對于發送地址的周期數:有的是 5 個周期,有的是 3 個周期,有的是 1 個周期。
1、 擦除流程
(1)片選
(2)發命令 0x60
(3)發頁地址(塊對齊,3 個周期)
(4)發命令 0xD0
(5)等待 NAND 空閑
(6)取消片選
2、 寫數據
(1)片選
(2)發命令 0x80
(3)發地址(頁對齊, 5 個周期)
(4)連續發送一頁數據
(5)發命令 0x10
(6)等待 NAND 空閑
(7)取消片選
3、 讀數據
1) 片選
2) 發命令 0x00
3) 發地址(頁對齊, 5 個周期)
4) 發命令 0x30
5) 等待 NAND 空閑
6) 連續讀一頁數據
7) 取消片選
4、 讀ID
1) 片選
2) 發命令 0x90
3) 發 0 地址( 1 個周期)
4) 連續讀 5 個字節的 ID
5) 取消片選
#include "types.h"#define NFCONF (*(volatile u32 *)0xB0E00000) #define NFCONT (*(volatile u32 *)0xB0E00004) #define NFCMMD (*(volatile u32 *)0xB0E00008) #define NFADDR (*(volatile u32 *)0xB0E0000C) #define NFDATA (*(volatile u8 *)0xB0E00010) #define NFSTAT (*(volatile u32 *)0xB0E00028)#define MP0_1CON (*(volatile u32 *)0xE02002E0) #define MP0_3CON (*(volatile u32 *)0xE0200320) #define MP0_6CON (*(volatile u32 *)0xE0200380)#define PAGE_SIZE 2048 #define BLOCK_SIZE (PAGE_SIZE * 64)/* 等待NAND準備好 */ static void inline nand_wait_ready() {while(!(NFSTAT & (1 << 0))); }/* 片選 */ static void inline nand_select_chip() {NFCONT &= ~(1 << 1); }/* 取消片選 */ static void inline nand_deselect_chip() {NFCONT |= (1 << 1); }/* 發命令 */ static void inline nand_cmd(u32 cmd) {NFCMMD = cmd; }/* 發地址(5個周期) */ static void nand_addr(u32 addr) {u32 col = addr % PAGE_SIZE; /* 頁內偏移 */u32 row = addr / PAGE_SIZE; /* 頁地址 */NFADDR = col & 0xFF;NFADDR = (col >> 8) & 0x7;NFADDR = row & 0xFF;NFADDR = (row >> 8) & 0xFF;NFADDR = (row >> 16) & 0x07; }/* 讀1byte數據 */ static u8 inline nand_read() {return NFDATA; }/* 寫1byte數據 */ static void inline nand_write(u8 data) {NFDATA = data; }/* 復位NAND */ static void nand_reset() {nand_select_chip();nand_cmd(0xFF);nand_wait_ready();nand_deselect_chip(); }/* NAND初始化 */ void nand_init() {/* HCLK_PSYS=133MHz(7.5ns) */NFCONF = (0x1 << 23) | /* Disable 1-bit and 4-bit ECC *//* 下面3個時間參數稍微比計算出的值大些(我這里依次加1),否則讀寫不穩定 */(0x3 << 12) | /* 7.5ns * 2 > 12ns tALS tCLS */(0x2 << 8) | /* (1+1) * 7.5ns > 12ns (tWP) */(0x1 << 4) | /* (0+1) * 7.5 > 5ns (tCLH/tALH) */(0x0 << 3) | /* SLC NAND Flash */(0x0 << 2) | /* 2KBytes/Page */(0x1 << 1); /* 5 address cycle *//* ** The setting all nCE[3:0] zero can not be allowed. Only ** one nCE can be asserted to enable external NAND flash ** memory. The lower bit has more priority when user set all ** nCE[3:0] zeros. */NFCONT = (0x1 << 1) | /* Disable chip select */(0x1 << 0); /* Enable NAND Flash Controller *//*** Port Map** CE1->Xm0CSn2-> MP01_2** CE2->Xm0CSn3-> MP01_3** CE3->Xm0CSn4-> MP01_4** CE4->Xm0CSn5-> MP01_5** CLE->Xm0FCLE-> MP03_0** ALE->Xm0FALE-> MP03_1** WE->Xm0FWEn-> MP03_2** RE->Xm0FREn-> MP03_3** RB1->Xm0FRnB0->MP03_4** RB2->Xm0FRnB1->MP03_5** RB3->Xm0FRnB2->MP03_6** RB4->Xm0FRnB3->MP03_7** IO[7:0]->Xm0DATA[7:0]->MP0_6[7:0]*/MP0_1CON &= ~(0xFFFF << 8);MP0_1CON |= (0x3333 << 8);MP0_3CON = 0x22222222;MP0_6CON = 0x22222222;nand_reset(); }/* 讀NAND ID */ void nand_read_id(u8 id[]) {int i;nand_select_chip();nand_cmd(0x90);NFADDR = 0x00;for (i = 0; i < 5; i++)id[i] = nand_read();nand_deselect_chip(); }/* 擦除一個塊 */ void nand_erase(u32 addr) { if (addr & (BLOCK_SIZE - 1)){printf("not block align\n");return;}u32 row = addr / PAGE_SIZE;nand_select_chip();nand_cmd(0x60);NFADDR = row & 0xff; NFADDR = (row >> 8) & 0xff;NFADDR = (row >> 16) & 0x07;nand_cmd(0xD0);nand_wait_ready();nand_deselect_chip(); }/* 讀一頁數據 */ void nand_read_page(u8 *buf, u32 addr) {if (addr & (PAGE_SIZE - 1)){printf("not page align\n");return;}int i;nand_select_chip();nand_cmd(0);nand_addr(addr);nand_cmd(0x30);nand_wait_ready();for(i = 0; i < PAGE_SIZE; i++){*buf++ = nand_read();}nand_deselect_chip(); }/* 隨機讀:從任意地址讀任意字節的數據 */ void nand_read_random(u8 *buf, u32 addr, u32 size) { nand_select_chip();nand_cmd(0);nand_addr(addr);nand_cmd(0x30);nand_wait_ready();int i;u32 col = addr % PAGE_SIZE; /* 頁內偏移 */for(i = col; i < size + col; i++){nand_cmd(0x05);NFADDR = i & 0xFF;NFADDR = (i >> 8) & 0x7;nand_cmd(0xE0);*buf++ = nand_read();}nand_deselect_chip(); }/* 寫一頁數據 */ void nand_write_page(u8 *buf, u32 addr) {if (addr & (PAGE_SIZE - 1)){printf("not page align\n");return;}int i;nand_select_chip();nand_cmd(0x80);nand_addr(addr);nand_wait_ready();for(i = 0; i < PAGE_SIZE; i++){nand_write(*buf++);}nand_cmd(0x10);nand_wait_ready();nand_deselect_chip(); } #include "types.h" #include "uart.h" // 這個文件前面UART串口博客有void bzero(u8 *s, int size) {int i = 0;for (; i < size; i++)s[i] = 0; }void main() { u8 buf[2048];int i;bzero(buf, 2048);nand_read_id(buf);printf("\nID:");for (i = 0; i < 5; i++){printf("%X ", buf[i]);}putchar('\n');nand_erase(0x80000); /* 擦除以0x80000地址開始的一個塊 */for (i = 0; i < 2048; i++)buf[i] = i % 255;nand_write_page(buf, 0x80000); /* 寫入1頁數據到0x80000地址 */bzero(buf, 2048);nand_read_page(buf, 0x80000); /* 從0x80000地址讀取一頁數據 *//* 打印讀取到的數據,與寫入的數據一致 */for (i = 0; i < 100; i++){if (i % 16 == 0)putchar('\n');printf("%X ", buf[i]);} }
? ? TQ210 開發板板載一片 1Gbyte 的 NAND FLASH——K9K8G08U0B,通過查詢K9K8G08U0B 芯片手冊可以得到如下信息:(理論知識不再介紹)
K9K8G08U0B : (1G + 32M) x 8bit 總大小
Data Register : (2K + 64) x 8bit 數據寄存器
Page Program : (2K + 64)Byte 頁編程
Block Erase : (128K + 4K)Byte 塊擦除
Page Read: (2K + 64)Byte 頁讀
?
我們需要按上面這個地址周期表來發地址。
對NFDATA 寄存器的定義(參考 S5PV210 芯片手冊 4.3.1.1 8-bit NAND Flash Memory Interface) ??
?#define NFDATA (*(volatile unsigned char *)0xB0E00010)
NFCONF 寄存器中 3 個時間參數稍微比計算的值大些(大 1 就可以),否則會出現讀寫不穩定
下面幾種操作流程中對于發送地址的周期數:有的是 5 個周期,有的是 3 個周期,有的是 1 個周期。
1、 擦除流程
(1)片選
(2)發命令 0x60
(3)發頁地址(塊對齊,3 個周期)
(4)發命令 0xD0
(5)等待 NAND 空閑
(6)取消片選
2、 寫數據
(1)片選
(2)發命令 0x80
(3)發地址(頁對齊, 5 個周期)
(4)連續發送一頁數據
(5)發命令 0x10
(6)等待 NAND 空閑
(7)取消片選
3、 讀數據
1) 片選
2) 發命令 0x00
3) 發地址(頁對齊, 5 個周期)
4) 發命令 0x30
5) 等待 NAND 空閑
6) 連續讀一頁數據
7) 取消片選
4、 讀ID
1) 片選
2) 發命令 0x90
3) 發 0 地址( 1 個周期)
4) 連續讀 5 個字節的 ID
5) 取消片選
#include "types.h"#define NFCONF (*(volatile u32 *)0xB0E00000) #define NFCONT (*(volatile u32 *)0xB0E00004) #define NFCMMD (*(volatile u32 *)0xB0E00008) #define NFADDR (*(volatile u32 *)0xB0E0000C) #define NFDATA (*(volatile u8 *)0xB0E00010) #define NFSTAT (*(volatile u32 *)0xB0E00028)#define MP0_1CON (*(volatile u32 *)0xE02002E0) #define MP0_3CON (*(volatile u32 *)0xE0200320) #define MP0_6CON (*(volatile u32 *)0xE0200380)#define PAGE_SIZE 2048 #define BLOCK_SIZE (PAGE_SIZE * 64)/* 等待NAND準備好 */ static void inline nand_wait_ready() {while(!(NFSTAT & (1 << 0))); }/* 片選 */ static void inline nand_select_chip() {NFCONT &= ~(1 << 1); }/* 取消片選 */ static void inline nand_deselect_chip() {NFCONT |= (1 << 1); }/* 發命令 */ static void inline nand_cmd(u32 cmd) {NFCMMD = cmd; }/* 發地址(5個周期) */ static void nand_addr(u32 addr) {u32 col = addr % PAGE_SIZE; /* 頁內偏移 */u32 row = addr / PAGE_SIZE; /* 頁地址 */NFADDR = col & 0xFF;NFADDR = (col >> 8) & 0x7;NFADDR = row & 0xFF;NFADDR = (row >> 8) & 0xFF;NFADDR = (row >> 16) & 0x07; }/* 讀1byte數據 */ static u8 inline nand_read() {return NFDATA; }/* 寫1byte數據 */ static void inline nand_write(u8 data) {NFDATA = data; }/* 復位NAND */ static void nand_reset() {nand_select_chip();nand_cmd(0xFF);nand_wait_ready();nand_deselect_chip(); }/* NAND初始化 */ void nand_init() {/* HCLK_PSYS=133MHz(7.5ns) */NFCONF = (0x1 << 23) | /* Disable 1-bit and 4-bit ECC *//* 下面3個時間參數稍微比計算出的值大些(我這里依次加1),否則讀寫不穩定 */(0x3 << 12) | /* 7.5ns * 2 > 12ns tALS tCLS */(0x2 << 8) | /* (1+1) * 7.5ns > 12ns (tWP) */(0x1 << 4) | /* (0+1) * 7.5 > 5ns (tCLH/tALH) */(0x0 << 3) | /* SLC NAND Flash */(0x0 << 2) | /* 2KBytes/Page */(0x1 << 1); /* 5 address cycle *//* ** The setting all nCE[3:0] zero can not be allowed. Only ** one nCE can be asserted to enable external NAND flash ** memory. The lower bit has more priority when user set all ** nCE[3:0] zeros. */NFCONT = (0x1 << 1) | /* Disable chip select */(0x1 << 0); /* Enable NAND Flash Controller *//*** Port Map** CE1->Xm0CSn2-> MP01_2** CE2->Xm0CSn3-> MP01_3** CE3->Xm0CSn4-> MP01_4** CE4->Xm0CSn5-> MP01_5** CLE->Xm0FCLE-> MP03_0** ALE->Xm0FALE-> MP03_1** WE->Xm0FWEn-> MP03_2** RE->Xm0FREn-> MP03_3** RB1->Xm0FRnB0->MP03_4** RB2->Xm0FRnB1->MP03_5** RB3->Xm0FRnB2->MP03_6** RB4->Xm0FRnB3->MP03_7** IO[7:0]->Xm0DATA[7:0]->MP0_6[7:0]*/MP0_1CON &= ~(0xFFFF << 8);MP0_1CON |= (0x3333 << 8);MP0_3CON = 0x22222222;MP0_6CON = 0x22222222;nand_reset(); }/* 讀NAND ID */ void nand_read_id(u8 id[]) {int i;nand_select_chip();nand_cmd(0x90);NFADDR = 0x00;for (i = 0; i < 5; i++)id[i] = nand_read();nand_deselect_chip(); }/* 擦除一個塊 */ void nand_erase(u32 addr) { if (addr & (BLOCK_SIZE - 1)){printf("not block align\n");return;}u32 row = addr / PAGE_SIZE;nand_select_chip();nand_cmd(0x60);NFADDR = row & 0xff; NFADDR = (row >> 8) & 0xff;NFADDR = (row >> 16) & 0x07;nand_cmd(0xD0);nand_wait_ready();nand_deselect_chip(); }/* 讀一頁數據 */ void nand_read_page(u8 *buf, u32 addr) {if (addr & (PAGE_SIZE - 1)){printf("not page align\n");return;}int i;nand_select_chip();nand_cmd(0);nand_addr(addr);nand_cmd(0x30);nand_wait_ready();for(i = 0; i < PAGE_SIZE; i++){*buf++ = nand_read();}nand_deselect_chip(); }/* 隨機讀:從任意地址讀任意字節的數據 */ void nand_read_random(u8 *buf, u32 addr, u32 size) { nand_select_chip();nand_cmd(0);nand_addr(addr);nand_cmd(0x30);nand_wait_ready();int i;u32 col = addr % PAGE_SIZE; /* 頁內偏移 */for(i = col; i < size + col; i++){nand_cmd(0x05);NFADDR = i & 0xFF;NFADDR = (i >> 8) & 0x7;nand_cmd(0xE0);*buf++ = nand_read();}nand_deselect_chip(); }/* 寫一頁數據 */ void nand_write_page(u8 *buf, u32 addr) {if (addr & (PAGE_SIZE - 1)){printf("not page align\n");return;}int i;nand_select_chip();nand_cmd(0x80);nand_addr(addr);nand_wait_ready();for(i = 0; i < PAGE_SIZE; i++){nand_write(*buf++);}nand_cmd(0x10);nand_wait_ready();nand_deselect_chip(); } #include "types.h" #include "uart.h" // 這個文件前面UART串口博客有void bzero(u8 *s, int size) {int i = 0;for (; i < size; i++)s[i] = 0; }void main() { u8 buf[2048];int i;bzero(buf, 2048);nand_read_id(buf);printf("\nID:");for (i = 0; i < 5; i++){printf("%X ", buf[i]);}putchar('\n');nand_erase(0x80000); /* 擦除以0x80000地址開始的一個塊 */for (i = 0; i < 2048; i++)buf[i] = i % 255;nand_write_page(buf, 0x80000); /* 寫入1頁數據到0x80000地址 */bzero(buf, 2048);nand_read_page(buf, 0x80000); /* 從0x80000地址讀取一頁數據 *//* 打印讀取到的數據,與寫入的數據一致 */for (i = 0; i < 100; i++){if (i % 16 == 0)putchar('\n');printf("%X ", buf[i]);} }
總結
以上是生活随笔為你收集整理的TQ210 —— NandFlash的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 软件测试设计用例面试题
- 下一篇: STM32解析SBUS信号例程详解