请选择 进入手机版 | 继续访问电脑版

万邦! 学习论坛

 找回密码
 立即注册
搜索
查看: 505|回复: 0

TQ210 —— NandFlash

[复制链接]
发表于 2018-3-30 10:20:55 | 显示全部楼层 |阅读模式
转载请注明出处:http://blog.csdn.net/wqx521
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) 取消片选
[cpp] view plain copy


  • #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 = 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();  
  • }  

[cpp] view plain copy


  • #include "types.h"  
  • #include "uart.h" // 这个文件前面UART串口博客有  
  •   
  • void bzero(u8 *s, int size)  
  • {  
  •     int i = 0;  
  •     for (; i < size; i++)  
  •         s = 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);  
  •     }  
  •     putchar('\n');  
  •       
  •     nand_erase(0x80000);            /* 擦除以0x80000地址开始的一个块 */  
  •       
  •     for (i = 0; i < 2048; i++)  
  •         buf = 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);  
  •     }  
  • }  
----------------------------------华丽的分界线-----------------------------北京万邦易嵌科技有限公司:专业提供单片机、M3/M4linuxAndroidQT技术服务、技术培训。
详细咨询请加QQ:715493858



QQ|Archiver|手机版|小黑屋|万邦易嵌学习论坛. ( 京ICP备17017219号 )

GMT+8, 2020-10-24 14:18

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表