Working on using AFATFS from Blackbox
This commit is contained in:
parent
84d3cc6175
commit
96182c7c07
2
Makefile
2
Makefile
|
@ -578,6 +578,8 @@ STM32F3DISCOVERY_SRC = \
|
|||
drivers/compass_ak8975.c \
|
||||
drivers/sdcard.c \
|
||||
drivers/sdcard_standard.c \
|
||||
io/asyncfatfs/asyncfatfs.c \
|
||||
io/asyncfatfs/fat_standard.c \
|
||||
$(HIGHEND_SRC) \
|
||||
$(COMMON_SRC)
|
||||
|
||||
|
|
|
@ -479,7 +479,7 @@ static void blackboxSetState(BlackboxState newState)
|
|||
break;
|
||||
case BLACKBOX_STATE_SHUTTING_DOWN:
|
||||
xmitState.u.startTime = millis();
|
||||
blackboxDeviceFlush();
|
||||
blackboxDeviceEndLog();
|
||||
break;
|
||||
default:
|
||||
;
|
||||
|
@ -1401,7 +1401,7 @@ void handleBlackbox(void)
|
|||
blackboxAdvanceIterationTimers();
|
||||
break;
|
||||
case BLACKBOX_STATE_SHUTTING_DOWN:
|
||||
//On entry of this state, startTime is set and a flush is performed
|
||||
//On entry of this state, startTime is set
|
||||
|
||||
/*
|
||||
* Wait for the log we've transmitted to make its way to the logger before we release the serial port,
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "config/config_master.h"
|
||||
|
||||
#include "io/flashfs.h"
|
||||
#include "io/asyncfatfs/asyncfatfs.h"
|
||||
|
||||
#ifdef BLACKBOX
|
||||
|
||||
|
@ -74,6 +75,12 @@ int32_t blackboxHeaderBudget;
|
|||
static serialPort_t *blackboxPort = NULL;
|
||||
static portSharing_e blackboxPortSharing;
|
||||
|
||||
#ifdef USE_SDCARD
|
||||
|
||||
static afatfsFilePtr_t sdFile;
|
||||
|
||||
#endif
|
||||
|
||||
void blackboxWrite(uint8_t value)
|
||||
{
|
||||
switch (masterConfig.blackbox_device) {
|
||||
|
@ -81,6 +88,11 @@ void blackboxWrite(uint8_t value)
|
|||
case BLACKBOX_DEVICE_FLASH:
|
||||
flashfsWriteByte(value); // Write byte asynchronously
|
||||
break;
|
||||
#endif
|
||||
#ifdef USE_SDCARD
|
||||
case BLACKBOX_DEVICE_SDCARD:
|
||||
afatfs_fputc(sdFile, value);
|
||||
break;
|
||||
#endif
|
||||
case BLACKBOX_DEVICE_SERIAL:
|
||||
default:
|
||||
|
@ -152,6 +164,13 @@ int blackboxPrint(const char *s)
|
|||
break;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SDCARD
|
||||
case BLACKBOX_DEVICE_SDCARD:
|
||||
length = strlen(s);
|
||||
afatfs_fwrite(sdFile, (const uint8_t*) s, length); // Ignore failures due to buffers filling up
|
||||
break;
|
||||
#endif
|
||||
|
||||
case BLACKBOX_DEVICE_SERIAL:
|
||||
default:
|
||||
pos = (uint8_t*) s;
|
||||
|
@ -488,6 +507,11 @@ bool blackboxDeviceFlush(void)
|
|||
return flashfsFlushAsync();
|
||||
#endif
|
||||
|
||||
#ifdef USE_SDCARD
|
||||
case BLACKBOX_DEVICE_SDCARD:
|
||||
return afatfs_flush();
|
||||
#endif
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -551,6 +575,17 @@ bool blackboxDeviceOpen(void)
|
|||
return true;
|
||||
break;
|
||||
#endif
|
||||
#ifdef USE_SDCARD
|
||||
case BLACKBOX_DEVICE_SDCARD:
|
||||
if (afatfs_getFilesystemState() != AFATFS_FILESYSTEM_STATE_READY || afatfs_isFull()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
blackboxMaxHeaderBytesPerIteration = BLACKBOX_TARGET_HEADER_BUDGET_PER_ITERATION;
|
||||
|
||||
return true;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -578,6 +613,28 @@ void blackboxDeviceClose(void)
|
|||
case BLACKBOX_DEVICE_FLASH:
|
||||
// No-op since the flash doesn't have a "close" and there's nobody else to hand control of it to.
|
||||
break;
|
||||
#endif
|
||||
#ifdef USE_SDCARD
|
||||
case BLACKBOX_DEVICE_SDCARD:
|
||||
afatfs_fclose(sdFile, NULL);
|
||||
sdFile = NULL;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate the current log (for devices which support separations between the logs of multiple flights)
|
||||
*/
|
||||
void blackboxDeviceEndLog(void)
|
||||
{
|
||||
switch (masterConfig.blackbox_device) {
|
||||
#ifdef USE_SDCARD
|
||||
case BLACKBOX_DEVICE_SDCARD:
|
||||
if (afatfs_fclose(sdFile, NULL)) {
|
||||
sdFile = NULL;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -593,6 +650,11 @@ bool isBlackboxDeviceFull(void)
|
|||
return flashfsIsEOF();
|
||||
#endif
|
||||
|
||||
#ifdef USE_SDCARD
|
||||
case BLACKBOX_DEVICE_SDCARD:
|
||||
return afatfs_isFull();
|
||||
#endif
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -614,6 +676,11 @@ void blackboxReplenishHeaderBudget()
|
|||
case BLACKBOX_DEVICE_FLASH:
|
||||
freeSpace = flashfsGetWriteBufferFreeSpace();
|
||||
break;
|
||||
#endif
|
||||
#ifdef USE_SDCARD
|
||||
case BLACKBOX_DEVICE_SDCARD:
|
||||
freeSpace = afatfs_getFreeBufferSpace();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
freeSpace = 0;
|
||||
|
@ -677,6 +744,12 @@ blackboxBufferReserveStatus_e blackboxDeviceReserveBufferSpace(int32_t bytes)
|
|||
return BLACKBOX_RESERVE_TEMPORARY_FAILURE;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SDCARD
|
||||
case BLACKBOX_DEVICE_SDCARD:
|
||||
// Assume that all writes will fit in the SDCard's buffers
|
||||
return BLACKBOX_RESERVE_TEMPORARY_FAILURE;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return BLACKBOX_RESERVE_PERMANENT_FAILURE;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,9 @@ typedef enum BlackboxDevice {
|
|||
#ifdef USE_FLASHFS
|
||||
BLACKBOX_DEVICE_FLASH,
|
||||
#endif
|
||||
#ifdef USE_SDCARD
|
||||
BLACKBOX_DEVICE_SDCARD,
|
||||
#endif
|
||||
|
||||
BLACKBOX_DEVICE_END
|
||||
} BlackboxDevice;
|
||||
|
@ -72,6 +75,7 @@ void blackboxWriteFloat(float value);
|
|||
bool blackboxDeviceFlush(void);
|
||||
bool blackboxDeviceOpen(void);
|
||||
void blackboxDeviceClose(void);
|
||||
void blackboxDeviceEndLog(void);
|
||||
|
||||
bool isBlackboxDeviceFull(void);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,66 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "fat_standard.h"
|
||||
|
||||
typedef struct afatfsFile_t *afatfsFilePtr_t;
|
||||
|
||||
typedef enum {
|
||||
AFATFS_FILESYSTEM_STATE_UNKNOWN,
|
||||
AFATFS_FILESYSTEM_STATE_FATAL,
|
||||
AFATFS_FILESYSTEM_STATE_INITIALIZATION,
|
||||
AFATFS_FILESYSTEM_STATE_READY,
|
||||
} afatfsFilesystemState_e;
|
||||
|
||||
typedef enum {
|
||||
AFATFS_OPERATION_IN_PROGRESS,
|
||||
AFATFS_OPERATION_SUCCESS,
|
||||
AFATFS_OPERATION_FAILURE,
|
||||
} afatfsOperationStatus_e;
|
||||
|
||||
typedef struct afatfsDirEntryPointer_t {
|
||||
uint32_t sectorNumberPhysical;
|
||||
int16_t entryIndex;
|
||||
} afatfsDirEntryPointer_t;
|
||||
|
||||
typedef afatfsDirEntryPointer_t afatfsFinder_t;
|
||||
|
||||
typedef enum {
|
||||
AFATFS_SEEK_SET,
|
||||
AFATFS_SEEK_CUR,
|
||||
AFATFS_SEEK_END,
|
||||
} afatfsSeek_e;
|
||||
|
||||
typedef void (*afatfsFileCallback_t)(afatfsFilePtr_t file);
|
||||
typedef void (*afatfsCallback_t)();
|
||||
|
||||
bool afatfs_fopen(const char *filename, const char *mode, afatfsFileCallback_t complete);
|
||||
bool afatfs_ftruncate(afatfsFilePtr_t file, afatfsFileCallback_t callback);
|
||||
bool afatfs_fclose(afatfsFilePtr_t file, afatfsCallback_t callback);
|
||||
bool afatfs_funlink(afatfsFilePtr_t file, afatfsCallback_t callback);
|
||||
|
||||
bool afatfs_feof(afatfsFilePtr_t file);
|
||||
void afatfs_fputc(afatfsFilePtr_t file, uint8_t c);
|
||||
uint32_t afatfs_fwrite(afatfsFilePtr_t file, const uint8_t *buffer, uint32_t len);
|
||||
uint32_t afatfs_fread(afatfsFilePtr_t file, uint8_t *buffer, uint32_t len);
|
||||
afatfsOperationStatus_e afatfs_fseek(afatfsFilePtr_t file, int32_t offset, afatfsSeek_e whence);
|
||||
bool afatfs_ftell(afatfsFilePtr_t file, uint32_t *position);
|
||||
|
||||
afatfsFilePtr_t afatfs_mkdir(const char *filename, afatfsFileCallback_t complete);
|
||||
bool afatfs_chdir(afatfsFilePtr_t dirHandle);
|
||||
|
||||
void afatfs_findFirst(afatfsFilePtr_t directory, afatfsFinder_t *finder);
|
||||
afatfsOperationStatus_e afatfs_findNext(afatfsFilePtr_t directory, afatfsFinder_t *finder, fatDirectoryEntry_t **dirEntry);
|
||||
|
||||
bool afatfs_flush();
|
||||
void afatfs_init();
|
||||
bool afatfs_destroy();
|
||||
void afatfs_poll();
|
||||
|
||||
uint32_t afatfs_getFreeBufferSpace();
|
||||
uint32_t afatfs_getContiguousFreeSpace();
|
||||
bool afatfs_isFull();
|
||||
|
||||
afatfsFilesystemState_e afatfs_getFilesystemState();
|
|
@ -0,0 +1,72 @@
|
|||
#include <ctype.h>
|
||||
|
||||
#include "fat_standard.h"
|
||||
|
||||
bool fat16_isEndOfChainMarker(uint16_t clusterNumber)
|
||||
{
|
||||
return clusterNumber >= 0xFFF8;
|
||||
}
|
||||
|
||||
// Pass the cluster number after fat32_decodeClusterNumber().
|
||||
bool fat32_isEndOfChainMarker(uint32_t clusterNumber)
|
||||
{
|
||||
return clusterNumber >= 0x0FFFFFF8;
|
||||
}
|
||||
|
||||
/**
|
||||
* FAT32 cluster numbers are really only 28 bits, and the top 4 bits must be left alone and not treated as part of the
|
||||
* cluster number (so various FAT drivers can use those bits for their own purposes, or they can be used in later
|
||||
* extensions)
|
||||
*/
|
||||
uint32_t fat32_decodeClusterNumber(uint32_t clusterNumber)
|
||||
{
|
||||
return clusterNumber & 0x0FFFFFFF;
|
||||
}
|
||||
|
||||
// fat32 needs fat32_decodeClusterNumber() applied first.
|
||||
bool fat_isFreeSpace(uint32_t clusterNumber)
|
||||
{
|
||||
return clusterNumber == 0;
|
||||
}
|
||||
|
||||
bool fat_isDirectoryEntryTerminator(fatDirectoryEntry_t *entry)
|
||||
{
|
||||
return entry->filename[0] == 0x00;
|
||||
}
|
||||
|
||||
bool fat_isDirectoryEntryEmpty(fatDirectoryEntry_t *entry)
|
||||
{
|
||||
return (unsigned char) entry->filename[0] == FAT_DELETED_FILE_MARKER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given "prefix.ext" style filename to the FAT format to be stored on disk.
|
||||
*
|
||||
* fatFilename must point to a buffer which is FAT_FILENAME_LENGTH bytes long. The buffer is not null-terminated.
|
||||
*/
|
||||
void fat_convertFilenameToFATStyle(const char *filename, uint8_t *fatFilename)
|
||||
{
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (*filename == '\0' || *filename == '.') {
|
||||
*fatFilename = ' ';
|
||||
} else {
|
||||
*fatFilename = toupper((unsigned char)*filename);
|
||||
filename++;
|
||||
}
|
||||
fatFilename++;
|
||||
}
|
||||
|
||||
if (*filename == '.') {
|
||||
filename++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (*filename == '\0') {
|
||||
*fatFilename = ' ';
|
||||
} else {
|
||||
*fatFilename = toupper((unsigned char)*filename);
|
||||
filename++;
|
||||
}
|
||||
fatFilename++;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MBR_PARTITION_TYPE_FAT16 0x06
|
||||
#define MBR_PARTITION_TYPE_FAT32 0x0B
|
||||
#define MBR_PARTITION_TYPE_FAT32_LBA 0x0C
|
||||
#define MBR_PARTITION_TYPE_FAT16_LBA 0x0E
|
||||
|
||||
// Signature bytes found at index 510 and 511 in the volume ID sector
|
||||
#define FAT_VOLUME_ID_SIGNATURE_1 0x55
|
||||
#define FAT_VOLUME_ID_SIGNATURE_2 0xAA
|
||||
|
||||
#define FAT_DIRECTORY_ENTRY_SIZE 32
|
||||
#define FAT_SMALLEST_LEGAL_CLUSTER_NUMBER 2
|
||||
|
||||
#define FAT_MAXIMUM_FILESIZE 0xFFFFFFFF
|
||||
|
||||
#define FAT12_MAX_CLUSTERS 4084
|
||||
#define FAT16_MAX_CLUSTERS 65524
|
||||
|
||||
#define FAT_FILE_ATTRIBUTE_READ_ONLY 0x01
|
||||
#define FAT_FILE_ATTRIBUTE_HIDDEN 0x02
|
||||
#define FAT_FILE_ATTRIBUTE_SYSTEM 0x04
|
||||
#define FAT_FILE_ATTRIBUTE_VOLUME_ID 0x08
|
||||
#define FAT_FILE_ATTRIBUTE_DIRECTORY 0x10
|
||||
#define FAT_FILE_ATTRIBUTE_ARCHIVE 0x20
|
||||
|
||||
#define FAT_FILENAME_LENGTH 11
|
||||
#define FAT_DELETED_FILE_MARKER 0xE5
|
||||
|
||||
typedef enum {
|
||||
FAT_FILESYSTEM_TYPE_INVALID,
|
||||
FAT_FILESYSTEM_TYPE_FAT12,
|
||||
FAT_FILESYSTEM_TYPE_FAT16,
|
||||
FAT_FILESYSTEM_TYPE_FAT32,
|
||||
} fatFilesystemType_e;
|
||||
|
||||
typedef struct mbrPartitionEntry_t {
|
||||
uint8_t bootFlag;
|
||||
uint8_t chsBegin[3];
|
||||
uint8_t type;
|
||||
uint8_t chsEnd[3];
|
||||
uint32_t lbaBegin;
|
||||
uint32_t numSectors;
|
||||
} __attribute__((packed)) mbrPartitionEntry_t;
|
||||
|
||||
typedef struct fat16Descriptor_t {
|
||||
uint8_t driveNumber;
|
||||
uint8_t reserved1;
|
||||
uint8_t bootSignature;
|
||||
uint32_t volumeID;
|
||||
char volumeLabel[11];
|
||||
char fileSystemType[8];
|
||||
} __attribute__((packed)) fat16Descriptor_t;
|
||||
|
||||
typedef struct fat32Descriptor_t {
|
||||
uint32_t FATSize32;
|
||||
uint16_t extFlags;
|
||||
uint16_t fsVer;
|
||||
uint32_t rootCluster;
|
||||
uint16_t fsInfo;
|
||||
uint16_t backupBootSector;
|
||||
uint8_t reserved[12];
|
||||
uint8_t driveNumber;
|
||||
uint8_t reserved1;
|
||||
uint8_t bootSignature;
|
||||
uint32_t volumeID;
|
||||
char volumeLabel[11];
|
||||
char fileSystemType[8];
|
||||
} __attribute__((packed)) fat32Descriptor_t;
|
||||
|
||||
typedef struct fatVolumeID_t {
|
||||
uint8_t jmpBoot[3];
|
||||
char oemName[8];
|
||||
uint16_t bytesPerSector;
|
||||
uint8_t sectorsPerCluster;
|
||||
uint16_t reservedSectorCount;
|
||||
uint8_t numFATs;
|
||||
uint16_t rootEntryCount;
|
||||
uint16_t totalSectors16;
|
||||
uint8_t media;
|
||||
uint16_t FATSize16;
|
||||
uint16_t sectorsPerTrack;
|
||||
uint16_t numHeads;
|
||||
uint32_t hiddenSectors;
|
||||
uint32_t totalSectors32;
|
||||
union {
|
||||
fat16Descriptor_t fat16;
|
||||
fat32Descriptor_t fat32;
|
||||
} fatDescriptor;
|
||||
} __attribute__((packed)) fatVolumeID_t;
|
||||
|
||||
typedef struct fatDirectoryEntry_t {
|
||||
char filename[FAT_FILENAME_LENGTH];
|
||||
uint8_t attrib;
|
||||
uint8_t ntReserved;
|
||||
uint8_t creationTimeTenths;
|
||||
uint16_t creationTime;
|
||||
uint16_t creationDate;
|
||||
uint16_t lastAccessDate;
|
||||
uint16_t firstClusterHigh;
|
||||
uint16_t lastWriteTime;
|
||||
uint16_t lastWriteDate;
|
||||
uint16_t firstClusterLow;
|
||||
uint32_t fileSize;
|
||||
} __attribute__((packed)) fatDirectoryEntry_t;
|
||||
|
||||
uint32_t fat32_decodeClusterNumber(uint32_t clusterNumber);
|
||||
|
||||
bool fat32_isEndOfChainMarker(uint32_t clusterNumber);
|
||||
bool fat16_isEndOfChainMarker(uint16_t clusterNumber);
|
||||
|
||||
bool fat_isFreeSpace(uint32_t clusterNumber);
|
||||
|
||||
bool fat_isDirectoryEntryTerminator(fatDirectoryEntry_t *entry);
|
||||
bool fat_isDirectoryEntryEmpty(fatDirectoryEntry_t *entry);
|
||||
|
||||
void fat_convertFilenameToFATStyle(const char *filename, uint8_t *fatFilename);
|
Loading…
Reference in New Issue