Discard logged files when blackbox was paused for the entire flight

This commit is contained in:
Nicholas Sherlock 2015-11-19 21:44:43 +13:00 committed by borisbstyle
parent a35ccd28de
commit e572ccebad
4 changed files with 101 additions and 39 deletions

View File

@ -347,6 +347,7 @@ STATIC_ASSERT((sizeof(blackboxConditionCache) * 8) >= FLIGHT_LOG_FIELD_CONDITION
static uint32_t blackboxIteration; static uint32_t blackboxIteration;
static uint16_t blackboxPFrameIndex, blackboxIFrameIndex; static uint16_t blackboxPFrameIndex, blackboxIFrameIndex;
static uint16_t blackboxSlowFrameIterationTimer; static uint16_t blackboxSlowFrameIterationTimer;
static bool blackboxLoggedAnyFrames;
/* /*
* We store voltages in I-frames relative to this, which was the voltage when the blackbox was activated. * We store voltages in I-frames relative to this, which was the voltage when the blackbox was activated.
@ -460,6 +461,9 @@ static void blackboxSetState(BlackboxState newState)
{ {
//Perform initial setup required for the new state //Perform initial setup required for the new state
switch (newState) { switch (newState) {
case BLACKBOX_STATE_PREPARE_LOG_FILE:
blackboxLoggedAnyFrames = false;
break;
case BLACKBOX_STATE_SEND_HEADER: case BLACKBOX_STATE_SEND_HEADER:
blackboxHeaderBudget = 0; blackboxHeaderBudget = 0;
xmitState.headerIndex = 0; xmitState.headerIndex = 0;
@ -578,6 +582,8 @@ static void writeIntraframe(void)
blackboxHistory[2] = blackboxHistory[0]; blackboxHistory[2] = blackboxHistory[0];
//And advance the current state over to a blank space ready to be filled //And advance the current state over to a blank space ready to be filled
blackboxHistory[0] = ((blackboxHistory[0] - blackboxHistoryRing + 1) % 3) + blackboxHistoryRing; blackboxHistory[0] = ((blackboxHistory[0] - blackboxHistoryRing + 1) % 3) + blackboxHistoryRing;
blackboxLoggedAnyFrames = true;
} }
static void blackboxWriteMainStateArrayUsingAveragePredictor(int arrOffsetInHistory, int count) static void blackboxWriteMainStateArrayUsingAveragePredictor(int arrOffsetInHistory, int count)
@ -693,6 +699,8 @@ static void writeInterframe(void)
blackboxHistory[2] = blackboxHistory[1]; blackboxHistory[2] = blackboxHistory[1];
blackboxHistory[1] = blackboxHistory[0]; blackboxHistory[1] = blackboxHistory[0];
blackboxHistory[0] = ((blackboxHistory[0] - blackboxHistoryRing + 1) % 3) + blackboxHistoryRing; blackboxHistory[0] = ((blackboxHistory[0] - blackboxHistoryRing + 1) % 3) + blackboxHistoryRing;
blackboxLoggedAnyFrames = true;
} }
/* Write the contents of the global "slowHistory" to the log as an "S" frame. Because this data is logged so /* Write the contents of the global "slowHistory" to the log as an "S" frame. Because this data is logged so
@ -855,18 +863,20 @@ void startBlackbox(void)
*/ */
void finishBlackbox(void) void finishBlackbox(void)
{ {
if (blackboxState == BLACKBOX_STATE_RUNNING || blackboxState == BLACKBOX_STATE_PAUSED) { switch (blackboxState) {
blackboxLogEvent(FLIGHT_LOG_EVENT_LOG_END, NULL); case BLACKBOX_STATE_DISABLED:
case BLACKBOX_STATE_STOPPED:
case BLACKBOX_STATE_SHUTTING_DOWN:
// We're already stopped/shutting down
break;
blackboxSetState(BLACKBOX_STATE_SHUTTING_DOWN); case BLACKBOX_STATE_RUNNING:
} else if (blackboxState != BLACKBOX_STATE_DISABLED && blackboxState != BLACKBOX_STATE_STOPPED case BLACKBOX_STATE_PAUSED:
&& blackboxState != BLACKBOX_STATE_SHUTTING_DOWN) { blackboxLogEvent(FLIGHT_LOG_EVENT_LOG_END, NULL);
/*
* We're shutting down in the middle of transmitting headers, so we can't log a "log completed" event. // Fall through
* Just give the port back and stop immediately. default:
*/ blackboxSetState(BLACKBOX_STATE_SHUTTING_DOWN);
blackboxDeviceClose();
blackboxSetState(BLACKBOX_STATE_STOPPED);
} }
} }
@ -1426,7 +1436,7 @@ void handleBlackbox(void)
* *
* Don't wait longer than it could possibly take if something funky happens. * Don't wait longer than it could possibly take if something funky happens.
*/ */
if (blackboxDeviceEndLog() && (millis() > xmitState.u.startTime + BLACKBOX_SHUTDOWN_TIMEOUT_MILLIS || blackboxDeviceFlush())) { if (blackboxDeviceEndLog(blackboxLoggedAnyFrames) && (millis() > xmitState.u.startTime + BLACKBOX_SHUTDOWN_TIMEOUT_MILLIS || blackboxDeviceFlush())) {
blackboxDeviceClose(); blackboxDeviceClose();
blackboxSetState(BLACKBOX_STATE_STOPPED); blackboxSetState(BLACKBOX_STATE_STOPPED);
} }

View File

@ -628,6 +628,8 @@ void blackboxDeviceClose(void)
} }
} }
#ifdef USE_SDCARD
static void blackboxLogDirCreated(afatfsFilePtr_t directory) static void blackboxLogDirCreated(afatfsFilePtr_t directory)
{ {
blackboxSDCard.logDirectory = directory; blackboxSDCard.logDirectory = directory;
@ -639,16 +641,19 @@ static void blackboxLogDirCreated(afatfsFilePtr_t directory)
static void blackboxLogFileCreated(afatfsFilePtr_t file) static void blackboxLogFileCreated(afatfsFilePtr_t file)
{ {
blackboxSDCard.logFile = file; if (file) {
blackboxSDCard.largestLogFileNumber++;
blackboxSDCard.state = BLACKBOX_SDCARD_READY_TO_LOG; blackboxSDCard.logFile = file;
blackboxSDCard.state = BLACKBOX_SDCARD_READY_TO_LOG;
} else {
// FS must have been busy, retry
blackboxSDCard.state = BLACKBOX_SDCARD_READY_TO_CREATE_LOG;
}
} }
static void blackboxCreateLogFile() static void blackboxCreateLogFile()
{ {
blackboxSDCard.largestLogFileNumber++; uint32_t remainder = blackboxSDCard.largestLogFileNumber + 1;
uint32_t remainder = blackboxSDCard.largestLogFileNumber;
char filename[13]; char filename[13];
@ -740,6 +745,8 @@ static bool blackboxSDCardBeginLog()
return false; return false;
} }
#endif
/** /**
* Begin a new log (for devices which support separations between the logs of multiple flights). * Begin a new log (for devices which support separations between the logs of multiple flights).
* *
@ -761,15 +768,24 @@ bool blackboxDeviceBeginLog(void)
/** /**
* Terminate the current log (for devices which support separations between the logs of multiple flights). * Terminate the current log (for devices which support separations between the logs of multiple flights).
* *
* retainLog - Pass true if the log should be kept, or false if the log should be discarded (if supported).
*
* Keep calling until this returns true * Keep calling until this returns true
*/ */
bool blackboxDeviceEndLog(void) bool blackboxDeviceEndLog(bool retainLog)
{ {
#ifndef USE_SDCARD
(void) retainLog;
#endif
switch (masterConfig.blackbox_device) { switch (masterConfig.blackbox_device) {
#ifdef USE_SDCARD #ifdef USE_SDCARD
case BLACKBOX_DEVICE_SDCARD: case BLACKBOX_DEVICE_SDCARD:
// Keep retrying until the close operation queues // Keep retrying until the close operation queues
if (afatfs_fclose(blackboxSDCard.logFile, NULL)) { if (
(retainLog && afatfs_fclose(blackboxSDCard.logFile, NULL))
|| (!retainLog && afatfs_funlink(blackboxSDCard.logFile, NULL))
) {
// Don't bother waiting the for the close to complete, it's queued now and will complete eventually // Don't bother waiting the for the close to complete, it's queued now and will complete eventually
blackboxSDCard.logFile = NULL; blackboxSDCard.logFile = NULL;
blackboxSDCard.state = BLACKBOX_SDCARD_READY_TO_CREATE_LOG; blackboxSDCard.state = BLACKBOX_SDCARD_READY_TO_CREATE_LOG;

View File

@ -77,7 +77,7 @@ bool blackboxDeviceOpen(void);
void blackboxDeviceClose(void); void blackboxDeviceClose(void);
bool blackboxDeviceBeginLog(void); bool blackboxDeviceBeginLog(void);
bool blackboxDeviceEndLog(void); bool blackboxDeviceEndLog(bool retainLog);
bool isBlackboxDeviceFull(void); bool isBlackboxDeviceFull(void);

View File

@ -274,6 +274,7 @@ typedef enum {
AFATFS_FILE_OPERATION_UNLINK, AFATFS_FILE_OPERATION_UNLINK,
#ifdef AFATFS_USE_FREEFILE #ifdef AFATFS_USE_FREEFILE
AFATFS_FILE_OPERATION_APPEND_SUPERCLUSTER, AFATFS_FILE_OPERATION_APPEND_SUPERCLUSTER,
AFATFS_FILE_OPERATION_LOCKED,
#endif #endif
AFATFS_FILE_OPERATION_APPEND_FREE_CLUSTER, AFATFS_FILE_OPERATION_APPEND_FREE_CLUSTER,
AFATFS_FILE_OPERATION_EXTEND_SUBDIRECTORY, AFATFS_FILE_OPERATION_EXTEND_SUBDIRECTORY,
@ -416,6 +417,12 @@ static bool isPowerOfTwo(unsigned int x)
return ((x != 0) && ((x & (~x + 1)) == x)); return ((x != 0) && ((x & (~x + 1)) == x));
} }
static uint32_t afatfs_firstCluster(afatfsFilePtr_t file)
{
// Take care that the uint16_t doesn't get promoted to signed int...
return ((uint32_t) file->directoryEntry.firstClusterHigh << 16) | (file->directoryEntry.firstClusterLow);
}
/** /**
* Check for conditions that should always be true (and if otherwise mean a bug or a corrupt filesystem). * Check for conditions that should always be true (and if otherwise mean a bug or a corrupt filesystem).
* *
@ -1065,8 +1072,7 @@ static afatfsFindClusterStatus_e afatfs_findClusterWithCondition(afatfsClusterSe
#ifdef AFATFS_USE_FREEFILE #ifdef AFATFS_USE_FREEFILE
// If we're looking inside the freefile, we won't find any free clusters! Skip it! // If we're looking inside the freefile, we won't find any free clusters! Skip it!
if (afatfs.freeFile.directoryEntry.fileSize > 0 && if (afatfs.freeFile.directoryEntry.fileSize > 0 && *cluster == afatfs_firstCluster(&afatfs.freeFile)) {
*cluster == (uint32_t) ((afatfs.freeFile.directoryEntry.firstClusterHigh << 16) + afatfs.freeFile.directoryEntry.firstClusterLow)) {
*cluster += (afatfs.freeFile.directoryEntry.fileSize + afatfs_clusterSize() - 1) / afatfs_clusterSize(); *cluster += (afatfs.freeFile.directoryEntry.fileSize + afatfs_clusterSize() - 1) / afatfs_clusterSize();
// Maintain alignment // Maintain alignment
@ -1141,9 +1147,11 @@ static afatfsOperationStatus_e afatfs_fileGetNextCluster(afatfsFilePtr_t file, u
(void) file; (void) file;
#else #else
if ((file->mode & AFATFS_FILE_MODE_CONTIGUOUS) != 0) { if ((file->mode & AFATFS_FILE_MODE_CONTIGUOUS) != 0) {
uint32_t freeFileStart = (afatfs.freeFile.directoryEntry.firstClusterHigh << 16) | afatfs.freeFile.directoryEntry.firstClusterLow; uint32_t freeFileStart = afatfs_firstCluster(&afatfs.freeFile);
// Would the next cluster lie outside the allocated file? (i.e. inside the freefile) afatfs_assert(currentCluster + 1 <= freeFileStart);
// Would the next cluster lie outside the allocated file? (i.e. beyond the end of the file into the start of the freefile)
if (currentCluster + 1 == freeFileStart) { if (currentCluster + 1 == freeFileStart) {
*nextCluster = 0; *nextCluster = 0;
} else { } else {
@ -1449,7 +1457,7 @@ static afatfsOperationStatus_e afatfs_appendSuperclusterContinue(afatfsFile_t *f
switch (opState->phase) { switch (opState->phase) {
case AFATFS_APPEND_SUPERCLUSTER_PHASE_INIT: case AFATFS_APPEND_SUPERCLUSTER_PHASE_INIT:
// Our file steals the first cluster of the freefile // Our file steals the first cluster of the freefile
freeFileStartCluster = (afatfs.freeFile.directoryEntry.firstClusterHigh << 16) | afatfs.freeFile.directoryEntry.firstClusterLow; freeFileStartCluster = afatfs_firstCluster(&afatfs.freeFile);
// The new supercluster needs to have its clusters chained contiguously and marked with a terminator at the end // The new supercluster needs to have its clusters chained contiguously and marked with a terminator at the end
opState->fatRewriteStartCluster = freeFileStartCluster; opState->fatRewriteStartCluster = freeFileStartCluster;
@ -1480,8 +1488,8 @@ static afatfsOperationStatus_e afatfs_appendSuperclusterContinue(afatfsFile_t *f
*/ */
newFreeFileStartCluster = freeFileStartCluster + afatfs_fatEntriesPerSector(); newFreeFileStartCluster = freeFileStartCluster + afatfs_fatEntriesPerSector();
afatfs.freeFile.directoryEntry.firstClusterLow = newFreeFileStartCluster;
afatfs.freeFile.directoryEntry.firstClusterHigh = newFreeFileStartCluster >> 16; afatfs.freeFile.directoryEntry.firstClusterHigh = newFreeFileStartCluster >> 16;
afatfs.freeFile.directoryEntry.firstClusterLow = newFreeFileStartCluster & 0xFFFF;
opState->phase = AFATFS_APPEND_SUPERCLUSTER_PHASE_UPDATE_FAT; opState->phase = AFATFS_APPEND_SUPERCLUSTER_PHASE_UPDATE_FAT;
goto doMore; goto doMore;
@ -1552,7 +1560,7 @@ static afatfsOperationStatus_e afatfs_appendSupercluster(afatfsFilePtr_t file, u
* We can go ahead and write to that space before the FAT and directory are updated by the * We can go ahead and write to that space before the FAT and directory are updated by the
* queued operation: * queued operation:
*/ */
file->cursorCluster = (afatfs.freeFile.directoryEntry.firstClusterHigh << 16) | afatfs.freeFile.directoryEntry.firstClusterLow; file->cursorCluster = afatfs_firstCluster(&afatfs.freeFile);
status = afatfs_appendSuperclusterContinue(file); status = afatfs_appendSuperclusterContinue(file);
@ -1722,7 +1730,7 @@ static bool afatfs_fseekAtomic(afatfsFilePtr_t file, int32_t offset)
// Seeks within a sector // Seeks within a sector
uint32_t newSectorOffset = offset + file->cursorOffset % AFATFS_SECTOR_SIZE; uint32_t newSectorOffset = offset + file->cursorOffset % AFATFS_SECTOR_SIZE;
// i.e. offset is non-negative and smaller than AFATFS_SECTOR_SIZE // i.e. newSectorOffset is non-negative and smaller than AFATFS_SECTOR_SIZE, we're staying within the same sector
if (newSectorOffset < AFATFS_SECTOR_SIZE) { if (newSectorOffset < AFATFS_SECTOR_SIZE) {
file->cursorOffset += offset; file->cursorOffset += offset;
return true; return true;
@ -1898,7 +1906,7 @@ afatfsOperationStatus_e afatfs_fseek(afatfsFilePtr_t file, int32_t offset, afatf
afatfs_fileUnlockCacheSector(file); afatfs_fileUnlockCacheSector(file);
file->cursorPreviousCluster = 0; file->cursorPreviousCluster = 0;
file->cursorCluster = (file->directoryEntry.firstClusterHigh << 16) | file->directoryEntry.firstClusterLow; file->cursorCluster = afatfs_firstCluster(file);
file->cursorOffset = 0; file->cursorOffset = 0;
// Then seek forwards by the offset // Then seek forwards by the offset
@ -2016,7 +2024,7 @@ static afatfsOperationStatus_e afatfs_extendSubdirectoryContinue(afatfsFile_t *d
memset(sectorBuffer, 0, AFATFS_SECTOR_SIZE); memset(sectorBuffer, 0, AFATFS_SECTOR_SIZE);
// If this is the first sector of a non-root directory, create the "." and ".." entries // If this is the first sector of a non-root directory, create the "." and ".." entries
if (afatfs.currentDirectory.directoryEntryPos.sectorNumberPhysical != 0 && directory->cursorOffset == 0) { if (directory->directoryEntryPos.sectorNumberPhysical != 0 && directory->cursorOffset == 0) {
fatDirectoryEntry_t *dirEntries = (fatDirectoryEntry_t *) sectorBuffer; fatDirectoryEntry_t *dirEntries = (fatDirectoryEntry_t *) sectorBuffer;
memset(dirEntries[0].filename, ' ', sizeof(dirEntries[0].filename)); memset(dirEntries[0].filename, ' ', sizeof(dirEntries[0].filename));
@ -2096,7 +2104,7 @@ static afatfsOperationStatus_e afatfs_extendSubdirectory(afatfsFile_t *directory
directory->operation.operation = AFATFS_FILE_OPERATION_EXTEND_SUBDIRECTORY; directory->operation.operation = AFATFS_FILE_OPERATION_EXTEND_SUBDIRECTORY;
opState->phase = AFATFS_EXTEND_SUBDIRECTORY_PHASE_INITIAL; opState->phase = AFATFS_EXTEND_SUBDIRECTORY_PHASE_INITIAL;
opState->parentDirectoryCluster = parentDirectory ? (parentDirectory->directoryEntry.firstClusterHigh << 16) | parentDirectory->directoryEntry.firstClusterLow : 0; opState->parentDirectoryCluster = parentDirectory ? afatfs_firstCluster(parentDirectory) : 0;
opState->callback = callback; opState->callback = callback;
afatfs_appendRegularFreeClusterInitOperationState(&opState->appendFreeCluster, directory->cursorPreviousCluster); afatfs_appendRegularFreeClusterInitOperationState(&opState->appendFreeCluster, directory->cursorPreviousCluster);
@ -2206,7 +2214,7 @@ static afatfsOperationStatus_e afatfs_ftruncateContinue(afatfsFilePtr_t file)
break; break;
case AFATFS_TRUNCATE_FILE_PREPEND_TO_FREEFILE: case AFATFS_TRUNCATE_FILE_PREPEND_TO_FREEFILE:
// Note, it's okay to run this code several times: // Note, it's okay to run this code several times:
oldFreeFileStart = (afatfs.freeFile.directoryEntry.firstClusterHigh << 16) | afatfs.freeFile.directoryEntry.firstClusterLow; oldFreeFileStart = afatfs_firstCluster(&afatfs.freeFile);
afatfs.freeFile.directoryEntry.firstClusterHigh = opState->startCluster >> 16; afatfs.freeFile.directoryEntry.firstClusterHigh = opState->startCluster >> 16;
afatfs.freeFile.directoryEntry.firstClusterLow = opState->startCluster & 0xFFFF; afatfs.freeFile.directoryEntry.firstClusterLow = opState->startCluster & 0xFFFF;
@ -2282,12 +2290,12 @@ bool afatfs_ftruncate(afatfsFilePtr_t file, afatfsFileCallback_t callback)
opState = &file->operation.state.truncateFile; opState = &file->operation.state.truncateFile;
opState->callback = callback; opState->callback = callback;
opState->phase = AFATFS_TRUNCATE_FILE_INITIAL; opState->phase = AFATFS_TRUNCATE_FILE_INITIAL;
opState->startCluster = (file->directoryEntry.firstClusterHigh << 16) | file->directoryEntry.firstClusterLow; opState->startCluster = afatfs_firstCluster(file);
opState->currentCluster = opState->startCluster; opState->currentCluster = opState->startCluster;
if ((file->mode & AFATFS_FILE_MODE_CONTIGUOUS) != 0) { if ((file->mode & AFATFS_FILE_MODE_CONTIGUOUS) != 0) {
// The file is contiguous and ends where the freefile begins // The file is contiguous and ends where the freefile begins
opState->endCluster = (afatfs.freeFile.directoryEntry.firstClusterHigh << 16) | afatfs.freeFile.directoryEntry.firstClusterLow; opState->endCluster = afatfs_firstCluster(&afatfs.freeFile);
} else { } else {
// The range of clusters to delete is not contiguous, so follow it as a linked-list instead // The range of clusters to delete is not contiguous, so follow it as a linked-list instead
opState->endCluster = 0; opState->endCluster = 0;
@ -2397,11 +2405,21 @@ static void afatfs_createFileContinue(afatfsFile_t *file)
// Is file empty? // Is file empty?
if (file->cursorCluster == 0) { if (file->cursorCluster == 0) {
if (file->type == AFATFS_FILE_TYPE_DIRECTORY && (file->mode & AFATFS_FILE_MODE_WRITE) != 0) { if (file->type == AFATFS_FILE_TYPE_DIRECTORY && (file->mode & AFATFS_FILE_MODE_WRITE) != 0) {
// Opening an empty directory. Append an empty cluster to it. This replaces our open file operation // Opening an empty directory. Append an empty cluster to it, this replaces our open file operation
file->operation.operation = AFATFS_FILE_OPERATION_NONE; file->operation.operation = AFATFS_FILE_OPERATION_NONE;
afatfs_extendSubdirectory(file, &afatfs.currentDirectory, opState->callback); afatfs_extendSubdirectory(file, &afatfs.currentDirectory, opState->callback);
break; break;
} }
if ((file->mode & AFATFS_FILE_MODE_CONTIGUOUS) != 0) {
if (afatfs_fileIsBusy(&afatfs.freeFile)) {
// Someone else's using the freefile, come back later.
break;
} else {
// Lock the freefile for our exclusive access
afatfs.freeFile.operation.operation = AFATFS_FILE_OPERATION_LOCKED;
}
}
} else { } else {
// We can't guarantee that the existing file contents are contiguous // We can't guarantee that the existing file contents are contiguous
file->mode &= ~AFATFS_FILE_MODE_CONTIGUOUS; file->mode &= ~AFATFS_FILE_MODE_CONTIGUOUS;
@ -2467,6 +2485,10 @@ bool afatfs_funlink(afatfsFilePtr_t file, afatfsCallback_t callback)
{ {
afatfsUnlinkFile_t *opState = &file->operation.state.unlinkFile; afatfsUnlinkFile_t *opState = &file->operation.state.unlinkFile;
if (!file || file->type == AFATFS_FILE_TYPE_NONE) {
return true;
}
/* /*
* Internally an unlink is implemented by first doing a ftruncate(), marking the directory entry as deleted, * Internally an unlink is implemented by first doing a ftruncate(), marking the directory entry as deleted,
* then doing a fclose() operation. * then doing a fclose() operation.
@ -2544,7 +2566,7 @@ static afatfsFilePtr_t afatfs_createFile(afatfsFilePtr_t file, const char *name,
return file; return file;
} }
static void afatfs_closeFileContinue(afatfsFilePtr_t file) static void afatfs_fcloseContinue(afatfsFilePtr_t file)
{ {
afatfsCacheBlockDescriptor_t *descriptor; afatfsCacheBlockDescriptor_t *descriptor;
afatfsCloseFile_t *opState = &file->operation.state.closeFile; afatfsCloseFile_t *opState = &file->operation.state.closeFile;
@ -2571,8 +2593,15 @@ static void afatfs_closeFileContinue(afatfsFilePtr_t file)
} }
} }
// Release locks on the sector at the file cursor position
afatfs_fileUnlockCacheSector(file); afatfs_fileUnlockCacheSector(file);
// Release our exclusive lock on the freefile if needed
if ((file->mode & AFATFS_FILE_MODE_CONTIGUOUS) != 0) {
afatfs_assert(afatfs.freeFile.operation.operation == AFATFS_FILE_OPERATION_LOCKED);
afatfs.freeFile.operation.operation = AFATFS_FILE_OPERATION_NONE;
}
file->type = AFATFS_FILE_TYPE_NONE; file->type = AFATFS_FILE_TYPE_NONE;
file->operation.operation = AFATFS_FILE_OPERATION_NONE; file->operation.operation = AFATFS_FILE_OPERATION_NONE;
@ -2599,7 +2628,7 @@ bool afatfs_fclose(afatfsFilePtr_t file, afatfsCallback_t callback)
} else { } else {
file->operation.operation = AFATFS_FILE_OPERATION_CLOSE; file->operation.operation = AFATFS_FILE_OPERATION_CLOSE;
file->operation.state.closeFile.callback = callback; file->operation.state.closeFile.callback = callback;
afatfs_closeFileContinue(file); afatfs_fcloseContinue(file);
return true; return true;
} }
} }
@ -2725,6 +2754,8 @@ bool afatfs_fopen(const char *filename, const char *mode, afatfsFileCallback_t c
if (file) { if (file) {
afatfs_createFile(file, filename, FAT_FILE_ATTRIBUTE_ARCHIVE, fileMode, complete); afatfs_createFile(file, filename, FAT_FILE_ATTRIBUTE_ARCHIVE, fileMode, complete);
} else if (complete) {
complete(NULL);
} }
return file != NULL; return file != NULL;
@ -2801,6 +2832,10 @@ uint32_t afatfs_fwrite(afatfsFilePtr_t file, const uint8_t *buffer, uint32_t len
break; break;
} }
if ((file->mode & AFATFS_FILE_MODE_CONTIGUOUS) != 0) {
afatfs_assert(file->cursorCluster < afatfs_firstCluster(&afatfs.freeFile));
}
len -= bytesToWriteThisSector; len -= bytesToWriteThisSector;
buffer += bytesToWriteThisSector; buffer += bytesToWriteThisSector;
cursorOffsetInSector = 0; cursorOffsetInSector = 0;
@ -2893,7 +2928,7 @@ static void afatfs_fileOperationContinue(afatfsFile_t *file)
afatfs_fseekInternalContinue(file); afatfs_fseekInternalContinue(file);
break; break;
case AFATFS_FILE_OPERATION_CLOSE: case AFATFS_FILE_OPERATION_CLOSE:
afatfs_closeFileContinue(file); afatfs_fcloseContinue(file);
break; break;
case AFATFS_FILE_OPERATION_UNLINK: case AFATFS_FILE_OPERATION_UNLINK:
afatfs_funlinkContinue(file); afatfs_funlinkContinue(file);
@ -2916,6 +2951,7 @@ static void afatfs_fileOperationContinue(afatfsFile_t *file)
case AFATFS_FILE_OPERATION_EXTEND_SUBDIRECTORY: case AFATFS_FILE_OPERATION_EXTEND_SUBDIRECTORY:
afatfs_extendSubdirectoryContinue(file); afatfs_extendSubdirectoryContinue(file);
break; break;
case AFATFS_FILE_OPERATION_LOCKED:
case AFATFS_FILE_OPERATION_NONE: case AFATFS_FILE_OPERATION_NONE:
; ;
break; break;