STM32学习笔记——FSMC 驱动大容量NAND FLASH [复制链接]
2013-10-30 15:19
375 查看
本文原创于观海听涛,原作者版权所有,转载请注明出处。 近几天开发项目需要用到STM32驱动NAND FLASH,但由于开发板例程以及固件库是用于小页(512B),我要用到的FLASH为1G bit的大页(2K),多走了两天弯路。以下笔记将说明如何将默认固件库修改为大页模式以驱动大容量NAND,并作驱动。
本文硬件:控制器:STM32F103ZET6,存储器:HY27UF081G2A
首先说一下NOR与NAND存储器的区别,此类区别网上有很多,在此仅大致说明:
1、Nor读取速度比NAND稍快 2、Nand写入速度比Nor快很多 3、NAND擦除速度(4ms)远快于Nor(5s) 4、Nor 带有SRAM接口,有足够的地址引脚来寻址,可以很轻松的挂接到CPU地址和数据总线上,对CPU要求低 5、NAND用八个(或十六个)引脚串行读取数据,数据总线地址总线复用,通常需要CPU支持驱动,且较为复杂 6、Nor主要占据1-16M容量市场,并且可以片内执行,适合代码存储 7、NAND占据8-128M及以上市场,通常用来作数据存储 8、NAND便宜一些 9、NAND寿命比Nor长 10、NAND会产生坏块,需要做坏块处理和ECC 更详细区别请继续百度,以上内容部分摘自神舟三号开发板手册
下面是NAND的存储结构:
由此图可看出NAND存储结构为立体式 正如硬盘的盘片被分为磁道,每个磁道又分为若干扇区,一块nand flash也分为若干block,每个block分为如干page。一般而言,block、page之间的关系随着芯片的不同而不同。 需要注意的是,对于flash的读写都是以一个page开始的,但是在读写之前必须进行flash的擦写,而擦写则是以一个block为单位的。 我们这次使用的HY27UF081G2A其PDF介绍: Memory Cell Array = (2K+64) Bytes x 64 Pages x 1,024 Blocks 由此可见,该NAND每页2K,共64页,1024块。其中:每页中的2K为主容量Data Field,64bit为额外容量Spare Field。Spare Field用于存贮检验码和其他信息用的,并不能存放实际的数据。由此可算出系统总容量为2K*64*1024=134217728个byte,即1Gbit。 NAND闪存颗粒硬件接口: 由此图可见,此颗粒为八位总线,地址数据复用,芯片为SOP48封装。
软件驱动:(此部分写的是伪码,仅用于解释含义,可用代码参见附件) 主程序:
#define BUFFER_SIZE 0x2000 //此部分定义缓冲区大小,即一次写入的数据
#define NAND_HY_MakerID 0xAD //NAND厂商号
#define NAND_HY_DeviceID 0xF1 //NAND器件号
/*配置与SRAM连接的FSMC BANK2 NAND*/
NAND_Init();
/*读取Nand Flash ID并打印*/
NAND_ReadID(&NAND_ID);
复制代码
if((NAND_ID.Maker_ID == NAND_HY_MakerID) && (NAND_ID.Device_ID == NAND_HY_DeviceID)) //判断器件符合
{
/*设置NAND FLASH的写地址*/
WriteReadAddr.Zone = 0x00;
WriteReadAddr.Block = 0x00;
WriteReadAddr.Page = 0x05;
/*擦除待写入数据的块*/
status = NAND_EraseBlock(WriteReadAddr); //写入前必须擦出
/*将写Nand Flash的数据BUFFER填充为从0x25开始的连续递增的一串数据 */
Fill_Buffer(TxBuffer, BUFFER_SIZE , 0x25); //填充数据以测试
/*将数据写入到Nand Flash中。WriteReadAddr:读写的起始地址*/
status = NAND_WriteSmallPage(TxBuffer, WriteReadAddr, PageNumber); //主要写入函数,此部分默认为小页需要修改
/*从Nand Flash中读回刚写入的数据。riteReadAddr:读写的起始地址*/
status = NAND_ReadSmallPage (RxBuffer, WriteReadAddr, PageNumber); //读取主要函数,也需要修改
/*判断读回的数据与写入的数据是否一致*/
for(j = 0; j < BUFFER_SIZE; j++)
{
if(TxBuffer[j] != RxBuffer[j])
{
WriteReadStatus++;
}
}
if (WriteReadStatus == 0)
{
printf("\n\r Nand Flash读写访问成功");
GPIO_ResetBits(GPIO_LED, DS2_PIN);
}
else
{
printf("\n\r Nand Flash读写访问失败");
printf("0x%x",WriteReadStatus);
GPIO_ResetBits(GPIO_LED, DS3_PIN);
}
}
else
{
printf("\n\r 没有检测到Nand Flash的ID");
GPIO_ResetBits(GPIO_LED, DS4_PIN);
}
复制代码
fsmc_nand.c文件:
void NAND_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
FSMC_NAND_PCCARDTimingInitTypeDef p;
FSMC_NANDInitTypeDef FSMC_NANDInitStructure;
/*FSMC总线使用的GPIO组时钟使能*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG, ENABLE);
/*FSMC CLE, ALE, D0->D3, NOE, NWE and NCE2初始化,推挽复用输出*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_14 | GPIO_Pin_15 |
GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 |
GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/*FSMC数据线FSMC_D[4:7]初始化,推挽复用输出*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/*FSMC NWAIT初始化,输入上拉*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/*FSMC INT2初始化,输入上拉*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOG, &GPIO_InitStructure);
/*--------------FSMC 总线 存储器参数配置------------------------------*/
p.FSMC_SetupTime = 0x1; //建立时间
p.FSMC_WaitSetupTime = 0x3; //等待时间
p.FSMC_HoldSetupTime = 0x2; //保持时间
p.FSMC_HiZSetupTime = 0x1; //高阻建立时间
FSMC_NANDInitStructure.FSMC_Bank = FSMC_Bank2_NAND; //使用FSMC BANK2
FSMC_NANDInitStructure.FSMC_Waitfeature = FSMC_Waitfeature_Enable; //使能FSMC的等待功能
FSMC_NANDInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b; //NAND Flash的数据宽度为8位
FSMC_NANDInitStructure.FSMC_ECC = FSMC_ECC_Enable; //使能ECC特性
FSMC_NANDInitStructure.FSMC_ECCPageSize = FSMC_ECCPageSize_2048Bytes; //ECC页大小2048
FSMC_NANDInitStructure.FSMC_TCLRSetupTime = 0x00;
FSMC_NANDInitStructure.FSMC_TARSetupTime = 0x00;
FSMC_NANDInitStructure.FSMC_CommonSpaceTimingStruct = &p;
FSMC_NANDInitStructure.FSMC_AttributeSpaceTimingStruct = &p;
FSMC_NANDInit(&FSMC_NANDInitStructure);
/*!使能FSMC BANK2 */
FSMC_NANDCmd(FSMC_Bank2_NAND, ENABLE);
}
复制代码
void NAND_ReadID(NAND_IDTypeDef* NAND_ID)
{
uint32_t data = 0;
/*!< Send Command to the command area */
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = 0x90;
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = 0x00;
/*!< Sequence to read ID from NAND flash */
data = *(__IO uint32_t *)(Bank_NAND_ADDR | DATA_AREA);
NAND_ID->Maker_ID = ADDR_1st_CYCLE (data);//四个周期读取四个ID
NAND_ID->Device_ID = ADDR_2nd_CYCLE (data);
NAND_ID->Third_ID = ADDR_3rd_CYCLE (data);
NAND_ID->Fourth_ID = ADDR_4th_CYCLE (data);
}
复制代码
uint32_t NAND_WriteSmallPage(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 */
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_AREA_A;
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_WRITE0;
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = 0x00;
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = 0x00;//添加此句
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS);
// *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS);//原版有此句
/*!< Calculate the size */
size = NAND_PAGE_SIZE + (NAND_PAGE_SIZE * numpagewritten);//统计写入数目
/*!< Write data */
for(; index < size; index++)
{
*(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA) = pBuffer[index];
}
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_WRITE_TRUE1;
/*!< Check status for successful operation */
status = NAND_GetStatus();
if(status == NAND_READY)
{
numpagewritten++;
NumPageToWrite--;
/*!< Calculate Next small page Address */
addressstatus = NAND_AddressIncrement(&Address);
}
}
return (status | addressstatus);
}
复制代码
读取函数同理修改
uint32_t NAND_EraseBlock(NAND_ADDRESS Address)
{
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_ERASE0;
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS);
// *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS);//两次即可
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_ERASE1;
return (NAND_GetStatus());
}
复制代码
fsmc_nand.h文件:
#define NAND_PAGE_SIZE ((uint16_t)0x0800) /* 512 bytes per page w/o Spare Area *///每页2K
#define NAND_BLOCK_SIZE ((uint16_t)0x0040) /* 32x512 bytes pages per block *///64个页
#define NAND_ZONE_SIZE ((uint16_t)0x0400) /* 1024 Block per zone *///1024个快
#define NAND_SPARE_AREA_SIZE ((uint16_t)0x0040) /* last 16 bytes as spare area */
#define NAND_MAX_ZONE ((uint16_t)0x0001) /* 4 zones of 1024 block */
复制代码
修改完即可实现512B至2K每页的变更
本文参考:器件手册,蔡于清——NAND器件读写操作,百度搜索 QQ458729218 附件:有效程序,器件手册
本文硬件:控制器:STM32F103ZET6,存储器:HY27UF081G2A
首先说一下NOR与NAND存储器的区别,此类区别网上有很多,在此仅大致说明:
1、Nor读取速度比NAND稍快 2、Nand写入速度比Nor快很多 3、NAND擦除速度(4ms)远快于Nor(5s) 4、Nor 带有SRAM接口,有足够的地址引脚来寻址,可以很轻松的挂接到CPU地址和数据总线上,对CPU要求低 5、NAND用八个(或十六个)引脚串行读取数据,数据总线地址总线复用,通常需要CPU支持驱动,且较为复杂 6、Nor主要占据1-16M容量市场,并且可以片内执行,适合代码存储 7、NAND占据8-128M及以上市场,通常用来作数据存储 8、NAND便宜一些 9、NAND寿命比Nor长 10、NAND会产生坏块,需要做坏块处理和ECC 更详细区别请继续百度,以上内容部分摘自神舟三号开发板手册
下面是NAND的存储结构:
由此图可看出NAND存储结构为立体式 正如硬盘的盘片被分为磁道,每个磁道又分为若干扇区,一块nand flash也分为若干block,每个block分为如干page。一般而言,block、page之间的关系随着芯片的不同而不同。 需要注意的是,对于flash的读写都是以一个page开始的,但是在读写之前必须进行flash的擦写,而擦写则是以一个block为单位的。 我们这次使用的HY27UF081G2A其PDF介绍: Memory Cell Array = (2K+64) Bytes x 64 Pages x 1,024 Blocks 由此可见,该NAND每页2K,共64页,1024块。其中:每页中的2K为主容量Data Field,64bit为额外容量Spare Field。Spare Field用于存贮检验码和其他信息用的,并不能存放实际的数据。由此可算出系统总容量为2K*64*1024=134217728个byte,即1Gbit。 NAND闪存颗粒硬件接口: 由此图可见,此颗粒为八位总线,地址数据复用,芯片为SOP48封装。
软件驱动:(此部分写的是伪码,仅用于解释含义,可用代码参见附件) 主程序:
#define BUFFER_SIZE 0x2000 //此部分定义缓冲区大小,即一次写入的数据
#define NAND_HY_MakerID 0xAD //NAND厂商号
#define NAND_HY_DeviceID 0xF1 //NAND器件号
/*配置与SRAM连接的FSMC BANK2 NAND*/
NAND_Init();
/*读取Nand Flash ID并打印*/
NAND_ReadID(&NAND_ID);
复制代码
Tips:NAND器件的ID包含四部分: 1st Manufacturer Code
2nd Device Identifier 3rd Internal chip number, cell Type, Number of Simultaneously Programmed pages. 4th Page size, spare size, Block size, Organization
2nd Device Identifier 3rd Internal chip number, cell Type, Number of Simultaneously Programmed pages. 4th Page size, spare size, Block size, Organization
if((NAND_ID.Maker_ID == NAND_HY_MakerID) && (NAND_ID.Device_ID == NAND_HY_DeviceID)) //判断器件符合
{
/*设置NAND FLASH的写地址*/
WriteReadAddr.Zone = 0x00;
WriteReadAddr.Block = 0x00;
WriteReadAddr.Page = 0x05;
/*擦除待写入数据的块*/
status = NAND_EraseBlock(WriteReadAddr); //写入前必须擦出
/*将写Nand Flash的数据BUFFER填充为从0x25开始的连续递增的一串数据 */
Fill_Buffer(TxBuffer, BUFFER_SIZE , 0x25); //填充数据以测试
/*将数据写入到Nand Flash中。WriteReadAddr:读写的起始地址*/
status = NAND_WriteSmallPage(TxBuffer, WriteReadAddr, PageNumber); //主要写入函数,此部分默认为小页需要修改
/*从Nand Flash中读回刚写入的数据。riteReadAddr:读写的起始地址*/
status = NAND_ReadSmallPage (RxBuffer, WriteReadAddr, PageNumber); //读取主要函数,也需要修改
/*判断读回的数据与写入的数据是否一致*/
for(j = 0; j < BUFFER_SIZE; j++)
{
if(TxBuffer[j] != RxBuffer[j])
{
WriteReadStatus++;
}
}
if (WriteReadStatus == 0)
{
printf("\n\r Nand Flash读写访问成功");
GPIO_ResetBits(GPIO_LED, DS2_PIN);
}
else
{
printf("\n\r Nand Flash读写访问失败");
printf("0x%x",WriteReadStatus);
GPIO_ResetBits(GPIO_LED, DS3_PIN);
}
}
else
{
printf("\n\r 没有检测到Nand Flash的ID");
GPIO_ResetBits(GPIO_LED, DS4_PIN);
}
复制代码
fsmc_nand.c文件:
void NAND_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
FSMC_NAND_PCCARDTimingInitTypeDef p;
FSMC_NANDInitTypeDef FSMC_NANDInitStructure;
/*FSMC总线使用的GPIO组时钟使能*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG, ENABLE);
/*FSMC CLE, ALE, D0->D3, NOE, NWE and NCE2初始化,推挽复用输出*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_14 | GPIO_Pin_15 |
GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 |
GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/*FSMC数据线FSMC_D[4:7]初始化,推挽复用输出*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/*FSMC NWAIT初始化,输入上拉*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/*FSMC INT2初始化,输入上拉*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOG, &GPIO_InitStructure);
/*--------------FSMC 总线 存储器参数配置------------------------------*/
p.FSMC_SetupTime = 0x1; //建立时间
p.FSMC_WaitSetupTime = 0x3; //等待时间
p.FSMC_HoldSetupTime = 0x2; //保持时间
p.FSMC_HiZSetupTime = 0x1; //高阻建立时间
FSMC_NANDInitStructure.FSMC_Bank = FSMC_Bank2_NAND; //使用FSMC BANK2
FSMC_NANDInitStructure.FSMC_Waitfeature = FSMC_Waitfeature_Enable; //使能FSMC的等待功能
FSMC_NANDInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b; //NAND Flash的数据宽度为8位
FSMC_NANDInitStructure.FSMC_ECC = FSMC_ECC_Enable; //使能ECC特性
FSMC_NANDInitStructure.FSMC_ECCPageSize = FSMC_ECCPageSize_2048Bytes; //ECC页大小2048
FSMC_NANDInitStructure.FSMC_TCLRSetupTime = 0x00;
FSMC_NANDInitStructure.FSMC_TARSetupTime = 0x00;
FSMC_NANDInitStructure.FSMC_CommonSpaceTimingStruct = &p;
FSMC_NANDInitStructure.FSMC_AttributeSpaceTimingStruct = &p;
FSMC_NANDInit(&FSMC_NANDInitStructure);
/*!使能FSMC BANK2 */
FSMC_NANDCmd(FSMC_Bank2_NAND, ENABLE);
}
复制代码
void NAND_ReadID(NAND_IDTypeDef* NAND_ID)
{
uint32_t data = 0;
/*!< Send Command to the command area */
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = 0x90;
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = 0x00;
/*!< Sequence to read ID from NAND flash */
data = *(__IO uint32_t *)(Bank_NAND_ADDR | DATA_AREA);
NAND_ID->Maker_ID = ADDR_1st_CYCLE (data);//四个周期读取四个ID
NAND_ID->Device_ID = ADDR_2nd_CYCLE (data);
NAND_ID->Third_ID = ADDR_3rd_CYCLE (data);
NAND_ID->Fourth_ID = ADDR_4th_CYCLE (data);
}
复制代码
uint32_t NAND_WriteSmallPage(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 */
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_AREA_A;
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_WRITE0;
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = 0x00;
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = 0x00;//添加此句
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS);
// *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS);//原版有此句
/*!< Calculate the size */
size = NAND_PAGE_SIZE + (NAND_PAGE_SIZE * numpagewritten);//统计写入数目
/*!< Write data */
for(; index < size; index++)
{
*(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA) = pBuffer[index];
}
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_WRITE_TRUE1;
/*!< Check status for successful operation */
status = NAND_GetStatus();
if(status == NAND_READY)
{
numpagewritten++;
NumPageToWrite--;
/*!< Calculate Next small page Address */
addressstatus = NAND_AddressIncrement(&Address);
}
}
return (status | addressstatus);
}
复制代码
读取函数同理修改
uint32_t NAND_EraseBlock(NAND_ADDRESS Address)
{
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_ERASE0;
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS);
// *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS);//两次即可
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_ERASE1;
return (NAND_GetStatus());
}
复制代码
fsmc_nand.h文件:
#define NAND_PAGE_SIZE ((uint16_t)0x0800) /* 512 bytes per page w/o Spare Area *///每页2K
#define NAND_BLOCK_SIZE ((uint16_t)0x0040) /* 32x512 bytes pages per block *///64个页
#define NAND_ZONE_SIZE ((uint16_t)0x0400) /* 1024 Block per zone *///1024个快
#define NAND_SPARE_AREA_SIZE ((uint16_t)0x0040) /* last 16 bytes as spare area */
#define NAND_MAX_ZONE ((uint16_t)0x0001) /* 4 zones of 1024 block */
复制代码
修改完即可实现512B至2K每页的变更
本文参考:器件手册,蔡于清——NAND器件读写操作,百度搜索 QQ458729218 附件:有效程序,器件手册
相关文章推荐
- STM32 FSMC学习笔记+补充(LCD的FSMC配置)
- STM32 FSMC学习笔记
- STM32学习笔记:FSMC详述
- NAND FLASH学习笔记之MTD下nand flash驱动(一)
- STM32 FSMC学习笔记
- STM32 FSMC 学习笔记
- STM32 FSMC学习笔记
- NAND FLASH学习笔记之MTD下nand flash驱动(二)————几个重要文件和几个重要的结构体
- STM32 FSMC学习笔记+补充(LCD的FSMC配置)
- NAND FLASH学习笔记之MTD下nand flash驱动(四)
- STM32的FSMC驱动TFT笔记
- 寒假学习之stm32(10)----显存,fsmc, LCD的驱动(待解决。。)
- STM32 FSMC学习笔记+补充(LCD的FSMC配置)
- STM32学习笔记之 USB驱动usb_endp.c文件和usb_istr.c文件分析
- NAND FLASH学习笔记之MTD下nand flash驱动(五)
- cortex_m3_stm32嵌入式学习笔记(二十二):触摸屏实验(触摸屏驱动)
- NAND FLASH学习笔记之MTD下nand flash驱动(六)
- 【linux学习笔记】硬链接和符号链接以及复制的区别
- STM32 FSMC学习笔记
- NAND FLASH学习笔记之MTD下nand flash驱动(七)---我的调试