轻松游戏!快乐分享!
上一篇:为孩子提供可定制通勤服务的印度创企piggyride获7500万卢比种子轮融资 下一篇:前WWE冠军科菲透迷失传奇变态页游sf露,曾在比赛中被打成真哭!

【兆易创新RISC-V开发板评测】04.实现FatFs移植到GD32 RISC-V开发平台

6.工程&资料

https://mbb.eet-china.com/forum/topic/76292_1_1.html

【兆易创新RISC-V开发板评测】04.实现FatFs移植到GD32 RISC-V开发平台

2

4.移植FatFs

将FatFs源文件ff14文件夹复制到工程的Utilities文件夹下,并刷新工程,即可显示出目录结构及对应的源文件了。在SPIFlash上实现FatFs文件系统主要是对diskio.c接口文件和ffconf.h配置文件的修改。

diskio.c接口文件源码如下所示:

<div><div><div>/*-----------------------------------------------------------------------*/

/*LowleveldiskI/OmoduleskeletonforFatFs(C)ChaN,2019*/

/*-----------------------------------------------------------------------*/

/*Ifaworkingstoragecontrolmoduleisavailable,itshouldbe*/

/*attachedtotheFatFsviaagluefunctionratherthanmodifyingit.*/

/*Thisisanexampleofgluefunctionstoattachvariousexsisting*/

/*storagecontrolmodulestotheFatFsmodulewithadefinedAPI.*/

/*-----------------------------------------------------------------------*/

#include"ff.h"/*Obtainsintegertypes*/

#include"diskio.h"/*Declarationsofdiskfunctions*/

#include"gd32vf103v_spi_flash_eval.h"

/*Definitionsofphysicaldrivenumberforeachdrive*/

#defineDEV_SPI_FLASH0

/*-----------------------------------------------------------------------*/

/*GetDriveStatus*/

/*-----------------------------------------------------------------------*/

DSTATUSdisk_status(

BYTEpdrv/*Physicaldrivenmubertoidentifythedrive*/

)

{

DSTATUSstat;

intresult;

switch(pdrv)

{

caseDEV_SPI_FLASH:returnRES_OK;

}

returnSTA_NOINIT;

}

/*-----------------------------------------------------------------------*/

/*InidializeaDrive*/

/*-----------------------------------------------------------------------*/

DSTATUSdisk_initialize(

BYTEpdrv/*Physicaldrivenmubertoidentifythedrive*/

)

{

DSTATUSstat;

intresult;

switch(pdrv)

{

caseDEV_SPI_FLASH:returnRES_OK;

}

returnSTA_NOINIT;

}

/*-----------------------------------------------------------------------*/

/*ReadSector(s)*/

/*-----------------------------------------------------------------------*/

DRESULTdisk_read(

BYTEpdrv,/*Physicaldrivenmubertoidentifythedrive*/

BYTE*buff,/*Databuffertostorereaddata*/

LBA_tsector,/*StartsectorinLBA*/

UINTcount/*Numberofsectorstoread*/

)

{

DRESULTres;

intresult;

//xUserPrintf("\r\ndrpdrv=%d,sector=%d,count=%d\r\n",pdrv,sector,count);

switch(pdrv)

{

caseDEV_SPI_FLASH:

for(;count>0;count--)

{

spi_flash_read(sector*SECTOR_SIZE,buff,SECTOR_SIZE);

sector+=1;

buff+=SECTOR_SIZE;

}

returnRES_OK;

}

returnRES_PARERR;

}

/*-----------------------------------------------------------------------*/

/*WriteSector(s)*/

/*-----------------------------------------------------------------------*/

#ifFF_FS_READONLY==0

DRESULTdisk_write(

BYTEpdrv,/*Physicaldrivenmubertoidentifythedrive*/

constBYTE*buff,/*Datatobewritten*/

LBA_tsector,/*StartsectorinLBA*/

UINTcount/*Numberofsectorstowrite*/

)

{

DRESULTres;

intresult;

//xUserPrintf("\r\ndwpdrv=%d,sector=%d,count=%d\r\n",pdrv,sector,count);

switch(pdrv)

{

caseDEV_SPI_FLASH:

for(;count>0;count--)

{

spi_flash_erase_sector(sector*SECTOR_SIZE);

spi_flash_write(sector*SECTOR_SIZE,(uint8_t*)buff,SECTOR_SIZE);

sector+=1;

buff+=SECTOR_SIZE;

}

returnRES_OK;

}

returnRES_PARERR;

}

#endif

/*-----------------------------------------------------------------------*/

/*MiscellaneousFunctions*/

/*-----------------------------------------------------------------------*/

DRESULTdisk_ioctl(

BYTEpdrv,/*Physicaldrivenmuber(0..)*/

BYTEcmd,/*Controlcode*/

void*buff/*Buffertosend/receivecontroldata*/

)

{

DRESULTres;

intresult;

switch(pdrv)

{

caseDEV_SPI_FLASH:

switch(cmd)

{

caseCTRL_SYNC:

res=RES_OK;

break;

caseGET_SECTOR_SIZE:

*(WORD*)buff=SECTOR_SIZE;

res=RES_OK;

break;

caseGET_BLOCK_SIZE:

*(DWORD*)buff=1;

res=RES_OK;

break;

caseGET_SECTOR_COUNT:

*(DWORD*)buff=SECTOR_COUNT;

res=RES_OK;

break;

default:

res=RES_PARERR;

break;

}

break;

default:res=RES_PARERR;break;

}

returnres;

}

DWORDget_fattime(void)

{

return0;

}

ffconf.h配置文件源码如下所示:

<div><div><div>/*---------------------------------------------------------------------------/

/FatFsFunctionalConfigurations

/---------------------------------------------------------------------------*/

#defineFFCONF_DEF86606/*RevisionID*/

/*---------------------------------------------------------------------------/

/FunctionConfigurations

/---------------------------------------------------------------------------*/

#defineFF_FS_READONLY0

/*Thisoptionswitchesread-onlyconfiguration.(0:Read/Writeor1:Read-only)

/Read-onlyconfigurationremoveswritingAPIfunctions,f_write(),f_sync(),

/f_unlink(),f_mkdir(),f_chmod(),f_rename(),f_truncate(),f_getfree()

/andoptionalwritingfunctionsaswell.*/

#defineFF_FS_MINIMIZE0

/*ThisoptiondefinesminimizationleveltoremovesomebasicAPIfunctions.

/

/0:Basicfunctionsarefullyenabled.

/1:f_stat(),f_getfree(),f_unlink(),f_mkdir(),f_truncate()andf_rename()

/areremoved.

/2:f_opendir(),f_readdir()andf_closedir()areremovedinadditionto1.

/3:f_lseek()functionisremovedinadditionto2.*/

#defineFF_USE_STRFUNC0

/*Thisoptionswitchesstringfunctions,f_gets(),f_putc(),f_puts()andf_printf().

/

/0:Disablestringfunctions.

/1:EnablewithoutLF-CRLFconversion.

/2:EnablewithLF-CRLFconversion.*/

#defineFF_USE_FIND0

/*Thisoptionswitchesfiltereddirectoryreadfunctions,f_findfirst()and

/f_findnext().(0:Disable,1:Enable2:Enablewithmatchingaltname[]too)*/

#defineFF_USE_MKFS1

/*Thisoptionswitchesf_mkfs()function.(0:Disableor1:Enable)*/

#defineFF_USE_FASTSEEK0

/*Thisoptionswitchesfastseekfunction.(0:Disableor1:Enable)*/

#defineFF_USE_EXPAND0

/*Thisoptionswitchesf_expandfunction.(0:Disableor1:Enable)*/

#defineFF_USE_CHMOD0

/*Thisoptionswitchesattributemanipulationfunctions,f_chmod()andf_utime().

/(0:Disableor1:Enable)AlsoFF_FS_READONLYneedstobe0toenablethisoption.*/

#defineFF_USE_LABEL0

/*Thisoptionswitchesvolumelabelfunctions,f_getlabel()andf_setlabel().

/(0:Disableor1:Enable)*/

#defineFF_USE_FORWARD0

/*Thisoptionswitchesf_forward()function.(0:Disableor1:Enable)*/

/*---------------------------------------------------------------------------/

/LocaleandNamespaceConfigurations

/---------------------------------------------------------------------------*/

#defineFF_CODE_PAGE936

/*ThisoptionspecifiestheOEMcodepagetobeusedonthetargetsystem.

/Incorrectcodepagesettingcancauseafileopenfailure.

/

/437-U.S.

/720-Arabic

/737-Greek

/771-KBL

/775-Baltic

/850-Latin1

/852-Latin2

/855-Cyrillic

/857-Turkish

/860-Portuguese

/861-Icelandic

/862-Hebrew

/863-CanadianFrench

/864-Arabic

/865-Nordic

/866-Russian

/869-Greek2

/932-Japanese(DBCS)

/936-SimplifiedChinese(DBCS)

/949-Korean(DBCS)

/950-TraditionalChinese(DBCS)

/0-Includeallcodepagesaboveandconfiguredbyf_setcp()

*/

#defineFF_USE_LFN0

#defineFF_MAX_LFN255

/*TheFF_USE_LFNswitchesthesupportforLFN(longfilename).

/

/0:DisableLFN.FF_MAX_LFNhasnoeffect.

/1:EnableLFNwithstaticworkingbufferontheBSS.AlwaysNOTthread-safe.

/2:EnableLFNwithdynamicworkingbufferontheSTACK.

/3:EnableLFNwithdynamicworkingbufferontheHEAP.

/

/ToenabletheLFN,ffunicode.cneedstobeaddedtotheproject.TheLFNfunction

/requierscertaininternalworkingbufferoccupies(FF_MAX_LFN+1)*2bytesand

/additional(FF_MAX_LFN+44)/15*32byteswhenexFATisenabled.

/TheFF_MAX_LFNdefinessizeoftheworkingbufferinUTF-16codeunitanditcan

/beinrangeof12to255.Itisrecommendedtobesetit255tofullysupportLFN

/specification.

/Whenusestackfortheworkingbuffer,takecareonstackoverflow.Whenuseheap

/memoryfortheworkingbuffer,memorymanagementfunctions,ff_memalloc()and

/ff_memfree()exemplifiedinffsystem.c,needtobeaddedtotheproject.*/

#defineFF_LFN_UNICODE0

/*ThisoptionswitchesthecharacterencodingontheAPIwhenLFNisenabled.

/

/0:ANSI/OEMincurrentCP(TCHAR=char)

/1:UnicodeinUTF-16(TCHAR=WCHAR)

/2:UnicodeinUTF-8(TCHAR=char)

/3:UnicodeinUTF-32(TCHAR=DWORD)

/

/AlsobehaviorofstringI/Ofunctionswillbeaffectedbythisoption.

/WhenLFNisnotenabled,thisoptionhasnoeffect.*/

#defineFF_LFN_BUF255

#defineFF_SFN_BUF12

/*ThissetofoptionsdefinessizeoffilenamemembersintheFILINFOstructure

/whichisusedtoreadoutdirectoryitems.Thesevaluesshouldbesuffcientfor

/thefilenamestoread.Themaximumpossiblelengthofthereadfilenamedepends

/oncharacterencoding.WhenLFNisnotenabled,theseoptionshavenoeffect.*/

#defineFF_STRF_ENCODE3

/*WhenFF_LFN_UNICODE>=1withLFNenabled,stringI/Ofunctions,f_gets(),

/f_putc(),f_putsandf_printf()convertthecharacterencodinginit.

/ThisoptionselectsassumptionofcharacterencodingONTHEFILEtobe

/read/writtenviathosefunctions.

/

/0:ANSI/OEMincurrentCP

/1:UnicodeinUTF-16LE

/2:UnicodeinUTF-16BE

/3:UnicodeinUTF-8

*/

#defineFF_FS_RPATH0

/*Thisoptionconfiguressupportforrelativepath.

/

/0:Disablerelativepathandremoverelatedfunctions.

/1:Enablerelativepath.f_chdir()andf_chdrive()areavailable.

/2:f_getcwd()functionisavailableinadditionto1.

*/

/*---------------------------------------------------------------------------/

/Drive/VolumeConfigurations

/---------------------------------------------------------------------------*/

#defineFF_VOLUMES1

/*Numberofvolumes(logicaldrives)tobeused.(1-10)*/

#defineFF_STR_VOLUME_ID0

#defineFF_VOLUME_STRS"RAM","NAND","CF","SD","SD2","USB","USB2","USB3"

/*FF_STR_VOLUME_IDswitchessupportforvolumeIDinarbitrarystrings.

/WhenFF_STR_VOLUME_IDissetto1or2,arbitrarystringscanbeusedasdrive

/numberinthepathname.FF_VOLUME_STRSdefinesthevolumeIDstringsforeach

/logicaldrives.NumberofitemsmustnotbelessthanFF_VOLUMES.Valid

/charactersforthevolumeIDstringsareA-Z,a-zand0-9,however,theyare

/comparedincase-insensitive.IfFF_STR_VOLUME_ID>=1andFF_VOLUME_STRSis

/notdefined,auserdefinedvolumestringtableneedstobedefinedas:

/

/constchar*VolumeStr[FF_VOLUMES]={"ram","flash","sd","usb",...

*/

#defineFF_MULTI_PARTITION0

/*Thisoptionswitchessupportformultiplevolumesonthephysicaldrive.

/Bydefault(0),eachlogicaldrivenumberisboundtothesamephysicaldrive

/numberandonlyanFATvolumefoundonthephysicaldrivewillbemounted.

/Whenthisfunctionisenabled(1),eachlogicaldrivenumbercanbeboundto

/arbitraryphysicaldriveandpartitionlistedintheVolToPart[].Alsof_fdisk()

/funcitonwillbeavailable.*/

#defineFF_MIN_SS512

#defineFF_MAX_SS4096

/*Thissetofoptionsconfigurestherangeofsectorsizetobesupported.(512,

/1024,2048or4096)Alwayssetboth512formostsystems,genericmemorycardand

/harddisk.Butalargervaluemayberequiredforon-boardflashmemoryandsome

/typeofopticalmedia.WhenFF_MAX_SSislargerthanFF_MIN_SS,FatFsisconfigured

/forvariablesectorsizemodeanddisk_ioctl()functionneedstoimplement

/GET_SECTOR_SIZEcommand.*/

#defineFF_LBA640

/*Thisoptionswitchessupportfor64-bitLBA.(0:Disableor1:Enable)

/Toenablethe64-bitLBA,alsoexFATneedstobeenabled.(FF_FS_EXFAT==1)*/

#defineFF_MIN_GPT0x100000000

/*MinimumnumberofsectorstoswitchGPTformattocreatepartitioninf_mkfsand

/f_fdiskfunction.0x100000000max.ThisoptionhasnoeffectwhenFF_LBA64==0.*/

#defineFF_USE_TRIM0

/*ThisoptionswitchessupportforATA-TRIM.(0:Disableor1:Enable)

/ToenableTrimfunction,alsoCTRL_TRIMcommandshouldbeimplementedtothe

/disk_ioctl()function.*/

/*---------------------------------------------------------------------------/

/SystemConfigurations

/---------------------------------------------------------------------------*/

#defineFF_FS_TINY0

/*Thisoptionswitchestinybufferconfiguration.(0:Normalor1:Tiny)

/Atthetinyconfiguration,sizeoffileobject(FIL)isshrinkedFF_MAX_SSbytes.

/Insteadofprivatesectorbuffereliminatedfromthefileobject,commonsector

/bufferinthefilesystemobject(FATFS)isusedforthefiledatatransfer.*/

#defineFF_FS_EXFAT0

/*ThisoptionswitchessupportforexFATfilesystem.(0:Disableor1:Enable)

/ToenableexFAT,alsoLFNneedstobeenabled.(FF_USE_LFN>=1)

/NotethatenablingexFATdiscardsANSIC(C89)compatibility.*/

#defineFF_FS_NORTC0

#defineFF_NORTC_MON1

#defineFF_NORTC_MDAY1

#defineFF_NORTC_YEAR2019

/*TheoptionFF_FS_NORTCswitchestimestampfunctiton.Ifthesystemdoesnothave

/anyRTCfunctionorvalidtimestampisnotneeded,setFF_FS_NORTC=1todisable

/thetimestampfunction.EveryobjectmodifiedbyFatFswillhaveafixedtimestamp

/definedbyFF_NORTC_MON,FF_NORTC_MDAYandFF_NORTC_YEARinlocaltime.

/Toenabletimestampfunction(FF_FS_NORTC=0),get_fattime()functionneedtobe

/addedtotheprojecttoreadcurrenttimeformreal-timeclock.FF_NORTC_MON,

/FF_NORTC_MDAYandFF_NORTC_YEARhavenoeffect.

/Theseoptionshavenoeffectinread-onlyconfiguration(FF_FS_READONLY=1).*/

#defineFF_FS_NOFSINFO0

/*IfyouneedtoknowcorrectfreespaceontheFAT32volume,setbit0ofthis

/option,andf_getfree()functionatfirsttimeaftervolumemountwillforce

/afullFATscan.Bit1controlstheuseoflastallocatedclusternumber.

/

/bit0=0:UsefreeclustercountintheFSINFOifavailable.

/bit0=1:DonottrustfreeclustercountintheFSINFO.

/bit1=0:UselastallocatedclusternumberintheFSINFOifavailable.

/bit1=1:DonottrustlastallocatedclusternumberintheFSINFO.

*/

#defineFF_FS_LOCK0

/*TheoptionFF_FS_LOCKswitchesfilelockfunctiontocontrolduplicatedfileopen

/andillegaloperationtoopenobjects.Thisoptionmustbe0whenFF_FS_READONLY

/is1.

/

/0:Disablefilelockfunction.Toavoidvolumecorruption,applicationprogram

/shouldavoidillegalopen,removeandrenametotheopenobjects.

/>0:Enablefilelockfunction.Thevaluedefineshowmanyfiles/sub-directories

/canbeopenedsimultaneouslyunderfilelockcontrol.Notethatthefile

/lockcontrolisindependentofre-entrancy.*/

/*#include<somertos.h>//O/Sdefinitions*/

#defineFF_FS_REENTRANT0

#defineFF_FS_TIMEOUT1000

#defineFF_SYNC_tHANDLE

/*TheoptionFF_FS_REENTRANTswitchesthere-entrancy(threadsafe)oftheFatFs

/moduleitself.Notethatregardlessofthisoption,fileaccesstodifferent

/volumeisalwaysre-entrantandvolumecontrolfunctions,f_mount(),f_mkfs()

/andf_fdisk()function,arealwaysnotre-entrant.Onlyfile/directoryaccess

/tothesamevolumeisundercontrolofthisfunction.

/

/0:Disablere-entrancy.FF_FS_TIMEOUTandFF_SYNC_thavenoeffect.

/1:Enablere-entrancy.Alsouserprovidedsynchronizationhandlers,

/ff_req_grant(),ff_rel_grant(),ff_del_syncobj()andff_cre_syncobj()

/function,mustbeaddedtotheproject.Samplesareavailablein

/option/syscall.c.

/

/TheFF_FS_TIMEOUTdefinestimeoutperiodinunitoftimetick.

/TheFF_SYNC_tdefinesO/Sdependentsyncobjecttype.e.g.HANDLE,ID,OS_EVENT*,

/SemaphoreHandle_tandetc.AheaderfileforO/Sdefinitionsneedstobe

/includedsomewhereinthescopeofff.h.*/

/*---Endofconfigurationoptions---*/

 5.FatFs演示示例

在FatFs接口文件和配置文件移植完成后,,我们在main.c中对文件系统进行初始化,主要是对磁盘的初始化和挂载操作,便于后面的文件操作:

<div><div><div>FATFSfs;

BYTEwork[FF_MAX_SS];

uint8_tfsFlag=0;

uint8_tfsTest=0;

voidxInitFileSystem(void)

{

FRESULTres;

res=f_mount(&fs,"0:",1);

if(res==FR_NO_FILESYSTEM)

{

res=f_mkfs("0:",0,work,sizeof(work));

if(res==FR_OK)

{

xUserPrintf("\r\nCreateanFAT/exFATvolumeonthelogicaldrive\r\n");

res=f_mount(&fs,"0:",1);

if(res==FR_OK)fsFlag=1;

}

}

else

{

fsFlag=1;

}

if(fsFlag)

{

xUserPrintf("\r\nRegistertheworkareaofthevolumesuccess\r\n");

}

}

然后我们添加一个简单的测试DEMO程序,主要功能是在hello.txt文件的尾部不断的插入新数据,然后再把hello.txt的内容读取出来并打印出来;为了方便测试,将这个函数添加到shell命令中了:

<div><div><div>voidxTestFileSystem(void)

{

FILfil;

UINTbw;

FRESULTres;

if(fsFlag)

{

charbuffer[200];

res=f_open(&fil,"0:hello.txt",FA_OPEN_APPEND|FA_WRITE);

if(res==FR_OK)

{

memset(buffer,0,sizeof(buffer));

sprintf(buffer,"%d",fsTest++%100);

res=f_write(&fil,buffer,1,&bw);

f_close(&fil);

}

res=f_open(&fil,"0:hello.txt",FA_OPEN_EXISTING|FA_READ);

if(res==FR_OK)

{

memset(buffer,0,sizeof(buffer));

res=f_read(&fil,buffer,200,&bw);

xUserPrintf("\r\nread:%d|%d=>>%s\r\n",res,bw,buffer);

f_close(&fil);

}

}

else

{

xUserPrintf("\r\nFileSystemInitFailed!\r\n");

}

}

如下图所示是测试过程和结果:

1

FatFs是一个应用在小型嵌入式系统中的通用文件系统(FAT/exFAT)模块。FatFs模块是遵循ANSIC(C89)编写的,与磁盘I/O层是完全分离的。因此,它是独立于平台的。它可以被整合到资源有限的小型微控制器中,如8051、PIC、AVR、ARM、Z80、RX等等;

本文中使用的是FatFs_R0.14版本,结合GD32RISV-V开发平台板载的SPIFLASH来实现文件系统的功能。FatFs官网及下载地址:

,当然也可以到面包板下载中心下载:

https://mbb.eet-china.com/download/36035.html

2.硬件原理图

从原理图上我们可以看到,SPIFlash使用的GD25Q16这颗芯片,其存储容量为2M字节;与MCU连接的接口使用的是硬件SPI0,另外CS操作引脚使用的是PE3。需要注意的是有一个JP12的跳线设置,需要将PA5与SPI0_SCK进行短接。

1

3.移植前准备

实现FatFs的移植是基于《【兆易创新RISC-V开发板评测】03.实现uGUI移植到GD32RISC-V开发平台》的工程上实现的。通过NucleiStudioIDE打开工程,在gd32vf103_eval.c文件中对硬件SPI接口进行配置初始化:

<div><div><div>/*!

\briefconfigspi0forspiflash

\param[in]none

\param[out]none

\retvalnone

*/

voidgd_eval_spi_init(void)

{

spi_parameter_structspi_init_struct;

spi_struct_para_init(&spi_init_struct);

/*peripheralclockenable*/

rcu_periph_clock_enable(RCU_GPIOA);

rcu_periph_clock_enable(RCU_GPIOE);

rcu_periph_clock_enable(RCU_AF);

rcu_periph_clock_enable(RCU_SPI0);

/*SPI0GPIOconfig:SCK/PA5,MISO/PA6,MOSI/PA7*/

gpio_init(GPIOA,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_5|GPIO_PIN_7);

gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_50MHZ,GPIO_PIN_6);

/*SPIflashCSpinconfig:SPIFlashCS/PE3*/

gpio_init(GPIOE,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_3);

/*deinitilizeSPIandtheparameters*/

spi_i2s_deinit(SPI0);

/*SPI0parameterconfig*/

spi_init_struct.trans_mode=SPI_TRANSMODE_FULLDUPLEX;

spi_init_struct.device_mode=SPI_MASTER;

spi_init_struct.frame_size=SPI_FRAMESIZE_8BIT;

spi_init_struct.clock_polarity_phase=SPI_CK_PL_HIGH_PH_2EDGE;

spi_init_struct.nss=SPI_NSS_SOFT;

spi_init_struct.prescale=SPI_PSC_8;

spi_init_struct.endian=SPI_ENDIAN_MSB;

spi_init(SPI0,&spi_init_struct);

/*SPIenable*/

spi_enable(SPI0);

}

/*!

\briefreadandwritespiflashbyspi0

\param[in]data:writetospiflash

\param[out]data:readfromspiflash

\retvalnone

*/

uint16_tgd_eval_spi_rw(uint16_tdata)

{

while(RESET==spi_i2s_flag_get(SPI0,SPI_FLAG_TBE));

spi_i2s_data_transmit(SPI0,data);

while(RESET==spi_i2s_flag_get(SPI0,SPI_FLAG_RBNE));

returnspi_i2s_data_receive(SPI0);

}

新建gd32vf103v_spi_flash_eval.c和gd32vf103v_spi_flash_eval.h两个文件,在这个文件中实现对SPIFlash的操作函数:

<div><div>#include"gd32vf103v_eval.h"

#include"gd32vf103v_spi_flash_eval.h"

#include<stdarg.h>

#include<string.h>

unsignedlongxUserPow(intx,inty)

{

unsignedlongsum=1;

while(y--)

{

sum*=x;

}

returnsum;

}

voidxUserPutChar(constcharch)

{

usart_data_transmit(USART0,(uint8_t)ch);

while(usart_flag_get(USART0,USART_FLAG_TBE)==RESET){

}

}

voidxUserPutString(constchar*str)

{

while(*str)

{

xUserPutChar(*str++);

}

}

voidxUserPrintNum(constintvalue,constintpow)

{

inttemp,count=0,data;

temp=value;

if(temp==0)

{

xUserPutChar(’0’);

}

else

{

while(temp)

{

count++;temp/=pow;

}

temp=value;

while(count)

{

data=temp/xUserPow(pow,count-1);

temp=temp%xUserPow(pow,count-1);

if(data<=9)xUserPutChar(data+’0’);

elsexUserPutChar(data+’a’-10);

count--;

}

}

}

voidxUserPrintf(constchar*str,...)

{

va_listap;

intval,r_val;

charcount,ch;

va_start(ap,str);

while(*str)

{

switch(*str)

{

case’%’:

str++;

switch(*str)

{

case’d’:

xUserPrintNum(va_arg(ap,int),10);

break;

case’x’:

xUserPrintNum(va_arg(ap,int),16);

break;

case’s’:

xUserPutString(va_arg(ap,char*));

break;

case’c’:

xUserPutChar((char)va_arg(ap,int));

break;

default:break;

}

break;

case’\n’:xUserPutChar(’\n’);break;

case’\r’:xUserPutChar(’\r’);break;

default:xUserPutChar(*str);break;

}

str++;

}

va_end(ap);

}

voidspi_flash_write_enable(void)

{

SPIFlashCS_L();

gd_eval_spi_rw(SPI_FLASH_CMD_WREN);

SPIFlashCS_H();

}

voidspi_flash_write_disable(void)

{

SPIFlashCS_L();

gd_eval_spi_rw(SPI_FLASH_CMD_WRDI);

SPIFlashCS_H();

}

voidspi_flash_wait_for_write_end(void)

{

uint8_tflag=0;

SPIFlashCS_L();

gd_eval_spi_rw(SPI_FLASH_CMD_RDSR);

do

{

flag=gd_eval_spi_rw(SPI_FLASH_DUMMY);

}while(flag&0x01);

SPIFlashCS_H();

}

voidspi_flash_erase_sector(uint32_taddress)

{

spi_flash_write_enable();

spi_flash_wait_for_write_end();

SPIFlashCS_L();

gd_eval_spi_rw(SPI_FLASH_CMD_SE);

gd_eval_spi_rw((address&0x00FF0000)>>0x10);

gd_eval_spi_rw((address&0x0000FF00)>>0x08);

gd_eval_spi_rw((address&0x000000FF)>>0x00);

SPIFlashCS_H();

spi_flash_wait_for_write_end();

}

voidspi_flash_erase_block32(uint32_taddress)

{

spi_flash_write_enable();

spi_flash_wait_for_write_end();

SPIFlashCS_L();

gd_eval_spi_rw(SPI_FLASH_CMD_BE32);

gd_eval_spi_rw((address&0x00FF0000)>>0x10);

gd_eval_spi_rw((address&0x0000FF00)>>0x08);

gd_eval_spi_rw((address&0x000000FF)>>0x00);

SPIFlashCS_H();

spi_flash_wait_for_write_end();

}

voidspi_flash_fast_read(uint32_taddress,uint8_t*buffer,uint16_tlength)

{

SPIFlashCS_L();

gd_eval_spi_rw(SPI_FLASH_CMD_FastRead);

gd_eval_spi_rw((address&0x00FF0000)>>0x10);

gd_eval_spi_rw((address&0x0000FF00)>>0x08);

gd_eval_spi_rw((address&0x000000FF)>>0x00);

gd_eval_spi_rw(SPI_FLASH_DUMMY);

for(uint16_ti=0;i<length;i++)

{

buffer

=gd_eval_spi_rw(SPI_FLASH_DUMMY);

}

SPIFlashCS_H();

}

voidspi_flash_page_program(uint32_taddress,uint8_t*buffer,uint16_tlength)

{

spi_flash_write_enable();

SPIFlashCS_L();

gd_eval_spi_rw(SPI_FLASH_CMD_PP);

gd_eval_spi_rw((address&0x00FF0000)>>0x10);

gd_eval_spi_rw((address&0x0000FF00)>>0x08);

gd_eval_spi_rw((address&0x000000FF)>>0x00);

for(uint16_ti=0;i<length;i++)

{

gd_eval_spi_rw(buffer

);

}

SPIFlashCS_H();

spi_flash_wait_for_write_end();

}

voidspi_flash_init(void)

{

gd_eval_spi_init();

SPIFlashCS_H();

xUserPrintf("\r\nSPIFlashInitOK!\r\n");

}

voidspi_flash_read(uint32_taddress,uint8_t*buffer,uint16_tlength)

{

spi_flash_fast_read(address,buffer,length);

}

voidspi_flash_write(uint32_taddress,uint8_t*buffer,uint16_tlength)

{

uint16_toffset=0;

uint16_tnum_head=0,num_tail=0,num_page=0;

num_head=PAGE_SIZE-(address%PAGE_SIZE);

//xUserPrintf("\r\nnum_head=%d,length=%d\r\n",num_head,length);

if(num_head>=length)

{

//xUserPrintf("\r\nLengthPP\r\n");

spi_flash_page_program(address,&buffer[offset],length);

}

else

{

//xUserPrintf("\r\nHeadPP\r\n");

spi_flash_page_program(address,&buffer[offset],num_head);

offset+=num_head;

length-=num_head;

address+=num_head;

num_page=length/PAGE_SIZE;

num_tail=length%PAGE_SIZE;

//xUserPrintf("\r\nnum_page=%d\r\n",num_page);

//xUserPrintf("\r\nnum_tail=%d\r\n",num_tail);

for(uint16_ti=0;i<num_page;i++)

{

//xUserPrintf("\r\nPagePP\r\n");

spi_flash_page_program(address,&buffer[offset],PAGE_SIZE);

offset+=PAGE_SIZE;

address+=PAGE_SIZE;

}

if(num_tail)

{

//xUserPrintf("\r\nTailPP\r\n");

spi_flash_page_program(address,&buffer[offset],num_tail);

}

}

}

voidspi_flash_shell_rdid(void)

{

uint32_tid=0;

SPIFlashCS_L();

gd_eval_spi_rw(SPI_FLASH_CMD_RDID);

id=gd_eval_spi_rw(SPI_FLASH_DUMMY);

id<<=8;

id|=gd_eval_spi_rw(SPI_FLASH_DUMMY);

id<<=8;

id|=gd_eval_spi_rw(SPI_FLASH_DUMMY);

xUserPrintf("\r\nSPIFlashRDID:0x%x\r\n",id);

SPIFlashCS_H();

}

voidspi_flash_shell_erase(uint32_taddress)

{

spi_flash_erase_sector(address);

xUserPrintf("\r\nSPIFlashSectorErase:0x%x\r\n",address);

}

voidspi_flash_shell_erase_all(void)

{

for(uint16_ti=0;i<SECTOR_COUNT;i++)

{

spi_flash_shell_erase(i*SECTOR_SIZE);

}

}

voidspi_flash_shell_read(uint32_taddress,uint16_tlength)

{

uint8_tbuffer[500];

memset(buffer,0,sizeof(buffer));

spi_flash_read(address,buffer,length);

xUserPrintf("\r\nSPIFlashRead:\r\n");

for(uint16_ti=0;i<length;i++)

{

xUserPrintf("0x%x",buffer

);

}

xUserPrintf("\r\n");

}

voidspi_flash_shell_write(uint32_taddress,uint16_tlength)

{

uint8_tbuffer[500];

for(uint16_ti=0;i<sizeof(buffer);i++)

{

buffer

=i%256;

}

spi_flash_write(address,buffer,length);

}

  • 共2页:
  • 上一页
  • 1
  • 2
  • 下一页

  • 除非注明,迷失传奇私服文章均为原创,转载请以链接形式标明本文地址

    本文地址:http://rrc.org.cn/sf/3828.html
    Copyright © 2018-2019 迷失传奇私服 版权所有