STM32 修改FatFs支持文件同时单写多读

您所在的位置:网站首页 多个进程打开同一个文件怎么操作 STM32 修改FatFs支持文件同时单写多读

STM32 修改FatFs支持文件同时单写多读

2024-07-14 04:16| 来源: 网络整理| 查看: 265

最近使用SD卡,需要上传文件到手机,这个功能需要支持同一个文件同时打开一个写入和一个读取句柄,写入的同时能够读取文件内容上传,写入都是写入文件末尾,文件是一个以小时为单位建的,要想上传当前小时内的文件,就必须支持单写多读功能

STM32芯片使用的是STM32 F412系列,使用STM32CubeMX配置的Keil5工程,找了一下配置发现有个可重入的设置

但是默认为Disabled,且只有Disabled可选,看了一下ffconf.h的代码,想直接在代码里修改为enable

重试修改后编译报错,主要因为_SYNC_t配置为空了

接着配置了FreeRTOS,FS_REENTRANT被自动修改为enable了,一阵小兴奋,立刻创建了一个测试文件,写了测试代码,对test.txt文件同时打开一个写入句柄和一个读取句柄,都是返回一个打开成功,另一个就打开返回失败。

不知道是我理解错了还是需要额外的其他配置

直接配置不行,那就直接修改FatFs的源码

FatFs本身是默认支持同一个文件打开多个读取句柄的,但是打开一个写入后其他都会返回失败,或者打开读取后不关闭再打开写入也会返回失败,错误码为:FR_LOCKED,                /* (16) The operation is rejected according to the file sharing policy */

依照这个错误,查找对应的代码,修改为支持单写入多读取,需要修改两个函数

static FRESULT chk_lock ( /* Check if the file can be accessed */ DIR* dp, /* Directory object pointing the file to be checked */ int acc /* Desired access type (0:Read, 1:Write, 2:Delete/Rename) */ ) { UINT i, be; /* Search file semaphore table */ for (i = be = 0; i < _FS_LOCK; i++) { if (Files[i].fs) { /* Existing entry */ if (Files[i].fs == dp->obj.fs && /* Check if the object matched with an open object */ Files[i].clu == dp->obj.sclust && Files[i].ofs == dp->dptr) break; } else { /* Blank entry */ be = 1; } } if (i == _FS_LOCK) { /* The object is not opened */ return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new object? */ } /* The object has been opened. Reject any open against writing file and all write mode open */ //return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; // 修改为支持多次打开,只支持一个写入,多个读取 if(acc == 0 || (Files[i].ctr & 0x100) == 0) { // 不是写入或者不是不存在写入锁,直接返回OK return FR_OK; } if((Files[i].ctr & 0x100) && acc != 0) { // 已经存在写入锁,禁止新写入锁 return FR_LOCKED; } return FR_LOCKED; } static UINT inc_lock ( /* Increment object open counter and returns its index (0:Internal error) */ DIR* dp, /* Directory object pointing the file to register or increment */ int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ ) { UINT i; for (i = 0; i < _FS_LOCK; i++) { /* Find the object */ if (Files[i].fs == dp->obj.fs && Files[i].clu == dp->obj.sclust && Files[i].ofs == dp->dptr) break; } if (i == _FS_LOCK) { /* Not opened. Register it as new. */ for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; if (i == _FS_LOCK) return 0; /* No free entry to register (int err) */ Files[i].fs = dp->obj.fs; Files[i].clu = dp->obj.sclust; Files[i].ofs = dp->dptr; Files[i].ctr = 0; } //if (acc && Files[i].ctr) return 0; /* Access violation (int err) */ //Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ Files[i].ctr = acc ? (Files[i].ctr | 0x100) : Files[i].ctr + 1; /* Set semaphore value *//*标志修改为支持一写多读标志*/ return i + 1; }

修改后就可以支持单写多读了

测试一个文件打开一个写入,两个读取的代码如下:

int8_t TestFileWriteRead(void) { char szTestFileName[] = "test.txt"; FIL fTestR; retSD = f_open(&fTestR, szTestFileName, FA_READ); if(FR_OK != retSD) { printf("read test:open file(%s) error : %d\r\n", szTestFileName, retSD); return -1; } FIL fTestW; retSD = f_open(&fTestW, szTestFileName, FA_WRITE | FA_OPEN_APPEND); if(FR_OK != retSD) { printf("write test:open file(%s) error : %d\r\n", szTestFileName, retSD); return -1; } FIL fTestR2; retSD = f_open(&fTestR2, szTestFileName, FA_READ); if(FR_OK != retSD) { printf("read2 test:open file(%s) error : %d\r\n", szTestFileName, retSD); return -1; } FIL fTestW2; retSD = f_open(&fTestW2, szTestFileName, FA_WRITE | FA_OPEN_APPEND); if(FR_OK != retSD) {// 这个会返回失败,因为已经打开一个写入 printf("write2 test:open file(%s) error : %d\r\n", szTestFileName, retSD); //return -1; } { char bufRead[512]; f_lseek(&fTestR, 100); UINT br = 0; retSD = f_read(&fTestR, bufRead, 500, &br); bufRead[br] = 0; printf("retSD:%d, read Data:%s\r\n", retSD, bufRead); } { char bufWrite[50] = "abcdefghijklmnopqrstuvwxyz"; UINT bw = 0; retSD = f_write(&fTestW, bufWrite, 26, &bw); printf("retSD:%d, write Data(%d):%s\r\n", retSD, bw, bufWrite); } { char bufRead[512]; f_lseek(&fTestR2, 10002); UINT br = 0; retSD = f_read(&fTestR2, bufRead, 500, &br); bufRead[br] = 0; printf("retSD:%d, read Data:%s\r\n", retSD, bufRead); } retSD = f_close(&fTestR); retSD = f_close(&fTestR2); retSD = f_close(&fTestW); return 0; }

由于直接修改FatFs源码,会担心使用STM32CubeMX再次生成工程时覆盖了修改的代码,我的做法是直接复制了一个ff.c文件到工程目录中,然后新建一个分组,将ff.c文件加入这个分组,然后将Middlewares/FatFs分组的ff.c文件右键移除就可以了,虽然每次使用STM32CubeMX重新生成工程都要删除一次,但至少不用担心自己修改的代码被覆盖

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3