NandFlash读数据方式
1.页读,读出页中主数据区的所有数据,提供页地址(行地址)
2.随机读,读出页中指定的存储单元的数据,提供页地址(行地址)和页内偏移(行地址)
代码编写
1.根据NandFlash中的读时序图写出工作流程,可以通过在芯片手册中搜索operation找到相关描述
2.主要关心的是IO脚上时序的变化
3.初始化闪存分为初始化闪存控制器和闪存芯片
4.对位操作
4.1.清零
x &= ~(y<<z) 对x的z位开始的y清零
4.2.置1
x |= y<<z 对x的z位开始的y置1
4.3.取数
x & y<<z 取出x的第z位开始的y
4.4.置数
x = y
/********************************************************************
*名称:flash
*作者:D
*时间:2015.11.08
*功能:闪存驱动
********************************************************************/ /********************************************************************
* 宏定义
********************************************************************/
#define NFCONF ( *((volatile unsigned long *)0x4E000000) ) //闪存配置寄存器
#define NFCONT ( *((volatile unsigned long *)0x4E000004) ) //闪存控制寄存器
#define NFCMMD ( *((volatile unsigned long *)0x4E000008) ) //闪存命令寄存器
#define NFADDR ( *((volatile unsigned long *)0x4E00000C) ) //闪存地址寄存器
#define NFDATA ( *((volatile unsigned char *)0x4E000010) ) //闪存数据寄存器
#define NFSTAT ( *((volatile unsigned long *)0x4E000020) ) //闪存状态寄存器 #define PAGE_SIZE 2048 //页大小 /********************************************************************
* 函数原型声明
********************************************************************/
void init_flash();
void init_flash_controller();
void reset_flash_chip(); void read_flash(unsigned long src, unsigned long dst, int len);
void read_page_flash(unsigned long page, unsigned char *buf); /********************************************************************
*名称:init_flash
*功能:初始化闪存
*********************************************************************/
void init_flash(){
//初始化闪存控制器
init_flash_controller(); //重置闪存芯片
reset_flash_chip();
} /********************************************************************
*名称:init_flash_controller
*功能:初始化闪存控制器
*********************************************************************/
void init_flash_controller(){
//初始化闪存配置寄存器
NFCONF = (1<<12)|(1<<8)|(1<<4); //设置TACLS:1 TWRPH0:1 TWRPH1:1 //初始化闪存控制寄存器
NFCONT = (1<<1)|(1<<0); //设置Reg_nCE:1 MODE:1
} /********************************************************************
*名称:reset_flash_chip
*功能:重置闪存芯片
*********************************************************************/
void reset_flash_chip(){
//选中闪存芯片
NFCONT &= ~(1<<1); //设置Reg_nCE:0 //清除忙信号
NFSTAT |= (1<<2); //设置RnB_TransDetect:0 //发送重启命令
NFCMMD = 0xFF; //等待忙信号
while( !(NFSTAT&(1<<2)) ); //当RnB_TransDetect等于1时,结束循环 //释放闪存芯片
NFCONT |= 1<<1; //设置Reg_nCE:1
} /********************************************************************
*名称:read_flash
*参数:
* src 源地址
* dst 目的地址
* len 读取长度
*返回:
* null
*功能:读闪存
*********************************************************************/
void read_flash(unsigned long src, unsigned long dst, int len){
unsigned long page; //页号
unsigned char *buf; //页缓存 while(len > 0){
page = src>>11; //设置页号
buf = (unsigned char *)dst; //设置页缓存
read_page_flash(page, buf); src +=PAGE_SIZE;
dst +=PAGE_SIZE;
len -=PAGE_SIZE;
}
} /********************************************************************
*名称:read_page_flash
*参数:
* page 页号
* buf 页缓存,2048字节
*返回:
* none
*功能:页读闪存
*********************************************************************/
void read_page_flash(unsigned long page, unsigned char *buf){
int i; //循环计数器 //选中闪存芯片
NFCONT &= ~(1<<1); //设置Reg_nCE:0 //清除忙信号
NFSTAT |= (1<<2); //设置RnB_TransDetect:0 //发送读命令(0x00)
NFCMMD = 0x00; //发送列地址
NFADDR = 0x00; //Col.Add1
NFADDR = 0x00; //Col.Add2 //发送行地址
NFADDR = (page>>0)&0xFF; //Row.Add1
NFADDR = (page>>8)&0xFF; //Row.Add2
NFADDR = (page>>16)&0xFF; //Row.Add3 //发送读命令(0x30)
NFCMMD = 0x30; //等待忙信号
while( !(NFSTAT&(1<<2)) ); //当RnB_TransDetect等于1时,结束循环 //读取数据
for(i = 0; i < PAGE_SIZE; i++){
buf[i] = NFDATA; //注意,NFDATA寄存器数据类型要和buf匹配,一个读周期读出一个字节
} //释放闪存芯片
NFCONT |= 1<<1; //设置Reg_nCE:1
}