STM32的FATFS文件系统移植的debug过程

本文分享了STM32移植FATFS文件系统时的debug过程,特别是针对FR_NO_FILESYSTEM错误的解决。内容包括移植步骤、SD卡文件结构、FATFS工作原理,以及解决因读写速度不同步导致的错误。通过添加延迟函数解决了问题。
摘要由CSDN通过智能技术生成

对于FATFS文件系统的移植,正点原子已经有比较完整的移植视频和相应源码。因此关于FATFS内部诸如diskio.c、ff.c和ffconf.h等文件的功能和修改这里就不再详述。博主在这里主要共享一下自己debug的一些过程(主要是针对FR_NO_FILESYSTEM),希望能让网友们在移植过程中少走一些弯路。

首先,对于移植FATFS,必经的几个步骤我还是再这里概述一下。
1. 移植好官方提供的.c和.h文件。(详情参照正点原子)
2. 编写diskio.c的硬件连接部分代码。
3. 配置好ffconf.h内部的控制用宏变量。
4. 编写好内存管理部分。这一块最开始我也没多大注意,但是十分必要。最简单的表述就是,你要把一个数据块写到SD卡中,你先得在内存中开辟一块空间来存放这些数据才行。

其次,博主描述一下自己遇到的第一个BUG。在f_mount挂载SD卡的时候,通过串口观察该函数的FREASULT型返回值,观察到的始终都是error 13: FR_NO_FILESYSTEM。为了弄清楚这个BUG的来源,我们最好弄清楚SD卡的文件结构以及FATFS文件系统本身的工作原理。

SD卡的文件结构:
在f_mount之前,博主先在PC机上格式化SD卡为FAT32格式。对于SD卡等存储介质,我们需要了解,它一般都有两个地址,一个是物理地址一个是逻辑地址,逻辑地址往往是物理地址基础上加一个偏移量,即逻辑地址零 = 物理地址零 + 偏移。
考虑已格式化为FAT32格式后,在物理地址零处的最初是的512个字节是MBR(Master Boot Record),即主引导记录。其中的前446个字节为引导代码,我们这里不做详解。接下来的64个字节为分区表,其中16个字节为一组总共四组,每一个组都描述了一个分区,最后两个字节为固定的末尾签名,0x55、0xAA。

物理扇区0处

物理扇区0处

我们可以看到在0x01BE处开始到0x01CD处的16个字节指示了一个分区。对于这16个字节,我们所需要知道的主要是以该16个字节距起始处偏移0x08个字节处为起始的四个字节表示的是跳转量。即从这个物理地址的0扇区到达逻辑地址的0扇区的偏移量(单位为扇区)。这里我们可以看到这个偏移量为0x0000_00E3。
于是我们到这个偏移量的扇区去看,就可以看到我们逻辑扇区0处的数据。也就是DBR(Dos Boot Record)Dos引导记录。这一块的引导记录与我们FATFS文件系统能否正常工作密切相关。

逻辑扇区0处

逻辑扇区0处

第一张图是从物理扇区打开看到的效果,第二张图是从逻辑扇区打开看到的效果。具体这一块数据的详细解释将在下面与FATFS内部的文件系统结构体FATFS struct结合在一起解释。

除此之外我们还需要知道的两大块是。对于FAT32,它从DBR开始,间隔若干扇区后会有一个根目录(Directory),在该根目录后间隔若干扇区后会有一个存储数据起始处。知道这点后,我们就可以开启下面的讨论了。

FATFS工作原理
首先我们需要熟悉结构体FATFS,FIL和DIR的具体含义。在我的理解里,FATFS结构体记录的主要是和FATFS文件系统本身相关的一些参数;FIL主要记录的是和特定文件有关的参数;DIR记录的是和目录有关的参数。
下面我们重点讨论一下FATFS的内部变量的含义。

typedef struct {
    BYTE    fs_type;        /* FAT sub-type (0:Not mounted) */
    BYTE    drv;            /* Physical drive number */
    BYTE    csize;          /* Sectors per cluster (1,2,4...128)簇的大小,一般一个簇 = 八个扇区;给文件分配簇的时候一次分配三个簇 */
    BYTE    n_fats;         /* Number of FAT copies (1 or 2) */
    BYTE    wflag;          /* win[] flag (b0:dirty) */
    BYTE    fsi_flag;       /* FSINFO flags (b7:disabled, b0:dirty) */
    WORD    id;             /* File system mount ID */
    WORD    n_rootdir;      /* Number of root directory entries (FAT12/16) */
#if _MAX_SS != _MIN_SS
    WORD    ssize;          /* Bytes per sector (512, 1024, 2048 or 4096) */
#endif
#if _FS_REENTRANT
    _SYNC_t sobj;           /* Identifier of sync object */
#endif
#if !_FS_READONLY
    DWORD   last_clust;     /* Last allocated cluster 最后写入的一个文件的最后一个簇的簇地址,这里标志的是下一个文件写进来的时候应该写在哪个位置上*/
    DWORD   free_clust;     /* Number of free clusters 这里标志的是该文件系统管理下还剩下多少个可用簇*/
#endif
#if _FS_RPATH
    DWORD   cdir;           /* Current directory start cluster (0:root) */
#endif
    DWORD   n_fatent;       /* Number of FAT entries, = number of clusters + 2 */
    DWORD   fsize;          /* Sectors per FAT 一个FAT分区共有多少个扇区*/
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值