Skip to content

Commit

Permalink
add AFATFS_ASYNC_IO flag and document it
Browse files Browse the repository at this point in the history
  • Loading branch information
Risca committed Jun 23, 2021
1 parent 9a0363c commit b7b4871
Show file tree
Hide file tree
Showing 15 changed files with 76 additions and 21 deletions.
14 changes: 14 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,17 @@ Cleanflight / Betaflight's "blackbox" logging system: [filesystem consumer code]
You'll notice that since most filesystem operations will fail and ask you to retry when the card is busy, it becomes
natural to call it using a state-machine from your app's main loop - where you only advance to the next state once the
current operation succeeds, calling afatfs_poll() in-between so that the filesystem can complete its queued tasks.
### Asynchronous I/O
There is experimental support for removing the need to call `afatfs_poll()` and to remove the `sdcard_poll()`
primitive. This feature can be activated by compiling AsyncFatFS with the "AFATFS_ASYNC_IO" flag. When this flag is
set, `afatfs_poll()` will be called internally from the callback function provided to `sdcard_readBlock()` and
`sdcard_writeBlock()`. AsyncFatFS will no longer call `sdcard_poll()` if this is enabled.
It is **strongly recommended** that `sdcard_readBlock()` and `sdcard_writeBlock()` implement some kind of scheduling
and never call the provided callback directly. Since the callback functions themselves will call `afatfs_poll()`
internally (in this mode), another call to any of the SD card primitives could be triggered. This will lead to
AsyncFatFS performing an unbounded amount of work (particularly at card init when writing the freefile) and using an
unbounded amount of stack size. If you have an infinite stack, then please go ahead. If not, then make sure that you
use the callbacks further up the stack, e.g. from your main loop.
22 changes: 20 additions & 2 deletions lib/asyncfatfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,9 @@ static void afatfs_fileOperationContinue(afatfsFile_t *file);
static uint8_t* afatfs_fileLockCursorSectorForWrite(afatfsFilePtr_t file);
static uint8_t* afatfs_fileRetainCursorSectorForRead(afatfsFilePtr_t file);
static void afatfs_fileOperationsPoll();
#ifdef AFATFS_ASYNC_IO
static void afatfs_poll();
#endif

static uint32_t roundUpTo(uint32_t value, uint32_t rounding)
{
Expand Down Expand Up @@ -641,7 +643,9 @@ static void afatfs_sdcardReadComplete(sdcardBlockOperation_e operation, uint32_t
break;
}
}
#ifdef AFATFS_ASYNC_IO
afatfs_poll();
#endif
}

/**
Expand Down Expand Up @@ -673,7 +677,9 @@ static void afatfs_sdcardWriteComplete(sdcardBlockOperation_e operation, uint32_
break;
}
}
#ifdef AFATFS_ASYNC_IO
afatfs_poll();
#endif
}

/**
Expand Down Expand Up @@ -3536,14 +3542,26 @@ static void afatfs_initContinue()
}
}

static bool afatfs_continue()
{
bool cont = true;
#ifndef AFATFS_ASYNC_IO
cont = sdcard_poll();
#endif
return cont ? afatfs_flush() : false;
}

/**
* Check to see if there are any pending operations on the filesystem and perform a little work (without waiting on the
* sdcard).
*/
static void afatfs_poll()
#ifdef AFATFS_ASYNC_IO
static
#endif
void afatfs_poll()
{
// Only attempt to continue FS operations if the card is present & ready, otherwise we would just be wasting time
if (afatfs_flush()) {
if (afatfs_continue()) {
switch (afatfs.filesystemState) {
case AFATFS_FILESYSTEM_STATE_INITIALIZATION:
afatfs_initContinue();
Expand Down
3 changes: 3 additions & 0 deletions lib/asyncfatfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ void afatfs_findLast(afatfsFilePtr_t directory);
bool afatfs_flush();
void afatfs_init();
bool afatfs_destroy(bool dirty);
#ifndef AFATFS_ASYNC_IO
void afatfs_poll();
#endif

uint32_t afatfs_getFreeBufferSpace();
uint32_t afatfs_getContiguousFreeSpace();
Expand Down
7 changes: 7 additions & 0 deletions lib/sdcard.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ bool sdcard_readBlock(uint32_t blockIndex, uint8_t *buffer, sdcard_operationComp
*/
sdcardOperationStatus_e sdcard_writeBlock(uint32_t blockIndex, uint8_t *buffer, sdcard_operationCompleteCallback_c callback, uint32_t callbackData);

/**
* Will be called by afatfs_poll() periodically for the SD card to perform in-progress transfers.
*
* Returns true if the card is ready to accept new commands.
*/
bool sdcard_poll();

/**
* Begin writing a series of consecutive blocks beginning at the given block index. This will allow (but not require)
* the SD card to pre-erase the number of blocks you specifiy, which can allow the writes to complete faster.
Expand Down
12 changes: 12 additions & 0 deletions tests/common.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "common.h"
#include "sdcard.h"

#include <stdlib.h>
#include <stdio.h>
Expand Down Expand Up @@ -65,3 +66,14 @@ void testAssert(bool condition, const char *errorMessage)
exit(-1);
}
}

void testPoll()
{
#ifdef AFATFS_ASYNC_IO
// Let's reuse the sdcard_poll() function for asynchronous I/O mode, even if it's not strictly necessary.
// It could as well be implemented as a separate worker thread.
sdcard_poll();
#else
afatfs_poll();
#endif
}
2 changes: 2 additions & 0 deletions tests/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ bool validateLogTestEntries(afatfsFilePtr_t file, uint32_t *entryIndex, uint32_t

void testAssert(bool condition, const char *errorMessage);

void testPoll();

#define TEST_LOG_ENTRY_SIZE 16
1 change: 0 additions & 1 deletion tests/sdcard_sim.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include "sdcard.h"

bool sdcard_poll();
bool sdcard_sim_init(const char *filename);
void sdcard_sim_destroy();
bool sdcard_sim_isReady();
4 changes: 2 additions & 2 deletions tests/test_file_delete.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ int main(int argc, char **argv)
bool keepGoing = true;

while (keepGoing) {
sdcard_poll();
testPoll();

switch (afatfs_getFilesystemState()) {
case AFATFS_FILESYSTEM_STATE_READY:
Expand All @@ -530,7 +530,7 @@ int main(int argc, char **argv)
}

while (!afatfs_destroy(false)) {
sdcard_poll();
testPoll();
}

sdcard_sim_destroy();
Expand Down
4 changes: 2 additions & 2 deletions tests/test_file_modes.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ int main(int argc, char **argv)
bool keepGoing = true;

while (keepGoing) {
sdcard_poll();
testPoll();

switch (afatfs_getFilesystemState()) {
case AFATFS_FILESYSTEM_STATE_READY:
Expand All @@ -235,7 +235,7 @@ int main(int argc, char **argv)
}

while (!afatfs_destroy(false)) {
sdcard_poll();
testPoll();
}

sdcard_sim_destroy();
Expand Down
6 changes: 3 additions & 3 deletions tests/test_file_size.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static void initFilesystem()
afatfs_init();

while (afatfs_getFilesystemState() != AFATFS_FILESYSTEM_STATE_READY) {
sdcard_poll();
testPoll();

if (afatfs_getFilesystemState() == AFATFS_FILESYSTEM_STATE_FATAL) {
fprintf(stderr, "[Fail] Fatal filesystem error during init\n");
Expand Down Expand Up @@ -252,7 +252,7 @@ int main(int argc, char **argv)
bool keepGoing = true;

while (keepGoing) {
sdcard_poll();
testPoll();

switch (afatfs_getFilesystemState()) {
case AFATFS_FILESYSTEM_STATE_READY:
Expand All @@ -270,7 +270,7 @@ int main(int argc, char **argv)
}

while (!afatfs_destroy(false)) {
sdcard_poll();
testPoll();
}

sdcard_sim_destroy();
Expand Down
6 changes: 3 additions & 3 deletions tests/test_file_size_powerloss.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ static void initFilesystem()
afatfs_init();

while (afatfs_getFilesystemState() != AFATFS_FILESYSTEM_STATE_READY) {
sdcard_poll();
testPoll();

if (afatfs_getFilesystemState() == AFATFS_FILESYSTEM_STATE_FATAL) {
fprintf(stderr, "[Fail] Fatal filesystem error during init\n");
Expand Down Expand Up @@ -248,7 +248,7 @@ int main(int argc, char **argv)
bool keepGoing = true;

while (keepGoing) {
sdcard_poll();
testPoll();

switch (afatfs_getFilesystemState()) {
case AFATFS_FILESYSTEM_STATE_READY:
Expand All @@ -266,7 +266,7 @@ int main(int argc, char **argv)
}

while (!afatfs_destroy(false)) {
sdcard_poll();
testPoll();
}

sdcard_sim_destroy();
Expand Down
4 changes: 2 additions & 2 deletions tests/test_logging_workload.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ int main(int argc, char **argv)
bool keepGoing = true;

while (keepGoing) {
sdcard_poll();
testPoll();

switch (afatfs_getFilesystemState()) {
case AFATFS_FILESYSTEM_STATE_READY:
Expand All @@ -225,7 +225,7 @@ int main(int argc, char **argv)
}

while (!afatfs_destroy(false)) {
sdcard_poll();
testPoll();
}

sdcard_sim_destroy();
Expand Down
4 changes: 2 additions & 2 deletions tests/test_root_fill.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ int main(int argc, char **argv)
bool keepGoing = true;

while (keepGoing) {
sdcard_poll();
testPoll();

switch (afatfs_getFilesystemState()) {
case AFATFS_FILESYSTEM_STATE_READY:
Expand All @@ -152,7 +152,7 @@ int main(int argc, char **argv)
}

while (!afatfs_destroy(false)) {
sdcard_poll();
testPoll();
}

sdcard_sim_destroy();
Expand Down
4 changes: 2 additions & 2 deletions tests/test_subdir_fill.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ int main(int argc, char **argv)
bool keepGoing = true;

while (keepGoing) {
sdcard_poll();
testPoll();

switch (afatfs_getFilesystemState()) {
case AFATFS_FILESYSTEM_STATE_READY:
Expand All @@ -171,7 +171,7 @@ int main(int argc, char **argv)
}

while (!afatfs_destroy(false)) {
sdcard_poll();
testPoll();
}

sdcard_sim_destroy();
Expand Down
4 changes: 2 additions & 2 deletions tests/test_volume_fill.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ int main(int argc, char **argv)
bool keepGoing = true;

while (keepGoing) {
sdcard_poll();
testPoll();

switch (afatfs_getFilesystemState()) {
case AFATFS_FILESYSTEM_STATE_READY:
Expand All @@ -236,7 +236,7 @@ int main(int argc, char **argv)
}

while (!afatfs_destroy(false)) {
sdcard_poll();
testPoll();
}

sdcard_sim_destroy();
Expand Down

0 comments on commit b7b4871

Please sign in to comment.