Skip to content

Commit b38dc20

Browse files
Lucjan BryndzaLucjan Bryndza
andauthored
[EGD-4135] FREERTOS vfat ff_fflush implementation (#878)
ff_fflush implementation is needed for sqlite3 when unexcepted power failure. Co-authored-by: Lucjan Bryndza <[email protected]>
1 parent 1a661f2 commit b38dc20

File tree

4 files changed

+165
-0
lines changed

4 files changed

+165
-0
lines changed

module-vfs/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,14 @@ set(PROJECT_INCLUDES
3434
${CMAKE_CURRENT_SOURCE_DIR}/board/free_rtos_custom/include
3535
)
3636

37+
set(FREERTOS_FAT_EXTSOURCES
38+
${CMAKE_CURRENT_SOURCE_DIR}/freertos-fat-custom/ff_stdio_flush.c
39+
${CMAKE_CURRENT_SOURCE_DIR}/freertos-fat-custom/ff_file_flush.c
40+
)
41+
3742
set(SOURCES ""
3843
${FREERTOS_FAT_SOURCES}
44+
${FREERTOS_FAT_EXTSOURCES}
3945
vfs-utils.cpp
4046
vfs.cpp
4147
)
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
2+
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
3+
4+
#include "ff_headers.h"
5+
#include "ff_file_flush.h"
6+
7+
#if (ffconfigUNICODE_UTF16_SUPPORT != 0)
8+
#include <wchar.h>
9+
#endif
10+
11+
FF_Error_t FF_Flush(FF_FILE *pxFile)
12+
{
13+
14+
FF_FILE *pxFileChain;
15+
FF_DirEnt_t xOriginalEntry;
16+
FF_Error_t xError;
17+
18+
/* Opening a do {} while( 0 )
19+
* loop to allow the use of the break statement. */
20+
do {
21+
if (pxFile == NULL) {
22+
xError = (FF_Error_t)(FF_ERR_NULL_POINTER | FF_CLOSE);
23+
break;
24+
}
25+
/* It is important to check that user doesn't supply invalid
26+
handle or a handle invalid because of "media removed" */
27+
xError = FF_CheckValid(pxFile);
28+
#if (ffconfigREMOVABLE_MEDIA != 0)
29+
if (FF_GETERROR(xError) == FF_ERR_FILE_MEDIA_REMOVED) {
30+
FF_PendSemaphore(pxFile->pxIOManager->pvSemaphore);
31+
pxFileChain = (FF_FILE *)pxFile->pxIOManager->FirstFile;
32+
if (pxFileChain == pxFile) {
33+
pxFile->pxIOManager->FirstFile = pxFile->pxNext;
34+
}
35+
else {
36+
while (pxFileChain) {
37+
if (pxFileChain->pxNext == pxFile) {
38+
pxFileChain->pxNext = pxFile->pxNext;
39+
break;
40+
}
41+
pxFileChain = pxFileChain->pxNext; /* Forgot this one */
42+
}
43+
}
44+
FF_ReleaseSemaphore(pxFile->pxIOManager->pvSemaphore);
45+
#if (ffconfigOPTIMISE_UNALIGNED_ACCESS != 0)
46+
ffconfigFREE(pxFile->pucBuffer);
47+
#endif /* ffconfigOPTIMISE_UNALIGNED_ACCESS */
48+
ffconfigFREE(pxFile); /* So at least we have freed the pointer. */
49+
xError = FF_ERR_NONE;
50+
break;
51+
}
52+
#endif /* ffconfigREMOVABLE_MEDIA */
53+
54+
if (FF_isERR(xError)) {
55+
/* FF_ERR_FILE_BAD_HANDLE or FF_ERR_NULL_POINTER */
56+
break;
57+
}
58+
59+
/* So here we have a normal valid file handle. */
60+
if (((pxFile->ulValidFlags & FF_VALID_FLAG_DELETED) == 0) &&
61+
((pxFile->ucMode & (FF_MODE_WRITE | FF_MODE_APPEND | FF_MODE_CREATE)) != 0)) {
62+
/* Get the directory entry and update it to show the new file size */
63+
if (FF_isERR(xError) == pdFALSE) {
64+
xError = FF_GetEntry(pxFile->pxIOManager, pxFile->usDirEntry, pxFile->ulDirCluster, &xOriginalEntry);
65+
66+
/* Now update the directory entry */
67+
if ((FF_isERR(xError) == pdFALSE) &&
68+
((pxFile->ulFileSize != xOriginalEntry.ulFileSize) || (pxFile->ulFileSize == 0UL))) {
69+
if (pxFile->ulFileSize == 0UL) {
70+
xOriginalEntry.ulObjectCluster = 0;
71+
}
72+
73+
xOriginalEntry.ulFileSize = pxFile->ulFileSize;
74+
xError = FF_PutEntry(
75+
pxFile->pxIOManager, pxFile->usDirEntry, pxFile->ulDirCluster, &xOriginalEntry, NULL);
76+
}
77+
}
78+
}
79+
#if (ffconfigOPTIMISE_UNALIGNED_ACCESS != 0)
80+
{
81+
if (pxFile->pucBuffer != NULL) {
82+
/* Ensure any unaligned points are pushed to the disk! */
83+
if (pxFile->ucState & FF_BUFSTATE_WRITTEN) {
84+
FF_Error_t xTempError;
85+
86+
xTempError = FF_BlockWrite(pxFile->pxIOManager, FF_FileLBA(pxFile), 1, pxFile->pucBuffer, pdFALSE);
87+
if (FF_isERR(xError) == pdFALSE) {
88+
xError = xTempError;
89+
}
90+
}
91+
pxFile->ucState = FF_BUFSTATE_INVALID;
92+
}
93+
}
94+
#endif
95+
if (FF_isERR(xError) == pdFALSE) {
96+
xError = FF_FlushCache(pxFile->pxIOManager); /* Ensure all modified blocks are flushed to disk! */
97+
}
98+
} while (pdFALSE);
99+
return xError;
100+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
2+
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
3+
4+
#pragma once
5+
#include "ff_file.h"
6+
7+
FF_Error_t FF_Flush(FF_FILE *pxFile);
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
2+
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
3+
4+
/* FreeRTOS includes. */
5+
#include "FreeRTOS.h"
6+
#include "task.h"
7+
#include "portable.h"
8+
9+
/* FreeRTOS+FAT includes. */
10+
#include "ff_headers.h"
11+
#include "ff_stdio.h"
12+
13+
#if (ffconfigTIME_SUPPORT != 0)
14+
#include <time.h>
15+
#endif
16+
17+
#include "ff_file_flush.h"
18+
19+
int prvFFErrorToErrno(FF_Error_t xError);
20+
21+
int ff_fflush(FF_FILE *pxStream)
22+
{
23+
FF_Error_t xError;
24+
int iReturn, ff_errno;
25+
26+
#if (ffconfigDEV_SUPPORT != 0)
27+
{
28+
/* Currently device support is in an experimental state. It will allow
29+
to create virtual files. The I/O data to those files will be redirected
30+
to their connected "drivers". */
31+
if (pxStream != NULL) {
32+
FF_Device_Flush(pxStream);
33+
}
34+
}
35+
#endif
36+
37+
xError = FF_Flush(pxStream);
38+
ff_errno = prvFFErrorToErrno(xError);
39+
40+
if (ff_errno == 0) {
41+
iReturn = 0;
42+
}
43+
else {
44+
/* Return -1 for error as per normal fclose() semantics. */
45+
iReturn = -1;
46+
}
47+
48+
/* Store the errno to thread local storage. */
49+
stdioSET_ERRNO(ff_errno);
50+
51+
return iReturn;
52+
}

0 commit comments

Comments
 (0)