FATFS一个小问题搞了我2天才解决.特此发帖,希望大家不要重蹈我的覆辙

问题:在做豪华版fatfs实验的时候,发现从综合实验移植过来的fatfs部分,f_mkdir不能正常工作,跟踪调试发现死在move_window函数里面,如下图红线处.


只要执行过红线,就进入hard_fault了...
经验告诉我,这肯定是内存访问有问题.
于是对比成功和失败两个版本的fs,wsect,fs->fatbase,fs->fsize 他们对应值都一样!!!
这样,哥迷茫了...
于是使出浑身解数,疯狂替换反替换,结果还是一样...
后来发现我的综合实验使用了-o1,等优化选项.于是设置为一模一样.此时终于可以f_mkdir了...
但是作为普通实验,没必要开优化啊...所以还得找原因.
没办法,最后用绝招了,从最简单的做起,把不相干的代码统统砍掉.最后在去掉malloc的时候,奇迹终于出现了...
把如下代码:
//为exfuns申请内存
//返回值:0,成功
//1,失败
u8 exfuns_init(void)
{
 fs[0]=(FATFS*)mymalloc(SRAMIN,sizeof(FATFS)); //为磁盘0工作区申请内存 
 fs[1]=(FATFS*)mymalloc(SRAMIN,sizeof(FATFS)); //为磁盘1工作区申请内存
 file=(FIL*)mymalloc(SRAMIN,sizeof(FIL));  //为file申请内存
 ftemp=(FIL*)mymalloc(SRAMIN,sizeof(FIL));  //为ftemp申请内存
 fatbuf=(u8*)mymalloc(SRAMIN,512);    //为fatbuf申请内存
 if(fs[0]&&fs[1]&&file&&ftemp&&fatbuf)return 0;  //申请有一个失败,即失败.
 else return 1; 
}
不用malloc,而直接用全局数组来实现,就可以正常工作.
然后发现FATFS本来只有562字节,但是sizeof之后,却是564字节,反复数了N遍,确认FATFS只有562字节,这多了的2个字节,肯定就是FATFS结构体数据对其的问题了,于是赶紧在FATFS结构体前面加上__paked关键字.如下:
__packed 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,2) */
 BYTE wflag;   /* win[] dirty flag (1:must be written back) */
 BYTE fsi_flag;  /* fsinfo dirty flag (1:must be written back) */
 WORD id;    /* File system mount ID */
 WORD n_rootdir;  /* Number of root directory entries (FAT12/16) */
#if _MAX_SS != 512
 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 */
 DWORD fsi_sector;  /* fsinfo sector (FAT32) */
#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 */
 DWORD fatbase;  /* FAT start sector */
 DWORD dirbase;  /* Root directory start sector (FAT32:Cluster#) */
 DWORD database;  /* Data start sector */
 DWORD winsect;  /* Current sector appearing in the win[] */
 BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */
} FATFS;

之后再用sizeof,得到FATFS大小是562字节了...
然后再次加入malloc,代码也可以正常工作了.
至此,该问题终于解决了.
究其原因,就是FATFS结构体的字节对齐问题.所以建议大家在自己建立结构体的时候,最好加上__packed关键字,免得再出现这种郁闷的情况.
浪费2天...
不过也有所收获.
建议直接修改 malloc 使之分配出来的内存字节对齐,而不是修改 FATFS 源码, 
如果强制用 pack 指令,最直接的影响就是程序的性能降低,虽然会节省 ram,但是省不了 flash
就算没有用 pack 指令,性能也可能会降低,而且如果运气不好,就会进入一些奇怪的错误中断了 
修改 malloc 可以提高程序的兼容性。在 32 位机上通常是 4 字节对齐的。
  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当然可以。以下是一个基于FatFs的SD卡数据读写程序的示例代码: ``` #include "stm32f4xx_hal.h" #include "ff.h" #include "fatfs_sd.h" FATFS fs; /* File system object */ FIL fil; /* File object */ FRESULT res; /* API result code */ UINT br, bw; /* Bytes read/written */ uint8_t SD_Path[4]; /* SD logical drive path */ void SD_Init(void) { FRESULT res; /* API result code */ FATFS SDFatFs; /* File system object for SD card logical drive */ char SDPath[4]; /* SD card logical drive path */ /*##-1- Link the SD driver ###########################*/ if (FATFS_LinkDriver(&SD_Driver, SDPath) == 0) { /*##-2- Register the file system object to the FatFs module ######*/ if (f_mount(&SDFatFs, (TCHAR const*)SD_Path, 0) != FR_OK) { /* FatFs Initialization Error */ Error_Handler(); } } } void SD_Write(char *data) { res = f_open(&fil, "file.txt", FA_OPEN_ALWAYS | FA_WRITE); if (res != FR_OK) { return; } res = f_lseek(&fil, f_size(&fil)); if (res != FR_OK) { f_close(&fil); return; } res = f_write(&fil, data, strlen(data), &bw); if (res != FR_OK) { f_close(&fil); return; } f_close(&fil); } void SD_Read(void) { res = f_open(&fil, "file.txt", FA_OPEN_ALWAYS | FA_READ); if (res != FR_OK) { return; } res = f_read(&fil, buffer, sizeof(buffer), &br); if (res != FR_OK) { f_close(&fil); return; } f_close(&fil); } ``` 在上面的代码中,我们首先需要初始化FatFs和SD卡。然后,我们可以使用SD_Write函数将数据写入SD卡中,使用SD_Read函数从SD卡中读取数据。这两个函数都使用f_open、f_write、f_read、f_lseek和f_close等FatFs API函数来操作SD卡。 在使用这些函数之前,我们需要在程序中定义全局变量FATFS fs、FIL fil和FRESULT res。FATFS fs是文件系统对象,FIL fil是文件对象,FRESULT res是API结果代码。 另外,我们需要在程序中包含ff.h头文件,并且调用FATFS_LinkDriver函数将SD卡驱动与FatFs链接起来。 需要注意的是,上述代码只是一个简单的示例,实际应用中还需要根据具体的需求进行修改和优化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值