首页 > 代码库 > STM32-移植FATFS的NANDFLASH驱动
STM32-移植FATFS的NANDFLASH驱动
一,建立工程FATFS源码
1,在http://elm-chan.org/fsw/ff/00index_e.html上下载ff007c.zip,并把ff007c.zip里面的
src文件夹复制到D:\works\EK-STM3210E-UCOSII下,并改名为Fatfs;
2,在IDE工程中右击选择“Add Group”建立“FATFS”文件组,并在“FATFS”上右击选择“Add Files”添加
D:\works\EK-STM3210E-UCOSII\Fatfs下的C文件;
3,把D:\works\EK-STM3210E-UCOSII\Fatfs文件夹目录添加到项目头文件搜索路径中,如:
$PROJ_DIR$\..\..\Fatfs
二,移植NANDFLASH驱动接口
1,把stm32f10x_stdperiph_lib_v3.0.0\Project\Examples\FSMC\NAND下的fsmc_nand.c复制到
D:\works\EK-STM3210E-UCOSII\Drivers下,并加入到工程的DRV文件组;
2,把stm32f10x_stdperiph_lib_v3.0.0\Project\Examples\FSMC\NAND下的fsmc_nand.h复制到
D:\works\EK-STM3210E-UCOSII\Include下;
3,在fsmc_nand.c前添加上#include "stm32f10x_conf.h",并把系统中的 "stm32f10x_conf.h"
文件的/* #include "stm32f10x_fsmc.h" */注释打开;
三,修改FATFS的配置文件
1,把D:\works\EK-STM3210E-UCOSII\Fatfs下的ff.h中的宏定义:
- #define _USE_MKFS 0
- #define _CODE_PAGE 932
- #define _FS_RPATH 0
- #define _MAX_SS 512
- 修改为:
- #define _USE_MKFS 1
- #define _CODE_PAGE 936
- #define _MAX_SS <span style="font-size:18px;color:#3333ff;">2048
- </span> #define _FS_RPATH 1
2,把D:\works\EK-STM3210E-UCOSII\Fatfs下的integer.h的宏定义:
- typedef enum { FALSE = 0, TRUE } BOOL;
- 修改为:
- typedef bool BOOL;//typedef enum { FALSE = 0, TRUE } BOOL;
四,修改FATFS的DISK/IO接口
1,把diskio.c复制后改名为nandio.c替换掉工程中的diskio.c,并添加到EWARM的工程中的
“FATFS”文件组;
2,媒介初始化直接返回正常的0:
- DSTATUS disk_initialize (BYTE drv)
- { return 0;}
3,媒介状态查询直接返回正常的0:
- DSTATUS disk_status (BYTE drv)
- { return 0;}
4,取系统系统直接返回0(自己可以按格式修改为真实时间):
- DWORD get_fattime (void)
- { return 0;}
5,媒介控制接口:
- DRESULT disk_ioctl (BYTE drv,BYTE ctrl, void *buff)
- {
- DRESULT res = RES_OK;
- uint32_t result;
- if (drv){ return RES_PARERR;}
- switch(ctrl)
- {
- case CTRL_SYNC:
- break;
- case GET_BLOCK_SIZE:
- <span style="color:#000099;">*(DWORD*)buff = NAND_BLOCK_SIZE</span>;
- break;
- case GET_SECTOR_COUNT:
- <span style="color:#000099;">*(DWORD*)buff = (((NAND_MAX_ZONE/2) * NAND_ZONE_SIZE) * NAND_BLOCK_SIZE);
- </span> break;
- case GET_SECTOR_SIZE:
- <span style="color:#000099;">*(WORD*)buff = NAND_PAGE_SIZE;
- </span> break;
- default:
- <span style="color:#000099;"> res = RES_PARERR;
- </span> break;
- }
- return res;
- }
6,媒介多扇区读接口:
- DRESULT disk_read (BYTE drv,BYTE *buff,DWORD sector,BYTE count)
- {
- uint32_t result;
- if (drv || !count){ return RES_PARERR;}
- result = FSMC_NAND_ReadSmallPage(buff, sector, count);
- if(result & NAND_READY){ return RES_OK; }
- else { return RES_ERROR; }
- }
7,媒介多扇区写接口:
- #if _READONLY == 0
- DRESULT disk_write (BYTE drv,const BYTE *buff,DWORD sector,BYTE count)
- {
- uint32_t result;
- uint32_t BackupBlockAddr;
- uint32_t WriteBlockAddr;
- uint16_t IndexTmp = 0;
- uint16_t OffsetPage;
- /* NAND memory write page at block address*/
- WriteBlockAddr = (sector/NAND_BLOCK_SIZE);
- /* NAND memory backup block address*/
- BackupBlockAddr = (WriteBlockAddr + (NAND_MAX_ZONE/2)*NAND_ZONE_SIZE);
- OffsetPage = sector%NAND_BLOCK_SIZE;
- if (drv || !count){ return RES_PARERR;}
- /* Erase the NAND backup Block */
- result = FSMC_NAND_EraseBlock(BackupBlockAddr*NAND_BLOCK_SIZE);
- /* Backup the NAND Write Block to High zone*/
- for (IndexTmp = 0; IndexTmp < NAND_BLOCK_SIZE; IndexTmp++ )
- {
- FSMC_NAND_MoveSmallPage (WriteBlockAddr*NAND_BLOCK_SIZE+IndexTmp,BackupBlockAddr*NAND_BLOCK_SIZE+IndexTmp);
- }
- /* Erase the NAND Write Block */
- result = FSMC_NAND_EraseBlock(WriteBlockAddr*NAND_BLOCK_SIZE);
- /*return write the block with modify*/
- for (IndexTmp = 0; IndexTmp < NAND_BLOCK_SIZE; IndexTmp++ )
- {
- if((IndexTmp>=OffsetPage)&&(IndexTmp < (OffsetPage+count)))
- {
- FSMC_NAND_WriteSmallPage((uint8_t *)buff, WriteBlockAddr*NAND_BLOCK_SIZE+IndexTmp, 1);
- buff = (uint8_t *)buff + NAND_PAGE_SIZE;
- }
- else
- {
- FSMC_NAND_MoveSmallPage (BackupBlockAddr*NAND_BLOCK_SIZE+IndexTmp,WriteBlockAddr*NAND_BLOCK_SIZE+IndexTmp);
- }
- }
- if(result == NAND_READY){ return RES_OK;}
- else { return RES_ERROR;}
- }
- #endif /* _READONLY */
五,调用接口及测试代码
1,调用接口,先初始化FSMC和NANDFLASH:
- //NANDFLASH HY27UF081G2A-TPCB
- #define NAND_HY_MakerID 0xAD
- #define NAND_HY_DeviceID 0xF1
- /* Configure the NAND FLASH */
- void NAND_Configuration(void)
- {
- NAND_IDTypeDef NAND_ID;
- /* Enable the FSMC Clock */
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
- /* FSMC Initialization */
- FSMC_NAND_Init();
- /* NAND read ID command */
- FSMC_NAND_ReadID(&NAND_ID);
- /* Verify the NAND ID */
- if((NAND_ID.Maker_ID == NAND_ST_MakerID) && (NAND_ID.Device_ID == NAND_ST_DeviceID))
- {
- printf("ST NANDFLASH");
- }
- else
- if((NAND_ID.Maker_ID == NAND_HY_MakerID) && (NAND_ID.Device_ID == NAND_HY_DeviceID))
- {
- printf("HY27UF081G2A-TPCB");
- }
- printf(" ID = 0x%x%x%x%x \n\r",NAND_ID.Maker_ID,NAND_ID.Device_ID,NAND_ID.Third_ID,NAND_ID.Fourth_ID);
- }
2,然后对媒介格式化,创建读写文件:
- void test_fatfs(void)
- {
- FATFS fs;
- FIL fl;
- FATFS *pfs;
- DWORD clust;
- unsigned int r,w,i;
- FRESULT res;
- // NF_CHKDSK(0,1024);
- display_page(0,0);
- // for mount
- res=f_mount(0,&fs);
- printf("f_mount=%x \n\r",res);
- // for format
- //res=f_mkfs(0,1,2048); //MUST Format for New NANDFLASH !!!
- //printf("f_mkfs=%x \n\r",res);
- // for
- pfs=&fs;
- res = f_getfree("/", &clust, &pfs);
- printf("f_getfree=%x \n\r",res);
- printf("\n\r%lu MB total drive space."
- "\n\r%lu MB available.\n\r",
- (DWORD)(pfs->max_clust - 2) * pfs->csize /2/1024,
- clust * pfs->csize /2/1024);
- // for read
- res=f_open(&fl,"/test2.dat",FA_OPEN_EXISTING | FA_READ);
- printf("f_open=%x \n\r",res);
- for(i=0;i<2;i++)
- {
- for(r = 0; r < NAND_PAGE_SIZE; r++)
- {
- RxBuffer[r]= 0xff;
- }
- res=f_read(&fl,RxBuffer,NAND_PAGE_SIZE,&r);
- printf("f_read=%x \n\r",res);
- if(res || r == 0)break;
- for(r = 0; r < NAND_PAGE_SIZE; r++)
- {
- printf("D[%08x]=%02x ",(i*NAND_PAGE_SIZE+r),RxBuffer[r]);
- if((r%8)==7)
- {printf("\n\r");}
- }
- }
- f_close(&fl);
- // for write
- res=f_open(&fl,"/test2.dat",FA_CREATE_ALWAYS | FA_WRITE);
- printf("f_open=%x \n\r",res);
- for(i=0;i<2;i++)
- {
- for(w = 0; w < NAND_PAGE_SIZE; w++)
- {
- TxBuffer[w]=((w<<0)&0xff);
- }
- res=f_write(&fl,TxBuffer,NAND_PAGE_SIZE,&w);
- printf("f_write=%x \n\r",res);
- if(res || w
- }
- f_close(&fl);
- // for umount
- f_mount(0,NULL);
- }
六,编写NANDFLASH接口
1,fsmc_nand.c文件:
- /* Includes ------------------------------------------------------------------*/
- #include "fsmc_nand.h"
- #include "stm32f10x_conf.h"
- /** @addtogroup StdPeriph_Examples
- * @{
- */
- /** @addtogroup FSMC_NAND
- * @{
- */
- /* Private typedef -----------------------------------------------------------*/
- /* Private define ------------------------------------------------------------*/
- #define FSMC_Bank_NAND FSMC_Bank2_NAND
- #define Bank_NAND_ADDR Bank2_NAND_ADDR
- #define Bank2_NAND_ADDR ((uint32_t)0x70000000)
- /* Private macro -------------------------------------------------------------*/
- /* Private variables ---------------------------------------------------------*/
- /* Private function prototypes -----------------------------------------------*/
- /* Private functions ---------------------------------------------------------*/
- /**
- * @brief Configures the FSMC and GPIOs to interface with the NAND memory.
- * This function must be called before any write/read operation
- * on the NAND.
- * @param None
- * @retval : None
- */
- void FSMC_NAND_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- FSMC_NANDInitTypeDef FSMC_NANDInitStructure;
- FSMC_NAND_PCCARDTimingInitTypeDef p;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
- RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG, 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);
- /* INT2 NAND pin configuration */
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
- GPIO_Init(GPIOG, &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_Enable;
- FSMC_NANDInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b;
- FSMC_NANDInitStructure.FSMC_ECC = FSMC_ECC_Enable;
- FSMC_NANDInitStructure.FSMC_ECCPageSize = FSMC_ECCPageSize_512Bytes;
- 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 NAND Bank Cmd Test */
- FSMC_NANDCmd(FSMC_Bank2_NAND, ENABLE);
- }
- /**
- * @brief Reads NAND memory‘s ID.
- * @param NAND_ID: pointer to a NAND_IDTypeDef structure which will hold
- * the Manufacturer and Device ID.
- * @retval : None
- */
- void FSMC_NAND_ReadID(NAND_IDTypeDef* NAND_ID)
- {
- uint32_t data = 0;
- /* Send Command to the command area */
- *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_READID;
- /* Send Address to the address area */
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = NAND_CMD_IDADDR;
- /* Sequence to read ID from NAND flash */
- data = *(__IO uint32_t *)(Bank_NAND_ADDR | DATA_AREA);
- NAND_ID->Maker_ID = DATA_1st_CYCLE (data);
- NAND_ID->Device_ID = DATA_2nd_CYCLE (data);
- NAND_ID->Third_ID = DATA_3rd_CYCLE (data);
- NAND_ID->Fourth_ID = DATA_4th_CYCLE (data);
- }
- /**
- * @brief This routine is for move one 2048 Bytes Page size to an other 2048 Bytes Page.
- * the copy-back program is permitted just between odd address pages or even address pages.
- * @param SourcePageAddress: Source page address
- * @param TargetPageAddress: Target page address
- * @retval : New status of the NAND operation. This parameter can be:
- * - NAND_TIMEOUT_ERROR: when the previous operation generate
- * a Timeout error
- * - NAND_READY: when memory is ready for the next operation
- * And the new status of the increment address operation. It can be:
- * - NAND_VALID_ADDRESS: When the new address is valid address
- * - NAND_INVALID_ADDRESS: When the new address is invalid address
- */
- uint32_t FSMC_NAND_MoveSmallPage(uint32_t SourcePageAddress, uint32_t TargetPageAddress)
- {
- uint32_t status = NAND_READY ;
- uint32_t data = 0xff;
- /* Page write command and address */
- *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_MOVE0;
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(SourcePageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(SourcePageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(SourcePageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(SourcePageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_MOVE1;
- while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
- *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_MOVE2;
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(TargetPageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(TargetPageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(TargetPageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(TargetPageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_MOVE3;
- while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
- /* Check status for successful operation */
- status = FSMC_NAND_GetStatus();
- data = *(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA);
- if(!(data&0x1)) status = NAND_READY;
- return (status);
- }
- /**
- * @brief This routine is for writing one or several 2048 Bytes Page size.
- * @param pBuffer: pointer on the Buffer containing data to be written
- * @param PageAddress: First page address
- * @param NumPageToWrite: Number of page to write
- * @retval : New status of the NAND operation. This parameter can be:
- * - NAND_TIMEOUT_ERROR: when the previous operation generate
- * a Timeout error
- * - NAND_READY: when memory is ready for the next operation
- * And the new status of the increment address operation. It can be:
- * - NAND_VALID_ADDRESS: When the new address is valid address
- * - NAND_INVALID_ADDRESS: When the new address is invalid address
- */
- uint32_t FSMC_NAND_WriteSmallPage(uint8_t *pBuffer, uint32_t PageAddress, uint32_t NumPageToWrite)
- {
- uint32_t index = 0x00, numpagewritten = 0x00,addressstatus = NAND_VALID_ADDRESS;
- uint32_t status = NAND_READY, size = 0x00;
- uint32_t data = 0xff;
- 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_WRITE0;
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(PageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(PageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(PageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(PageAddress);
- /* 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_WRITE1;
- while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
- /* Check status for successful operation */
- status = FSMC_NAND_GetStatus();
- data = *(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA);
- if(!(data&0x1)) status = NAND_READY;
- if(status == NAND_READY)
- {
- numpagewritten++; NumPageToWrite--;
- /* Calculate Next small page Address */
- if(PageAddress++ > (NAND_MAX_ZONE*NAND_ZONE_SIZE*NAND_BLOCK_SIZE))
- { addressstatus = NAND_INVALID_ADDRESS;}
- }
- }
- return (status | addressstatus);
- }
- /**
- * @brief This routine is for sequential read from one or several
- * 2048 Bytes Page size.
- * @param pBuffer: pointer on the Buffer to fill
- * @param PageAddress: First page address
- * @param NumPageToRead: Number of page to read
- * @retval : New status of the NAND operation. This parameter can be:
- * - NAND_TIMEOUT_ERROR: when the previous operation generate
- * a Timeout error
- * - NAND_READY: when memory is ready for the next operation
- * And the new status of the increment address operation. It can be:
- * - NAND_VALID_ADDRESS: When the new address is valid address
- * - NAND_INVALID_ADDRESS: When the new address is invalid address
- */
- uint32_t FSMC_NAND_ReadSmallPage(uint8_t *pBuffer, uint32_t PageAddress, uint32_t NumPageToRead)
- {
- uint32_t index = 0x00, numpageread = 0x00, addressstatus = NAND_VALID_ADDRESS;
- uint32_t status = NAND_READY, size = 0x00;
- *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_READ1;
- while((NumPageToRead != 0x0) && (addressstatus == NAND_VALID_ADDRESS))
- {
- /* Page Read command and page address */
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(PageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(PageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(PageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(PageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_READ2;
- 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]= *(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA);
- }
- numpageread++; NumPageToRead--;
- /* Calculate page address */
- if(PageAddress++ > (NAND_MAX_ZONE*NAND_ZONE_SIZE*NAND_BLOCK_SIZE))
- { addressstatus = NAND_INVALID_ADDRESS;}
- }
- status = FSMC_NAND_GetStatus();
- return (status | addressstatus);
- }
- /**
- * @brief This routine erase complete block from NAND FLASH
- * @param PageAddress: Any address into block to be erased
- * @retval :New status of the NAND operation. This parameter can be:
- * - NAND_TIMEOUT_ERROR: when the previous operation generate
- * a Timeout error
- * - NAND_READY: when memory is ready for the next operation
- */
- uint32_t FSMC_NAND_EraseBlock(uint32_t PageAddress)
- {
- uint32_t data = 0xff, status = NAND_ERROR;
- *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_ERASE0;
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(PageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(PageAddress);
- *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_ERASE1;
- while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
- /* Read status operation ------------------------------------ */
- FSMC_NAND_GetStatus();
- data = *(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA);
- if(!(data&0x1)) status = NAND_READY;
- return (status);
- }
- /**
- * @brief This routine reset the NAND FLASH
- * @param None
- * @retval :NAND_READY
- */
- uint32_t FSMC_NAND_Reset(void)
- {
- *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_RESET;
- return (NAND_READY);
- }
- /**
- * @brief Get the NAND operation status
- * @param None
- * @retval :New status of the NAND operation. This parameter can be:
- * - NAND_TIMEOUT_ERROR: when the previous operation generate
- * a Timeout error
- * - NAND_READY: when memory is ready for the next operation
- */
- uint32_t FSMC_NAND_GetStatus(void)
- {
- uint32_t timeout = 0x1000000, status = NAND_READY;
- status = FSMC_NAND_ReadStatus();
- /* Wait for a NAND operation to complete or a TIMEOUT to occur */
- while ((status != NAND_READY) &&( timeout != 0x00))
- {
- status = FSMC_NAND_ReadStatus();
- timeout --;
- }
- if(timeout == 0x00)
- {
- status = NAND_TIMEOUT_ERROR;
- }
- /* Return the operation status */
- return (status);
- }
- /**
- * @brief Reads the NAND memory status using the Read status command
- * @param None
- * @retval :The status of the NAND memory. This parameter can be:
- * - NAND_BUSY: when memory is busy
- * - NAND_READY: when memory is ready for the next operation
- * - NAND_ERROR: when the previous operation gererates error
- */
- uint32_t FSMC_NAND_ReadStatus(void)
- {
- uint32_t data = 0x00, status = NAND_BUSY;
- /* Read status operation ------------------------------------ */
- *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_STATUS;
- data = *(__IO uint8_t *)(Bank_NAND_ADDR);
- if((data & NAND_ERROR) == NAND_ERROR)
- {
- status = NAND_ERROR;
- }
- else if((data & NAND_READY) == NAND_READY)
- {
- status = NAND_READY;
- }
- else
- {
- status = NAND_BUSY;
- }
- return (status);
- }
2,fsmc_nand.h文件:
- /* Define to prevent recursive inclusion -------------------------------------*/
- #ifndef __FSMC_NAND_H
- #define __FSMC_NAND_H
- /* Includes ------------------------------------------------------------------*/
- #include "stm32f10x.h"
- /* Exported types ------------------------------------------------------------*/
- typedef struct
- {
- uint8_t Maker_ID;
- uint8_t Device_ID;
- uint8_t Third_ID;
- uint8_t Fourth_ID;
- }NAND_IDTypeDef;
- typedef struct
- {
- uint16_t Zone;
- uint16_t Block;
- uint16_t Page;
- } NAND_ADDRESS;
- /* Exported constants --------------------------------------------------------*/
- /* NAND Area definition for STM3210E-EVAL Board RevD */
- #define CMD_AREA (uint32_t)(1<<16) /* A16 = CLE high */
- #define ADDR_AREA (uint32_t)(1<<17) /* A17 = ALE high */
- #define DATA_AREA ((uint32_t)0x00000000)
- /* FSMC NAND memory command */
- #define NAND_CMD_READ1 ((uint8_t)0x00)
- #define NAND_CMD_READ2 ((uint8_t)0x30)
- #define NAND_CMD_WRITE0 ((uint8_t)0x80)
- #define NAND_CMD_WRITE1 ((uint8_t)0x10)
- #define NAND_CMD_MOVE0 ((uint8_t)0x00)
- #define NAND_CMD_MOVE1 ((uint8_t)0x35)
- #define NAND_CMD_MOVE2 ((uint8_t)0x85)
- #define NAND_CMD_MOVE3 ((uint8_t)0x10)
- #define NAND_CMD_ERASE0 ((uint8_t)0x60)
- #define NAND_CMD_ERASE1 ((uint8_t)0xD0)
- #define NAND_CMD_READID ((uint8_t)0x90)
- #define NAND_CMD_IDADDR ((uint8_t)0x00)
- #define NAND_CMD_STATUS ((uint8_t)0x70)
- #define NAND_CMD_RESET ((uint8_t)0xFF)
- /* NAND memory status */
- #define NAND_VALID_ADDRESS ((uint32_t)0x00000100)
- #define NAND_INVALID_ADDRESS ((uint32_t)0x00000200)
- #define NAND_TIMEOUT_ERROR ((uint32_t)0x00000400)
- #define NAND_BUSY ((uint32_t)0x00000000)
- #define NAND_ERROR ((uint32_t)0x00000001)
- #define NAND_READY ((uint32_t)0x00000040)
- /* FSMC NAND memory parameters */
- //#define NAND_PAGE_SIZE ((uint16_t)0x0200) /* 512 bytes per page w/o Spare Area */
- //#define NAND_BLOCK_SIZE ((uint16_t)0x0020) /* 32x512 bytes pages per block */
- //#define NAND_ZONE_SIZE ((uint16_t)0x0400) /* 1024 Block per zone */
- //#define NAND_SPARE_AREA_SIZE ((uint16_t)0x0010) /* last 16 bytes as spare area */
- //#define NAND_MAX_ZONE ((uint16_t)0x0004) /* 4 zones of 1024 block */
- /* FSMC NAND memory HY27UF081G2A-TPCB parameters */
- #define NAND_PAGE_SIZE ((uint16_t)0x0800) /* 2048 bytes per page w/o Spare Area */
- #define NAND_BLOCK_SIZE ((uint16_t)0x0040) /* 64x2048 bytes pages per block */
- #define NAND_ZONE_SIZE ((uint16_t)0x0200) /* 512 Block per zone */
- #define NAND_SPARE_AREA_SIZE ((uint16_t)0x0040) /* last 64 bytes as spare area */
- #define NAND_MAX_ZONE ((uint16_t)0x0002) /* 2 zones of 1024 block */
- /* FSMC NAND memory data computation */
- #define DATA_1st_CYCLE(DATA) (uint8_t)((DATA)& 0xFF) /* 1st data cycle */
- #define DATA_2nd_CYCLE(DATA) (uint8_t)(((DATA)& 0xFF00) >> 8) /* 2nd data cycle */
- #define DATA_3rd_CYCLE(DATA) (uint8_t)(((DATA)& 0xFF0000) >> 16) /* 3rd data cycle */
- #define DATA_4th_CYCLE(DATA) (uint8_t)(((DATA)& 0xFF000000) >> 24) /* 4th data cycle */
- /* FSMC NAND memory HY27UF081G2A-TPCB address computation */
- #define ADDR_1st_CYCLE(PADDR) (uint8_t)(0x0) /* 1st addressing cycle */
- #define ADDR_2nd_CYCLE(PADDR) (uint8_t)(0x0) /* 2nd addressing cycle */
- #define ADDR_3rd_CYCLE(PADDR) (uint8_t)(PADDR & 0xFF) /* 3rd addressing cycle */
- #define ADDR_4th_CYCLE(PADDR) (uint8_t)((PADDR>>8) & 0xFF) /* 4th addressing cycle */
- /* Exported macro ------------------------------------------------------------*/
- /* Exported functions ------------------------------------------------------- */
- void FSMC_NAND_Init(void);
- void FSMC_NAND_ReadID(NAND_IDTypeDef* NAND_ID);
- uint32_t FSMC_NAND_WriteSmallPage(uint8_t *pBuffer, uint32_t Address, uint32_t NumPageToWrite);
- uint32_t FSMC_NAND_ReadSmallPage (uint8_t *pBuffer, uint32_t Address, uint32_t NumPageToRead);
- uint32_t FSMC_NAND_MoveSmallPage (uint32_t SourcePageAddress, uint32_t TargetPageAddress);
- //uint32_t FSMC_NAND_WriteSpareArea(uint8_t *pBuffer, NAND_ADDRESS Address, uint32_t NumSpareAreaTowrite);
- //uint32_t FSMC_NAND_ReadSpareArea(uint8_t *pBuffer, NAND_ADDRESS Address, uint32_t NumSpareAreaToRead);
- uint32_t FSMC_NAND_EraseBlock(uint32_t Address);
- uint32_t FSMC_NAND_Reset(void);
- uint32_t FSMC_NAND_GetStatus(void);
- uint32_t FSMC_NAND_ReadStatus(void);
- //uint32_t FSMC_NAND_AddressIncrement(NAND_ADDRESS* Address);
- #endif /* __FSMC_NAND_H */
STM32-移植FATFS的NANDFLASH驱动