STM32 FSMC NAND控制器 驱动NAND FLASH 注意事项

xiaoxiao2021-02-28  26

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);}

转载请注明原文地址: https://www.6miu.com/read-2400347.html

最新回复(0)