Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
DIY综合交流区
[RealTouch例程]NandFlash 的基本使用
发布于 2012-09-01 18:59:14 浏览:7153
订阅该版
NANDFLASH 本章节介绍了STM32的NandFlash控制器和K9F2G08的部分信息。并实现了对其的基本操作,通过本章学习你将基本掌握STM32 NandFlash控制器以及K9F2G08的使用方法。 1. STM32 NANDFLASH控制器简介 STM32的NandFlash控制器是包含在FSMC中的,它可以控制多种设备,在此只针对NandFlash控制部分给予介绍。 FSMC共控制4个Banks,其中Bank2和Bank3可用于挂载NandFlash。Bank2的地址空间为0x7000 0000到0x7800 0000,Bank3的地址空间为0x8000 0000到0x8800 0000。bank2/bank3的前半部分为公共区,后半部分为属性区,这两个区的低256KB部分又被分为3个段:数据段(开始64KB)、命令段(第二个64KB)地址段(最后128KB)。用户可以使用这三个段访问NandFlash:写命令到命令段任意位置可向NandFlash发送命令、。。。、读写NandFlash时可访问数据段任意位置。在通过数据段访问NandFlash时你可以不必增加数据地址。 FSMC可以控制8位或16位的NandFlash,在这里仅对8位NandFlash相关部分给予介绍,表1是8位NandFlash要用到的引脚介绍。 表1. 8位NandFlash FSMC信号名称 I/O 功能 A[17] O 地址锁存使能 A[16] O 命令锁存使能 D[7:0] I/O 8位地址/数据复用端口 NCE[x] O 片选,x=2/,3 NOE(=NRE) O 输出使能 NWE O 写使能 NWAIT/INT[3:2] I NandFlash就绪/忙信号 输入给FMSC 1.1 NANDFLASH操作 一个典型的读页操作可以分为如下几个步骤完成: 1) 配置FSMC_PCRx与FSMC_PMEMx寄存器以使能相应的存储Bank。 2) CPU写一个命令字节到公共存储区(例如三星的NandFlash设备 可以写0x00)。 3) CPU发送4字节的起始地址(小容量设备3字节)到公共区或属 性区(地址顺序为先[7:0],再[16:9],[24:17],64Mbit x 8bit设备需要在最后发送[25])。 4) 等待NandFlash就绪(R/NB变为高电平)。 5) 然后CPU就可以一字节一字节的从公共区读出数据(主数据与额外数据)。 1.2 NANDFLASH控制器寄存器介绍 表1.2.1 控制寄存器 19 17 16 13 12 9 6 5 4 3 2 1 保留 保留 ECCPS TAR TCLR 保留 ECCEN PWID PTYP PBKEN PWAITEN 位19:17 ECCPS表示ECC页大小,其取值与含义如下所示: ? B000 - 256字节 ? B001 - 512字节 ? B010 - 1024字节 ? B011 - 2048字节 ? B100 - 4096字节 ? B101 - 8192字节 位16:13 TAR表示ALE到RE之间的延时,用来设置ALE低电平到RE低电平之间需要经过多少个HCLK时钟周期。延时T = (TAR + SET + 1)/ HCLK(SET is MEMSET or ATTSET according to the addressed space)。 位12:9 TCLR表示CLE到RE之间的延时,来设置ALE低电平到RE低电平之间需要经过多少个HCLK时钟周期。延时T = (TCLR + SET + 1)/ HCLK。 位6 ECCEN表示ECC计数使能,0禁止、1开启。 位5:4 PWID表示数据总线宽度,0表示8位、1为16位其它取值保留。 位3 PTYP表示存储器类型,1为NandFlash、0为PC卡。 位2 PBKEN表示PC卡NandFlash存储Bank使能,0表示禁止、1为使能。 位1 PWAITEN表示等待使能,0禁止、1使能。 表1.2.2 FIFO状态与中断寄存器 31 7 6 5 4 3 2 1 0 保留 FEMPT IFEN ILEN IREN IFS ILS IRS 位6 FEMPT表示FIFO是否为空,1为空、非空。 位5 IFEN表示中断下降沿检测使能,1使能、0禁止。 位4 ILEN表示中断高电平检测使能,1使能、0禁止。 位3 IREN表示中断上升沿检测使能,1使能、0禁止。 位2 IFS表示中断下降沿状态。 位1 ILS表示中断高电平状态。 位0 IRS 表示中断上升沿状态。 表格1.2.3 共公存储区时序寄存器 31 24 23 6 15 8 7 0 MEMHIZ MEMHOLD MEMWAIT MEMSET 位31:24 MEMHIZ表示公共存储区数据总线高阻时间,用来设置启动一个对公共区写访问后数据总线应保持多少个HCLK时钟周期的高阻状态(初始值255)。 位23:16 MEMHOLD表示公共存储区保持时间,用来设置通过公共存储区访问NandFlash时命令无效置位后应保持多少个HCLK时钟周期的地址(初始值255)。 位15:8 MEMWAIT表示公共存储区等待时间,用来定义判定命令(NWE, NOE)的最小周期((MEMWAIT+1)/ HCLK)。如果在到达设定的时间后NWAIT任然为低则命令判定的时间会延长(初始值255)。 位7:0 MEMSET表示公共存储区设置时间,用来定义在判定命令(NEW,NOE)前的多少个HCLK设置地址。 2. 本例程所用硬件介绍 本例程主要使用了K9F2G08,它是一个8位NandFlash包含256MB主存区和8MB额外存储区。每页大小为2KB+64B,每块大小为128KB+4KB。页编程时间200?s块擦出时间1.5ms。命令、地址、数据复用I/O端口。 2.1 引脚描述 表2.1 K9F2G08引脚定义 引脚名称 说明 I/O 0~7 用于输入命令、地址和数据的输入输出。当芯片未被选择或输出被禁止时I/O引脚处于高阻状态。 CLE 命令锁存使能;当CLE为高电平时,命令在NWE信号的上升沿通过I/O引脚锁存进命令寄存器。 ALE 地址锁存使能;当ALE为高电平时,地址在NWE的上升沿锁存进地址寄存器。 NCE 芯片使能; NRE 读使能; NWE 写使能;在NWE上升沿时命令、地址、数据被锁存 NWP 写保护; R/NB 就绪/忙状态;输出低电平表示忙,高表示就绪,这个引脚是开漏输出且当芯片未选择或输出禁止时不会变为高阻。 Vcc 电源; Vss 地 ; N.C 无效引脚; 2.2 地址传输格式 表2.2 地址传输格式 顺序 I/O0 I/O1 I/O2 I/O3 I/O4 I/O5 I/O6 I/O7 1st A0 A1 A2 A3 A4 A5 A6 A7 2nd A8 A9 A10 A11 0 0 0 0 3rd A12 A13 A14 A15 A16 A17 A18 A19 4th A20 A21 A22 A23 A24 A25 A26 A27 5th A28 0 0 0 0 0 0 0 A0-A11为行地址,是NandFlash内数据寄存器的地址,A12-A28为列地址。 2.3 NANDFLASH操作命令码 表2.3 命令 功能 1st 2nd 设备忙时可接受的命令 Read 0x00 0x30 Read for Copy Back 0x00 0x35 Read ID 0x90 - Reset 0xFF - O Page Program 0x80 0x10 Two-Plane Page Program 0x80-0x11 0x81-0x10 Copy-Back Program 0x85 0x10 Two-Plane Copy-Back Program 0x85-0x11 0x81-0x10 Block Erase 0x60 0xD0 Two-Plane Block Erase 0x60-0x60 0xD0 Random Data Input 0x85 - Random Data Output 0x05 0xE0 Read Status 0x70 - O Read Status 2 0xF1 - O 备注:随机数据读写只能在一个页中执行。 2.4 ID中包含的信息 表2.4 芯片ID 第一字节 厂商ID 第二字节 设备ID 第三字节 内部芯片编号、存储单元类型、同时编程的页面数 第四字节 页大小、块大小、额外区大小、 第五字节 Plane Number, Plane Size 表2.5 第三字节ID数据 名称 描述 I/O7 I/O6 I/O 5 4 I/O 3 2 I/O 1 0 芯片编号 1 2 4 8 0 0 0 1 1 0 1 1 单元类型 2级单元 4级单元 8级单元 16级单元 0 0 0 1 1 0 1 1 同时编程页数 1 2 4 8 0 0 0 1 1 0 1 1 多芯片间交错编程 不支持 0 1 Cache编程 不支持 0 1 表2.6 第四字节ID数据 名称 描述 7 6 5 4 3 2 1 0 页大小 1KB 2KB 4KB 8KB 0 0 0 1 1 0 1 1 块大小 64KB 128KB 256KB 512KB 0 0 0 1 1 0 1 1 额外区大小(B/512B) 8 16 0 1 Organization X8 X16 0 1 串行访问最低限度 50/30ns 25ns 保留 保留 0 1 0 1 0 1 0 1 表格2.7 第五字节ID数据 名称 描述 7 6 5 4 3 2 1 0 Number of plane 1 2 4 8 0 0 0 1 1 0 1 1 Plane size 64Mbit 128Mbit 256Mbit 512Mbit 1Gbit 2Gbit 4Gbit 8Gbit 0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1 保留 0 0 0 3. 例程 本例程主要实现了对NandFlash的基本操作:读ID、读写数据和擦出。关于NandFlash以及相关GPIO的初始化过程和函数中用到的一些宏定义请参见示例工程,这里仅对NandFlash的几个基本操作给予介绍。 3.1 读设备ID 代码3-1 读取设备ID ```/* fsmc_nand.c */ void FSMC_NAND_ReadID(NAND_IDTypeDef* NAND_ID) { /* Send Command to the command area */ *(vu8 *)(NAND_FLASH_START_ADDR | CMD_AREA) = NAND_CMD_READID; /* Send Address to the address area */ *(vu8 *)(NAND_FLASH_START_ADDR | ADDR_AREA) = 0x00; /* Sequence to read ID from NAND flash */ NAND_ID->Maker_ID = *(vu8 *)(NAND_FLASH_START_ADDR | DATA_AREA); NAND_ID->Device_ID = *(vu8 *)(NAND_FLASH_START_ADDR | DATA_AREA); NAND_ID->Third_ID = *(vu8 *)(NAND_FLASH_START_ADDR | DATA_AREA); NAND_ID->Fourth_ID = *(vu8 *)(NAND_FLASH_START_ADDR | DATA_AREA); NAND_ID->Fifth_ID = *(vu8 *)(NAND_FLASH_START_ADDR | DATA_AREA); } ```有些NandFlash控制器中有命令寄存器、地址寄存器和数据寄存器,但在STM32中是命令区、地址区和数据区的概念。它有很大的一块区域,只要向这块区域的任意位置写命令、地址和数据都能实现相应的发送。RealTouch使用Bank3挂载NandFlash,因此NAND_FLASH_START_ADDR被定义为0x80000000。 CMD_AREA为0x010000,ADDR_AREA为0x020000,DATA_AREA为0x000000(见STM32参考手册 Table 166)。读设备ID的时序为先发送读ID命令(NAND_CMD_READID)再发送地址0x00,然后就可以一个字节一个字节地读出5字节的ID数据。 3.2 块擦除 代码3-2 块擦除 ```/* fsmc_nand.c */ uint32_t FSMC_NAND_EraseBlock(NAND_ADDRESS Address) { *(vu8 *)(NAND_FLASH_START_ADDR | CMD_AREA) = NAND_CMD_ERASE0; *(vu8 *)(NAND_FLASH_START_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS); *(vu8 *)(NAND_FLASH_START_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS); #ifdef K9F2G08 *(vu8 *)(NAND_FLASH_START_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS); #endif *(vu8 *)(NAND_FLASH_START_ADDR | CMD_AREA) = NAND_CMD_ERASE1; while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0); return (FSMC_NAND_GetStatus()); } ```块擦出的时序是先发送第一个擦出命令,再发出3个字节的列地址(A12-A17会被NandFlash忽略)然后发出第二个擦出命令。NandFlash的R/NB引脚接在PG6上的,因此此处通过PG6判断设备是否忙。 3.3 读取一页的数据 代码3-3 读取一页的数据 ```/* fsmc_nand.c */ uint32_t FSMC_NAND_ReadPage(uint8_t *pBuffer, NAND_ADDRESS Address, uint32_t NumPageToRead) { uint32_t index = 0x00, numpageread = 0x00, addressstatus = NAND_VALID_ADDRESS; uint32_t status = NAND_READY, size = 0x00; while((NumPageToRead != 0x0) && (addressstatus == NAND_VALID_ADDRESS)) { /* Page Read command and page address */ *(vu8 *)(NAND_FLASH_START_ADDR | CMD_AREA) = NAND_CMD_READ_1; *(vu8 *)(NAND_FLASH_START_ADDR | ADDR_AREA) = 0x00; *(vu8 *)(NAND_FLASH_START_ADDR | ADDR_AREA) = 0X00; *(vu8 *)(NAND_FLASH_START_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS); *(vu8 *)(NAND_FLASH_START_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS); #ifdef K9F2G08 *(vu8 *)(NAND_FLASH_START_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS); #endif *(vu8 *)(NAND_FLASH_START_ADDR | CMD_AREA) = NAND_CMD_READ_TRUE; while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 ); /* Calculate the size */ size = NAND_PAGE_SIZE + (NAND_PAGE_SIZE * numpageread); /* Get Data into Buffer */ for(; index < size; index++) { pBuffer[index]= *(vu8 *)(NAND_FLASH_START_ADDR | DATA_AREA); } numpageread++; NumPageToRead--; /* Calculate page address */ addressstatus = FSMC_NAND_AddressIncrement(&Address); } status = FSMC_NAND_GetStatus(); return (status | addressstatus); } ```读页的处理过程跟块擦出比较类似,这里两个行地址为0表示从一页的开始处读取数据。 3.4 写数据 代码3-4 写数据 ```/* fsmc_nand.c */ uint32_t FSMC_NAND_WritePage(uint8_t *pBuffer, NAND_ADDRESS Address, uint32_t NumPageToWrite) { uint32_t index = 0x00, numpagewritten = 0x00, addressstatus = NAND_VALID_ADDRESS; uint32_t status = NAND_READY, size = 0x00; while((NumPageToWrite != 0x00) && (addressstatus == NAND_VALID_ADDRESS) && (status == NAND_READY)) { /* Page write command and address */ *(vu8 *)(NAND_FLASH_START_ADDR | CMD_AREA) = NAND_CMD_PAGEPROGRAM; *(vu8 *)(NAND_FLASH_START_ADDR | ADDR_AREA) = 0x00; *(vu8 *)(NAND_FLASH_START_ADDR | ADDR_AREA) = 0X00; *(vu8 *)(NAND_FLASH_START_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS); *(vu8 *)(NAND_FLASH_START_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS); #ifdef K9F2G08 *(vu8 *)(NAND_FLASH_START_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS); #endif /* Calculate the size */ size = NAND_PAGE_SIZE + (NAND_PAGE_SIZE * numpagewritten); /* Write data */ for(; index < size; index++) { *(vu8 *)(NAND_FLASH_START_ADDR | DATA_AREA) = pBuffer[index]; } *(vu8 *)(NAND_FLASH_START_ADDR | CMD_AREA) = NAND_CMD_PAGEPROGRAM_TRUE; while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 ); /* Check status for successful operation */ status = FSMC_NAND_GetStatus(); if(status == NAND_READY) { numpagewritten++; NumPageToWrite--; /* Calculate Next page Address */ addressstatus = FSMC_NAND_AddressIncrement(&Address); } } return (status | addressstatus); } ``` 4. 下载运行 执行fsmc_nand.c中的FSMC_NAND_Test就可对NandFlash进行基本的读写测试了。在这个函数中首先读取了设备ID以判断型号,并擦出NandFlash中的某块,然后写入一页数据再读取出来进行对比。如果无误则通过串口输出“Nand Flash is OK”否则输出“Nand Flash is error”。下图是运行结果: ![nand.png](/uploads/88_9721fc3eb7978a6f871f1913ad19afe2.png) ![NandFlash的基本使用.pdf](/uploads/88_afef443f4dfff77db54df4b8449d60c0.pdf) ![RealTouch_NandFlash.zip](/uploads/88_550df4ea2c839e18e1a518ec8a8ca30b.zip)
查看更多
1
个回答
默认排序
按发布时间排序
撰写答案
登录
注册新账号
关注者
0
被浏览
7.2k
关于作者
shaolin
这家伙很懒,什么也没写!
提问
115
回答
444
被采纳
0
关注TA
发私信
相关问题
1
[项目]搞个开源的硬件项目
2
硬件计划贴,及时更新,欢迎提意见
3
软件计划贴,及时更新,欢迎提意见::WMA,MOUNT,LWIP等问题急需解决.
4
MMS协议
5
定点的wma解压库-libwma
6
QQ群记录 [20090821]
7
STM32网络收音机PCB报名征集
8
第一版调试记录
9
第二版硬件讨论
10
RADIO项目相关模块规格--欢迎大家自己做板时规格与此兼容,减少重复劳动
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
2
RT-Thread 发布 EtherKit开源以太网硬件!
3
rt-thread使用cherryusb实现虚拟串口
4
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
5
《原子操作:程序世界里的“最小魔法单位”解析》
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
8
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
3
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部