1. 概述
我的TQ2440开发板上安装有2M的NOR FLASH和512M的NAND FLASH。
NOR FLASH 的特点是芯片内执行(XIP, eXecute In Place),应用程序可以直接在 NOR FLASH 里运行,不必再把代码读到系统RAM中(可以节约SRAM的成本)。NOR的传输效率很高,在1~4MB的小容量时具有很高的成本效益,但是很低的写入和擦除速度大大影响了它的性能。
NAND FLASH的特点是有很高的存储密度,并且写入和擦除速度也很快,但是无法直接寻址运行程序,接口上需要专门的控制器。另外NAND FLASH 非常容易出现坏区,所以需要有校验的算法。
因此,NOR FLASH一般保存启动代码和系统固件,相当于BISO。NAND FLASH用于存储数据,相当于硬盘。
可参照这篇文章:
RAM、NAND Flash、NOR Flash的区别详解
下面从硬件连接、NANDFLASH内部结构、读写操作、控制器寄存器设置、编程例子等几个方面进行展开。
2. NANDFLASH的硬件连接
我的TQ2440开发板上的NAND FLASH型号是K9F4G08U0B,最后的B代表第3代--3rd Generation。
NAND FLASH的命名规则详见: Nand Flash 命名规则
硬件连接关系如下图所示。
GPA接口复用如下:
经查” TQ2440_V2核心板原理图”,GPA21未连接,如下图:
S3C2440提供OM[1:0],NCON,GPG13,GPG14,GPG15这5个信号来选择NAND FLASH启动,参见S3C2440中文手册,可知:
TQ2440核心板提供的连接关系:
由上图可知,电阻NR5未焊接,即NCON与GND是断路,所以:NCON=1,GPG13=1,GPG14=1,GPG15=0。即,先进NAND Flash,每个页面2K字节,需要5个地址周期,8位宽度。
3. NANDFLASH内部组织结构
如下图所示:
由上图可知K9F4G08结构:
共4096个块,每个块有64个页,因此共有4096x64 = 256K 个页,每个页有效存储数据是2K字节,因此总共有效存储容量512M字节。
访问一个数据需要共5个周期(Cycle):
第1,2个周期访问列(A0—A11),即访问页内,2^11=2K
第3,4,5个周期访问行(A12—A29),即访问块, 2^(29-11)=2^18=256K。
具体到程序代码中是这样:
NF_Send_Addr(0x00);
NF_Send_Addr(0x00);
NF_Send_Addr((page_number) & 0xff);
NF_Send_Addr((page_number >> 8) & 0xff);
NF_Send_Addr((page_number >> 16) & 0x3);
分5个周期。因为读写一般是按页为单位进行,所以前2行发0x00,后面3行把页号分3次发到A12--A19上。
4. 读写操作
对NAND FLASH的访问操作(读,写,擦除)可按照下面的步骤:
a.发送命令:是哪种操作,读,写,擦除?
b.发送地址:对哪一个地址操作
c. 发送数据。
5. 控制器寄存器设置
简单读写编程需要设置的寄存器包括:
GPACON : 将GPA17—GPA22设置为NAND FLASH控制器信号;
NFCONF : 主要确定TACLS、TWRPH0、TWRPH1的值;
NFCONT:用于开启NAND FLASH控制器,设置是否使能软件上锁;
NFCMD:用于写入命令;
NFADDR:用于写入要访问的地址;
NFDATA:要写入的数据放到这里;
NFSTAT: 用于检测NAND FLASH是否处于忙状态。
对于GPACON设置如下 (虽然GPA21未用到):
rGPACON &=~(0X3F << 17) ;
rGPACON |= (0X3F<< 17) ;
对于NFCONF,需要了解各参数对应关系。 S3C2440手册中如下图:
NAND FLASH的datasheet的时序关系:
由上图可知,TWRPH0 = tWP ,TWRPH1 = tCLH(= tALH)
例程中,FCLK=200MHz,HCLK=100MHz,PCKL=50MHz,因此:
tCLH = 5ns,Duration = 10ns *(TWRPH1+1) ==> TWRPH1=0
tWP = 12ns,Duration = 10ns *(TWRPH0+1) = 12min ==> TWRPH0>=1即可
tCLS - tWP = TACLS= 0ns,==> TACLS>=0,取TACLS=1.
NFCONT控制的第0位
NFCMMD
NFADDR
NFDATA(只使用了低8位)
NFSTAT
定义如下宏定义:
#define NF_Send_Cmd(cmd) {rNFCMD = (cmd); }
#define NF_Send_Addr(addr) {rNFADDR = (addr); }
#define NF_Send_Data(data) {rNFDATA8 = (data); }
#define NF_Enable() {rNFCONT &= ~(1<<1); } //nand flash控制器使能
#define NF_Disable() {rNFCONT |= (1<<1); }
#define NF_Enable_RB() {rNFSTAT |= (1<<2); } //开启RnB监视模式;
#define NF_Check_Busy() {while(!(rNFSTAT&(1<<0)));}
#define NF_Read_Byte() (rNFDATA8)
6. 读器件ID程序
读器件ID的命令是90H,接下来5个周期读到产品信息码:
由上图可知,发送Address后有一个tREA延时。
读ID的程序如下:
void NF_ReadID(unsigned char *buf)
{
int i;
NF_Enable();
NF_Enable_RB();
NF_Send_Cmd(CMD_READID); // read id command
NF_Send_Addr(0x0);
for ( i = 0; i < 100; i++ );
*buf = NF_Read_Byte();
*(buf+1) = NF_Read_Byte();
*(buf+2) = NF_Read_Byte();
*(buf+3) = NF_Read_Byte();
*(buf+4) = NF_Read_Byte();
NF_Disable();
}
主程序如下:
#define ESC_KEY 0x1b
unsigned char table[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46};
int Main()
{
int i;
unsigned char key ;
unsigned char nandID[5];
Uart0_Init(115200);
NF_Init();
NF_ReadID(nandID);
Uart0_Printf( "nNand Flash ID:n" );
for(i=0;i<5;i++){
Uart0_Putc(table[nandID[i]>>4]);
Uart0_Putc(table[nandID[i]&0x0f]);
Uart0_Printf(" t");
}
Uart0_Printf( "nPress 'ESC' key to Exi n" );
while(1)
{
key = Uart0_Getc();
if( key == ESC_KEY ) { return 1; }
}
return 0;
}
7. 写入/读出 一个Block
先向第17个Block写入00—FF,然后把第17个Block中的数据读出来,并从串口0输出。
主程序如下:
#define ESC_KEY 0x1b
unsigned char table[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46};
int Main()
{
unsigned char key ;
unsigned char srcbuf[2048],dstbuf[2048] ;
unsigned int i=1 ;
Uart0_Init(115200);
NF_Init();
for(i = 0 ; i < 2048 ; i++)
{
srcbuf[i] = i ;
}
NF_EraseBlock(17) ;
Uart0_Printf( "nWrite 0-FF to block[17] of NandFlash n" );
NF_WritePage(17,4,srcbuf) ;
Uart0_Printf( "nRead block[17] of NandFlash :n" );
NF_ReadPage(17,4, dstbuf);
for(i = 0 ; i < 2048 ; i++)
{
Uart0_Putc(table[dstbuf[i]/16]) ;
Uart0_Putc(table[dstbuf[i]%16]) ;
Uart0_Putc(' ') ;
}
Uart0_Printf( "nPress 'ESC' key to Exi n" );
while(1)
{
key = Uart0_Getc();
if( key == ESC_KEY ){ return 1; }
}
return 0 ;
}
设计资源 培训 开发板 精华推荐
- 基于 ADL6010 的免校准回波损耗测量系统
- LT3504 演示板、具有 100% 占空比操作的四路 40V/1A 降压型开关稳压器
- STM32F103C8T6核心板
- MIC2920A-12WS 400mA低压降稳压器典型应用
- STCS2A 2 A 最大恒流 LED 驱动器的典型应用
- ADL5391-EVALZ,基于 ADL5391 2.0 GHz 模拟乘法器的评估板
- LTC2253IUH 演示板,高速 ADC,VDD = +3.0V,125Msps,12 位 10MHz
- MC33074DR2G 具有迟滞功能的低输入电压比较器的典型应用
- 使用 Analog Devices 的 LT1305CS8 的参考设计
- LTC3110EUF 500mA USB 充电/备用应用的典型应用电路,具有可变充电功率 PCHRG,取决于系统负载