9G-STM32 EWARM开发过程简介之五--移植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 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<NAND_PAGE_SIZE)break;
}
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 */
七,NFTL代码层
有关NFTL代码,自行处理。
最近编辑记录 缥缈九哥 (2020-05-09 20:17:51)
离线