历史上的今天
返回首页

历史上的今天

今天是:2025年04月25日(星期五)

正在发生

2020年04月25日 | ARM9 mini2451裸机学习——NAND flash驱动学习 2

2020-04-25 来源:eefocus

上一篇文章主要学习了NAND Falsh的基础知识,今天则来总结NAND Flash的初始化,以及块擦除,页的读写操作,以及芯片id号的获取。


6. NAND FLASH 的操作接口


我们知道,函数在调用时需要使用栈,当项目的函数调用关系复杂时,尤其是存在多级


函数调用时,容易导致栈溢出,此处函数调用的开销也会逐渐加大。


为了更好的解决上述问题,一般使用宏的形式来实现规模较小的函数,因为宏调用时在


预处理阶段,由预处理器对源程序中的宏进行展开,所以宏展开不占用运行时间。


因为每一次宏调用都需要进行宏展开,所以会加大程序的代码量,因此规模较大的函数


不宜使用宏的形式来实现


① NAND FLASH 使能函数


#define NF_Enable() {rNFCONT &=~(1<<1);} //选中芯片


② NAND FLASH 失能函数


#define NF_Disable() {rNFCONT |=(1<<1);}

③ NAND FLASH 发送命令函数


#define NF_Send_Cmd(cmd) {rNFCMD = (cmd);}


④ NAND FLASH 发送地址函数


#define NF_Send_Addr(addr) {rNFADDR =addr;}


⑤ NAND FLASH 发送数据函数


#define NF_Send_Data(data) {rNFDATA8 =(data);}


⑥ NAND FLASH 使能忙检测函数


#define NF_Enable_RB() {rNFSTAT |= (1<< 4);}

⑦ NAND FLASH 判忙函数


#define NF_Check_Busy() {while(!(rNFSTAT& (1 << 0)));} // 0 busy ,1 ready


⑧ NAND FLASH 读字节函数


#define NF_Read_Byte() (rNFDATA8)


7. 怎样对 NAND 进行复位?


① 选中 NAND FLASH


② 使能 NAND 判忙检测


③ 发送复位命令(0xff)


④ 等待复位完成


⑤ 取消选中 NAND FLASH


8. 怎样对 NAND 进行初始化?


① 配置 GPA 相关 IO 口


② 设置相关时间参数


③ 关闭 NAND 中断,打开 NAND 控制器


④ NAND 相关状态清零


⑤ 复位 NAND


9. 怎样擦除一个块?


① 复位 NAND


② 选中 NAND FLASH


③ 使能 NAND 判忙检测


④ 发送块擦除发起命令(0x60)


⑤ 发送块地址


⑥ 发送块擦除确认命令(0xd0)


⑦ 等待擦除完成


⑧ 取消选中芯片


10. 怎样写一页?


① 复位 NAND FLASH


② 选中 NAND FLASH


③ 使能 NAND 判忙检测


④ 发送写页发起命令(0x80)


⑤ 发送页地址


⑥ 发送 2048 个数据


⑦ 发送写页确认命令(0x10)


⑧ 等待写完成


⑨ 取消选中芯片


11. 怎样读一页


① 复位 NAND FLASH


② 选中 NAND FLASH


③ 发送页读取发起命令(0x00)


④ 发送读地址


⑤ 发送页读取确认命令(0x30)


⑥ 等待命令完成


⑦ 读取 2048 个命令


⑧ 取消选中芯片


12.NAND FLASH 的地址模式

源代码分析(代码编译环境:win8,keil4):


宏定义,具体参数查DATASHEET,不再赘叙。


#define rNFCONF (*(volatile unsigned long *)(0x4e000000))

#define rNFCONT (*(volatile unsigned long *)(0x4e000004))

#define rNFCMD (*(volatile unsigned long *)(0x4e000008))

#define rNFADDR (*(volatile unsigned long *)(0x4e00000c))

#define rNFDATA8  (*(volatile unsigned char *)(0x4e000010))

#define rNFSTAT   (*(volatile unsigned long *)(0x4e000028))

#define rGPACON  (*(volatile unsigned long *)(0x56000000))


//NAND FLASH 使能函数

#define NF_Enable() {rNFCONT &= ~(1<<1);} //选中芯片

//NAND FLASH 失能函数

#define NF_Disable() {rNFCONT |= (1<<1);}

//NAND FLASH 发送命令函数

#define NF_Send_Cmd(cmd) {rNFCMD = (cmd);}

//NAND FLASH 发送地址函数

#define NF_Send_Addr(addr) {rNFADDR = addr;}

//NAND FLASH 发送数据函数

#define NF_Send_Data(data) {rNFDATA8 = (data);}

//NAND FLASH 使能忙检测函数

#define NF_Enable_RB() {rNFSTAT |= (1 << 4);}

//NAND FLASH 判忙函数

#define NF_Check_Busy() {while(!(rNFSTAT & (1 << 0)));} // 0 busy ,1 ready

//NAND FLASH 读字节函数

#define NF_Read_Byte() (rNFDATA8) //因为需要赋值操作,所以不加;

一些操作命令


注意:某些命令需要发送两次,操作前后各发送一次,成对出现,第二次发送的是确认命令。



NAND Flash复位函数

#define NF_CMD_RESET         0xff


void nand_reset(void) //nand复位函数

{

NF_Enable(); //选中芯片

NF_Check_RB(); //忙检测

NF_Send_Cmd(NF_CMD_RESET); //发送复位命令

NF_Check_Busy(); //忙等待

NF_Disable(); //取消选中芯片

}


NAND Flash初始化函数


#define TACLS 1

#define TWRPH0 4

#define TAWTH1 1


#define NAND_INT_DIABLE 0

#define NAND_ENABLE 1


void nand_init(void)

{

rGPACON &= ~(0x3f<<17); //未操作将操作的位置清零

rGPACON |= (0x3f<<17); //初始化GPA

rNFCONT = (TACLS<<12)|(TWRPH0<<8)|(TAWTH1<<4);

rNFCONT = (NAND_INT_DIABLE<<12)|(NAND_ENABLE<<0);

rNFSTAT = 0x0; //NAND相关状态清零

nand_reset(); //复位

}


擦除一块内容


#define NF_CMD_ERASE1        0x60

#define NF_CMD_ERASE2        0xd0


void nand_erase(unsigned int block) //块擦除

{

unsigned int blocknum = (block<<6); //左移6位(A12-A17)到A18

nand_reset();

NF_Enable();

NF_Check_RB();

NF_Send_Cmd(NF_CMD_ERASE1); //发送块擦除指令

NF_Send_Addr(blocknum & 0xff); //&0xff是为了擦除高百位 第一次发送实际只发送A18 A19两位

NF_Send_Addr((blocknum>>8) & 0xff); //发送接下来的8位地址

NF_Send_Addr((blocknum>>16) & 0xff);

NF_Send_Cmd(NF_CMD_ERASE2); //发送确认块擦除指令

NF_Check_Busy(); //忙等待

NF_Disable(); //取消选中芯片

}

A0-A11用来页内寻址


A18-A28用来块寻址


A12-A17用来表示某块中的第几页

NAND寻址需要发送5次,一次发送8位数据(8个I/O口)。


block<<6,block左移6位,原本第三次(因为发送了指令,根据NAND内部机制,直接从第三次开始发送)A12的数据成了A18的数据,而A18-A28用来块寻址。


blocknum>>8,blocknum右移8位,即将block左移的6位再加上第三次发送的2位地址。


向NAND写入一页内容


#define NF_CMD_WRITE1        0x80

#define NF_CMD_WRITE2        0x10


void nand_write_page(unsigned int block,unsigned int page,unsigned char * str) //写一页

{

unsigned int pagenum = (block<<6) + page;

unsigned int i;

nand_reset(); //nand复位

NF_Enable(); //选中芯片

NF_Check_RB(); //忙检测

NF_Send_Cmd(NF_CMD_WRITE1); //发送读操作指令

NF_Send_Addr(0x0);

NF_Send_Addr(0x0);

NF_Send_Addr(pagenum & 0xff);

NF_Send_Addr((pagenum>>8) & 0xff);

NF_Send_Addr((pagenum>>16) & 0xff);

for(i=0; i<2048; i++)

{

NF_Send_Data(str[i]); //发送数据

}

NF_Send_Cmd(NF_CMD_WRITE2); //发送读操作确认命令

NF_Check_Busy(); //忙等待

NF_Disable(); //取消选中芯片

}


读取一页内容


#define NF_CMD_READ1         0x00

#define NF_CMD_READ2         0x30


void nand_read_page(unsigned int block,unsigned int page,unsigned char * str) //读一页

{

unsigned int pagenum = (block<<6) + page;

unsigned int i;

nand_reset(); //nand复位

NF_Enable(); //选中芯片

NF_Check_RB(); //忙检测

NF_Send_Cmd(NF_CMD_READ1); //发送读操作指令

NF_Send_Addr(0x0);

NF_Send_Addr(0x0);

NF_Send_Addr(pagenum & 0xff);

NF_Send_Addr((pagenum>>8) & 0xff);

NF_Send_Addr((pagenum>>16) & 0xff);

NF_Send_Cmd(NF_CMD_READ2);

NF_Check_Busy(); //忙等待

for(i=0; i<2048; i++)

{

str[i] = NF_Read_Byte(); //读字节

}

NF_Disable(); //取消选中芯片

}


读取NAND Flash的ID号


#define NF_CMD_READ_ID  0x90


void nand_read_ID(unsigned char * str) //读取nand flash芯片id

{

unsigned int i;

NF_Enable(); //选中nand flash

NF_Check_RB(); //忙检测

NF_Send_Cmd(NF_CMD_READ_ID); //发送读取芯片id命令

NF_Send_Addr(0x0);

NF_Check_Busy(); //忙等待

for(i=0; i<2048; i++)

{

str[i] = NF_Read_Byte(); //读字节

}

NF_Disable(); //取消选中芯片

}

推荐阅读

史海拾趣

Axon' Cable公司的发展小趣事

Axon' Cable公司自1965年在法国成立起,便致力于通讯连接器的研发与生产。在创业初期,公司面临着资金短缺、技术瓶颈和市场竞争的诸多挑战。然而,Axon' Cable凭借其坚定的信念和不懈的努力,逐步突破了技术难关,并成功开发出了一系列具有竞争力的产品。这些产品在市场上得到了广泛认可,为公司的后续发展奠定了坚实的基础。

ANADIGICS公司的发展小趣事

品质是Axon' Cable公司的生命线。公司始终坚持以客户需求为导向,不断提升产品品质和服务水平。Axon' Cable建立了完善的质量管理体系,并通过了多项国际认证。同时,公司还注重持续改进和创新,不断优化生产流程和提高生产效率。这些努力使得Axon' Cable的产品在品质上始终保持领先地位,赢得了客户的信任和好评。

这些故事虽然无法涵盖Axon' Cable公司发展的全部细节,但试图展现了其在电子行业中的成长轨迹和取得的成就。通过这些故事,我们可以看到Axon' Cable公司凭借其坚定的信念、不懈的努力和创新精神,在电子行业中不断发展壮大,成为了一家具有全球影响力的知名企业。

ABLIC公司的发展小趣事

ABLIC的起源可以追溯到精工电子有限公司旗下的精工半导体有限公司(SII Semiconductor Corporation)。在半导体产业蓬勃发展的背景下,日本政府通过政策投资银行对SII进行了注资,使其在原有业务基础上进一步拓展。然而,随着股权结构的变动,SII决定在2018年进行品牌重塑,更名为ABLIC,并专注于模拟半导体业务的发展。这一决策标志着ABLIC踏上了全新的发展道路。

Deltron / DEM Manufacturing公司的发展小趣事

为了进一步扩大市场份额和增强竞争力,DEM Manufacturing积极寻求与其他企业的战略合作。公司与其他电子行业的领军企业建立了长期稳定的合作关系,共同开发新产品、拓展新市场。这些合作不仅为公司带来了更多的商业机会,还促进了整个电子行业的发展和进步。

请注意,以上故事梗概是基于已知事实进行的概括和虚构,旨在展示Deltron / DEM Manufacturing公司在电子行业中的发展历程和成就。具体细节和实际情况可能有所不同。

Chiplus Semiconductor Corp公司的发展小趣事

随着全球半导体市场的不断扩大,Chiplus也加快了市场拓展的步伐。公司不仅在日本、欧盟、美国和泛太平洋亚洲地区建立了稳定的客户群体,还积极开拓新兴市场,提升品牌知名度和影响力。同时,Chiplus还加强了与全球知名企业的合作,通过技术合作、产业链协同等方式,共同推动半导体行业的发展。

Bce Sud公司的发展小趣事

随着公司规模的扩大和市场份额的提升,Bce Sud开始实施国际化战略。公司先后在多个国家和地区设立了研发中心和销售网络,进一步扩大了市场份额。通过与国际知名企业的合作与交流,Bce Sud不断提升自身的技术水平和国际竞争力。

问答坊 | AI 解惑

智能型充电器的电源和显示的设计

智能型充电器的电源和显示的设计--AVR单片机做的好东西…

查看全部问答>

51单片机外部中断问题

小女子我初学单片机,很多不懂得地方,向大家请教下啊 关于使用外部中断点亮发光二极管的问题,为实现同一功能,写了两方案,具体程序和问题如下 方案一: ORG 0000H LJMP MAIN ORG 0003H LJMP INT MAIN: SETB EA  /*首先开启总中 ...…

查看全部问答>

[转载] 簡易開核 輕鬆暢玩 ASUS M4A89GTD PRO/USB3 (存開箱)

AMD 現今最夯的口號 我想還是  核心動力全開 小弟也藉由這次開核風氣 入手了M4A89GTD PRO/USB3 入手也一陣子了 就來發個開箱吧 本次的主角出現了 X2 555 與M4A89GTD PRO/USB3 這次華碩用的主機板的彩盒還滿亮眼的 在一張,把閃 ...…

查看全部问答>

如何实现快进和快退的功能

现在需要用Waveout函数系列来实现播放wav文件的功能,播放功能已经实现,现在实现快进的功能的时候出现了一个问题,就是在按下快进按钮的时候, 原来已经读入缓冲区的音频内容还在, 请问这时候如何去清除缓冲区内的音频内容.…

查看全部问答>

wince 串口的处理速度问题

    用串口与MCU通信,用57600波特率,8位数据,1位停止位,无校验位。mcu端发送一个数据包号请求命令(共10个字节长度),wince端收到后,解析出包号,把对应包号的数据发送给MCU(共40个字节长度)。mcu端收到数据后继续请求下一包数据 ...…

查看全部问答>

12月3号xilinx北京研讨会资料上传

12月3号xilinx北京研讨会资料上传 只是将培训中相关的课件pdf上传了 其他有需要的 可以再上传    …

查看全部问答>

STM32没有MPU

                                 如题,是不是没有MPU(Memory protect unit)?…

查看全部问答>

【忽悠】STM32的技术研讨会先睹为快

此次STM32的技术研讨会的一个重要的部分是,与使用STM32的工程师们面对面的讨论一些大家普遍碰到的问题。STM32是个新产品,Cortex-M3也是个新产品,有很多应用上的概念与大家原有的概念是相通的,也有一些概念是有些人没有碰到过的,我们希望 ...…

查看全部问答>

求助331274-0011是ST的哪个型号MCU??

                                 331274-0011 是ST的哪个型号MCU?? 请告知,多谢.…

查看全部问答>

09.29【每周讨论】12岁的编程天才,英雄出少年

12岁的编程天才 田众和,1999年生,今年12岁,任时代网络软件工作室CEO兼CTO(技术总监)。小学4年级自学编程,创作第一个比较成熟的编程作品Othink系统,获得第一笔创业资金300元,招聘并领导11人团队,集资2000余元创建工作室,4个月盈利三万余 ...…

查看全部问答>