SD卡-fatfs文件系统移植
此篇文章在2022年12月31日被记录
FATFS文件系统移植
上文中完成了sd卡的驱动代码,本文陈述如何系统移植文件系统
源码下载
源码可以登录fatfs官网下载:http://elm-chan.org/fsw/ff/archives.html 我这里下载最新版本的源码包,下载完成后解压到本地大致浏览源码包的文件结构,主目录下有documents与source两个文件夹,其中documents中教会用户如何使用fatfs,source中主要包含三部分代码:
- 物理层接口:diskio.c/diskio.h
- fatfs源码:ff.c/ff.h
- fatfs配置文件:ffconf.h
- 操作系统扩展功能:ffsystem.c
- 语言编码表:ffunicode.c
我移植时的需求:不使用操作系统,编码语言使用英文,所以我只用到diskio.c/diskio.h、ff.c/ff.h、ffconf.h这五个文件,并将其添加到自己的工程中
接口绑定
上文中我们完成了sd卡的驱动代码,预留了如下几个接口:
uint8_t SD_WaitReady(void);
uint8_t SD_Init(void);
uint32_t SD_GetSectorCount(void);
uint8_t SD_ReadDisk(uint8_t*buf,uint32_t sector,uint8_t cnt);
uint8_t SD_WriteDisk(const uint8_t*buf,uint32_t sector,uint8_t cnt);
我们将其与diskio.c中的接口文件绑定:
首先需要新建一个我们自己的设备并删除掉代码中的示例设备:
#define DEV_SD 0
在获取磁盘状态的代码中新增我们的设备代码(这里我让我的设备状态无论如何返回OK):
DSTATUS disk_status (
BYTE pdrv
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case DEV_SD :
stat = RES_OK;
return stat;
}
return STA_NOINIT;
}
在磁盘初始化代码中绑定我们的SD卡初始化代码:
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case DEV_SD :
result = SD_Init();
if(0 == result)
{
stat = RES_OK;
}
return stat;
}
return STA_NOINIT;
}
在设备读扇区接口中绑定我们的读sd卡设备代码:
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_SD :
result = SD_ReadDisk(buff, sector, count);
if(0 == result)
{
res = RES_OK;
}
return res;
}
return RES_PARERR;
}
在设备写数据接口中绑定我们的写sd卡数据代码:
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_SD :
result = SD_WriteDisk(buff, sector, count);
if(0 == result)
{
res = RES_OK;
}
return res;
}
return RES_PARERR;
}
在设备状态获取接口中返回我们的设备状态代码:
这里总共获取设备的四种状态:
- 设备是否就绪
- 设备的扇区数量,取决于内存卡多大
- 设备的块大小-恒定512
- 设备的扇区大小-恒定512
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_SD :
switch (cmd) {
case CTRL_SYNC:
if(0 == SD_WaitReady())
{
return RES_OK;
}
else
{
printf("not ready\r\n");
return RES_NOTRDY;
}
case GET_SECTOR_COUNT: *(DWORD * )buff = SD_GetSectorCount();return RES_OK;
case GET_SECTOR_SIZE: *(DWORD * )buff = 512 ;return RES_OK;
case GET_BLOCK_SIZE: *(WORD * )buff = 512 ;return RES_OK;
}
return res;
}
return RES_PARERR;
}
fatfs配置
FF_FS_READONLY -是否开启只读功能
FF_FS_MINIMIZE -是否裁剪功能
FF_USE_FIND -是否开启文件寻找功能
FF_USE_MKFS -是否开启格式化功能(重要)
FF_FS_NORTC -关闭RTC功能(如果使用rtc则需要实现获取时间的接口)
FF_CODE_PAGE -使用哪种编码语言
详细的配置说明可以查看官网文档
文件系统demo测试
以上完成fatfs的移植,我们就可以在单片机上对SD卡实现PC端一样的文件操作,详细的接口使用还是去看官方文档,我实现了一个demo,挂载sd卡,如果未成功挂载SD卡就将其格式化,然后读取sd卡中的test.jpg,并拷贝一份重命名为copy.jpg:
uint8_t stat;
stat=f_mount(&fs,"0:",1);//SD卡挂载
printf("f_mount:%d\r\n",stat);
if(stat!=FR_OK)
{
printf("f_mkfs :FAT32\r\n");
stat = f_mkfs("0:", 0,(void*)f_mkfs_buff,sizeof(f_mkfs_buff));
if(stat!=FR_OK)
{
printf("f_mkfs failed\r\n");
}
else
{
printf("f_mkfs successed\r\n");
}
}
else
{
printf("SD Card init successed\r\n");
}
FIL fp;
FRESULT res;
UINT bw;
UINT br;
res=f_open(&fp,"0:/test.jpg",FA_READ);
printf("read test.jpg:%d\r\n",res);
uint32_t size = fp.obj.objsize;
printf("test.jpg size is :%d\r\n",size);
char *data = (char *)malloc(size);
res=f_read(&fp,data,size,&br);
f_close(&fp);
res=f_open(&fp,"0:/copy.jpg",FA_READ|FA_WRITE|FA_CREATE_ALWAYS);
if(res==FR_OK)
{
printf("creat copy.jpg\r\n");
res=f_write(&fp,data,size,&bw);
if(res==FR_OK)
{
printf("write copy.jpg\r\n");
}
}
else
{
printf("error :%d\r\n",res);
}
f_close(&fp);
free(data);
printf("over \r\n");
最终再将内存卡插在电脑上可以发现存在被拷贝的图片(为什么是大写名称我也不知道,可能遗漏了某些东西):
其他可能存在的坑:为了保证格式化为FAT32格式,可是又懒滴写配置文件,在f_mkfs源码中修改默认的格式化类型为FAT32格式,这样可以实现windows系统更快的识别内存卡:
static const MKFS_PARM defopt = {FM_FAT32, 0, 0, 0, 0};
本文作者:shumei52
本文链接:https://www.cnblogs.com/shumei52/p/18599795
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步