S3C2440开发板裸机程序系列07—NAND FLASH存储器

发布者:legend9最新更新时间:2019-04-26 来源: eefocus关键字:S3C2440  开发板  裸机程序  NAND  FLASH存储器 手机看文章 扫描二维码
随时随地手机看文章

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 ;

}


关键字:S3C2440  开发板  裸机程序  NAND  FLASH存储器 引用地址:S3C2440开发板裸机程序系列07—NAND FLASH存储器

上一篇:裸机系列——s3c2440lcd汉字显示
下一篇:S3C2440裸机实战 之一 创建初始工程

小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved