NinjaFlight
|
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <platform.h>
#include "asyncfatfs.h"
#include "fat_standard.h"
#include "drivers/sdcard.h"
Data Structures | |
union | afatfsFATSector_t |
struct | afatfsCacheBlockDescriptor_t |
struct | afatfsFreeSpaceSearch_t |
struct | afatfsFreeSpaceFAT_t |
struct | afatfsCreateFile_t |
struct | afatfsSeek_t |
struct | afatfsAppendSupercluster_t |
struct | afatfsAppendFreeCluster_t |
struct | afatfsExtendSubdirectory_t |
struct | afatfsTruncateFile_t |
struct | afatfsDeleteFile_t |
struct | afatfsCloseFile_t |
struct | afatfsFileOperation_t |
struct | afatfsFile_t |
struct | afatfs_t |
Typedefs | |
typedef union afatfsFATSector_t | afatfsFATSector_t |
typedef struct afatfsCacheBlockDescriptor_t | afatfsCacheBlockDescriptor_t |
typedef struct afatfsFreeSpaceSearch_t | afatfsFreeSpaceSearch_t |
typedef struct afatfsFreeSpaceFAT_t | afatfsFreeSpaceFAT_t |
typedef struct afatfsCreateFile_t | afatfsCreateFile_t |
typedef struct afatfsSeek_t | afatfsSeek_t |
typedef struct afatfsAppendSupercluster_t | afatfsAppendSupercluster_t |
typedef struct afatfsAppendFreeCluster_t | afatfsAppendFreeCluster_t |
typedef struct afatfsExtendSubdirectory_t | afatfsExtendSubdirectory_t |
typedef struct afatfsTruncateFile_t | afatfsTruncateFile_t |
typedef struct afatfsDeleteFile_t | afatfsUnlinkFile_t |
typedef struct afatfsCloseFile_t | afatfsCloseFile_t |
typedef struct afatfsFileOperation_t | afatfsFileOperation_t |
typedef struct afatfsFile_t | afatfsFile_t |
typedef struct afatfs_t | afatfs_t |
#define AFATFS_CACHE_DISCARDABLE 8 |
#define AFATFS_CACHE_LOCK 4 |
#define AFATFS_CACHE_READ 1 |
#define AFATFS_CACHE_RETAIN 16 |
#define AFATFS_CACHE_WRITE 2 |
#define AFATFS_DEFAULT_FILE_DATE FAT_MAKE_DATE(2015, 12, 01) |
#define AFATFS_DEFAULT_FILE_TIME FAT_MAKE_TIME(00, 00, 00) |
#define AFATFS_FAT16_FAT_ENTRIES_PER_SECTOR (AFATFS_SECTOR_SIZE / sizeof(uint16_t)) |
#define AFATFS_FAT32_FAT_ENTRIES_PER_SECTOR (AFATFS_SECTOR_SIZE / sizeof(uint32_t)) |
#define AFATFS_FILE_MODE_APPEND 4 |
#define AFATFS_FILE_MODE_CONTIGUOUS 8 |
#define AFATFS_FILE_MODE_CREATE 16 |
#define AFATFS_FILE_MODE_READ 1 |
#define AFATFS_FILE_MODE_RETAIN_DIRECTORY 32 |
#define AFATFS_FILE_MODE_WRITE 2 |
#define AFATFS_FILES_PER_DIRECTORY_SECTOR (AFATFS_SECTOR_SIZE / sizeof(fatDirectoryEntry_t)) |
#define AFATFS_FREEFILE_LEAVE_CLUSTERS 100 |
#define AFATFS_FREESPACE_FILENAME "FREESPAC.E" |
#define AFATFS_INTROSPEC_LOG_FILENAME "ASYNCFAT.LOG" |
#define AFATFS_MAX_OPEN_FILES 3 |
#define AFATFS_MIN_MULTIPLE_BLOCK_WRITE_COUNT 4 |
#define AFATFS_NUM_CACHE_SECTORS 8 |
#define AFATFS_NUM_FATS 2 |
#define AFATFS_SECTOR_SIZE 512 |
#define AFATFS_USE_FREEFILE |
#define MAX | ( | a, | |
b | |||
) | ((a) > (b) ? (a) : (b)) |
#define MIN | ( | a, | |
b | |||
) | ((a) < (b) ? (a) : (b)) |
#define ONLY_EXPOSE_FOR_TESTING static |
This is a FAT16/FAT32 filesystem for SD cards which uses asynchronous operations: The caller need never wait for the SD card to be ready.
On top of the regular FAT32 concepts, we add the idea of a "super cluster". Given one FAT sector, a super cluster is the series of clusters which corresponds to all of the cluster entries in that FAT sector. If files are allocated on super-cluster boundaries, they will have FAT sectors which are dedicated to them and independent of all other files.
We can pre-allocate a "freefile" which is a file on disk made up of contiguous superclusters. Then when we want to allocate a file on disk, we can carve it out of the freefile, and know that the clusters will be contiguous without needing to read the FAT at all (the freefile's FAT is completely determined from its start cluster and file size, which we get from the directory entry). This allows for extremely fast append-only logging.
typedef struct afatfsAppendFreeCluster_t afatfsAppendFreeCluster_t |
typedef struct afatfsAppendSupercluster_t afatfsAppendSupercluster_t |
typedef struct afatfsCacheBlockDescriptor_t afatfsCacheBlockDescriptor_t |
typedef struct afatfsCloseFile_t afatfsCloseFile_t |
typedef struct afatfsCreateFile_t afatfsCreateFile_t |
typedef struct afatfsExtendSubdirectory_t afatfsExtendSubdirectory_t |
typedef union afatfsFATSector_t afatfsFATSector_t |
typedef struct afatfsFile_t afatfsFile_t |
typedef struct afatfsFileOperation_t afatfsFileOperation_t |
typedef struct afatfsFreeSpaceFAT_t afatfsFreeSpaceFAT_t |
typedef struct afatfsFreeSpaceSearch_t afatfsFreeSpaceSearch_t |
typedef struct afatfsSeek_t afatfsSeek_t |
typedef struct afatfsTruncateFile_t afatfsTruncateFile_t |
typedef struct afatfsDeleteFile_t afatfsUnlinkFile_t |
anonymous enum |
enum afatfsFATPattern_e |
enum afatfsFileType_e |
bool afatfs_chdir | ( | afatfsFilePtr_t | directory | ) |
Change the working directory to the directory with the given handle (use fopen). Pass NULL for directory
in order to change to the root directory.
Returns true on success, false if you should call again later to retry. After changing into a directory, your handle to that directory may be closed by fclose().
ONLY_EXPOSE_FOR_TESTING uint32_t afatfs_clusterSize | ( | void | ) |
Size of a FAT cluster in bytes
bool afatfs_destroy | ( | bool | dirty | ) |
Shut down the filesystem, flushing all data to the disk. Keep calling until it returns true.
dirty - Set to true to skip the flush operation and terminate immediately (buffered data will be lost!)
bool afatfs_fclose | ( | afatfsFilePtr_t | file, |
afatfsCallback_t | callback | ||
) |
Returns true if an operation was successfully queued to close the file and destroy the file handle. If the file is currently busy, false is returned and you should retry later.
If provided, the callback will be called after the operation completes (pass NULL for no callback).
If this function returns true, you should not make any further calls to the file (as the handle might be reused for a new file).
bool afatfs_feof | ( | afatfsFilePtr_t | file | ) |
Returns true if the file's pointer position currently lies at the end-of-file point (i.e. one byte beyond the last byte in the file).
void afatfs_findFirst | ( | afatfsFilePtr_t | directory, |
afatfsFinder_t * | finder | ||
) |
Initialise the finder so that the first call with the directory to findNext() will return the first file in the directory.
void afatfs_findLast | ( | afatfsFilePtr_t | directory | ) |
Release resources associated with a find operation. Calling this more than once is harmless.
afatfsOperationStatus_e afatfs_findNext | ( | afatfsFilePtr_t | directory, |
afatfsFinder_t * | finder, | ||
fatDirectoryEntry_t ** | dirEntry | ||
) |
Attempt to advance the directory pointer finder
to the next entry in the directory.
Returns: AFATFS_OPERATION_SUCCESS - A pointer to the next directory entry has been loaded into *dirEntry. If the directory was exhausted then *dirEntry will be set to NULL. AFATFS_OPERATION_IN_PROGRESS - The disk is busy. The pointer is not advanced, call again later to retry.
bool afatfs_flush | ( | void | ) |
Attempt to flush dirty cache pages out to the sdcard, returning true if all flushable data has been flushed.
bool afatfs_fopen | ( | const char * | filename, |
const char * | mode, | ||
afatfsFileCallback_t | complete | ||
) |
Begin the process of opening a file with the given name in the current working directory (paths in the filename are not supported) using the given mode.
To open the current working directory, pass "." for filename.
The complete() callback is called when finished with either a file handle (file was opened) or NULL upon failure.
Supported file mode strings:
r - Read from an existing file w - Create a file for write access, if the file already exists then truncate it a - Create a file for write access to the end of the file only, if the file already exists then append to it
r+ - Read and write from an existing file w+ - Read and write from an existing file, if the file doesn't already exist it is created a+ - Read from or append to an existing file, if the file doesn't already exist it is created TODO
as - Create a new file which is stored contiguously on disk (high performance mode/freefile) for append or write ws If the file is already non-empty or freefile support is not compiled in then it will fall back to non-contiguous operation.
All other mode strings are illegal. In particular, don't add "b" to the end of the mode string.
Returns false if the the open failed really early (out of file handles).
void afatfs_fputc | ( | afatfsFilePtr_t | file, |
uint8_t | c | ||
) |
Write a single character to the file at the current cursor position. If the cache is too busy to accept the write, it is silently dropped.
uint32_t afatfs_fread | ( | afatfsFilePtr_t | file, |
uint8_t * | buffer, | ||
uint32_t | len | ||
) |
Attempt to read len
bytes from file
into the buffer
.
Returns the number of bytes actually read.
0 will be returned when: The filesystem is busy (try again later) EOF was reached (check afatfs_isEof())
Fewer bytes than requested will be read when: The read spans a AFATFS_SECTOR_SIZE boundary and the following sector was not available in the cache yet.
afatfsOperationStatus_e afatfs_fseek | ( | afatfsFilePtr_t | file, |
int32_t | offset, | ||
afatfsSeek_e | whence | ||
) |
Attempt to seek the file cursor from the given point (whence
) by the given offset, just like C's fseek().
AFATFS_SEEK_SET with offset 0 will always return AFATFS_OPERATION_SUCCESS.
Returns: AFATFS_OPERATION_SUCCESS - The seek was completed immediately AFATFS_OPERATION_IN_PROGRESS - The seek was queued and will complete later. Feel free to attempt read/write operations on the file, they'll fail until the seek is complete. AFATFS_OPERATION_FAILURE - The seek could not be queued because the file was busy with another operation, try again later.
bool afatfs_ftell | ( | afatfsFilePtr_t | file, |
uint32_t * | position | ||
) |
Get the byte-offset of the file's cursor from the start of the file.
Returns true on success, or false if the file is busy (try again later).
bool afatfs_ftruncate | ( | afatfsFilePtr_t | file, |
afatfsFileCallback_t | callback | ||
) |
Queue an operation to truncate the file to zero bytes in length.
Returns true if the operation was successfully queued or false if the file is busy (try again later).
The callback is called once the file has been truncated (some time after this routine returns).
bool afatfs_funlink | ( | afatfsFilePtr_t | file, |
afatfsCallback_t | callback | ||
) |
Delete and close the file.
Returns true if the operation was successfully queued (callback will be called some time after this routine returns) or false if the file is busy and you should try again later.
uint32_t afatfs_fwrite | ( | afatfsFilePtr_t | file, |
const uint8_t * | buffer, | ||
uint32_t | len | ||
) |
Attempt to write len
bytes from buffer
into the file
.
Returns the number of bytes actually written.
0 will be returned when: The filesystem is busy (try again later)
Fewer bytes will be written than requested when: The write spanned a sector boundary and the next sector's contents/location was not yet available in the cache. Or you tried to extend the length of the file but the filesystem is full (check afatfs_isFull()).
uint32_t afatfs_getContiguousFreeSpace | ( | void | ) |
Return the available size of the freefile (used for files in contiguous append mode)
afatfsFilesystemState_e afatfs_getFilesystemState | ( | void | ) |
uint32_t afatfs_getFreeBufferSpace | ( | void | ) |
Get a pessimistic estimate of the amount of buffer space that we have available to write to immediately.
afatfsError_e afatfs_getLastError | ( | void | ) |
void afatfs_init | ( | void | ) |
bool afatfs_isFull | ( | void | ) |
Returns true if either the freefile or the regular cluster pool has been exhausted during a previous write operation.
bool afatfs_mkdir | ( | const char * | filename, |
afatfsFileCallback_t | callback | ||
) |
Create a new directory with the given name, or open the directory if it already exists.
The directory will be passed to the callback, or NULL if the creation failed.
Returns true if the directory creation was begun, or false if there are too many open files.
void afatfs_poll | ( | void | ) |
Check to see if there are any pending operations on the filesystem and perform a little work (without waiting on the sdcard). You must call this periodically.
ONLY_EXPOSE_FOR_TESTING uint32_t afatfs_superClusterSize | ( | void | ) |
Size of a AFATFS supercluster in bytes