移植FATFS的NANDFLASH驱动
STM32F407移植FATFS文件系统(版本R0.09b)到SD卡(硬件SPI总线)
STM32F407移植FATFS⽂件系统(版本R0.09b)到SD卡(硬件SPI总线)⼀、序⾔经常在⽹上、群⾥看到很多⼈问关于STM32的FATFS⽂件系统移植的问题,刚好⾃⼰最近的⼯程项⽬需要使⽤SD卡,为了让⼤家少⾛弯路,我把我的学习过程和⽅法贡献给⼤家。
⼆、SD卡简介安全数字卡(简称SD卡),最初引进应⽤于⼿持式可携带电⼦产品,在⼀个⼩尺⼨产品上可靠的存储数据,如移动电话,数码相机等。
1、SD卡简介请参考如下博⽂2、SD卡种类请参考如下博⽂3、SD卡简介和种类请参考如下博⽂4、MMC、SD、TF、SDIO、SDMMC简介三、SD卡总线协议简介SD卡⽀持2种总线协议,即SDIO总线协议和SPI总线协议。
SDIO总线协议速度快,SPI总线相对SDIO总线速度要慢很多,但是⽬前市⾯上很多单⽚机不⽀持SDIO总线协议,只有中⾼端单⽚机(例如:STM32F407)才⽀持SDIO总线协议。
1、SDIO总线协议利⽤该总线协议,可以使⽤最多四条数据线实现主机与SD卡之间的数据传输,所以速度相对⽽⾔可以达到最⾼,但是需要主机具有SDIO控制器,才可以使⽤该协议。
2、SPI总线协议如果主机不⽀持SDIO协议,那么可以使⽤SPI协议对SD卡进⾏操作。
虽然速度⽐SDIO慢,但是硬件上更加简单,只需要四根线便可以实现与SD卡进⾏通讯。
3、SDIO协议与SPI协议的⽐较SDIO协议与SPI协议相较⽽⾔,SDIO协议读写SD卡的速度更快,再加上其⽀持4线模式,即利⽤4条数据线,同时发送4Bits数据,数据的传输效率就更⾼了,但是由于使⽤的引脚较多,所以也导致了控制相对⽐较困难。
⽽SPI外设只具有两条数据线MISO和MOSI,分别⽤作数据的输⼊和输出,由于引脚较少,所以控制相对较容易。
但是,数据的传输效率相对⽽⾔就⽐较低了。
但是,两中协议的共同之处在于:均是通过命令实现对SD卡的控制,仍然是结合状态机实现编程。
4、SD卡如何⼯作在SPI模式下当SD卡上电之后,只有第⼀次发送的CMD0命令才可以选择SD卡⼯作在SPI模式下。
linux2.6nandflash驱动说明
linux2.6nandflash驱动说明linux2.6.14移植---nandflash--by farsight 一、实验目的本实验是在前面网络芯片驱动实验的基础上,加入了对nandflash的支持,从而进一步完善系统结构,通过移植的过程来了解nandflash的移植方法。
二、实验设备1、虚拟机ubuntu7.042、优龙公司开发板fs2410以及开发板中移植好的u-boot1.1.43、串口线和网线、电源各一根三、实验步骤1、指明分区信息在arch/arm/mach-s3c2410/decs.c文件中:root@farsight:/source/kernel/linux-2.6.14# vim arch/arm/mach-s3c2410/devs.c在文件中添加以下信息:1、建立分区表:#include#include#includestatic struct mtd_partition partition_info[]={{name: "kernel",size: 0x001c0000,offset: 0x00040000,},{name: "root",size: 0x02300000,offset: 0x00200000,},{name: "yaffs",size: 0x01B00000,offset: 0x02500000,}};2、加入nandflash分区struct s3c2410_nand_set nandset={nr_partitions: 4,partitions:partition_info,};3、建立nandflash文件支持:struct s3c2410_platform_nand superlpplatform={tacls:0,twrph0:30,twrph1:0,sets:&nandset,nr_sets:1,};2、加入nand flash芯片支持到nand flash驱动修改此文件中的s3c_device_nand结构体变量,添加对dev成员的赋值:struct platform_device s3c_device_nand = {.name = "s3c2410-nand",.id = -1,.num_resources = ARRAY_SIZE(s3c_nand_resource),.resource = s3c_nand_resource,.dev={.platform_data=&superlpplatform}};3、指定启动时初始化kernel启动时依据我们对分区的设置进行初始配置,修改arch/arm/mach-s3c2410/mach-smdk2410.c文件root@farsight:/source/kernel/linux-2.6.14#vim arch/arm/mach-s3c2410/mach-smdk2410.c 修改smdk2410_devices[].指明初始化时包括我们在前面所设置的flash信息static struct platform_device *smdk2410_devices[] __initdata = {&s3c_device_usb,&s3c_device_lcd,&s3c_device_wdt,&s3c_device_i2c,&s3c_device_iis,&s3c_device_nand, /*added*/};4、配置MTDDevice Drivers --->Memory Technology Devices (MTD) --->[*] MTD partitioning supportNAND Flash Device Drivers ---><*> NAND Device Support<*> NAND Flash support for S3C2410/S3C2440 SoC5、编译内核root@farsight:/source/kernel/linux-2.6.14# make zImageroot@farsight:/source/kernel/linux-2.6.14# cp arch/arm/boot/zImage /tftpboot 启动开发板进行下载。
Nand flash驱动移植及带硬件Ecc的Jffs2文件系统制作
Nand flash驱动移植及带硬件Ecc的Jffs2文件系统制作cd /new_disk/weiyan/linux-2.6.25vi arch/arm/mach-s3c2440/mach-smdk2440.c修改板级配置文件,为统一驱动的配置,设备的配置信息一般在此文件中添加。
1)添加头文件#include <linux/mtd/nand.h>#include <linux/mtd/nand_ecc.h>#include <linux/mtd/partitions.h>#include <asm/plat-s3c/nand.h>#include <asm/plat-s3c24xx/pm.h>2)添加nand划分信息static struct mtd_partition wy_nand_part[] = {[0] = { //u-boot及内存存放的分区.name = "BOOT",.size = SZ_2M,.offset = 0,},[1] = { //文件系统存放的分区.name = "ROOTFS",.offset = SZ_2M,.size = SZ_32M,},[2] = { //剩余空间.name = "BACKUP",.offset = SZ_32M + SZ_2M,.size = SZ_32M - SZ_2M,},};static struct s3c2410_nand_set wy_nand_sets[] = {[0] = {.name = "NAND",.nr_chips = 1,.nr_partitions = ARRAY_SIZE(wy_nand_part),.partitions = wy_nand_part,},};3)添加nand flash的读写匹配时间,各时间定义如图static struct s3c2410_platform_nand wy_nand_info = {.tacls = 10,.twrph0 = 25,.twrph1 = 10,.nr_sets = ARRAY_SIZE(wy_nand_sets),.sets = wy_nand_sets,};4)添加nand设备到初始化表static struct platform_device *smdk2440_devices[] __initdata = { ……(此处省略其他设备,添加时请注意。
移植FATFS的NANDFLASH驱动
STM32EWARM开发过程简介之五--移植FATFS的NANDFLASH驱动一,建立工程FATFS源码1,在/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_MKFS0#define_CODE_PAGE932#define_FS_RPATH0#define_MAX_SS512修改为:#define_USE_MKFS1#define_CODE_PAGE936#define_MAX_SS2048#define_FS_RPATH12,把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){return0;}3,媒介状态查询直接返回正常的0:DSTATUS disk_status(BYTE drv){return0;}4,取系统系统直接返回0(自己可以按格式修改为真实时间):DWORD get_fattime(void){return0;}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==0DRESULT 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_MakerID0xAD#define NAND_HY_DeviceID0xF1/*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");}elseif((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 mountres=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);//forpfs=&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 readres=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 writeres=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 umountf_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 NCE2NAND 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->D7NAND 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);/*INT2NAND 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 one2048Bytes Page size to an other2048Bytes 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 several2048Bytes 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*2048Bytes 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)/*512bytes per page w/o Spare Area*/ //#define NAND_BLOCK_SIZE((uint16_t)0x0020)/*32x512bytes pages per block*///#define NAND_ZONE_SIZE((uint16_t)0x0400)/*1024Block per zone*///#define NAND_SPARE_AREA_SIZE((uint16_t)0x0010)/*last16bytes as spare area*///#define NAND_MAX_ZONE((uint16_t)0x0004)/*4zones of1024block*//*FSMC NAND memory HY27UF081G2A-TPCB parameters*/#define NAND_PAGE_SIZE((uint16_t)0x0800)/*2048bytes per page w/o Spare Area*/ #define NAND_BLOCK_SIZE((uint16_t)0x0040)/*64x2048bytes pages per block*/#define NAND_ZONE_SIZE((uint16_t)0x0200)/*512Block per zone*/#define NAND_SPARE_AREA_SIZE((uint16_t)0x0040)/*last64bytes as spare area*/#define NAND_MAX_ZONE((uint16_t)0x0002)/*2zones of1024block*//*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代码,自行处理。
STM32F429利用CUBEMX移植FATFS文件系统成功!!!
STM32F429利⽤CUBEMX移植FATFS⽂件系统成功⽂件系统对于⼀个专业的嵌⼊式系统⽽⾔必不可少,博主这两天利⽤STM32F429成功移植了FATFS,特来分享⼀下学习⼼得,避免新⼈采坑。
我是在SD卡上实现的,因此你需要利⽤SDIO接⼝扩展⼀个SD卡,具体实现如下:进⼊Configuration界⾯,基本参数的不⽤配置,但是需要开启中断和DMA,配置如下:点击OK,关闭Configuration窗⼝。
在MiddleWares下拉列表中打开FATFS,选中SD卡。
进⼊FATFS的Configuration界⾯,配置如下:解释⼀下改动的两个参数,⼀个选择读取中⽂类型的⽂件,另⼀个是使能长字节名称命名(如果不选择,只有8字节,超过8字节会出现Hardware Fault),⽂件系统的磁盘选择3个(⽅便挂载其他内存)最后,再设置选择中,把stack的空间⼤⼩设置为0X1000⼤⼩。
以上,便完成可在CUBEMX中配置FATFS⽂件系统,点击⽣成⼯程⽂件。
可以看到,在⼯程⽬录下,⽣成了这样⼀些⽂件:具体什么内容先不管,我们需要在main中添加⼀些代码测试我们的⽂件管理系统。
⾸先添加如下所⽰的全局变量:/* USER CODE BEGIN PV *//* Private variables ---------------------------------------------------------*/uint32_t byteswritten; /* File write counts */uint32_t bytesread; /* File read counts */uint8_t wtext[] = "This is STM32 working with FatFs"; /* File write buffer */uint8_t rtext[100]; /* File read buffers */char filename[] = "STM32cube.txt";/* USER CODE END PV */在初始化之后,while(1)之前添加如下代码int main(void){/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration----------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_TIM6_Init();MX_FMC_Init();MX_USART1_UART_Init();MX_TIM7_Init();MX_USART3_UART_Init();MX_DMA2D_Init();MX_LTDC_Init();MX_SPI5_Init();MX_SDIO_SD_Init();MX_FATFS_Init();/* Initialize interrupts */MX_NVIC_Init();/* USER CODE BEGIN 2 */delay_init(180);LED_Init();KEY_Init();SDRAM_Init();LCD_Init();ESP8266_Init(); //WIFI ͨѶģ¿éW25QXX_Init(); //Íⲿ SPI FLASH --- 32MBFTL_Init(); //Íⲿ NAND FLASH --- 512MBmy_mem_init(SRAMIN); //½«SRAMÖÐ60KBÄÚ´æÓÃÓÚÄÚ´æ¹ÜÀíϵͳ my_mem_init(SRAMEX); //½«SDRAMÖÐ15MBÄÚ´æÓÃÓÚÄÚ´æ¹ÜÀíϵͳ ITEnable();PeriphInit();GUI_Init();Show_SDcard_Info();LCD_ShowString(400,400,400,24,24,"****** FatFs Example ******");retSD = f_mount(&SDFatFS, "0:", 0);if(retSD){LCD_ShowString(400,440,400,24,24,"****** mount error ******");LCD_ShowNum(800,440,retSD,2,24);Error_Handler();}elseLCD_ShowString(400,440,400,24,24,"****** mount success ******");retSD = f_open(&SDFile, filename, FA_CREATE_ALWAYS | FA_WRITE);if(retSD){LCD_ShowString(400,480,400,24,24,"****** open file error ******");LCD_ShowNum(800,480,retSD,2,24);Error_Handler();}elseLCD_ShowString(400,480,400,24,24,"****** open file success ******");retSD = f_write(&SDFile, wtext, sizeof(wtext), (void *)&byteswritten);if(retSD){LCD_ShowString(400,520,400,24,24,"****** write file error ******");LCD_ShowNum(800,520,retSD,2,24);Error_Handler();}elseLCD_ShowString(400,520,400,24,24,"****** write file success ******");retSD = f_close(&SDFile);if(retSD){LCD_ShowString(400,560,400,24,24,"****** close file error ******");LCD_ShowNum(800,560,retSD,2,24);Error_Handler();}elseLCD_ShowString(400,560,400,24,24,"****** close file success ******");/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */}OK,编译通过,下载程序,运⾏结果如下所⽰:之后你便可以在SD卡中找到你创建的⽂件STM32cube.txt。
NAND Flash驱动程序结构
NAND Flash驱动程序1、NAND Flash驱动程序框架FAT文件系统下的NAND Flash驱动程序采用了分层结构。
驱动程序的上层是Flash抽象层,是物理操作无关层,该层对NAND Flash的操作进行抽象,并采用一定的策略平衡了NAND Flash的擦写。
NAND Flash驱动程序的结构如图5.5所示。
图5.5 FAT下NAND Flash驱动结构在图中:File System即文件系统。
在这里,采用的是FAT文件系统。
FAT文件系统是一种采用链式分配方式的文件系统。
并没有对NAND Flash的特点优化,因此需要在下层的驱动程序做优化。
Flash Driver即NAND Flash驱动程序。
对上层的文件系统提供以DSK为前缀的流驱动接口。
该层驱动程序本身分为两层:FAL层、F MD层。
(1)、FAL层即Flash Abstraction Layer,Flash抽象层。
该层主要提供三个功能:A、将物理的Flash抽象成统一的接口提供给上层的文件系统。
B、将逻辑扇区地址转换成物理扇区地址。
上层的FAT文件系统使用的是逻辑扇区地址,并不是真正的物理扇区,其转换由FAL实现。
C、对Flash实现损耗平衡("Wear-level")。
为了避免反复的擦写Flash的同一个块,需要一种策略来减少反复的擦写块。
(2)、FMD层即Flash Media Driver,Flash介质驱动层。
该层实现FAL层的请求,对Flash物理扇区进行操作。
Flash Hardware即NAND Flash物理芯片。
2、FAL层(Flash Abstraction Layer)1)函数接口定义FAL层对上的函数接口也就是整个NAND Flash驱动程序的对外接口,由于NAND Flash 是块设备,Windows CE中块设备采用的是流驱动接口,流驱动接口是一个标准的统一接口,只是各个驱动的前缀不同,在这里NAND Flash函数接口的前缀为“DSK”,这个前缀也使得Windows CE将“DSKxx:”的文件名看作为设备,使得我们能够通过Windows CE标准的Win32 API,如CreateFile、DeviceIOControl等来对设备进行打开、读写等操作。
在pc机上移植fatfs文件系统(windowslinux)(一)
在pc机上移植fatfs⽂件系统(windowslinux)(⼀)开始我的技术⽣涯~哈哈,⽼⼤给我分配了⼀个以前都没接触到的任务。
在PC机上移植fatfs⽂件系统。
以前我认为的移植是调⽤底层提供的API接⼝,在PC机上模拟,测试通过后再移植到⽬标板上。
这次的移植竟然是移植到PC机上。
我的开始考虑到的硬件基础:⽂件系统要在硬件存储介质上运⾏,例如u盘啊、SD卡啊。
那这次没有硬件设备,怎么模拟呢。
diskio.c是和底层硬件相关的⽂件。
解决⽅案是⽤创建⼀个具有⼀定⼤⼩的⽂件来作为存储载体。
开始有了⼀点思路。
我就开始了⼈⽣的第⼀次移植。
我⽤的是fatfs 0.08b 最新版。
0.08b版本多了⼏个API接⼝。
并且前辈们反映移植遇到的问题解决了。
下到了源代码有2个⽂件夹。
doc ⾥⾯我没仔细看。
src⾥⾯就是源代码了。
diskio.c是⾃⼰写的。
是⼀些贴近底层硬件的函数。
我看了CSDN⾥⾯⼀些前辈关于移植fatfs的资料。
⾸先第⼀步就是配置ffconf.hfatfs有2个版本。
⼀个是tiny版本。
这个版本适合⽐较⼩的RAM,eg:单⽚机。
我⽤的是正常版。
#define_FS_TINY0/* 0:Normal or 1:Tiny */因为移植后要测试读与写是否匹配,所以设置为读写功能。
#define _FS_READONLY 0/* 0:Read/Write or 1:Read only */#define _FS_MINIMIZE3/* 0 to 3 */ 我⽤了全部功能,因为没要求要裁剪。
这个具体实现以后再慢慢琢磨。
#define_USE_MKFS1/* 0:Disable or 1:Enable */ 如果是在PC机上模拟,这个必须设置成1.因为这个参数,我搞了1天。
下⾯再详述。
#define _CODE_PAGE936 简体中⽂#define_MAX_SS512/* 512, 1024, 2048 or 4096 */ ⼀个扇区512字节#define_USE_ERASE1/* 0:Disable or 1:Enable */ 具备擦除功能,这个功能我⽬前还没测试过。
第12章 NandFlash驱动移植 Linux系统移植(第2版) 教学课件
void __iomem
*IO_ADDR_R;
/*读地址*/
void __iomem
*IO_ADDR_W;
/*写地址*/
/*对字节的操作函数声明*/
uint8_t (*read_byte)(struct mtd_info *mtd);
/*读一个字节*/
u16
(*read_word)(struct mtd_info *mtd);
命令功能:表示对块擦除操作。 命令代码:首先写入60h进入擦写模式;
再输入块地址,即将要擦除的块;接着写 入D0h表示擦写结束。
7.Read Status
命令功能:表示读取内部状态寄存器值的 命令。
命令代码:70h。
12.1.2 NandFlash控制器
对于2440的NandFlash控制器中,寄存器有以下12种,与2410相比 寄存器的设置有些变换,具体寄存器中每个bit的设置可以参考 2440文档。
2.Read2
命令功能:表示将要读取NandFlash存储 空间中一页的后半部分,且将内置指针定 位到后半部分的第一个字节。
命令代码:01h。
3.Read ID
命令功能:表示读取NandFlash芯片的ID 号。
命令代码:90h。
4.Reset
命令功能:表示重新启动NandFlash芯片。 命令代码:FFh。
(*scan_bbt)(struct mtd_info *mtd);
/*进行附加错误状态检查操作*/
int
(*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
基于STM32F407的FatFs文件系统在SD卡驱动上的移植
基于STM32F407的FatFs文件系统在SD卡驱动上的移植2014-2-26最近在做SD卡驱动,以前移植过efsl,觉得用的人不是很多,现在移植个FatFs,也跟上队伍。
第一步,保证SD卡底层驱动函数正确,包括SD卡初始化、SD扇区读写等。
第二步,下载FatFs源码,名为ff9b.zip,解压在src文件夹中可以得到diskio.c、ff.c、以及\option\cc936.c这三个源码文件,在STM32F407工程文件中创建FatFs文件夹,加入这几个源码以及相应头文件,并且在系统Include Path中加入这个文件夹的位置,以编译时找到其头文件。
第三步开始移植。
diskio.c这个文件中定义了fatfs文件系统与硬件存储器之间的接口函数,供文件系统调用,包括disk_initialize、disk_status、disk_read、disk_write、disk_ioctl五个函数。
ff.c中存放了FatFs文件操作的常用函数,包括文件以及文件夹的操作。
cc936.c是简体汉字编码文件。
首先在ffconf.h中配置文件系统。
将#define_CODE_PAGE 932 改为936以支持简体中文,原来默认支持日文,不知道为啥,莫非这个东东是日本人写的?先不研究。
编译一下,发现如下错误:#if !_USE_LFN || _CODE_PAGE != 936#error This file is not needed incurrent configuration. Remove from the project.#endif其中宏定义_USE_LFN表明是否使用长文件名,修改为1,使用静态区BSS存储,最长文件名为255个字符。
重新编译,发现有很多没有定义的函数,包括例如ATA_disk_initialize、ATA_disk_status、ATA_disk_read、ATA_disk_write等,由于我们使用的介质是SD卡,删掉其他ATA、USB以及MMC相关的函数,只留下SD_disk_initialize、SD_disk_status、SD_disk_read、SD_disk_write、SD_disk_ioctl以及get_fattime这几个函数。
移植FATFS的NANDFLASH驱动
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,
} /* 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;}
STM32下FatFs的移植,实现了坏块管理,硬件ECC,ECC纠错,并进行擦写均衡分析
STM32 下FatFs的移植,实现了坏块管理,硬件ECC,ECC纠错,探写均衡分析作者:观海QQ:5316221、摘要在STM32 单片机上,成功移植 FatFs 0.12b,使用的 Nand Flash 芯片为K9F2G08 。
特点:系统配合 FatFs 实现了坏块管理,硬件ECC,软件 ECC 纠错2、代码分析2.1、擦写均衡分析在create_chain 函数中实现,每次分配都由当前scl 指向的free cluster 开始,逐块检查,是否有可用cluster 存在。
如果没有则取下一块,直到回到起始点,说明已经没有free cluster 了。
因为每次都紧邻scl 取free cluster, 那么每次的起始scl 值在哪里,就决定了擦写位置。
通过查看代码,很可惜,发现scl 每次都重新从1 开始查找free cluster。
所以,默认条件下,FatFs 不支持擦写均衡。
如果能把每次分配的cluster号记录下来,下次接着向后分配,则可实现擦写均衡。
未来有时间再来实现吧。
也许你现在就能实现哦,另忘了实现了分享一份给我。
2.2、坏块管理分析通过2.1对create_chain 函数的分析,我们知道get_fat是完成真实的free cluster的分配。
而每次get_fat 函数都会调用move_window 函数实际的读入一次该sector。
所以,我们只需要在读取函数中,对坏块进行检查,返回出错,则分配的cluster 自动移到下一个。
从而完成跳过坏块存储数据。
具体实现如下:如果FSMC_NAND_ReadSmallPage 检测到坏块,则NAND_disk_read 返回RES_ERROR。
2.3、STM32的硬件ECC在FSMC_NAND_Init 函数中打开STM32的硬件ECC配置。
如下红色字。
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_256Bytes;FSMC_NANDInitStructure.FSMC_TCLRSetupTime = 0x00;FSMC_NANDInitStructure.FSMC_TARSetupTime = 0x00;FSMC_NANDInitStructure.FSMC_CommonSpaceTimingStruct = &p;FSMC_NANDInitStructure.FSMC_AttributeSpaceTimingStruct = &p;这里使用的是FSMC_ECCPageSize_256Bytes,而K9F2G08 的最小page 为2048, 所以,我们在驱动中,会再把2048 的page 页再分为8个256的小页面分别进行ECC 运算。
移植Nand flash驱动了解Linux内核Nand Flash的实现_华清远见
移植Nand flash驱动了解Linux内核Nand Flash的实现如何通过移植Nand flash驱动,了解Linux内核Nand Flash的实现?本篇文章就来教你如何实行!在说到正题之前,先来介绍一下Nand Flash吧!Nand-flash存储器是flash存储器的一种,其内部采用非线性宏单元模式,为固态大容量内存的实现提供了廉价有效的解决方案。
Nand-flash存储器具有容量较大,改写速度快等优点,适用于大量数据的存储,因而在业界得到了越来越广泛的应用,如嵌入式产品中包括数码相机、MP3随身听记忆卡、体积小巧的U盘等。
下面回到正题。
【实验目的】Nand flash 是嵌入式系统最常用的内部存储设备,通过移植Nand flash驱动,了解Linux内核Nand Flash的实现。
说明:在本系统移植课程实验中命令行提示符“$”表示是在主机上执行,“#”表示在目标板执行。
【实验环境】● 主机:Ubuntu 10.10 (64bit);● 目标机:FS_S5PC100平台;● 交叉编译工具链:arm-eabi-4.4.0(Android4.0.4自带交叉工具链);【实验步骤】1. 添加驱动文件添加针对我们平台的Nand flash驱动。
● 拷贝s3c_nand.c到drivers/mtd/nand下;● 拷贝regs-nand.h到arch/arm/mach-s5pc100/include/mach下;cp s3c_nand.c drivers/mtd/nandcpregs-nand.h arch/arm/mach-s5pc100/include/mach2. 修改文件针对平台上的nand flash设备,修改drivers/mtd/nand/nand_base.c第2975行。
for (i = 0; i< 5; i++)3. 配置文件修改● 修改drivers/mtd/nand/Kconfig,在if mtd_nand(216行)下面添加如下内容:config MTD_NAND_S3Ctristate "NAND Flash support for S3C SoC"depends on (ARCH_S3C64XX || ARCH_S5P64XX || ARCH_S5PC1XX|| ARCH_S5PC100) && MTD_NANDhelpThis enables the NAND flash controller on the S3C.No board specfic support is done by this driver, each boardmust advertise a platform_device for the driver to attach.config MTD_NAND_S3C_DEBUGbool "S3C NAND driver debug"depends on MTD_NAND_S3ChelpEnable debugging of the S3C NAND driverconfig MTD_NAND_S3C_HWECCbool "S3C NAND Hardware ECC"depends on MTD_NAND_S3ChelpEnable the use of the S3C's internal ECC generator whenusing NAND. Early versions of the chip have had problems withincorrect ECC generation, and if using these, the default ofsoftware ECC is preferable.If you lay down a device with the hardware ECC, then you willcurrently not be able to switch to software, as there is noimplementation for ECC method used by the S3C● 修改drivers/mtd/nand/Makefile添加如下内容(19行):obj-$(CONFIG_MTD_NAND_S3C) += s3c_nand.o4. 平台代码修改修改arch/arm/mach-s5pc100/mach-smdkc100.c添加如下内容:● 添加头文件1 #if defined (CONFIG_MTD_NAND_S3C)2 #include3 #include4 #include5 #endif● 添加平台设备01 #if defined(CONFIG_MTD_NAND_S3C)02 /* Nand Flash Support */03 static structmtd_partition s5pc100_nand_part[] = {04 [0] = {05 .name = "bootloader",06 .size = SZ_1M,07 .offset = 0,08 },09 [1] = {10 .name = "kernel",11 .offset = MTDPART_OFS_APPEND,12 .size = SZ_1M*3,13 },14 [2] = {15 .name = "rootfs",16 .offset = MTDPART_OFS_APPEND,17 .size = MTDPART_SIZ_FULL,18 },19 };2021 struct s3c_nand_mtd_info s5pc100_nand_mtd_part_info = {22 .chip_nr = 1,23 .mtd_part_nr = ARRAY_SIZE(s5pc100_nand_part),24 .partition = s5pc100_nand_part,25 };2627 static struct resource s5pc100_nand_resource[] = {28 [0] = {29 .start = 0xE7200000,30 .end = 0xE7200000 + SZ_1M,31 .flags = IORESOURCE_MEM,32 }33 };3435 structplatform_device s5pc100_device_nand = {36 .name = "s5pc100-nand",37 .id = -1,38 .num_resources = ARRAY_SIZE(s5pc100_nand_resource),39 .resource = s5pc100_nand_resource,40 .dev = {41 .platform_data = &s5pc100_nand_mtd_part_info,42 }43 };44 #endif● 添加平台设备列表在smdkc100_device[]结构体数组中添加如下内容:1 #if defined(CONFIG_MTD_NAND_S3C)2 &s5pc100_device_nand,3 #endif5. 相关头文件修改修改arch/arm/plat-samsung/include/plat/nand.h添加如下内容:1 #if defined(CONFIG_MTD_NAND_S3C)2 struct s3c_nand_mtd_info {3 uintchip_nr;4 uintmtd_part_nr;5 structmtd_partition *partition;6 };7 #endif6. 配置内核$ make menuconfigDevice Drivers ---><*> Memory Technology Device (MTD) support ---><*> Caching block device access to MTD devices<*> NAND Device Support ---><*> NAND Flash support for S3C SoC[*] S3C NAND Hardware ECC-*- Enable the block layer --->Partition Types --->[*] Advanced partition selection[*] PC BIOS (MSDOS partition tables) support[*] BSD disklabel (FreeBSD partition tables) support 7. 编译内核编译内核并拷贝到tftpboot下。
FAT文件系统在NAND Flash存储器上的改进设计
FAT文件系统在NAND Flash存储器上的改进设计类别:电子综合阅读:1177嵌入式系统的大量数据都存储在其F1ash芯片上。
根据Flash器件的固有特性,构建一个适合管理NAND Flash存储器的FAT文件系统,并阐述具体的设计思想。
该系统改进了FAT表和FRT表的存储方式,延长了存储器的使用寿命,提高了稳定性。
NAND Flash存储器是一种数据正确性非理想的器件,容易出现位反转现象,同时在使用中可能会有坏损单元。
数据写入必须在李白的区块或者擦除后的区块巾进行,其底层技术要求以块为单位进行擦除(将“Oxff”写入到要擦除的存储块中),再按页写入。
Flash存储器的擦除次数是有限的,一般是100000次。
当某块执行过度的擦除操作后,这一块的存储空间将会变为“只读”状态,不能再写入数据。
根据以上特点,为了避免某些块的过度操作,而导致存储卡使用寿命降低,设计专门针对Flash存储器的文件系统是必要的。
1 NAND FIash存储器的特点NAND Flash存储器的读取操作与普通SRAM存储器类似,可以随机读取,读出的速度也很快。
芯片生产厂商规定存储空间的第1块必须是有效块,装载了出厂标识、系统配置等信息;而其他块可能在使用前就足坏块,需要在初次使用时进行坏块检测并标记,禁止数据写入,由于存储器每一块的内部结构都是相互独立的,坏块并不影响系统的操作。
在设计NAND Flash文件系统前,首先要了解其内部结构。
目前市面上的NAND Flash芯片单片容量已高达lGB,存储器容量最高达4GB(由4片1GB的芯片封装而成)。
知名的NAND Flash 制造商有Samsung、Tashiba等公司。
下面以Samsung公司的K9wAG08UlM为例,说明大容量NAN D Flash芯片的组织结构。
在K9WAG08U1M中,页(page)是最基本的组织单位。
每页有2048+64= 2112字节,64页构成一个块。
FATFS移植
STM32中FatFS移植前言与废话做项目时网找资料,不会的东西上网查阅一下多半可以解决,一些尚未解决的问题也会有所启发。
最近由于项目的需要,仔细阅读了SD卡相关内容,顺藤摸瓜学习FatFS。
网上关于SD卡和FatFS的内容非常的多,重复的部分我就不介绍了,我把移植和使用部分的经验和大家分享一下。
刚开始的时候,我找来一些现成的代码研究一下,不用说看的是一头雾水。
看FatFS示例代码,也不知如何移植。
最后还是下定决心,慢慢的阅读FatFS的相关文档和范例代码,对于移植部分一点一点的研究,相信一定会有所收获。
一、硬件准备开始移植之前,你必须要有一块SD卡。
从形状上来说,有普通的SD卡,有很小的microSD卡,microSD卡就是手机中长见的TF卡。
购买microSD卡的时候,往往会附带一个SD卡套,那么小个头的microSD卡就变成了普通的SD卡,接口都是一样的。
但是还是您注意了,建议大家购买2G以下的SD卡(如果可以的话,买个128M 的SD卡就可以达到实验的效果,价格也非常便宜)。
刚开始移植的时候,我使用了4G的SD卡,但是发现程序无法完成SD卡的初始化。
查阅网上相关的资料,发现SD卡技术已2G作为分界线,大于或者等于4G的卡属于高速SD卡,和小于或者等于4G的SD卡略有区别。
二、软件准备在进行移植之前,先编写一些最简单的STM32程序。
在调试之前,我都会完成USART的初始化和发送函数,通过串口把STM32的运行状态打印出来,这样配合Jlink硬件调试,可以很快的找到错误。
由于SD卡可以使用SPI进行读写操作,所以还需要完成SPI 的初始化工作。
先来说一下USART的操作,我个人比较喜欢使用系统的printf函数,所以还需要引入stdio头文件。
在IAR中必须设定option的某个选项。
如下图所示。
除了完成USART的初始化工作以外,还需要重写fputc函数,具体的代码如下。
1int fputc(int ch, FILE * f)2{3USART_SendData(USART1, (uint8_t)ch);4while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET );5return ch;6}复制代码然后说一下SPI的初始化工作。
u_boo移植(六)之支持Nand Flash操作
u_boo移植(六)之支持Nand Flash操作通过上一节uboot中Nand Flash操作的部分源码分析我们可以知道,如果想在uboot中驱动我们自己开发板上的Nand Flash设备,只需要完成以下几件事情就可以了。
1.修改include/configs/fsc100.h,定义宏CONFIG_CMD_NAND,取消宏CONFIG_CMD_ONENAND2.修改include/configs/fsc100.h,定义宏CONFIG_SYS_MAX_NAND_DEVICE,值为13.需要在drivers/mtd/nand目录下添加s5pc100_nand.c文件,完成FSC100的NAND Flash设备初始化(1)初始化Nand Flash硬件接线到SOC上的GPIO口(2)初始化SOC的Nand Flash控制器(3)实现s5pc100_hwcontrol函数中实现根据ctrl值是否含有NAND_CLE、NAND_ALE来决定是向NFCMD寄存器写值还是向NFADDR寄存器写值(4)实现s5pc00_select_chip函数,完成对Nand Flash设备片选和取消片选(5)实现s5pc100_dev_ready函数,完成对Nand Flash设备进行是否忙碌探测关于如何对Nand Flash进行读、写、擦除、坏块管理等操作,uboot源码中的MTD框架已经帮我们做好了。
好了,我们已经知道需要干什么了,接下来就开始干活吧!一、修改include/configs/fsc100.h文件,添加和取消相应的宏在fsc100.h文件里面,添加以下代码:二、drivers/mtd/nand目录下添加s5pc100_nand.c文件大家可以将此目录下的s3c2410_nand.c拷贝成s5pc100_nand.c,然后进行修改。
下面给出给我修改的代码:需要注意的是,不同的开发板配置不一样,流程都一样,说白了就是操作的寄存器不一样,大家可以根据自己开发板实际情况自行修改。
FatFs文件系统的移植
FatFs文件系统的移植因为需要,又不想自己写,所以就移植了一个文件系统。
说下我的硬件和开发工具:接成TRUE IDE模式下的CF卡(也就是相当于一块硬盘了),三星S3C2440的ARM9,开发工具是很老很老的D版的ADS 1.2。
我在网上看到的嵌入式系统上面常用的文件系统有UCOSII公司的UC/FS,支持CF卡,硬盘,SD/MMC卡,还有NAND FLASH等等,比较多,不过是商用的,需要银子的,有周立功的用于教学用(为什么说是用于教学用的,呵呵,等下就说)的ZLG/FS,还找到了开源、免费的两个,其中一个叫做efsl,另一个叫做FatFs。
现在先不考虑版权的问题,选择一个比较合适的文件系统。
第一个UC/FS文件系统没得什么说的,UCOSII那个公司开发的,稳定性,兼容性应该都不会差。
第二个是ZLG/FS。
周立功的很多的开发板上面都送了这个文件系统的源代码的,在网上找到一个现成的读写硬盘的,只是是基于LPC2200系列的处理器的。
第三个是efsl,是一个开源的项目,免费,只需要提供读扇区和写扇区2个函数。
第四个是FatFs,跟efsl一样,也是一个开源的项目,移植的时候比efsl多几个简单的函数。
这里补充一下CF卡和硬盘的简单的资料,CF卡有三种模式,其中有一个叫TRUE IDE,接成这个模式以后,就跟他的模式名字一样,他就是一个硬盘,对他进行读写,也就相当于对一个硬盘进行读写。
当引脚OE(好像是叫OE,具体参考CF卡文档)在上电的时候检测到拉低,那么CF卡就进入TRUE IDE模式。
读写硬盘的时候,在只写一次LBA,只发送一个命令(读或者写)的情况下,最多可以读或者写256个扇区(当然也可以读一个扇区,读或者写多少个扇区在扇区计数器count里面),其中,发一个读或者写命令,读或者写256个扇区所需要的时间,比分256次去读写这些扇区所需要的时间要短得多,效率要高得多,我现在需要的是一个读写的速度比较快,效率比较高的文件系统,因此,底层的读写扇区必须要每写一个命令就可以读写多个扇区,读写扇区的函数必须要有扇区计数器(前面的count)这个参数,才可能满足要求。
FATFS在ATmega64上针对Flash的移植
FATFS在ATmega64上针对Flash的移植摘要:本文介绍一种适用于单片机的嵌入式文件系统FATFS MOULE,它具有容易移植、功能强大和易于使用等优点。
同时以A VR系列的ATmega64单片机为例,给出了相应的软件系统设计,并进行速率测试。
关键词:FatFs 文件系统A VR Flash1 概述1.1 FATFS简介FATFS是一个通用的文件系统模块,专门为小型的嵌入式系统而实现的FAT 文件系统,支持FATl2、FATl6 和FAT32。
它用标准C语言编写,因此具有硬件平台独立性,在简单修改的情况下可以很方便移植到8051、A VR、ARM 等系列单片机上。
FATFS分离缓冲FAT结构的每个文件,可以快速访问多个文件,支持多个存储媒介,并特别对8/16位单片机做了优化。
1.2 FATFS文件系统结构FATFS一开始就是为了单片机上使用而设计的,具有良好的层次结构。
最顶层是应用层,使用者无需理会FATFS的内部结构和FAT协议,只需要调用FATFS 提供给用户的API,如f_open、f_read、f_write、f_close 等,即以方便读/写文件。
中间层FATFS实现了FAT文件读/写协议。
除非有必要,使用者一般不用修改,使用时将需要头文件ff.h直接包含进去即可。
移植时需要提供底层接口,它包括存储媒介读/写接口Disk I/O和供给文件创建、修改时间的实时时钟。
2 移植FATFS移植时只需要提供底层接口,它包括存储媒介读/写接口Disk I/O和供给文件创建、修改时间的实时时钟。
移植过程主要需要三步:(1)编写SPI 和FLASH 接口代码;(2)编写Disk I/O;(3)FATFS的配置。
2.1 编写SPI 和FLASH接口代码ATmega64与FLASH使用SPI通信模式。
这就需要ATmega64提供SPI读/写接口代码,主要包括初始化、读和写。
在具备SPI读/写接口的基础上编写FLASH接口代码,需要编写四个基本接口函数:(1)从FLASH读一页数据,void flash_page_read_si(uint32_t sector,uint8_t *data)(2)从FLASH读多页数据,void flash_page_read_mu(uint32_t sector,uint8_t count,uint8_t *data)(3)向FLASH写一页数据,void flash_page_write_si(uint32_t sector,uint8_t *data)(4)向FLASH写多页数据,void flash_page_write_mu(uint32_t sector,uint8_t count,uint8_t *data)2.2 编写Disk I/O编写好存储媒介的接口代码后,就可以编写DiskIO 了,需要编写6 个接口函数,分别是:(1)DSTATUSdisk_initialize ( BYTE drv );存储媒介初始化函数。
nand flash驱动编写与移植
第七部分 Nand flash 驱动的编写与移植1 Nand flash 工作原理S3C2410板的Nand Flash 支持由两部分组成:Nand Flash 控制器(集成在S3C2410 CPU)和Nand Flash 存储芯片(K9F1208U0B )两大部分组成。
当要访问Nand Flash 中的数据时,必须通过Nand Flash 控制器发送命令才能完成。
所以, Nand Flash 相当于S3C2410的一个外设,而不位于它的内存地址区.1.1 Nand flash 芯片工作原理Nand flash 芯片型号为Samsung K9F1208U0B ,数据存储容量为64MB ,采用块页式存储管理。
8个I/O 引脚充当数据、地址、命令的复用端口。
1.1.1芯片内部存储布局及存储操作特点一片Nand flash 为一个设备(device), 其数据存储分层为:1设备(Device) = 4096 块(Blocks)1块(Block) = 32页/行(Pages/rows) ;页与行是相同的意思,叫法不一样1字节(Bytes) = 数据块大小(512Bytes) + OOB 块大小(16Bytes)在每一页中,最后16个字节(又称OOB )用于Nand Flash 命令执行完后设置状态用,剩余512个字节又分为前半部分和后半部分。
可以通过Nand Flash 命令00h/01h/50h 分别对前半部、后半部、OOB 进行定位通过Nand Flash 内置的指针指向各自的首地址。
存储操作特点:1. 擦除操作的最小单位是块。
2. Nand Flash 芯片每一位(bit)只能从1变为0,而不能从0变为1,所以在对其进行写入操作之前要一定将相应块擦除(擦除即是将相应块得位全部变为1).3. OOB 部分的第六字节(即517字节)标志是否是坏块,如果不是坏块该值为FF ,否则为坏块。
4. 除OOB 第六字节外,通常至少把OOB 的前3个字节存放Nand Flash 硬件ECC 码(关于硬件ECC 码请参看Nandflash 控制器一节).1.1.2重要芯片引脚功能I/O0I/O7:复用引脚。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
STM32 EWARM开发过程简介之五--移植FATFS的NANDFLASH驱动一,建立工程FATFS源码1,在/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 12,把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 == 0DRESULT 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");}elseif((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 mountres=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);// forpfs=&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 readres=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 writeres=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 umountf_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 T argetPageAddress: T arget 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 T argetPageAddress);//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代码,自行处理。