历史上的今天
今天是:2024年12月06日(星期五)
2020年12月06日 | TQ210 —— NandFlash
2020-12-06 来源:eefocus
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 alignn");
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 alignn");
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 alignn");
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]);
}
}
上一篇:ARM在嵌入式系统中的应用
下一篇:TQ210 —— LCD
史海拾趣
|
作为汽车产业与电子产业的完美结合,汽车电子业的发展相对于汽车市场而言更加迅猛。据估计,近几年的年增长率均超过50%,是拉动汽车工业发展的重要因素。到目前为止,绝大多数国外大型的跨国汽车电子企业已在中国设厂。为了进一步扩大在中国的市场 ...… 查看全部问答> |
|
艾克赛尔(Axelwave)无线网络――无线监控在高速公路的应用 近年来中国经济的飞速发展,使中国的公路建设,尤其是高速公路的建设上了一个新台阶。而随着现代化高速公路的建设,新一代高速公路视频监控系统,日益成为高速公路监管的重要手段。无线监控凭借其简便、快速、受环境影响小的特点,也逐步成为高速公 ...… 查看全部问答> |
|
在基于软件无线电的某无线通信信号侦收平台的设计中,天线接收到的信号经过变频器处理和A/D变换之后,经过高速通道把采集的信号送入主控板进行数据分发处理。系统的结构框图如图1所示。 图1 主控板的系统结构框图 主控板的硬件核 ...… 查看全部问答> |
|
wince提供的api只能录制成wave吧? 录成mp3需要使用开源的lame库? 我现在在模拟器上能录制成wave, 调用lame库把wave转成mp3不成功,似乎是lame库内存异常了. 哪位大侠有CE5.0下能用的lame库? 或者还有其它方式能直接录成mp3? 我的邮箱:victor_20 ...… 查看全部问答> |
|
signal abc: std_logic_vector(5 downto 0):=(others=>\'0\');困扰很久,一直不明白。哪位大侠能给详解一下?谢谢!… 查看全部问答> |
|
【有圖有真相】基于MSP430 LaunchPad 和2.4G RF Module 的聊天室 前段時間在論壇的活動中拿了MSP430 LaunchPad,總要起點作用吧。 就做了這個史上最無聊,最無用的聊天工具。辦公室的工程師每人分一塊LaunchPad,接上我們公司常用的2.4G RF Module 用VB寫了個上位機軟件 然后就可以大家一起吹水了。 史上最 ...… 查看全部问答> |




