STM32F103外挂SPIFlash,内嵌FatFS⽂件系统,并通过
USB接PC可访问F。。。
早两天往Stm32上移植Fatfs⽂件系统,花了⼀些时间;
后⾯⼜花了些时间移植Stm32的USB功能;
在这个过程中,⾃⼰摸索了很多东西,也向⾥的⾼⼈请教过,所以希望把这部分东西记录下,⽅便⾃⼰以后和想寻这⽅⾯知识的⼈查看。
下⾯按照上⾯的介绍分⼏步来介绍移植驱动所做的⼯作。
fatfs⽂件系统的移植
在下载的源码⾥⾯可以看到source⽂件下⾯有上⾯这些⽂件。这就是我们要移植的⽂件系统。
其实为了⽅便移植前辈们在这个上⾯已经完善了很多很多,我们只需要做⽐较少的改动就可以应⽤起来;我们需要修改的⽂件是diskio.c这个⽂件⾥⾯的⼏个标准接⼝:
DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
DWORD get_fattime (void);
在diskio.c中定义了⼏个磁盘设备:
#define DEV_RAM        0    /* Example: Map Ramdisk to physical drive 0 */
#define DEV_MMC        1    /* Example: Map MMC/SD card to physical drive 1 */
#define DEV_USB        2    /* Example: Map USB MSD to physical drive 2 */
在对应的⼏个操作函数⾥⾯也有这⼏个设备对应的操作,但是我们只⽤⼀个spi-flash所以就只定义⼀个:
#define    SPI_FLASH    0
定义扇区⼤⼩,块⼤⼩,扇区个数
#define FLASH_SECTOR_SIZE  (4*1024)
#define FLASH_BLOCK_SIZE 64
u16 FLASH_SECTOR_COUNT = 4*1024*1024/(4*1024);
获取磁盘状态直接返回成功:
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case SPI_FLASH :return RES_OK;
}
return STA_NOINIT;
}
初始化磁盘的函数,主要是把spi-flash初始化:
DSTATUS disk_initialize (
BYTE pdrv    /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat;
int result;
char t = 0;
switch (pdrv) {
case SPI_FLASH :
//init spi-bus
SPI_Flash_Init();
if(SPI_FLASH_TYPE != FLASH_ADDRESS)
stat = RES_NOTRDY;
else
stat = RES_OK;
return stat;
}
return STA_NOINIT;
}
读取⽂件系统驱动接⼝:读取单位以sector(扇区)为单位
DRESULT disk_read (
BYTE pdrv,  /* Physical drive nmuber to identify the drive */
BYTE *buff,  /* Data buffer to store read data */
DWORD sector, /* Start sector in LBA */
UINT count  /* Number of sectors to read */
)
{
int result;
switch (pdrv) {
case SPI_FLASH :
for(;count>0;count--)
{
SPI_Flash_Read(buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);  sector++;
buff+=FLASH_SECTOR_SIZE;
}
return RES_OK;
}
return RES_PARERR;
}
写⽂件系统驱动接⼝:写⼊也是以sector为单位
const BYTE *buff, /* Data to be written */
DWORD sector,  /* Start sector in LBA */
UINT count  /* Number of sectors to write */
)
{
int result;
switch (pdrv) {
case SPI_FLASH :
for(;count>0;count--)
{
SPI_Flash_Write((u8*)buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);  sector++;
buff+=FLASH_SECTOR_SIZE;
}
return RES_OK;
}
return RES_PARERR;
}
⽂件系统⼀些控制命令:主要是获取⼀些磁盘的参数
DRESULT disk_ioctl (
BYTE pdrv,  /* Physical drive nmuber (0..) */
BYTE cmd,  /* Control code */
void *buff  /* Buffer to send/receive control data */
)
{
DRESULT res = RES_OK;
int result;
switch (pdrv) {
case SPI_FLASH :
switch(cmd)
{
system的头文件case CTRL_SYNC:
res = RES_OK;
break;
case GET_SECTOR_SIZE:
*(WORD*)buff = FLASH_SECTOR_SIZE;
res = RES_OK;
break;
case GET_BLOCK_SIZE:
*(WORD*)buff = FLASH_BLOCK_SIZE;
res = RES_OK;
break;
case GET_SECTOR_COUNT:
*(DWORD*)buff = FLASH_SECTOR_COUNT;
res = RES_OK;
break;
default:
res = RES_PARERR;
break;
}
}
return res;
}
⽂件系统时间的接⼝:
DWORD get_fattime (void)
{
return ((rtc.w_year - 1980)<<25)|\
(rtc.w_month<<21)|\
(rtc.w_date<<16)|\
(rtc.hour<<11)|\
(rtc.min<<5)|\
rtc.sec;
}
到这⾥驱动基本上就移植完了,下⾯要做的就是初始化⽂件系统:在ffconf.h⽂件中可以配置⽂件系统的参数和功能,因为⼀开始我们的flash是没有⽂件系统的,需要⾃⼰格式化⼀下,所以需要有创建⽂件系统的功能:
#define FF_USE_MKFS        1//默认是0
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
创建⽂件系统:
⾸先尝试挂载⽂件系统
挂载成功则返回成功,挂载失败则创建⽂件系统
创建失败则返回失败,创建成功再⼀次尝试挂载
static FATFS sysFs;
static BYTE gFsWork[FF_MAX_SS]; /* Work area (larger is better for processing time) */
static BYTE gFsInited = 0;
static int fileSystemInit()
{
FRESULT res = 0;
res = f_mount (&sysFs,"0:",1);
if(res != 0)
{
res = f_mkfs("0:", FM_FAT,0, gFsWork, sizeof gFsWork);
if(res == 0)
{
res = f_mount (&sysFs,"0:",1);
if(res == 0)
{
gFsInited = 1;
return 0;
}
else
return -1;
}
else
return -1;
}
else
gFsInited = 1;
return 0;
}
⽂件系统测试:
static int fileSystemTest()
{
FIL fil;
UINT bw;
FRESULT res = 0;
if(gFsInited)
{
static char i = 0;
char b[5] = {0};
res = f_open(&fil, "0:/", FA_OPEN_APPEND | FA_WRITE);
if (res == 0)
{
/
* Write a message */
sprintf(b,"%d",i++%10);
res = f_write(&fil, b, 1, &bw);
f_close(&fil);
}
res = f_open(&fil, "0:/", FA_READ);
if (res == 0)
{
/* read a message */
char buffer[256];
memset(buffer,0,sizeof(256));
res = f_read(&fil,buffer,255,&bw);
printf("read:%d|%d =>>%s\r\n",res,bw,buffer);
f_close(&fil);
}
}
return 0;
}
测试输出:
read:0|1 =>>0
read:0|2 =>>01
read:0|3 =>>012
read:0|4 =>>0123
read:0|5 =>>01234
read:0|6 =>>012345
read:0|7 =>>0123456
read:0|8 =>>01234567
read:0|9 =>>012345678
usb功能的移植
这部分驱动⽤原⼦哥的实验”实验50 USB读卡器实验“中的⽂件:
拷贝例程中的驱动:USB⽂件下到项⽬中,然后把刚才项⽬中初始化和测试⽂件系统的代码注释掉。第⼀步:案例中定义了两个存储介质(SD卡和SPI-Flash),但是我们只需要SPI-Flash,所以将
#define MAX_LUN  0//原来为1
然后把磁盘操作改为只是对磁盘0有效: