1、初始化
void FSMC_NAND_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; FSMC_NANDInitTypeDef FSMC_NANDInitStructure; FSMC_NAND_PCCARDTimingInitTypeDef p; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE); /*-- GPIO Configuration ------------------------------------------------------*//* CLE, ALE, D0->D3, NOE, NWE and NCE2 NAND pin configuration */ 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); /* D4->D7 NAND pin configuration */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10; GPIO_Init(GPIOE, &GPIO_InitStructure);/* NWAIT NAND pin configuration 读/忙输出引脚定义可能不一样*/ 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 Configuration ------------------------------------------------------*/ p.FSMC_SetupTime = 0x1; p.FSMC_WaitSetupTime = 0x3; p.FSMC_HoldSetupTime = 0x2; p.FSMC_HiZSetupTime = 0x1; FSMC_NANDInitStructure.FSMC_Bank = FSMC_Bank2_NAND; FSMC_NANDInitStructure.FSMC_Waitfeature = FSMC_Waitfeature_Disable; FSMC_NANDInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b; FSMC_NANDInitStructure.FSMC_ECC = FSMC_ECC_Disable; //FSMC_ECC_Enable; // FSMC_NANDInitStructure.FSMC_ECCPageSize = FSMC_ECCPageSize_512Bytes; FSMC_NANDInitStructure.FSMC_TCLRSetupTime = 0x00; //×?éù10ns,????oóμ??μê?(1+1+4)*HCLK=82.8ns FSMC_NANDInitStructure.FSMC_TARSetupTime = 0x00; //×?éù10ns,????oóμ??μê?(1+1+4)*HCLK=82.8ns FSMC_NANDInitStructure.FSMC_CommonSpaceTimingStruct = &p; FSMC_NANDInitStructure.FSMC_AttributeSpaceTimingStruct = &p; FSMC_NANDInit(&FSMC_NANDInitStructure); FSMC_NANDCmd(FSMC_Bank2_NAND, ENABLE); FSMC_NAND_Reset();}
2、HY27US08561A 页、块 大小定义
/* FSMC NAND memory parameters *///HY27US08561A 512bit*32page*1024block*2zone#define NAND_PAGE_SIZE ((u16)0x0200) /* 512 bytes per page w/o Spare Area */#define NAND_BLOCK_SIZE ((u16)0x0020) /* 32x512 bytes pages per block */#define NAND_ZONE_SIZE ((u16)0x0400) /* 1024 Block per zone */#define NAND_SPARE_AREA_SIZE ((u16)0x0010) /* last 16 bytes as spare area */
#define NAND_MAX_ZONE ((u16)0x0002) /* 2 zones of 1024 block */
3、寄存器地址定义
#define NAND_FLASH_START_ADDR 0X70000000//地址区0x020000~0x03FFFF软件只需对命令区的任意一个地址写入命令即可
#define CMD_AREA 1<<16 //发送命令
#define ADDR_AREA 1<<17 //发送地址
4、测试
#include "fsmc_nand.h"static u8 RxBuf1[NAND_PAGE_SIZE]={11};//接收数据数组1static u8 TxBuf1[NAND_PAGE_SIZE]={0};;//fs数据数组2 NAND_ADDRESS WriteReadAddr;void FSMC_readdata(NAND_ADDRESS Address){ FSMC_NAND_ReadSmallPage(RxBuf1, Address,1);}void textr(){ WriteReadAddr.Zone = 0x00; WriteReadAddr.Block = 0x00; WriteReadAddr.Page = 0x00; FSMC_readdata(WriteReadAddr); SP=RxBuf1[0];//测试一个字节}void textw(){ WriteReadAddr.Zone = 0x00; WriteReadAddr.Block = 0x00; WriteReadAddr.Page = 0x00; TxBuf1[0]=p[PB1];//改变测试数据 FSMC_NAND_EraseBlock(WriteReadAddr);FSMC_NAND_WriteSmallPage(TxBuf1, WriteReadAddr, 1); }
5、读写代码
/*读页*/
uint32_t FSMC_NAND_ReadSmallPage(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; //0x00读命令 *(vu8 *)(NAND_FLASH_START_ADDR | ADDR_AREA) = 0x00;//前两字节为column地址 *(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); *(vu8 *)(NAND_FLASH_START_ADDR | CMD_AREA) = NAND_CMD_READ_TRUE;//0x30 /* 读忙脚 */ while( GPIO_ReadInputDataBit(GPIOD, 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);}
/*写页*/
uint32_t FSMC_NAND_WriteSmallPage(const 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); /* 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(GPIOD, GPIO_Pin_6) == 0 ); /* Check status for successful operation */ status = FSMC_NAND_GetStatus(); if(status == NAND_READY) { numpagewritten++; NumPageToWrite--; /* Calculate Next small page Address */ addressstatus = FSMC_NAND_AddressIncrement(&Address); } } return (status | addressstatus);}