TQ210 —— NandFlash
转载请注明出处:http://blog.csdn.net/wqx521TQ210 —— 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 页读
https://img-blog.csdn.net/20160906223021915
我们需要按上面这个地址周期表来发地址。
对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) 取消片选
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 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 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->Xm0DATA->MP0_6
[*] */
[*] 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();
[*]}
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;
[*] 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/M4、linux、Android、QT技术服务、技术培训。详细咨询请加QQ:715493858
页:
[1]