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 2048 #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: *(DWORD*)buff = NAND_BLOCK_SIZE; break; case GET_SECTOR_COUNT: *(DWORD*)buff = (((NAND_MAX_ZONE/2) * NAND_ZONE_SIZE) * NAND_BLOCK_SIZE); break; case GET_SECTOR_SIZE: *(WORD*)buff = NAND_PAGE_SIZE; break; default: res = RES_PARERR; 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 */