[国嵌攻略][052][NandFlash驱动设计_读]
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 }