diff --git a/USB/README.TXT b/USB/README.TXT new file mode 100644 index 0000000..7557052 --- /dev/null +++ b/USB/README.TXT @@ -0,0 +1,19 @@ +USB support is implemented using the STM32 USB Device library. + +The library is copied into the core project to make customizations easier to maintain +across different ports. The USBD library supports all versions of the HAL and LL. + +GEX uses USB classes CDC/ACM and MSC/SCSI. +The two classes are combined into a composite class with association descriptors. + +USB interrupts are processed by the USBD library and endpoint callbacks in the composite +class are fired. To avoid race conditions (and because DAPlink did it the same way), the +events are notified to the USB thread (TaskMain) which calls endpoint handlers in the +corresponding class drivers. + +VFS is handled synchronously on the main thread. CDC messages (TinyFrame data) are queued +and processed by the message queue thread. This makes it possible to query hardware +(e.g. slow USART or NeoPixel) without stalling the USB communication. This arrangement +also makes it possible to wait on a binary semaphore when sending data back to host. The +semaphore is set from the CDC TxComplete callback and taken by the TinyFrame write +function, serving as a form of flow control. diff --git a/cortex_handlers.c b/cortex_handlers.c index 6e5584d..37ebfd8 100644 --- a/cortex_handlers.c +++ b/cortex_handlers.c @@ -1,3 +1,8 @@ +// +// Some FreeRTOS / CortexM callbacks are implemented here +// (moved from the top level project for easier maintenance) +// + /* Includes ------------------------------------------------------------------*/ #include "platform.h" diff --git a/debug.h b/debug.h index 65ec0fd..c6b1c8e 100644 --- a/debug.h +++ b/debug.h @@ -1,6 +1,8 @@ // // Created by MightyPork on 2017/11/04. // +// Debugging functions +// #ifndef GEX_DEBUG_H #define GEX_DEBUG_H @@ -12,12 +14,19 @@ #if USE_DEBUG_UART +/** Externally defined function for writing to the debug UART */ extern void debug_write(const char *buf, uint16_t len); +/** Debug printf, used in the macros below */ void _DO_PRINTF(const char *format, ...) __attribute__((format(printf,1,2))) ; + +/** putsn to debug */ void PUTSN(const char *string, uint16_t len); + +/** puts to debug */ void PUTS(const char *string); +/** puts with just a newline */ static inline void PUTNL(void) { debug_write("\r\n", 2); @@ -33,6 +42,12 @@ static inline void PUTCHAR(char ch) debug_write(&ch, 1); } +// NOTE: Those macros use puts instead of printf if the format is the only arg. +// this saves ROM and stack overhead + +/** + * Debug printf + */ #define PRINTF(format, ...) do { \ if (VA_ARG_COUNT(__VA_ARGS__) == 0) { \ PUTS(format); \ @@ -41,6 +56,9 @@ static inline void PUTCHAR(char ch) } \ } while (0) +/** + * Debug printf (with a newline) + */ #define dbg(format, ...) do { \ if (VA_ARG_COUNT(__VA_ARGS__) == 0) { \ PUTS(format); \ @@ -50,14 +68,13 @@ static inline void PUTCHAR(char ch) PUTNL(); \ } while (0) - #else -#define dbg(format, ...) do {} while (0) -#define PRINTF(format, ...) do {} while (0) -#define PUTSN(string, len) do {} while (0) -#define PUTS(string) do {} while (0) -#define PUTNL() do {} while (0) -#define PUTCHAR(ch) do {} while (0) + #define dbg(format, ...) do {} while (0) + #define PRINTF(format, ...) do {} while (0) + #define PUTSN(string, len) do {} while (0) + #define PUTS(string) do {} while (0) + #define PUTNL() do {} while (0) + #define PUTCHAR(ch) do {} while (0) #endif #endif //GEX_DEBUG_H diff --git a/freertos.c b/freertos.c index 24116d4..b19b04a 100644 --- a/freertos.c +++ b/freertos.c @@ -1,3 +1,7 @@ +// +// FreeRTOS setup +// + /** ****************************************************************************** * File Name : freertos.c diff --git a/gex_hooks.h b/gex_hooks.h index 20a1362..8419fd0 100644 --- a/gex_hooks.h +++ b/gex_hooks.h @@ -1,6 +1,8 @@ // // Created by MightyPork on 2017/12/15. // +// Callbacks from the top level main() function etc +// #ifndef GEX_GEX_HOOKS_H #define GEX_GEX_HOOKS_H diff --git a/stm32_assert.h b/stm32_assert.h index f3c9e09..22985a9 100644 --- a/stm32_assert.h +++ b/stm32_assert.h @@ -1,6 +1,8 @@ // // Created by MightyPork on 2017/11/20. // +// Assert handling with traps +// #ifndef STM32_ASSERT_H #define STM32_ASSERT_H diff --git a/utils/avrlibc.h b/utils/avrlibc.h index 16a8770..683d8b5 100644 --- a/utils/avrlibc.h +++ b/utils/avrlibc.h @@ -1,14 +1,59 @@ // // Created by MightyPork on 2017/11/26. // +// Those are low memory footprint implementations of some stdlib functions +// taken from the AVR libc. They are used instead of newlib versions. +// #ifndef GEX_AVRLIBC_H_H #define GEX_AVRLIBC_H_H +/** + * atoi() - parse decimal int from ASCII + * + * @param p - string + * @return int, 0 on failure + */ int avr_atoi(const char *p); -long avr_strtol(const char *nptr, char **endptr, register int base); + +/** + * atol() - parse decimal long int from ASCII + * + * @param p - string + * @return int, 0 on failure + */ long avr_atol(const char *p); + +/** + * strtol() - parse integer number form string. + * this is internally called by atol and atoi + * + * 0x is allowed for bases 0 and 16 + * + * @param nptr - string to parse + * @param endptr - NULL or pointer to string where the end will be stored (first bad char) + * @param base - base 2, 10, 16.... 0 for auto + * @return the number + */ +long avr_strtol(const char *nptr, char **endptr, register int base); + +/** + * Parse double from ASCII + * + * @param nptr - string to parse + * @param endptr - NULL or pointer to string where the end will be stored (first bad char) + * @return the number + */ double avr_strtod (const char * nptr, char ** endptr); + +/** + * like strtol(), but unsigned (and hence higher max value) + * + * @param nptr - string to parse + * @param endptr - NULL or pointer to string where the end will be stored (first bad char) + * @param base - base 2, 10, 16.... 0 for auto + * @return the number + */ unsigned long avr_strtoul(const char *nptr, char **endptr, register int base); #endif //GEX_AVRLIBC_H_H diff --git a/utils/circ_buf.h b/utils/circ_buf.h index a293e5d..69e5fcd 100644 --- a/utils/circ_buf.h +++ b/utils/circ_buf.h @@ -1,3 +1,7 @@ +// +// This is a circular buffer implementation borrowed from the DAPLink firmware +// + /** * @file circ_buf.h * @brief Implementation of a circular buffer diff --git a/utils/cortex_utils.h b/utils/cortex_utils.h index d52cc7a..6cb114a 100644 --- a/utils/cortex_utils.h +++ b/utils/cortex_utils.h @@ -1,6 +1,8 @@ // // Created by MightyPork on 2017/11/26. // +// Cortex-M utilities (low level stuff missing from CMSIS) +// #ifndef GEX_CORTEX_UTILS_H #define GEX_CORTEX_UTILS_H diff --git a/utils/error.h b/utils/error.h index 7c624be..b5d64a8 100644 --- a/utils/error.h +++ b/utils/error.h @@ -1,23 +1,6 @@ -/** - * @file error.h - * @brief collection of known errors and accessor for the friendly string - * - * DAPLink Interface Firmware - * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// +// Error codes and labels. Loosely based on DAPLink, with more codes added. +// #ifndef ERROR_H #define ERROR_H @@ -59,7 +42,10 @@ X(OUT_OF_MEM, "Not enough RAM") \ X(RESOURCE_NOT_AVAILABLE, NULL) -// Keep in sync with the list error_message + +/** + * The return value for all functions with error reporting. + */ typedef enum { #define X(name, text) E_##name, X_ERROR_CODES @@ -67,8 +53,6 @@ typedef enum { ERROR_COUNT } error_t; -const char *error_get_message(error_t error) __attribute__((pure)); -const char *error_get_name(error_t error) __attribute__((pure)); /** Check return value and return it if not E_SUCCESS */ #define TRY(call) do { \ @@ -77,6 +61,24 @@ const char *error_get_name(error_t error) __attribute__((pure)); if (E_SUCCESS != _rv) return _rv; \ } while (0) + +/** + * Get a user-friendly message from a E_* enum value + * + * @param error - E_* value + * @return string, error name or description + */ +const char *error_get_message(error_t error) __attribute__((pure)); + + +/** + * Get error name from a E_* enum value + * + * @param error - E_* value + * @return string, error name + */ +const char *error_get_name(error_t error) __attribute__((pure)); + #ifdef __cplusplus } #endif diff --git a/utils/hexdump.h b/utils/hexdump.h index c1de480..f3d290c 100644 --- a/utils/hexdump.h +++ b/utils/hexdump.h @@ -1,6 +1,9 @@ // // Created by MightyPork on 2017/12/04. // +// Memory dumping utility from: https://stackoverflow.com/a/7776146/2180189 +// Prints bytes in the usual hexdump format (as HEX and ASCII) +// #ifndef GEX_HEXDUMP_H #define GEX_HEXDUMP_H diff --git a/utils/ini_parser.h b/utils/ini_parser.h index 4265965..52b36ac 100644 --- a/utils/ini_parser.h +++ b/utils/ini_parser.h @@ -1,8 +1,14 @@ +// +// INI file parser with a FSM generated by Ragel. This was originally written for ESPTerm +// Used to extract sections, keys and values from user-provided settings file +// + #ifndef INIPARSE_STREAM_H #define INIPARSE_STREAM_H #include "platform.h" +// toggleable logging func #ifdef DEBUG_INI #define ini_error(fmt, ...) dbg("! INI err: "#fmt, ##__VA_ARGS__) #else diff --git a/utils/ini_writer.h b/utils/ini_writer.h index 0ae4ca3..7212de9 100644 --- a/utils/ini_writer.h +++ b/utils/ini_writer.h @@ -1,12 +1,19 @@ // // Created by MightyPork on 2017/12/01. // +// Utility for generating a INI file with support for extracting individual sectors +// and measuring total length without buffering. This is used to build the INI files +// for the VFS and config. +// #ifndef INIWRITER_H #define INIWRITER_H #include "platform.h" +/** + * INI writer handle + */ typedef struct iniwriter_ { char *ptr; uint32_t skip; @@ -18,7 +25,7 @@ typedef struct iniwriter_ { * * This buffer is used internally by printf-like iw functions. * It can be used to prepare buffer for iw_buff or iw_string, - * but must not be used for %s substitutions in iw_* functions. + * but must NOT be used for %s substitutions in iw_* functions. */ extern char *iwbuffer; diff --git a/utils/macro.h b/utils/macro.h index 1c65320..130b7a8 100644 --- a/utils/macro.h +++ b/utils/macro.h @@ -1,3 +1,7 @@ +// +// static assert and general purpose useful macros, borrowed in part from the DAPLink project +// + /** * @file macro.h * @brief useful things + Special asserts and macros diff --git a/utils/malloc_safe.h b/utils/malloc_safe.h index da3a6bd..5f9d372 100644 --- a/utils/malloc_safe.h +++ b/utils/malloc_safe.h @@ -1,3 +1,9 @@ +// +// Safe malloc with error file:line logging, using the FreeRTOS-provided malloc facility +// The custom malloc implementation is safer than the poorly documented hacks provided by +// newlib, written primarily for the desktop rather than embedded. +// + #ifndef MALLOC_SAFE_H #define MALLOC_SAFE_H diff --git a/utils/snprintf.h b/utils/snprintf.h index 549c87c..a451969 100644 --- a/utils/snprintf.h +++ b/utils/snprintf.h @@ -1,6 +1,8 @@ // // Created by MightyPork on 2017/11/09. // +// Small sprintf/snprintf implementation, used instead of the newlib one. +// #ifndef GEX_SNPRINTF_H #define GEX_SNPRINTF_H @@ -15,13 +17,6 @@ size_t fixup_vasprintf(char **ptr, const char *format, va_list ap); size_t fixup_asprintf(char **ptr, const char *format, ...); size_t fixup_sprintf(char *ptr, const char *format, ...); -// Trap for using newlib functions -//#define vsnprintf fuck1 -//#define snprintf fuck2 -//#define vasprintf fuck3 -//#define asprintf fuck4 -//#define sprintf fuck5 - #define VSNPRINTF(...) fixup_vsnprintf(__VA_ARGS__) #define SNPRINTF(...) fixup_snprintf(__VA_ARGS__) #define VASPRINTF(...) fixup_vasprintf(__VA_ARGS__) diff --git a/utils/stacksmon.c b/utils/stacksmon.c index 1fce31c..0a765c7 100644 --- a/utils/stacksmon.c +++ b/utils/stacksmon.c @@ -15,7 +15,6 @@ struct stackhandle { uint32_t len; }; -#define STACK_NUM 3 static uint32_t nextidx = 0; static struct stackhandle stacks[STACK_NUM]; diff --git a/utils/stacksmon.h b/utils/stacksmon.h index 80dd3e5..cddc53b 100644 --- a/utils/stacksmon.h +++ b/utils/stacksmon.h @@ -1,6 +1,8 @@ // // Created by MightyPork on 2017/12/04. // +// Utility for monitoring usage levels of FreeRTOS stacks and printing it in a nice table +// #ifndef GEX_STACKSMON_H #define GEX_STACKSMON_H @@ -8,9 +10,29 @@ #include "platform.h" #if USE_STACK_MONITOR + +/** Number of tracked stacks, max */ +#define STACK_NUM 3 + +/** + * Check canaries and trap if they're dead + */ void stackmon_check_canaries(void); + +/** + * Dump stacks usage table + */ void stackmon_dump(void); + +/** + * Register a stack to be monitored + * + * @param description - stack name + * @param buffer - stack buffer + * @param len - stack size in bytes + */ void stackmon_register(const char *description, void *buffer, uint32_t len); + #else #define stackmon_check_canaries() do {} while(0) #define stackmon_dump() do {} while(0) diff --git a/utils/str_utils.h b/utils/str_utils.h index a4170e0..b25e6b6 100644 --- a/utils/str_utils.h +++ b/utils/str_utils.h @@ -1,3 +1,8 @@ +// +// Simple string testing / manipulation functions, mainly used when +// building/parsing the config INI files +// + #ifndef PLATFORSTR_UTILS_H #define PLATFORSTR_UTILS_H @@ -125,17 +130,20 @@ const char *str_4(uint32_t n, uint32_t nc, const char *c, uint32_t nd, const char *d); +/** Convert string to one of two numeric options */ uint32_t str_parse_2(const char *tpl, const char *a, uint32_t na, const char *b, uint32_t nb, bool *suc); +/** Convert string to one of three numeric options */ uint32_t str_parse_3(const char *tpl, const char *a, uint32_t na, const char *b, uint32_t nb, const char *c, uint32_t nc, bool *suc); +/** Convert string to one of four numeric options */ uint32_t str_parse_4(const char *tpl, const char *a, uint32_t na, const char *b, uint32_t nb, @@ -143,7 +151,7 @@ uint32_t str_parse_4(const char *tpl, const char *d, uint32_t nd, bool *suc); -/** Convert bool to Y or N */ +/** Convert bool to a Y or N constant string */ #define str_yn(cond) ((cond) ? ("Y") : ("N")) #endif diff --git a/version.h b/version.h index 995e1e2..da30beb 100644 --- a/version.h +++ b/version.h @@ -1,6 +1,8 @@ // // Created by MightyPork on 2017/12/08. // +// GEX version string +// #ifndef GEX_VERSION_H #define GEX_VERSION_H diff --git a/vfs/file_stream.h b/vfs/file_stream.h index 3d6e8d1..ab642f7 100644 --- a/vfs/file_stream.h +++ b/vfs/file_stream.h @@ -1,3 +1,8 @@ +// +// File streams, this was used in DAPLink to capture and flash the firmware update image. +// Here we detect only the settings INI files, which start by two hash symbols. +// + /** * @file file_stream.h * @brief Different file stream parsers that are supported @@ -42,16 +47,19 @@ typedef enum { STREAM_TYPE_NONE } stream_type_t; -// Stateless function to identify a filestream by its contents +/** Stateless function to identify a filestream by its contents */ stream_type_t stream_start_identify(const uint8_t *data, uint32_t size); -// Stateless function to identify a filestream by its name +/** Stateless function to identify a filestream by its name */ stream_type_t stream_type_from_name(const vfs_filename_t filename); +/** Open a stream (only one can be open at all times) */ error_t stream_open(stream_type_t stream_type); +/** Write some data to an open stream */ error_t stream_write(const uint8_t *data, uint32_t size); +/** Close the open stream */ error_t stream_close(void); #ifdef __cplusplus diff --git a/vfs/vfs_manager.c b/vfs/vfs_manager.c index 152c915..1a3adc4 100644 --- a/vfs/vfs_manager.c +++ b/vfs/vfs_manager.c @@ -328,7 +328,7 @@ void vfs_if_usbd_msc_read_sect(uint32_t sector, uint8_t *buf, uint32_t num_of_se vfs_read(sector, buf, num_of_sectors); } -void vfs_if_usbd_msc_write_sect(uint32_t sector, uint8_t *buf, uint32_t num_of_sectors) +void vfs_if_usbd_msc_write_sect(uint32_t sector, const uint8_t *buf, uint32_t num_of_sectors) { sync_assert_usb_thread(); vfs_printf("\033[32mWRITE @ %d, len %d\033[0m", (int)sector, (int)num_of_sectors); diff --git a/vfs/vfs_manager.h b/vfs/vfs_manager.h index b9c181e..7e35858 100644 --- a/vfs/vfs_manager.h +++ b/vfs/vfs_manager.h @@ -1,3 +1,10 @@ +// +// The main VFS state machine, mostly based on DAPLink +// +// TODO many errors were originally written to a FAIL.TXT file for the user to see, +// those are now caught by assert_param(0) and crash the whole system. This is not ideal. +// + /** * @file vfs_manager.h * @brief Methods that build and manipulate a virtual file system @@ -29,61 +36,114 @@ extern "C" { #endif +/** + * Flag that we're plugged into Windows. + * This is detected by characteristic writes of some system metadata store (which we discard) + */ extern bool vfs_is_windows; /* Callable from anywhere */ -// Enable or disable the virtual filesystem +/** Enable or disable the virtual filesystem */ void vfs_mngr_fs_enable(bool enabled); -// Remount the virtual filesystem +/** + * Remount the virtual filesystem + * + * @param force_full - use media ready toggle instead of just notifying of modified data + * (this should be more reliable, but can also be more intrusive) + */ void vfs_mngr_fs_remount(bool force_full); /* Callable only from the thread running the virtual fs */ -// Initialize the VFS manager -// Must be called after USB has been initialized (usbd_init()) -// Notes: Must only be called from the thread runnning USB +/** + * Initialize the VFS manager + * Must be called after USB has been initialized (usbd_init()) + * + * @note Must only be called from the thread runnning USB + * @param enabled + */ void vfs_mngr_init(bool enabled); -// Run the vfs manager state machine -// Notes: Must only be called from the thread runnning USB + +/** + * Run the vfs manager state machine + * + * @note Must only be called from the thread runnning USB + * @param elapsed_ms + */ void vfs_mngr_periodic(uint32_t elapsed_ms); -// Return the status of the last transfer or E_SUCCESS -// if none have been performed yet +/** + * Return the status of the last transfer or E_SUCCESS + * if none have been performed yet + * + * @return success + */ error_t vfs_mngr_get_transfer_status(void); /* Use functions */ -// Build the filesystem by calling vfs_init and then adding files with vfs_create_file +/** + * Build the filesystem by calling vfs_init and then adding files with vfs_create_file + */ void vfs_user_build_filesystem(void); -// Called when a file on the filesystem changes -void vfs_user_file_change_handler(const vfs_filename_t filename, vfs_file_change_t change, vfs_file_t file, vfs_file_t new_file_data); +/** + * Called when a file on the filesystem changes + * + * @param filename - name of the changed file + * @param change - type of change + * @param file - data pointer (?) + * @param new_file_data - new data pointer (?) + */ +void vfs_user_file_change_handler(const vfs_filename_t filename, + vfs_file_change_t change, + vfs_file_t file, vfs_file_t new_file_data); -// Called when VFS is disconnecting +/** + * Called when VFS is disconnecting + */ void vfs_user_disconnecting(void); - - // --- interface --- + +/** + * Initialize, call form the MSC init callback + */ void vfs_if_usbd_msc_init(void); + +/** + * MSC wants to read a sector + * + * @param sector - first sector number + * @param buf - destination + * @param num_of_sectors - length + */ void vfs_if_usbd_msc_read_sect(uint32_t sector, uint8_t *buf, uint32_t num_of_sectors); -void vfs_if_usbd_msc_write_sect(uint32_t sector, uint8_t *buf, uint32_t num_of_sectors); + +/** + * MSC wants to write a sector + * + * @param sector - first sector number + * @param buf - data + * @param num_of_sectors - length + */ +void vfs_if_usbd_msc_write_sect(uint32_t sector, const uint8_t *buf, uint32_t num_of_sectors); typedef struct { uint32_t MemorySize; uint16_t BlockSize; - uint32_t BlockGroup; // LUN? + uint32_t BlockGroup; // LUN uint32_t BlockCount; -// uint8_t *BlockBuf; // apparently unused :thaenkin: bool MediaReady; bool MediaChanged; } vfs_info_t; +/** VFS info struct - some are used by SCSI/MSC */ extern volatile vfs_info_t vfs_info; #ifdef __cplusplus diff --git a/vfs/vfs_user.c b/vfs/vfs_user.c index 653225c..cad2cee 100644 --- a/vfs/vfs_user.c +++ b/vfs/vfs_user.c @@ -1,3 +1,7 @@ +// +// Here are defined the files and handlers +// + /** * @file vfs_user.c * @brief Implementation of vfs_user.h @@ -27,6 +31,7 @@ const vfs_filename_t daplink_drive_name = VFS_DRIVE_NAME; + static uint32_t read_iw_sector(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors, void (*handler)(IniWriter *)) { const uint32_t avail = num_sectors*VFS_SECTOR_SIZE; @@ -38,6 +43,7 @@ static uint32_t read_iw_sector(uint32_t sector_offset, uint8_t *data, uint32_t n return avail - iw.count; } + // File callback to be used with vfs_add_file to return file contents static uint32_t read_file_units_ini(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors) { @@ -45,18 +51,21 @@ static uint32_t read_file_units_ini(uint32_t sector_offset, uint8_t *data, uint3 return read_iw_sector(sector_offset, data, num_sectors, settings_build_units_ini); } + static uint32_t read_file_system_ini(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors) { vfs_printf("Read SYSTEM.INI"); return read_iw_sector(sector_offset, data, num_sectors, settings_build_system_ini); } + static uint32_t read_file_pinout_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors) { vfs_printf("Read PINOUT.TXT"); return read_iw_sector(sector_offset, data, num_sectors, settings_build_pinout_txt); } + void vfs_user_build_filesystem(void) { dbg("Rebuilding VFS..."); @@ -69,6 +78,7 @@ void vfs_user_build_filesystem(void) vfs_create_file("PINOUT TXT", read_file_pinout_txt, NULL, iw_measure_total(settings_build_pinout_txt)); } + // Callback to handle changes to the root directory. Should be used with vfs_set_file_change_callback void vfs_user_file_change_handler(const vfs_filename_t filename, vfs_file_change_t change, @@ -98,6 +108,7 @@ void vfs_user_file_change_handler(const vfs_filename_t filename, } } + void vfs_user_disconnecting(void) { // maybe reset... diff --git a/vfs/virtual_fs.h b/vfs/virtual_fs.h index 5b75b41..e0066e7 100644 --- a/vfs/virtual_fs.h +++ b/vfs/virtual_fs.h @@ -1,3 +1,8 @@ +// +// The guts of the virtual FAT16 are implemented here. +// This is taken from DAPLink and some memory-wasting bits are commented out or removed. +// + /** * @file virtual_fs.h * @brief FAT 12/16 filesystem handling @@ -28,6 +33,7 @@ extern "C" { #endif +// Toggleable debug funcs #if DEBUG_VFS #define vfs_printf(...) do { dbg(__VA_ARGS__); } while(0) #define vfs_printf_nonl(...) do { PRINTF(__VA_ARGS__); } while(0) @@ -48,6 +54,7 @@ extern "C" { #define VFS_MAX_FILES 16 #define VFS_DISK_SIZE MB(32) +/** Filename typedef */ typedef char vfs_filename_t[11]; typedef enum { @@ -69,51 +76,116 @@ typedef enum { notification will also occur*/ } vfs_file_change_t; +/** File typedef */ typedef void *vfs_file_t; + +/** Sector struct typedef */ typedef uint32_t vfs_sector_t; -// Callback for when data is written to a file on the virtual filesystem +/** + * Callback for when data is written to a file on the virtual filesystem + */ typedef void (*vfs_write_cb_t)(uint32_t sector_offset, const uint8_t *data, uint32_t num_sectors); -// Callback for when data is ready from the virtual filesystem + +/** + * Callback for when data is ready from the virtual filesystem + */ typedef uint32_t (*vfs_read_cb_t)(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors); -// Callback for when a file's attributes are changed on the virtual filesystem. Note that the 'file' parameter -// can be saved and compared to other files to see if they are referencing the same object. The -// same cannot be done with new_file_data since it points to a temporary buffer. + +/** + * Callback for when a file's attributes are changed on the virtual filesystem. + * Note that the 'file' parameter can be saved and compared to other files to see if + * they are referencing the same object. The same cannot be done with new_file_data + * since it points to a temporary buffer. + */ typedef void (*vfs_file_change_cb_t)(const vfs_filename_t filename, vfs_file_change_t change, vfs_file_t file, vfs_file_t new_file_data); -// Initialize the filesystem with the given size and name +/** + * Initialize the filesystem with the given size and name + * + * @param drive_name + * @param disk_size + */ void vfs_init(const vfs_filename_t drive_name, uint32_t disk_size); -// Get the total size of the virtual filesystem +/** + * Get the total size of the virtual filesystem + */ uint32_t vfs_get_total_size(void); -// Add a file to the virtual FS and return a handle to this file. -// This must be called before vfs_read or vfs_write are called. -// Adding a new file after vfs_read or vfs_write have been called results in undefined behavior. -vfs_file_t vfs_create_file(const vfs_filename_t filename, vfs_read_cb_t read_cb, vfs_write_cb_t write_cb, uint32_t len); +/** + * Add a file to the virtual FS and return a handle to this file. + * This must be called before vfs_read or vfs_write are called. + * Adding a new file after vfs_read or vfs_write have been called results in undefined behavior. + * + * @param filename + * @param read_cb + * @param write_cb + * @param len + * @return + */ +vfs_file_t vfs_create_file(const vfs_filename_t filename, + vfs_read_cb_t read_cb, vfs_write_cb_t write_cb, + uint32_t len); -// Set the attributes of a file +/** + * Set the attributes of a file + * + * @param file + * @param attr + */ void vfs_file_set_attr(vfs_file_t file, vfs_file_attr_bit_t attr); -// Get the starting sector of this file. -// NOTE - If the file size is 0 there is no starting -// sector so VFS_INVALID_SECTOR will be returned. +/** + * Get the starting sector of this file. + * NOTE - If the file size is 0 there is no starting + * sector so VFS_INVALID_SECTOR will be returned. + * + * @param file + * @return + */ vfs_sector_t vfs_file_get_start_sector(vfs_file_t file); -// Get the size of the file. +/** + * Get the size of the file. + * + * @param file + * @return + */ uint32_t vfs_file_get_size(vfs_file_t file); -// Get the attributes of a file +/** + * Get the attributes of a file + * + * @param file + * @return + */ vfs_file_attr_bit_t vfs_file_get_attr(vfs_file_t file); -// Set the callback when a file is created, deleted or has atributes changed. +/** + * Set the callback when a file is created, deleted or has atributes changed. + * + * @param cb + */ void vfs_set_file_change_callback(vfs_file_change_cb_t cb); -// Read one or more sectors from the virtual filesystem +/** + * Read one or more sectors from the virtual filesystem + * + * @param sector + * @param buf + * @param num_of_sectors + */ void vfs_read(uint32_t sector, uint8_t *buf, uint32_t num_of_sectors); -// Write one or more sectors to the virtual filesystem +/** + * Write one or more sectors to the virtual filesystem + * + * @param sector + * @param buf + * @param num_of_sectors + */ void vfs_write(uint32_t sector, const uint8_t *buf, uint32_t num_of_sectors); bool vfs_find_file(uint32_t start_sector, vfs_filename_t *destFilename, vfs_file_t **destFile);