diff --git a/conf/modules/logger_sd_chibios.xml b/conf/modules/logger_sd_chibios.xml
index c3fc119d3e..3bb2595682 100644
--- a/conf/modules/logger_sd_chibios.xml
+++ b/conf/modules/logger_sd_chibios.xml
@@ -9,6 +9,10 @@
Files are written on a FAT file system using the FatFS library and can be accessed
by using the autopilot as a mass storage (plug USB while the board is running).
+
+
+
+
tlsf
+
+
diff --git a/conf/telemetry/fixedwing_flight_recorder.xml b/conf/telemetry/fixedwing_flight_recorder.xml
index cbd7da7005..3209f2bc1d 100644
--- a/conf/telemetry/fixedwing_flight_recorder.xml
+++ b/conf/telemetry/fixedwing_flight_recorder.xml
@@ -35,6 +35,7 @@
+
diff --git a/sw/airborne/arch/chibios/mcu_periph/ram_arch.h b/sw/airborne/arch/chibios/mcu_periph/ram_arch.h
index 04f3d56500..f3dc976c5d 100644
--- a/sw/airborne/arch/chibios/mcu_periph/ram_arch.h
+++ b/sw/airborne/arch/chibios/mcu_periph/ram_arch.h
@@ -54,9 +54,17 @@
#error "section defined only for STM32F1, STM32F4 and STM32F7"
#endif
-#define IN_STD_SECTION(var) var __attribute__ ((section(STD_SECTION), aligned(8)))
-#define IN_FAST_SECTION(var) var __attribute__ ((section(FAST_SECTION), aligned(8)))
-#define IN_DMA_SECTION(var) var __attribute__ ((section(DMA_SECTION), aligned(8)))
+#define IN_STD_SECTION_NOINIT(var) var __attribute__ ((section(STD_SECTION), aligned(8)))
+#define IN_STD_SECTION_CLEAR(var) var __attribute__ ((section(STD_SECTION "_clear"), aligned(8)))
+#define IN_STD_SECTION(var) var __attribute__ ((section(STD_SECTION "_init"), aligned(8)))
+
+#define IN_FAST_SECTION_NOINIT(var) var __attribute__ ((section(FAST_SECTION), aligned(8)))
+#define IN_FAST_SECTION_CLEAR(var) var __attribute__ ((section(FAST_SECTION "_clear"), aligned(8)))
+#define IN_FAST_SECTION(var) var __attribute__ ((section(FAST_SECTION "_init"), aligned(8)))
+
+#define IN_DMA_SECTION_NOINIT(var) var __attribute__ ((section(DMA_SECTION), aligned(8)))
+#define IN_DMA_SECTION_CLEAR(var) var __attribute__ ((section(DMA_SECTION "_clear"), aligned(8)))
+#define IN_DMA_SECTION(var) var __attribute__ ((section(DMA_SECTION "_init"), aligned(8)))
#endif
diff --git a/sw/airborne/boards/apogee/chibios/v1.0/ffconf.h b/sw/airborne/boards/apogee/chibios/v1.0/ffconf.h
index cd1c5cca30..f7c786cab2 100644
--- a/sw/airborne/boards/apogee/chibios/v1.0/ffconf.h
+++ b/sw/airborne/boards/apogee/chibios/v1.0/ffconf.h
@@ -2,176 +2,196 @@
#include "ch.h"
/*---------------------------------------------------------------------------/
-/ FatFs - FAT file system module configuration file R0.10b (C)ChaN, 2014
+/ FatFs - FAT file system module configuration file
/---------------------------------------------------------------------------*/
-#ifndef _FFCONF
-#define _FFCONF 8051 /* Revision ID */
-
+#define _FFCONF 68020 /* Revision ID */
/*---------------------------------------------------------------------------/
-/ Functions and Buffer Configurations
+/ Function Configurations
/---------------------------------------------------------------------------*/
-#define _FS_TINY 0 /* 0:Normal or 1:Tiny */
-/* When _FS_TINY is set to 1, it reduces memory consumption _MAX_SS bytes each
-/ file object. For file data transfer, FatFs uses the common sector buffer in
-/ the file system object (FATFS) instead of private sector buffer eliminated
-/ from the file object (FIL). */
+#define _FS_READONLY 0
+/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
+/ Read-only configuration removes writing API functions, f_write(), f_sync(),
+/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
+/ and optional writing functions as well. */
-#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */
-/* Setting _FS_READONLY to 1 defines read only configuration. This removes
-/ writing functions, f_write(), f_sync(), f_unlink(), f_mkdir(), f_chmod(),
-/ f_rename(), f_truncate() and useless f_getfree(). */
-
-
-#define _FS_MINIMIZE 0 /* 0 to 3 */
-/* The _FS_MINIMIZE option defines minimization level to remove API functions.
+#define _FS_MINIMIZE 0
+/* This option defines minimization level to remove some basic API functions.
/
/ 0: All basic functions are enabled.
-/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_chmod(), f_utime(),
-/ f_truncate() and f_rename() function are removed.
+/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
+/ are removed.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
-#define _USE_STRFUNC 2 /* 0:Disable or 1-2:Enable */
-/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
+#define _USE_STRFUNC 0
+/* This option switches string functions, f_gets(), f_putc(), f_puts() and
+/ f_printf().
+/
+/ 0: Disable string functions.
+/ 1: Enable without LF-CRLF conversion.
+/ 2: Enable with LF-CRLF conversion. */
-#define _USE_MKFS 1 /* 0:Disable or 1:Enable */
-/* To enable f_mkfs() function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
+#define _USE_FIND 1
+/* This option switches filtered directory read functions, f_findfirst() and
+/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
-#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */
-/* To enable fast seek feature, set _USE_FASTSEEK to 1. */
+#define _USE_MKFS 1
+/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
-#define _USE_LABEL 0 /* 0:Disable or 1:Enable */
-/* To enable volume label functions, set _USE_LAVEL to 1 */
+#define _USE_FASTSEEK 1
+/* This option switches fast seek function. (0:Disable or 1:Enable) */
-#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */
-/* To enable f_forward() function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
+#define _USE_EXPAND 1
+/* This option switches f_expand function. (0:Disable or 1:Enable) */
+
+
+#define _USE_CHMOD 1
+/* This option switches attribute manipulation functions, f_chmod() and f_utime().
+/ (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */
+
+
+#define _USE_LABEL 1
+/* This option switches volume label functions, f_getlabel() and f_setlabel().
+/ (0:Disable or 1:Enable) */
+
+
+#define _USE_FORWARD 1
+/* This option switches f_forward() function. (0:Disable or 1:Enable) */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
-#define _CODE_PAGE 1252
-/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
+#define _CODE_PAGE 850
+/* This option specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
-/ 932 - Japanese Shift_JIS (DBCS, OEM, Windows)
-/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
-/ 949 - Korean (DBCS, OEM, Windows)
-/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
-/ 1250 - Central Europe (Windows)
-/ 1251 - Cyrillic (Windows)
-/ 1252 - Latin 1 (Windows)
-/ 1253 - Greek (Windows)
-/ 1254 - Turkish (Windows)
-/ 1255 - Hebrew (Windows)
-/ 1256 - Arabic (Windows)
-/ 1257 - Baltic (Windows)
-/ 1258 - Vietnam (OEM, Windows)
-/ 437 - U.S. (OEM)
-/ 720 - Arabic (OEM)
-/ 737 - Greek (OEM)
-/ 775 - Baltic (OEM)
-/ 850 - Multilingual Latin 1 (OEM)
-/ 858 - Multilingual Latin 1 + Euro (OEM)
-/ 852 - Latin 2 (OEM)
-/ 855 - Cyrillic (OEM)
-/ 866 - Russian (OEM)
-/ 857 - Turkish (OEM)
-/ 862 - Hebrew (OEM)
-/ 874 - Thai (OEM, Windows)
-/ 1 - ASCII (Valid for only non-LFN configuration) */
+/ 1 - ASCII (No extended character. Non-LFN cfg. only)
+/ 437 - U.S.
+/ 720 - Arabic
+/ 737 - Greek
+/ 771 - KBL
+/ 775 - Baltic
+/ 850 - Latin 1
+/ 852 - Latin 2
+/ 855 - Cyrillic
+/ 857 - Turkish
+/ 860 - Portuguese
+/ 861 - Icelandic
+/ 862 - Hebrew
+/ 863 - Canadian French
+/ 864 - Arabic
+/ 865 - Nordic
+/ 866 - Russian
+/ 869 - Greek 2
+/ 932 - Japanese (DBCS)
+/ 936 - Simplified Chinese (DBCS)
+/ 949 - Korean (DBCS)
+/ 950 - Traditional Chinese (DBCS)
+*/
-#define _USE_LFN 2 /* 0 to 3 */
-#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
-/* The _USE_LFN option switches the LFN feature.
+#define _USE_LFN 3
+#define _MAX_LFN 255
+/* The _USE_LFN switches the support of long file name (LFN).
/
-/ 0: Disable LFN feature. _MAX_LFN has no effect.
+/ 0: Disable support of LFN. _MAX_LFN has no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
-/ When enable LFN feature, Unicode handling functions ff_convert() and ff_wtoupper()
-/ function must be added to the project.
-/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. When use stack for the
-/ working buffer, take care on stack overflow. When use heap memory for the working
-/ buffer, memory management functions, ff_memalloc() and ff_memfree(), must be added
-/ to the project. */
+/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added
+/ to the project. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and
+/ additional 608 bytes at exFAT enabled. _MAX_LFN can be in range from 12 to 255.
+/ It should be set 255 to support full featured LFN operations.
+/ When use stack for the working buffer, take care on stack overflow. When use heap
+/ memory for the working buffer, memory management functions, ff_memalloc() and
+/ ff_memfree(), must be added to the project. */
-#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */
-/* To switch the character encoding on the FatFs API (TCHAR) to Unicode, enable LFN
-/ feature and set _LFN_UNICODE to 1. This option affects behavior of string I/O
-/ functions. This option must be 0 when LFN feature is not enabled. */
+#define _LFN_UNICODE 0
+/* This option switches character encoding on the API. (0:ANSI/OEM or 1:UTF-16)
+/ To use Unicode string for the path name, enable LFN and set _LFN_UNICODE = 1.
+/ This option also affects behavior of string I/O functions. */
-#define _STRF_ENCODE 3 /* 0:ANSI/OEM, 1:UTF-16LE, 2:UTF-16BE, 3:UTF-8 */
-/* When Unicode API is enabled by _LFN_UNICODE option, this option selects the character
-/ encoding on the file to be read/written via string I/O functions, f_gets(), f_putc(),
-/ f_puts and f_printf(). This option has no effect when Unicode API is not enabled. */
-
-
-#define _FS_RPATH 2 /* 0 to 2 */
-/* The _FS_RPATH option configures relative path feature.
+#define _STRF_ENCODE 3
+/* When _LFN_UNICODE == 1, this option selects the character encoding ON THE FILE to
+/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
/
-/ 0: Disable relative path feature and remove related functions.
-/ 1: Enable relative path. f_chdrive() and f_chdir() function are available.
+/ 0: ANSI/OEM
+/ 1: UTF-16LE
+/ 2: UTF-16BE
+/ 3: UTF-8
+/
+/ This option has no effect when _LFN_UNICODE == 0. */
+
+
+#define _FS_RPATH 1
+/* This option configures support of relative path.
+/
+/ 0: Disable relative path and remove related functions.
+/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
/ 2: f_getcwd() function is available in addition to 1.
-/
-/ Note that output of the f_readdir() fnction is affected by this option. */
+*/
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
-#define _VOLUMES 1
+#define _VOLUMES 1
/* Number of volumes (logical drives) to be used. */
-#define _STR_VOLUME_ID 0 /* 0:Use only 0-9 for drive ID, 1:Use strings for drive ID */
-#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
-/* When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
-/ number in the path name. _VOLUME_STRS defines the drive ID strings for each logical
-/ drives. Number of items must be equal to _VOLUMES. Valid characters for the drive ID
-/ strings are: 0-9 and A-Z. */
+#define _STR_VOLUME_ID 0
+#define _VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
+/* _STR_VOLUME_ID switches string support of volume ID.
+/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
+/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
+/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
+/ the drive ID strings are: A-Z and 0-9. */
-#define _MULTI_PARTITION 0 /* 0:Single partition, 1:Enable multiple partition */
-/* By default(0), each logical drive number is bound to the same physical drive number
-/ and only a FAT volume found on the physical drive is mounted. When it is set to 1,
-/ each logical drive number is bound to arbitrary drive/partition listed in VolToPart[].
-*/
+#define _MULTI_PARTITION 0
+/* This option switches support of multi-partition on a physical drive.
+/ By default (0), each logical drive number is bound to the same physical drive
+/ number and only an FAT volume found on the physical drive will be mounted.
+/ When multi-partition is enabled (1), each logical drive number can be bound to
+/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
+/ funciton will be available. */
-#define _MIN_SS 512
-#define _MAX_SS 512
-/* These options configure the range of sector size to be supported. (512, 1024, 2048 or
-/ 4096) Always set both 512 for most systems, all memory card and harddisk. But a larger
-/ value may be required for on-board flash memory and some type of optical media.
-/ When _MAX_SS is larger than _MIN_SS, FatFs is configured to variable sector size and
-/ GET_SECTOR_SIZE command must be implemented to the disk_ioctl() function. */
+#define _MIN_SS 512
+#define _MAX_SS 512
+/* These options configure the range of sector size to be supported. (512, 1024,
+/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
+/ harddisk. But a larger value may be required for on-board flash memory and some
+/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
+/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
+/ disk_ioctl() function. */
-#define _USE_ERASE 1 /* 0:Disable or 1:Enable */
-/* To enable sector erase feature, set _USE_ERASE to 1. Also CTRL_ERASE_SECTOR command
-/ should be added to the disk_ioctl() function. */
+#define _USE_TRIM 0
+/* This option switches support of ATA-TRIM. (0:Disable or 1:Enable)
+/ To enable Trim function, also CTRL_TRIM command should be implemented to the
+/ disk_ioctl() function. */
-#define _FS_NOFSINFO 0 /* 0 to 3 */
-/* If you need to know correct free space on the FAT32 volume, set bit 0 of this option
-/ and f_getfree() function at first time after volume mount will force a full FAT scan.
-/ Bit 1 controls the last allocated cluster number as bit 0.
+#define _FS_NOFSINFO 0
+/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
+/ option, and f_getfree() function at first time after volume mount will force
+/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
/ bit0=1: Do not trust free cluster count in the FSINFO.
@@ -185,55 +205,66 @@
/ System Configurations
/---------------------------------------------------------------------------*/
-#define _FS_REENTRANT 1 /* 0:Disable or 1:Enable */
-#define _FS_TIMEOUT MS2ST(1000) /* Timeout period in unit of time tick */
-#define _SYNC_t semaphore_t* /* O/S dependent sync object type. e.g. HANDLE, OS_EVENT*, ID, SemaphoreHandle_t and etc.. */
-/* The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs module.
+#define _FS_TINY 0
+/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
+/ At the tiny configuration, size of file object (FIL) is reduced _MAX_SS bytes.
+/ Instead of private sector buffer eliminated from the file object, common sector
+/ buffer in the file system object (FATFS) is used for the file data transfer. */
+
+
+#define _FS_EXFAT 1
+/* This option switches support of exFAT file system. (0:Disable or 1:Enable)
+/ When enable exFAT, also LFN needs to be enabled. (_USE_LFN >= 1)
+/ Note that enabling exFAT discards C89 compatibility. */
+
+
+#define _FS_NORTC 0
+#define _NORTC_MON 1
+#define _NORTC_MDAY 1
+#define _NORTC_YEAR 2016
+/* The option _FS_NORTC switches timestamp functiton. If the system does not have
+/ any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable
+/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
+/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time.
+/ To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be
+/ added to the project to get current time form real-time clock. _NORTC_MON,
+/ _NORTC_MDAY and _NORTC_YEAR have no effect.
+/ These options have no effect at read-only configuration (_FS_READONLY = 1). */
+
+
+#define _FS_LOCK 0
+/* The option _FS_LOCK switches file lock function to control duplicated file open
+/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
+/ is 1.
+/
+/ 0: Disable file lock function. To avoid volume corruption, application program
+/ should avoid illegal open, remove and rename to the open objects.
+/ >0: Enable file lock function. The value defines how many files/sub-directories
+/ can be opened simultaneously under file lock control. Note that the file
+/ lock control is independent of re-entrancy. */
+
+
+#define _FS_REENTRANT 1
+#define _FS_TIMEOUT MS2ST(1000)
+#define _SYNC_t semaphore_t*
+/* The option _FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
+/ module itself. Note that regardless of this option, file access to different
+/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
+/ and f_fdisk() function, are always not re-entrant. Only file/directory access
+/ to the same volume is under control of this function.
/
/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
-/ function must be added to the project.
-*/
-
-
-#define _WORD_ACCESS 1 /* 0 or 1 */
-/* The _WORD_ACCESS option is an only platform dependent option. It defines
-/ which access method is used to the word data on the FAT volume.
+/ function, must be added to the project. Samples are available in
+/ option/syscall.c.
/
-/ 0: Byte-by-byte access. Always compatible with all platforms.
-/ 1: Word access. Do not choose this unless under both the following conditions.
-/
-/ * Address misaligned memory access is always allowed for ALL instructions.
-/ * Byte order on the memory is little-endian.
-/
-/ If it is the case, _WORD_ACCESS can also be set to 1 to improve performance and
-/ reduce code size. Following table shows an example of some processor types.
-/
-/ ARM7TDMI 0 ColdFire 0 V850E2 0
-/ Cortex-M3 0 Z80 0/1 V850ES 0/1
-/ Cortex-M0 0 RX600(LE) 0/1 TLCS-870 0/1
-/ AVR 0/1 RX600(BE) 0 TLCS-900 0/1
-/ AVR32 0 RL78 0 R32C 0
-/ PIC18 0/1 SH-2 0 M16C 0/1
-/ PIC24 0 H8S 0 MSP430 0
-/ PIC32 0 H8/300H 0 x86 0/1
-*/
+/ The _FS_TIMEOUT defines timeout period in unit of time tick.
+/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
+/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
+/ included somewhere in the scope of ff.h. */
+
+/* #include // O/S definitions */
-
-
-#define _FS_LOCK 0 /* 0:Disable or >=1:Enable */
-/* To enable file lock control feature, set _FS_LOCK to non-zero value.
-/ The value defines how many files/sub-directories can be opened simultaneously
-/ with file lock control. This feature uses bss _FS_LOCK * 12 bytes.
-/
-/ IMPORTANT NOTE:
-/ For Paparazzi, we don't need file locking since all file are written sequentially
-/ from one thread (thdSdLog)
-/
-*/
-
-
-
-#endif /* _FFCONF */
+/*--- End of configuration options ---*/
diff --git a/sw/airborne/boards/apogee/chibios/v1.0/mcuconf.h b/sw/airborne/boards/apogee/chibios/v1.0/mcuconf.h
index a3b7ad8acb..3f2e1a001a 100644
--- a/sw/airborne/boards/apogee/chibios/v1.0/mcuconf.h
+++ b/sw/airborne/boards/apogee/chibios/v1.0/mcuconf.h
@@ -379,14 +379,17 @@
#define STM32_SDC_SDIO_UNALIGNED_SUPPORT FALSE
#define STM32_SDC_WRITE_TIMEOUT_MS 250
#define STM32_SDC_READ_TIMEOUT_MS 15
-#define SDLOG_ALL_BUFFERS_SIZE 8192
-#define SDLOG_MAX_MESSAGE_LEN 252
-#define SDLOG_QUEUE_BUCKETS 1024
+
/*
- * workaround hardware bug in REV.A revision of old STM32F4 (sold in 2012, early 2013)
+ sdlog message buffer and queue configuration
*/
+#define SDLOG_QUEUE_BUCKETS 1024
+#define SDLOG_MAX_MESSAGE_LEN 252
+#define SDLOG_NUM_FILES 2
+#define SDLOG_ALL_BUFFERS_SIZE (SDLOG_NUM_FILES*4096)
+
+
-#define STM32_USE_REVISION_A_FIX 1
#endif /* _MCUCONF_H_ */
diff --git a/sw/airborne/boards/chimera/chibios/v1.0/ffconf.h b/sw/airborne/boards/chimera/chibios/v1.0/ffconf.h
index cd1c5cca30..f7c786cab2 100644
--- a/sw/airborne/boards/chimera/chibios/v1.0/ffconf.h
+++ b/sw/airborne/boards/chimera/chibios/v1.0/ffconf.h
@@ -2,176 +2,196 @@
#include "ch.h"
/*---------------------------------------------------------------------------/
-/ FatFs - FAT file system module configuration file R0.10b (C)ChaN, 2014
+/ FatFs - FAT file system module configuration file
/---------------------------------------------------------------------------*/
-#ifndef _FFCONF
-#define _FFCONF 8051 /* Revision ID */
-
+#define _FFCONF 68020 /* Revision ID */
/*---------------------------------------------------------------------------/
-/ Functions and Buffer Configurations
+/ Function Configurations
/---------------------------------------------------------------------------*/
-#define _FS_TINY 0 /* 0:Normal or 1:Tiny */
-/* When _FS_TINY is set to 1, it reduces memory consumption _MAX_SS bytes each
-/ file object. For file data transfer, FatFs uses the common sector buffer in
-/ the file system object (FATFS) instead of private sector buffer eliminated
-/ from the file object (FIL). */
+#define _FS_READONLY 0
+/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
+/ Read-only configuration removes writing API functions, f_write(), f_sync(),
+/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
+/ and optional writing functions as well. */
-#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */
-/* Setting _FS_READONLY to 1 defines read only configuration. This removes
-/ writing functions, f_write(), f_sync(), f_unlink(), f_mkdir(), f_chmod(),
-/ f_rename(), f_truncate() and useless f_getfree(). */
-
-
-#define _FS_MINIMIZE 0 /* 0 to 3 */
-/* The _FS_MINIMIZE option defines minimization level to remove API functions.
+#define _FS_MINIMIZE 0
+/* This option defines minimization level to remove some basic API functions.
/
/ 0: All basic functions are enabled.
-/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_chmod(), f_utime(),
-/ f_truncate() and f_rename() function are removed.
+/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
+/ are removed.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
-#define _USE_STRFUNC 2 /* 0:Disable or 1-2:Enable */
-/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
+#define _USE_STRFUNC 0
+/* This option switches string functions, f_gets(), f_putc(), f_puts() and
+/ f_printf().
+/
+/ 0: Disable string functions.
+/ 1: Enable without LF-CRLF conversion.
+/ 2: Enable with LF-CRLF conversion. */
-#define _USE_MKFS 1 /* 0:Disable or 1:Enable */
-/* To enable f_mkfs() function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
+#define _USE_FIND 1
+/* This option switches filtered directory read functions, f_findfirst() and
+/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
-#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */
-/* To enable fast seek feature, set _USE_FASTSEEK to 1. */
+#define _USE_MKFS 1
+/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
-#define _USE_LABEL 0 /* 0:Disable or 1:Enable */
-/* To enable volume label functions, set _USE_LAVEL to 1 */
+#define _USE_FASTSEEK 1
+/* This option switches fast seek function. (0:Disable or 1:Enable) */
-#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */
-/* To enable f_forward() function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
+#define _USE_EXPAND 1
+/* This option switches f_expand function. (0:Disable or 1:Enable) */
+
+
+#define _USE_CHMOD 1
+/* This option switches attribute manipulation functions, f_chmod() and f_utime().
+/ (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */
+
+
+#define _USE_LABEL 1
+/* This option switches volume label functions, f_getlabel() and f_setlabel().
+/ (0:Disable or 1:Enable) */
+
+
+#define _USE_FORWARD 1
+/* This option switches f_forward() function. (0:Disable or 1:Enable) */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
-#define _CODE_PAGE 1252
-/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
+#define _CODE_PAGE 850
+/* This option specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
-/ 932 - Japanese Shift_JIS (DBCS, OEM, Windows)
-/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
-/ 949 - Korean (DBCS, OEM, Windows)
-/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
-/ 1250 - Central Europe (Windows)
-/ 1251 - Cyrillic (Windows)
-/ 1252 - Latin 1 (Windows)
-/ 1253 - Greek (Windows)
-/ 1254 - Turkish (Windows)
-/ 1255 - Hebrew (Windows)
-/ 1256 - Arabic (Windows)
-/ 1257 - Baltic (Windows)
-/ 1258 - Vietnam (OEM, Windows)
-/ 437 - U.S. (OEM)
-/ 720 - Arabic (OEM)
-/ 737 - Greek (OEM)
-/ 775 - Baltic (OEM)
-/ 850 - Multilingual Latin 1 (OEM)
-/ 858 - Multilingual Latin 1 + Euro (OEM)
-/ 852 - Latin 2 (OEM)
-/ 855 - Cyrillic (OEM)
-/ 866 - Russian (OEM)
-/ 857 - Turkish (OEM)
-/ 862 - Hebrew (OEM)
-/ 874 - Thai (OEM, Windows)
-/ 1 - ASCII (Valid for only non-LFN configuration) */
+/ 1 - ASCII (No extended character. Non-LFN cfg. only)
+/ 437 - U.S.
+/ 720 - Arabic
+/ 737 - Greek
+/ 771 - KBL
+/ 775 - Baltic
+/ 850 - Latin 1
+/ 852 - Latin 2
+/ 855 - Cyrillic
+/ 857 - Turkish
+/ 860 - Portuguese
+/ 861 - Icelandic
+/ 862 - Hebrew
+/ 863 - Canadian French
+/ 864 - Arabic
+/ 865 - Nordic
+/ 866 - Russian
+/ 869 - Greek 2
+/ 932 - Japanese (DBCS)
+/ 936 - Simplified Chinese (DBCS)
+/ 949 - Korean (DBCS)
+/ 950 - Traditional Chinese (DBCS)
+*/
-#define _USE_LFN 2 /* 0 to 3 */
-#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
-/* The _USE_LFN option switches the LFN feature.
+#define _USE_LFN 3
+#define _MAX_LFN 255
+/* The _USE_LFN switches the support of long file name (LFN).
/
-/ 0: Disable LFN feature. _MAX_LFN has no effect.
+/ 0: Disable support of LFN. _MAX_LFN has no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
-/ When enable LFN feature, Unicode handling functions ff_convert() and ff_wtoupper()
-/ function must be added to the project.
-/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. When use stack for the
-/ working buffer, take care on stack overflow. When use heap memory for the working
-/ buffer, memory management functions, ff_memalloc() and ff_memfree(), must be added
-/ to the project. */
+/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added
+/ to the project. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and
+/ additional 608 bytes at exFAT enabled. _MAX_LFN can be in range from 12 to 255.
+/ It should be set 255 to support full featured LFN operations.
+/ When use stack for the working buffer, take care on stack overflow. When use heap
+/ memory for the working buffer, memory management functions, ff_memalloc() and
+/ ff_memfree(), must be added to the project. */
-#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */
-/* To switch the character encoding on the FatFs API (TCHAR) to Unicode, enable LFN
-/ feature and set _LFN_UNICODE to 1. This option affects behavior of string I/O
-/ functions. This option must be 0 when LFN feature is not enabled. */
+#define _LFN_UNICODE 0
+/* This option switches character encoding on the API. (0:ANSI/OEM or 1:UTF-16)
+/ To use Unicode string for the path name, enable LFN and set _LFN_UNICODE = 1.
+/ This option also affects behavior of string I/O functions. */
-#define _STRF_ENCODE 3 /* 0:ANSI/OEM, 1:UTF-16LE, 2:UTF-16BE, 3:UTF-8 */
-/* When Unicode API is enabled by _LFN_UNICODE option, this option selects the character
-/ encoding on the file to be read/written via string I/O functions, f_gets(), f_putc(),
-/ f_puts and f_printf(). This option has no effect when Unicode API is not enabled. */
-
-
-#define _FS_RPATH 2 /* 0 to 2 */
-/* The _FS_RPATH option configures relative path feature.
+#define _STRF_ENCODE 3
+/* When _LFN_UNICODE == 1, this option selects the character encoding ON THE FILE to
+/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
/
-/ 0: Disable relative path feature and remove related functions.
-/ 1: Enable relative path. f_chdrive() and f_chdir() function are available.
+/ 0: ANSI/OEM
+/ 1: UTF-16LE
+/ 2: UTF-16BE
+/ 3: UTF-8
+/
+/ This option has no effect when _LFN_UNICODE == 0. */
+
+
+#define _FS_RPATH 1
+/* This option configures support of relative path.
+/
+/ 0: Disable relative path and remove related functions.
+/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
/ 2: f_getcwd() function is available in addition to 1.
-/
-/ Note that output of the f_readdir() fnction is affected by this option. */
+*/
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
-#define _VOLUMES 1
+#define _VOLUMES 1
/* Number of volumes (logical drives) to be used. */
-#define _STR_VOLUME_ID 0 /* 0:Use only 0-9 for drive ID, 1:Use strings for drive ID */
-#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
-/* When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
-/ number in the path name. _VOLUME_STRS defines the drive ID strings for each logical
-/ drives. Number of items must be equal to _VOLUMES. Valid characters for the drive ID
-/ strings are: 0-9 and A-Z. */
+#define _STR_VOLUME_ID 0
+#define _VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
+/* _STR_VOLUME_ID switches string support of volume ID.
+/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
+/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
+/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
+/ the drive ID strings are: A-Z and 0-9. */
-#define _MULTI_PARTITION 0 /* 0:Single partition, 1:Enable multiple partition */
-/* By default(0), each logical drive number is bound to the same physical drive number
-/ and only a FAT volume found on the physical drive is mounted. When it is set to 1,
-/ each logical drive number is bound to arbitrary drive/partition listed in VolToPart[].
-*/
+#define _MULTI_PARTITION 0
+/* This option switches support of multi-partition on a physical drive.
+/ By default (0), each logical drive number is bound to the same physical drive
+/ number and only an FAT volume found on the physical drive will be mounted.
+/ When multi-partition is enabled (1), each logical drive number can be bound to
+/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
+/ funciton will be available. */
-#define _MIN_SS 512
-#define _MAX_SS 512
-/* These options configure the range of sector size to be supported. (512, 1024, 2048 or
-/ 4096) Always set both 512 for most systems, all memory card and harddisk. But a larger
-/ value may be required for on-board flash memory and some type of optical media.
-/ When _MAX_SS is larger than _MIN_SS, FatFs is configured to variable sector size and
-/ GET_SECTOR_SIZE command must be implemented to the disk_ioctl() function. */
+#define _MIN_SS 512
+#define _MAX_SS 512
+/* These options configure the range of sector size to be supported. (512, 1024,
+/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
+/ harddisk. But a larger value may be required for on-board flash memory and some
+/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
+/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
+/ disk_ioctl() function. */
-#define _USE_ERASE 1 /* 0:Disable or 1:Enable */
-/* To enable sector erase feature, set _USE_ERASE to 1. Also CTRL_ERASE_SECTOR command
-/ should be added to the disk_ioctl() function. */
+#define _USE_TRIM 0
+/* This option switches support of ATA-TRIM. (0:Disable or 1:Enable)
+/ To enable Trim function, also CTRL_TRIM command should be implemented to the
+/ disk_ioctl() function. */
-#define _FS_NOFSINFO 0 /* 0 to 3 */
-/* If you need to know correct free space on the FAT32 volume, set bit 0 of this option
-/ and f_getfree() function at first time after volume mount will force a full FAT scan.
-/ Bit 1 controls the last allocated cluster number as bit 0.
+#define _FS_NOFSINFO 0
+/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
+/ option, and f_getfree() function at first time after volume mount will force
+/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
/ bit0=1: Do not trust free cluster count in the FSINFO.
@@ -185,55 +205,66 @@
/ System Configurations
/---------------------------------------------------------------------------*/
-#define _FS_REENTRANT 1 /* 0:Disable or 1:Enable */
-#define _FS_TIMEOUT MS2ST(1000) /* Timeout period in unit of time tick */
-#define _SYNC_t semaphore_t* /* O/S dependent sync object type. e.g. HANDLE, OS_EVENT*, ID, SemaphoreHandle_t and etc.. */
-/* The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs module.
+#define _FS_TINY 0
+/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
+/ At the tiny configuration, size of file object (FIL) is reduced _MAX_SS bytes.
+/ Instead of private sector buffer eliminated from the file object, common sector
+/ buffer in the file system object (FATFS) is used for the file data transfer. */
+
+
+#define _FS_EXFAT 1
+/* This option switches support of exFAT file system. (0:Disable or 1:Enable)
+/ When enable exFAT, also LFN needs to be enabled. (_USE_LFN >= 1)
+/ Note that enabling exFAT discards C89 compatibility. */
+
+
+#define _FS_NORTC 0
+#define _NORTC_MON 1
+#define _NORTC_MDAY 1
+#define _NORTC_YEAR 2016
+/* The option _FS_NORTC switches timestamp functiton. If the system does not have
+/ any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable
+/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
+/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time.
+/ To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be
+/ added to the project to get current time form real-time clock. _NORTC_MON,
+/ _NORTC_MDAY and _NORTC_YEAR have no effect.
+/ These options have no effect at read-only configuration (_FS_READONLY = 1). */
+
+
+#define _FS_LOCK 0
+/* The option _FS_LOCK switches file lock function to control duplicated file open
+/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
+/ is 1.
+/
+/ 0: Disable file lock function. To avoid volume corruption, application program
+/ should avoid illegal open, remove and rename to the open objects.
+/ >0: Enable file lock function. The value defines how many files/sub-directories
+/ can be opened simultaneously under file lock control. Note that the file
+/ lock control is independent of re-entrancy. */
+
+
+#define _FS_REENTRANT 1
+#define _FS_TIMEOUT MS2ST(1000)
+#define _SYNC_t semaphore_t*
+/* The option _FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
+/ module itself. Note that regardless of this option, file access to different
+/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
+/ and f_fdisk() function, are always not re-entrant. Only file/directory access
+/ to the same volume is under control of this function.
/
/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
-/ function must be added to the project.
-*/
-
-
-#define _WORD_ACCESS 1 /* 0 or 1 */
-/* The _WORD_ACCESS option is an only platform dependent option. It defines
-/ which access method is used to the word data on the FAT volume.
+/ function, must be added to the project. Samples are available in
+/ option/syscall.c.
/
-/ 0: Byte-by-byte access. Always compatible with all platforms.
-/ 1: Word access. Do not choose this unless under both the following conditions.
-/
-/ * Address misaligned memory access is always allowed for ALL instructions.
-/ * Byte order on the memory is little-endian.
-/
-/ If it is the case, _WORD_ACCESS can also be set to 1 to improve performance and
-/ reduce code size. Following table shows an example of some processor types.
-/
-/ ARM7TDMI 0 ColdFire 0 V850E2 0
-/ Cortex-M3 0 Z80 0/1 V850ES 0/1
-/ Cortex-M0 0 RX600(LE) 0/1 TLCS-870 0/1
-/ AVR 0/1 RX600(BE) 0 TLCS-900 0/1
-/ AVR32 0 RL78 0 R32C 0
-/ PIC18 0/1 SH-2 0 M16C 0/1
-/ PIC24 0 H8S 0 MSP430 0
-/ PIC32 0 H8/300H 0 x86 0/1
-*/
+/ The _FS_TIMEOUT defines timeout period in unit of time tick.
+/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
+/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
+/ included somewhere in the scope of ff.h. */
+
+/* #include // O/S definitions */
-
-
-#define _FS_LOCK 0 /* 0:Disable or >=1:Enable */
-/* To enable file lock control feature, set _FS_LOCK to non-zero value.
-/ The value defines how many files/sub-directories can be opened simultaneously
-/ with file lock control. This feature uses bss _FS_LOCK * 12 bytes.
-/
-/ IMPORTANT NOTE:
-/ For Paparazzi, we don't need file locking since all file are written sequentially
-/ from one thread (thdSdLog)
-/
-*/
-
-
-
-#endif /* _FFCONF */
+/*--- End of configuration options ---*/
diff --git a/sw/airborne/boards/chimera/chibios/v1.0/mcuconf.h b/sw/airborne/boards/chimera/chibios/v1.0/mcuconf.h
index d19af0de4f..804007fd78 100644
--- a/sw/airborne/boards/chimera/chibios/v1.0/mcuconf.h
+++ b/sw/airborne/boards/chimera/chibios/v1.0/mcuconf.h
@@ -452,11 +452,13 @@
#define STM32_SDC_SDMMC1_DMA_PRIORITY 3
#define STM32_SDC_SDMMC1_IRQ_PRIORITY 9
-/* sdlog message buffer and queue configuration
+/*
+ sdlog message buffer and queue configuration
*/
-#define SDLOG_QUEUE_BUCKETS 512
-#define SDLOG_ALL_BUFFERS_SIZE 8192
+#define SDLOG_QUEUE_BUCKETS 1024
#define SDLOG_MAX_MESSAGE_LEN 252
+#define SDLOG_NUM_FILES 1
+#define SDLOG_ALL_BUFFERS_SIZE (SDLOG_NUM_FILES*4096*2)
/*
* WDG driver system settings.
diff --git a/sw/airborne/boards/px4fmu/chibios/v2.4/ffconf.h b/sw/airborne/boards/px4fmu/chibios/v2.4/ffconf.h
index cd1c5cca30..f7c786cab2 100644
--- a/sw/airborne/boards/px4fmu/chibios/v2.4/ffconf.h
+++ b/sw/airborne/boards/px4fmu/chibios/v2.4/ffconf.h
@@ -2,176 +2,196 @@
#include "ch.h"
/*---------------------------------------------------------------------------/
-/ FatFs - FAT file system module configuration file R0.10b (C)ChaN, 2014
+/ FatFs - FAT file system module configuration file
/---------------------------------------------------------------------------*/
-#ifndef _FFCONF
-#define _FFCONF 8051 /* Revision ID */
-
+#define _FFCONF 68020 /* Revision ID */
/*---------------------------------------------------------------------------/
-/ Functions and Buffer Configurations
+/ Function Configurations
/---------------------------------------------------------------------------*/
-#define _FS_TINY 0 /* 0:Normal or 1:Tiny */
-/* When _FS_TINY is set to 1, it reduces memory consumption _MAX_SS bytes each
-/ file object. For file data transfer, FatFs uses the common sector buffer in
-/ the file system object (FATFS) instead of private sector buffer eliminated
-/ from the file object (FIL). */
+#define _FS_READONLY 0
+/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
+/ Read-only configuration removes writing API functions, f_write(), f_sync(),
+/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
+/ and optional writing functions as well. */
-#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */
-/* Setting _FS_READONLY to 1 defines read only configuration. This removes
-/ writing functions, f_write(), f_sync(), f_unlink(), f_mkdir(), f_chmod(),
-/ f_rename(), f_truncate() and useless f_getfree(). */
-
-
-#define _FS_MINIMIZE 0 /* 0 to 3 */
-/* The _FS_MINIMIZE option defines minimization level to remove API functions.
+#define _FS_MINIMIZE 0
+/* This option defines minimization level to remove some basic API functions.
/
/ 0: All basic functions are enabled.
-/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_chmod(), f_utime(),
-/ f_truncate() and f_rename() function are removed.
+/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
+/ are removed.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
-#define _USE_STRFUNC 2 /* 0:Disable or 1-2:Enable */
-/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
+#define _USE_STRFUNC 0
+/* This option switches string functions, f_gets(), f_putc(), f_puts() and
+/ f_printf().
+/
+/ 0: Disable string functions.
+/ 1: Enable without LF-CRLF conversion.
+/ 2: Enable with LF-CRLF conversion. */
-#define _USE_MKFS 1 /* 0:Disable or 1:Enable */
-/* To enable f_mkfs() function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
+#define _USE_FIND 1
+/* This option switches filtered directory read functions, f_findfirst() and
+/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
-#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */
-/* To enable fast seek feature, set _USE_FASTSEEK to 1. */
+#define _USE_MKFS 1
+/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
-#define _USE_LABEL 0 /* 0:Disable or 1:Enable */
-/* To enable volume label functions, set _USE_LAVEL to 1 */
+#define _USE_FASTSEEK 1
+/* This option switches fast seek function. (0:Disable or 1:Enable) */
-#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */
-/* To enable f_forward() function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
+#define _USE_EXPAND 1
+/* This option switches f_expand function. (0:Disable or 1:Enable) */
+
+
+#define _USE_CHMOD 1
+/* This option switches attribute manipulation functions, f_chmod() and f_utime().
+/ (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */
+
+
+#define _USE_LABEL 1
+/* This option switches volume label functions, f_getlabel() and f_setlabel().
+/ (0:Disable or 1:Enable) */
+
+
+#define _USE_FORWARD 1
+/* This option switches f_forward() function. (0:Disable or 1:Enable) */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
-#define _CODE_PAGE 1252
-/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
+#define _CODE_PAGE 850
+/* This option specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
-/ 932 - Japanese Shift_JIS (DBCS, OEM, Windows)
-/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
-/ 949 - Korean (DBCS, OEM, Windows)
-/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
-/ 1250 - Central Europe (Windows)
-/ 1251 - Cyrillic (Windows)
-/ 1252 - Latin 1 (Windows)
-/ 1253 - Greek (Windows)
-/ 1254 - Turkish (Windows)
-/ 1255 - Hebrew (Windows)
-/ 1256 - Arabic (Windows)
-/ 1257 - Baltic (Windows)
-/ 1258 - Vietnam (OEM, Windows)
-/ 437 - U.S. (OEM)
-/ 720 - Arabic (OEM)
-/ 737 - Greek (OEM)
-/ 775 - Baltic (OEM)
-/ 850 - Multilingual Latin 1 (OEM)
-/ 858 - Multilingual Latin 1 + Euro (OEM)
-/ 852 - Latin 2 (OEM)
-/ 855 - Cyrillic (OEM)
-/ 866 - Russian (OEM)
-/ 857 - Turkish (OEM)
-/ 862 - Hebrew (OEM)
-/ 874 - Thai (OEM, Windows)
-/ 1 - ASCII (Valid for only non-LFN configuration) */
+/ 1 - ASCII (No extended character. Non-LFN cfg. only)
+/ 437 - U.S.
+/ 720 - Arabic
+/ 737 - Greek
+/ 771 - KBL
+/ 775 - Baltic
+/ 850 - Latin 1
+/ 852 - Latin 2
+/ 855 - Cyrillic
+/ 857 - Turkish
+/ 860 - Portuguese
+/ 861 - Icelandic
+/ 862 - Hebrew
+/ 863 - Canadian French
+/ 864 - Arabic
+/ 865 - Nordic
+/ 866 - Russian
+/ 869 - Greek 2
+/ 932 - Japanese (DBCS)
+/ 936 - Simplified Chinese (DBCS)
+/ 949 - Korean (DBCS)
+/ 950 - Traditional Chinese (DBCS)
+*/
-#define _USE_LFN 2 /* 0 to 3 */
-#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
-/* The _USE_LFN option switches the LFN feature.
+#define _USE_LFN 3
+#define _MAX_LFN 255
+/* The _USE_LFN switches the support of long file name (LFN).
/
-/ 0: Disable LFN feature. _MAX_LFN has no effect.
+/ 0: Disable support of LFN. _MAX_LFN has no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
-/ When enable LFN feature, Unicode handling functions ff_convert() and ff_wtoupper()
-/ function must be added to the project.
-/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. When use stack for the
-/ working buffer, take care on stack overflow. When use heap memory for the working
-/ buffer, memory management functions, ff_memalloc() and ff_memfree(), must be added
-/ to the project. */
+/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added
+/ to the project. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and
+/ additional 608 bytes at exFAT enabled. _MAX_LFN can be in range from 12 to 255.
+/ It should be set 255 to support full featured LFN operations.
+/ When use stack for the working buffer, take care on stack overflow. When use heap
+/ memory for the working buffer, memory management functions, ff_memalloc() and
+/ ff_memfree(), must be added to the project. */
-#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */
-/* To switch the character encoding on the FatFs API (TCHAR) to Unicode, enable LFN
-/ feature and set _LFN_UNICODE to 1. This option affects behavior of string I/O
-/ functions. This option must be 0 when LFN feature is not enabled. */
+#define _LFN_UNICODE 0
+/* This option switches character encoding on the API. (0:ANSI/OEM or 1:UTF-16)
+/ To use Unicode string for the path name, enable LFN and set _LFN_UNICODE = 1.
+/ This option also affects behavior of string I/O functions. */
-#define _STRF_ENCODE 3 /* 0:ANSI/OEM, 1:UTF-16LE, 2:UTF-16BE, 3:UTF-8 */
-/* When Unicode API is enabled by _LFN_UNICODE option, this option selects the character
-/ encoding on the file to be read/written via string I/O functions, f_gets(), f_putc(),
-/ f_puts and f_printf(). This option has no effect when Unicode API is not enabled. */
-
-
-#define _FS_RPATH 2 /* 0 to 2 */
-/* The _FS_RPATH option configures relative path feature.
+#define _STRF_ENCODE 3
+/* When _LFN_UNICODE == 1, this option selects the character encoding ON THE FILE to
+/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
/
-/ 0: Disable relative path feature and remove related functions.
-/ 1: Enable relative path. f_chdrive() and f_chdir() function are available.
+/ 0: ANSI/OEM
+/ 1: UTF-16LE
+/ 2: UTF-16BE
+/ 3: UTF-8
+/
+/ This option has no effect when _LFN_UNICODE == 0. */
+
+
+#define _FS_RPATH 1
+/* This option configures support of relative path.
+/
+/ 0: Disable relative path and remove related functions.
+/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
/ 2: f_getcwd() function is available in addition to 1.
-/
-/ Note that output of the f_readdir() fnction is affected by this option. */
+*/
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
-#define _VOLUMES 1
+#define _VOLUMES 1
/* Number of volumes (logical drives) to be used. */
-#define _STR_VOLUME_ID 0 /* 0:Use only 0-9 for drive ID, 1:Use strings for drive ID */
-#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
-/* When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
-/ number in the path name. _VOLUME_STRS defines the drive ID strings for each logical
-/ drives. Number of items must be equal to _VOLUMES. Valid characters for the drive ID
-/ strings are: 0-9 and A-Z. */
+#define _STR_VOLUME_ID 0
+#define _VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
+/* _STR_VOLUME_ID switches string support of volume ID.
+/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
+/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
+/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
+/ the drive ID strings are: A-Z and 0-9. */
-#define _MULTI_PARTITION 0 /* 0:Single partition, 1:Enable multiple partition */
-/* By default(0), each logical drive number is bound to the same physical drive number
-/ and only a FAT volume found on the physical drive is mounted. When it is set to 1,
-/ each logical drive number is bound to arbitrary drive/partition listed in VolToPart[].
-*/
+#define _MULTI_PARTITION 0
+/* This option switches support of multi-partition on a physical drive.
+/ By default (0), each logical drive number is bound to the same physical drive
+/ number and only an FAT volume found on the physical drive will be mounted.
+/ When multi-partition is enabled (1), each logical drive number can be bound to
+/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
+/ funciton will be available. */
-#define _MIN_SS 512
-#define _MAX_SS 512
-/* These options configure the range of sector size to be supported. (512, 1024, 2048 or
-/ 4096) Always set both 512 for most systems, all memory card and harddisk. But a larger
-/ value may be required for on-board flash memory and some type of optical media.
-/ When _MAX_SS is larger than _MIN_SS, FatFs is configured to variable sector size and
-/ GET_SECTOR_SIZE command must be implemented to the disk_ioctl() function. */
+#define _MIN_SS 512
+#define _MAX_SS 512
+/* These options configure the range of sector size to be supported. (512, 1024,
+/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
+/ harddisk. But a larger value may be required for on-board flash memory and some
+/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
+/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
+/ disk_ioctl() function. */
-#define _USE_ERASE 1 /* 0:Disable or 1:Enable */
-/* To enable sector erase feature, set _USE_ERASE to 1. Also CTRL_ERASE_SECTOR command
-/ should be added to the disk_ioctl() function. */
+#define _USE_TRIM 0
+/* This option switches support of ATA-TRIM. (0:Disable or 1:Enable)
+/ To enable Trim function, also CTRL_TRIM command should be implemented to the
+/ disk_ioctl() function. */
-#define _FS_NOFSINFO 0 /* 0 to 3 */
-/* If you need to know correct free space on the FAT32 volume, set bit 0 of this option
-/ and f_getfree() function at first time after volume mount will force a full FAT scan.
-/ Bit 1 controls the last allocated cluster number as bit 0.
+#define _FS_NOFSINFO 0
+/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
+/ option, and f_getfree() function at first time after volume mount will force
+/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
/ bit0=1: Do not trust free cluster count in the FSINFO.
@@ -185,55 +205,66 @@
/ System Configurations
/---------------------------------------------------------------------------*/
-#define _FS_REENTRANT 1 /* 0:Disable or 1:Enable */
-#define _FS_TIMEOUT MS2ST(1000) /* Timeout period in unit of time tick */
-#define _SYNC_t semaphore_t* /* O/S dependent sync object type. e.g. HANDLE, OS_EVENT*, ID, SemaphoreHandle_t and etc.. */
-/* The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs module.
+#define _FS_TINY 0
+/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
+/ At the tiny configuration, size of file object (FIL) is reduced _MAX_SS bytes.
+/ Instead of private sector buffer eliminated from the file object, common sector
+/ buffer in the file system object (FATFS) is used for the file data transfer. */
+
+
+#define _FS_EXFAT 1
+/* This option switches support of exFAT file system. (0:Disable or 1:Enable)
+/ When enable exFAT, also LFN needs to be enabled. (_USE_LFN >= 1)
+/ Note that enabling exFAT discards C89 compatibility. */
+
+
+#define _FS_NORTC 0
+#define _NORTC_MON 1
+#define _NORTC_MDAY 1
+#define _NORTC_YEAR 2016
+/* The option _FS_NORTC switches timestamp functiton. If the system does not have
+/ any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable
+/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
+/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time.
+/ To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be
+/ added to the project to get current time form real-time clock. _NORTC_MON,
+/ _NORTC_MDAY and _NORTC_YEAR have no effect.
+/ These options have no effect at read-only configuration (_FS_READONLY = 1). */
+
+
+#define _FS_LOCK 0
+/* The option _FS_LOCK switches file lock function to control duplicated file open
+/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
+/ is 1.
+/
+/ 0: Disable file lock function. To avoid volume corruption, application program
+/ should avoid illegal open, remove and rename to the open objects.
+/ >0: Enable file lock function. The value defines how many files/sub-directories
+/ can be opened simultaneously under file lock control. Note that the file
+/ lock control is independent of re-entrancy. */
+
+
+#define _FS_REENTRANT 1
+#define _FS_TIMEOUT MS2ST(1000)
+#define _SYNC_t semaphore_t*
+/* The option _FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
+/ module itself. Note that regardless of this option, file access to different
+/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
+/ and f_fdisk() function, are always not re-entrant. Only file/directory access
+/ to the same volume is under control of this function.
/
/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
-/ function must be added to the project.
-*/
-
-
-#define _WORD_ACCESS 1 /* 0 or 1 */
-/* The _WORD_ACCESS option is an only platform dependent option. It defines
-/ which access method is used to the word data on the FAT volume.
+/ function, must be added to the project. Samples are available in
+/ option/syscall.c.
/
-/ 0: Byte-by-byte access. Always compatible with all platforms.
-/ 1: Word access. Do not choose this unless under both the following conditions.
-/
-/ * Address misaligned memory access is always allowed for ALL instructions.
-/ * Byte order on the memory is little-endian.
-/
-/ If it is the case, _WORD_ACCESS can also be set to 1 to improve performance and
-/ reduce code size. Following table shows an example of some processor types.
-/
-/ ARM7TDMI 0 ColdFire 0 V850E2 0
-/ Cortex-M3 0 Z80 0/1 V850ES 0/1
-/ Cortex-M0 0 RX600(LE) 0/1 TLCS-870 0/1
-/ AVR 0/1 RX600(BE) 0 TLCS-900 0/1
-/ AVR32 0 RL78 0 R32C 0
-/ PIC18 0/1 SH-2 0 M16C 0/1
-/ PIC24 0 H8S 0 MSP430 0
-/ PIC32 0 H8/300H 0 x86 0/1
-*/
+/ The _FS_TIMEOUT defines timeout period in unit of time tick.
+/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
+/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
+/ included somewhere in the scope of ff.h. */
+
+/* #include // O/S definitions */
-
-
-#define _FS_LOCK 0 /* 0:Disable or >=1:Enable */
-/* To enable file lock control feature, set _FS_LOCK to non-zero value.
-/ The value defines how many files/sub-directories can be opened simultaneously
-/ with file lock control. This feature uses bss _FS_LOCK * 12 bytes.
-/
-/ IMPORTANT NOTE:
-/ For Paparazzi, we don't need file locking since all file are written sequentially
-/ from one thread (thdSdLog)
-/
-*/
-
-
-
-#endif /* _FFCONF */
+/*--- End of configuration options ---*/
diff --git a/sw/airborne/boards/px4fmu/chibios/v2.4/mcuconf.h b/sw/airborne/boards/px4fmu/chibios/v2.4/mcuconf.h
index a43c196aee..d0389d581c 100644
--- a/sw/airborne/boards/px4fmu/chibios/v2.4/mcuconf.h
+++ b/sw/airborne/boards/px4fmu/chibios/v2.4/mcuconf.h
@@ -383,9 +383,15 @@
#define STM32_SDC_SDIO_UNALIGNED_SUPPORT FALSE
#define STM32_SDC_WRITE_TIMEOUT_MS 250
#define STM32_SDC_READ_TIMEOUT_MS 15
-#define SDLOG_ALL_BUFFERS_SIZE 8192
-#define SDLOG_MAX_MESSAGE_LEN 252
-#define SDLOG_QUEUE_BUCKETS 1024
+
+/*
+ sdlog message buffer and queue configuration
+ */
+#define SDLOG_QUEUE_BUCKETS 1024
+#define SDLOG_MAX_MESSAGE_LEN 252
+#define SDLOG_NUM_FILES 2
+#define SDLOG_ALL_BUFFERS_SIZE (SDLOG_NUM_FILES*4096*2)
+
/*
* workaround hardware bug in REV.A revision of old STM32F4 (sold in 2012, early 2013)
diff --git a/sw/airborne/modules/loggers/sdlog_chibios.c b/sw/airborne/modules/loggers/sdlog_chibios.c
index c61323e6d3..94a2fcc49e 100644
--- a/sw/airborne/modules/loggers/sdlog_chibios.c
+++ b/sw/airborne/modules/loggers/sdlog_chibios.c
@@ -46,6 +46,15 @@
#define SDLOG_START_DELAY 30
#endif
+// Auto-flush period (in seconds)
+#ifndef SDLOG_AUTO_FLUSH_PERIOD
+#define SDLOG_AUTO_FLUSH_PERIOD 10
+#endif
+
+// Contiguous storage memory (in Mo)
+#ifndef SDLOG_CONTIGUOUS_STORAGE_MEM
+#define SDLOG_CONTIGUOUS_STORAGE_MEM 50
+#endif
#if (!defined USE_ADC_WATCHDOG) || (USE_ADC_WATCHDOG == 0)
#error sdlog_chibios need USE_ADC_WATCHDOG in order to properly close files when power is unplugged
@@ -67,7 +76,7 @@ static __attribute__((noreturn)) void thd_startlog(void *arg);
*/
static THD_WORKING_AREA(wa_thd_bat_survey, 1024);
static __attribute__((noreturn)) void thd_bat_survey(void *arg);
-static void powerOutageIsr (void);
+static void powerOutageIsr(void);
event_source_t powerOutageSource;
event_listener_t powerOutageListener;
@@ -83,9 +92,28 @@ static const char FR_LOG_DIR[] = "FLIGHT_RECORDER";
FileDes flightRecorderLogFile = -1;
#endif
+/** sdlog status
+ */
+static enum {
+ SDLOG_STOPPED = 0,
+ SDLOG_RUNNING,
+ SDLOG_ERROR
+} chibios_sdlog_status;
+
+#if PERIODIC_TELEMETRY
+#include "subsystems/datalink/telemetry.h"
+static void send_sdlog_status(struct transport_tx *trans, struct link_device *dev)
+{
+ uint8_t status = (uint8_t) chibios_sdlog_status;
+ uint8_t errno = (uint8_t) sdLogGetStorageStatus();
+ uint32_t used = (uint32_t) sdLogGetNbBytesWrittenToStorage();
+ pprz_msg_send_LOGGER_STATUS(trans, dev, AC_ID, &status, &errno, &used);
+}
+#endif
+
// Functions for the generic device API
-static int sdlog_check_free_space(struct chibios_sdlog* p __attribute__((unused)), long *fd, uint16_t len)
+static int sdlog_check_free_space(struct chibios_sdlog *p __attribute__((unused)), long *fd, uint16_t len)
{
SdLogBuffer *sdb;
SdioError status = sdLogAllocSDB(&sdb, len);
@@ -97,7 +125,7 @@ static int sdlog_check_free_space(struct chibios_sdlog* p __attribute__((unused)
}
}
-static void sdlog_transmit(struct chibios_sdlog* p __attribute__((unused)), long fd, uint8_t byte)
+static void sdlog_transmit(struct chibios_sdlog *p __attribute__((unused)), long fd, uint8_t byte)
{
SdLogBuffer *sdb = (SdLogBuffer *) fd;
uint8_t *data = (uint8_t *) sdLogGetBufferFromSDB(sdb);
@@ -105,14 +133,14 @@ static void sdlog_transmit(struct chibios_sdlog* p __attribute__((unused)), long
sdLogSeekBufferFromSDB(sdb, 1);
}
-static void sdlog_transmit_buffer(struct chibios_sdlog* p __attribute__((unused)), long fd, uint8_t *data, uint16_t len)
+static void sdlog_transmit_buffer(struct chibios_sdlog *p __attribute__((unused)), long fd, uint8_t *data, uint16_t len)
{
SdLogBuffer *sdb = (SdLogBuffer *) fd;
memcpy(sdLogGetBufferFromSDB(sdb), data, len);
sdLogSeekBufferFromSDB(sdb, len);
}
-static void sdlog_send(struct chibios_sdlog* p, long fd)
+static void sdlog_send(struct chibios_sdlog *p, long fd)
{
SdLogBuffer *sdb = (SdLogBuffer *) fd;
sdLogWriteSDB(*(p->file), sdb);
@@ -137,25 +165,34 @@ void chibios_sdlog_init(struct chibios_sdlog *sdlog, FileDes *file)
void sdlog_chibios_init(void)
{
+ chibios_sdlog_status = SDLOG_STOPPED;
+#if PERIODIC_TELEMETRY
+ register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_LOGGER_STATUS, send_sdlog_status);
+#endif
+
// Start polling on USB
usbStorageStartPolling();
// Start log thread
chThdCreateStatic(wa_thd_startlog, sizeof(wa_thd_startlog),
- NORMALPRIO+2, thd_startlog, NULL);
+ NORMALPRIO + 2, thd_startlog, NULL);
}
-void sdlog_chibios_finish(bool flush)
+void sdlog_chibios_finish(const bool flush)
{
if (pprzLogFile != -1) {
+ // disable all the LEDs to save energy and maximize chance to flush files
+ // to mass storage and avoid infamous dirty bit on filesystem
+ led_disable();
sdLogCloseAllLogs(flush);
- sdLogFinish ();
+ sdLogFinish();
pprzLogFile = 0;
#if FLIGHTRECORDER_SDLOG
flightRecorderLogFile = 0;
#endif
}
+ chibios_sdlog_status = SDLOG_STOPPED;
}
static void thd_startlog(void *arg)
@@ -164,10 +201,11 @@ static void thd_startlog(void *arg)
chRegSetThreadName("start log");
// Wait before starting the log if needed
- chThdSleepSeconds (SDLOG_START_DELAY);
+ chThdSleepSeconds(SDLOG_START_DELAY);
// Check if we are already in USB Storage mode
- if (usbStorageIsItRunning ())
- chThdSleepSeconds (20000); // stuck here for hours FIXME stop the thread ?
+ if (usbStorageIsItRunning()) {
+ chThdSleepSeconds(20000); // stuck here for hours FIXME stop the thread ?
+ }
// Init sdlog struct
chibios_sdlog_init(&chibios_sdlog, &pprzLogFile);
@@ -175,37 +213,52 @@ static void thd_startlog(void *arg)
// Check for init errors
sdOk = true;
- if (sdLogInit (NULL) != SDLOG_OK) {
+ if (sdLogInit(NULL) != SDLOG_OK) {
sdOk = false;
- }
- else {
- removeEmptyLogs (PPRZ_LOG_DIR, PPRZ_LOG_NAME, 50);
- if (sdLogOpenLog (&pprzLogFile, PPRZ_LOG_DIR, PPRZ_LOG_NAME, true) != SDLOG_OK)
+ } else {
+ removeEmptyLogs(PPRZ_LOG_DIR, PPRZ_LOG_NAME, 50);
+ if (sdLogOpenLog(&pprzLogFile, PPRZ_LOG_DIR, PPRZ_LOG_NAME, SDLOG_AUTO_FLUSH_PERIOD, true) != SDLOG_OK) {
sdOk = false;
-
+ }
+ // try to reserve contiguous mass storage memory
+ sdLogExpandLogFile(pprzLogFile, SDLOG_CONTIGUOUS_STORAGE_MEM, false);
#if FLIGHTRECORDER_SDLOG
- removeEmptyLogs (FR_LOG_DIR, FLIGHTRECORDER_LOG_NAME, 50);
- if (sdLogOpenLog (&flightRecorderLogFile, FR_LOG_DIR, FLIGHTRECORDER_LOG_NAME, false) != SDLOG_OK)
+ removeEmptyLogs(FR_LOG_DIR, FLIGHTRECORDER_LOG_NAME, 50);
+ if (sdLogOpenLog(&flightRecorderLogFile, FR_LOG_DIR, FLIGHTRECORDER_LOG_NAME, SDLOG_AUTO_FLUSH_PERIOD, false) != SDLOG_OK) {
sdOk = false;
+ }
+ // try to reserve contiguous mass storage memory
+ sdLogExpandLogFile(flightRecorderLogFile, SDLOG_CONTIGUOUS_STORAGE_MEM, false);
#endif
}
if (sdOk) {
// Create Battery Survey Thread with event
- chEvtObjectInit (&powerOutageSource);
- chThdCreateStatic (wa_thd_bat_survey, sizeof(wa_thd_bat_survey),
- NORMALPRIO+2, thd_bat_survey, NULL);
+ chEvtObjectInit(&powerOutageSource);
+ chThdCreateStatic(wa_thd_bat_survey, sizeof(wa_thd_bat_survey),
+ NORMALPRIO + 2, thd_bat_survey, NULL);
+
+ chibios_sdlog_status = SDLOG_RUNNING;
+ } else {
+ chibios_sdlog_status = SDLOG_ERROR;
}
while (true) {
-#ifdef LED_SDLOG
- LED_TOGGLE(LED_SDLOG);
+#ifdef SDLOG_LED
+ LED_TOGGLE(SDLOG_LED);
#endif
// Blink faster if init has errors
- chThdSleepMilliseconds (sdOk == true ? 1000 : 200);
- static uint32_t timestamp = 0;
+ chThdSleepMilliseconds(sdOk == true ? 1000 : 200);
+ if (sdLogGetStorageStatus() != SDLOG_OK) {
+ chibios_sdlog_status = SDLOG_ERROR;
+ sdOk = false;
+ } else {
+ chibios_sdlog_status = SDLOG_RUNNING;
+ sdOk = true;
+ }
#if HAL_USE_RTC && USE_GPS
+ static uint32_t timestamp = 0;
// FIXME this could be done somewhere else, like in sys_time
// we sync gps time to rtc every 5 seconds
if (chVTGetSystemTime() - timestamp > 5000) {
@@ -214,7 +267,7 @@ static void thd_startlog(void *arg)
// Unix timestamp of the GPS epoch 1980-01-06 00:00:00 UTC
const uint32_t unixToGpsEpoch = 315964800;
struct tm time_tm;
- time_t univTime = ((gps.week * 7 * 24 * 3600) + (gps.tow/1000)) + unixToGpsEpoch;
+ time_t univTime = ((gps.week * 7 * 24 * 3600) + (gps.tow / 1000)) + unixToGpsEpoch;
gmtime_r(&univTime, &time_tm);
// Chibios date struct
RTCDateTime date;
@@ -231,25 +284,26 @@ static void thd_startlog(void *arg)
static void thd_bat_survey(void *arg)
{
(void)arg;
- chRegSetThreadName ("battery survey");
+ chRegSetThreadName("battery survey");
chEvtRegister(&powerOutageSource, &powerOutageListener, 1);
- chThdSleepMilliseconds (2000);
+ chThdSleepMilliseconds(2000);
register_adc_watchdog(&SDLOG_BAT_ADC, SDLOG_BAT_CHAN, V_ALERT, &powerOutageIsr);
chEvtWaitOne(EVENT_MASK(1));
- sdlog_chibios_finish (true);
+ // in case of powerloss, we should go fast and avoid to flush ram buffer
+ sdlog_chibios_finish(false);
chThdExit(0);
mcu_deep_sleep();
- chThdSleepMilliseconds (TIME_INFINITE);
- while (1); // never goes here, only to avoid compiler warning: 'noreturn' function does return
+ chThdSleep(TIME_INFINITE);
+ while (true); // never goes here, only to avoid compiler warning: 'noreturn' function does return
}
/*
powerOutageIsr is called within a lock zone from an isr, so no lock/unlock is needed
*/
-static void powerOutageIsr (void)
+static void powerOutageIsr(void)
{
chEvtBroadcastI(&powerOutageSource);
}
diff --git a/sw/airborne/modules/loggers/sdlog_chibios.h b/sw/airborne/modules/loggers/sdlog_chibios.h
index db902fd408..6025790cbf 100644
--- a/sw/airborne/modules/loggers/sdlog_chibios.h
+++ b/sw/airborne/modules/loggers/sdlog_chibios.h
@@ -49,7 +49,6 @@ extern FileDes flightRecorderLogFile;
extern void sdlog_chibios_init(void);
extern void sdlog_chibios_finish(bool flush);
-
/** chibios_sdlog structure
*/
struct chibios_sdlog {
diff --git a/sw/airborne/modules/loggers/sdlog_chibios/msg_queue.c b/sw/airborne/modules/loggers/sdlog_chibios/msg_queue.c
index 0ddd782815..a2aa557165 100644
--- a/sw/airborne/modules/loggers/sdlog_chibios/msg_queue.c
+++ b/sw/airborne/modules/loggers/sdlog_chibios/msg_queue.c
@@ -140,7 +140,11 @@ int32_t msgqueue_pop_timeout(MsgQueue *que, void **msgPtr, const systime_t timou
{
MsgPtrLen mpl = {.ptrOfst = 0, .len = 0};
- const msg_t status = chMBFetch(&que->mb, (msg_t *) &mpl.msg_ptr_len, timout);
+ msg_t status;
+ do {
+ status = chMBFetch(&que->mb, (msg_t *) &mpl.msg_ptr_len, timout);
+ } while (status == MSG_RESET);
+
if (status != MSG_OK) {
return MsgQueue_MAILBOX_TIMEOUT;
}
diff --git a/sw/airborne/modules/loggers/sdlog_chibios/sdLog.c b/sw/airborne/modules/loggers/sdlog_chibios/sdLog.c
index f21a7e3021..4d1f565d4a 100644
--- a/sw/airborne/modules/loggers/sdlog_chibios/sdLog.c
+++ b/sw/airborne/modules/loggers/sdlog_chibios/sdLog.c
@@ -35,35 +35,41 @@
#include "mcu_periph/sdio.h"
#include
-
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define MIN(x , y) (((x) < (y)) ? (x) : (y))
#define MAX(x , y) (((x) > (y)) ? (x) : (y))
+#define IS_POWER_OF_TWO(s) ((s) && !((s) & ((s) - 1)))
-
-// Number of files opened simultaneously
-// Set to 2 by default since we have the default log file
-// and optionally the flight recorder file
-//
-// WARNING:
-// - if _FS_LOCK is set to 0, there is no limit on simultaneously opened file,
-// but no file locking, all fatfs operations should be done from same thread
-// - if _FS_LOCK is > 0, each file is in a different subdir, so _FS_LOCK should
-// be set to 2 * nbFile
-#ifndef SDLOG_NUM_BUFFER
-#define SDLOG_NUM_BUFFER 2
+#ifndef SDLOG_NUM_FILES
+#error SDLOG_NUM_FILES should be defined in mcuconf.h
#endif
-#ifndef SDLOG_ALL_BUFFERS_SIZE
-#error SDLOG_ALL_BUFFERS_SIZE should be defined in mcuconf.h
+#if _FATFS < 8000
+#if _FS_SHARE != 0 && _FS_SHARE < SDLOG_NUM_FILES
+#error if _FS_SHARE is not zero, it should be equal of superior to SDLOG_NUM_FILES
#endif
-#define SDLOG_WRITE_BUFFER_SIZE (SDLOG_ALL_BUFFERS_SIZE/SDLOG_NUM_BUFFER)
+
+#else // _FATFS > 8000
+#if _FS_LOCK != 0 && _FS_LOCK < SDLOG_NUM_FILES
+#error if _FS_LOCK is not zero, it should be equal of superior to SDLOG_NUM_FILES
+#endif
+#endif
+
+#ifndef SDLOG_ALL_BUFFERS_SIZE
+#error SDLOG_ALL_BUFFERS_SIZE should be defined in mcuconf.h
+#endif
+
+#if SDLOG_ALL_BUFFERS_SIZE > 65536
+#error constraint 512 <= SDLOG_ALL_BUFFERS_SIZE <= 65536 not meet
+#endif
+
+#define SDLOG_WRITE_BUFFER_SIZE (SDLOG_ALL_BUFFERS_SIZE/SDLOG_NUM_FILES)
#ifndef SDLOG_MAX_MESSAGE_LEN
-#error SDLOG_MAX_MESSAGE_LEN should be defined in mcuconf.h
+#error SDLOG_MAX_MESSAGE_LENshould be defined in mcuconf.h
#endif
#ifndef SDLOG_QUEUE_BUCKETS
@@ -74,19 +80,27 @@
#warning "_FS_REENTRANT = 0 in ffconf.h DO NOT open close file during log"
#endif
+#if SDLOG_WRITE_BUFFER_SIZE < 512
+#error SDLOG_ALL_BUFFERS_SIZE / SDLOG_NUM_FILES cannot be < 512
+#endif
+
+#if (!(IS_POWER_OF_TWO (SDLOG_WRITE_BUFFER_SIZE)))
+#error SDLOG_ALL_BUFFERS_SIZE / SDLOG_NUM_FILES should be a POWER OF 2
+#endif
#ifdef SDLOG_NEED_QUEUE
#include "modules/loggers/sdlog_chibios/msg_queue.h"
#include "mcu_periph/ram_arch.h"
+
/*
The buffers that do DMA are the caches (named buf) in the FIL and FATFS struct of fatfs library
It's the only buffers that have to reside in DMA capable memory.
- The buffer associated with message queue, and the cache buffer for caching file write
- could reside in non DMA capable memory.
-
+ The buffer associated with message queue, and the cache buffer for caching file write
+ could reside in non DMA capable memory.
+
stm32f4 : regular sram : 128ko, dma, slow
ccm sram : 64ko, no_dma, fast
@@ -96,7 +110,7 @@
-static msg_t IN_STD_SECTION (queMbBuffer[SDLOG_QUEUE_BUCKETS]);
+static msg_t IN_STD_SECTION_CLEAR(queMbBuffer[SDLOG_QUEUE_BUCKETS]);
static MsgQueue messagesQueue;
#define WRITE_BYTE_CACHE_SIZE 15 // limit overhead :
@@ -113,6 +127,8 @@ struct LogMessage {
struct FilePoolUnit {
FIL fil;
+ uint32_t autoFlushPeriod;
+ systime_t lastFlushTs;
bool inUse;
bool tagAtClose;
// optimise write byte by caching at send level now that we are based upon tlsf where
@@ -121,13 +137,16 @@ struct FilePoolUnit {
uint8_t writeByteSeek;
};
-static struct FilePoolUnit IN_DMA_SECTION (fileDes[SDLOG_NUM_BUFFER]) = {
- [0 ... SDLOG_NUM_BUFFER - 1] = {
- .fil = {0}, .inUse = false, .tagAtClose = false,
+static struct FilePoolUnit IN_DMA_SECTION(fileDes[SDLOG_NUM_FILES]) = {
+ [0 ... SDLOG_NUM_FILES - 1] = {
+ .fil = {{0}}, .inUse = false, .tagAtClose = false,
.writeByteCache = NULL, .writeByteSeek = 0
}
};
+static volatile size_t nbBytesWritten = 0;
+static SdioError storageStatus = SDLOG_OK;
+
typedef enum {
FCNTL_WRITE = 0b00,
FCNTL_FLUSH = 0b01,
@@ -135,19 +154,18 @@ typedef enum {
FCNTL_EXIT = 0b11
} FileFcntl;
-struct _SdLogBuffer {
+struct _SdLogBuffer {
LogMessage *lm;
size_t len;
uint32_t offset;
-};
-
+} ;
#define LOG_MESSAGE_PREBUF_LEN (SDLOG_MAX_MESSAGE_LEN+sizeof(LogMessage))
#endif // SDLOG_NEED_QUEUE
/* File system object */
-static IN_DMA_SECTION (FATFS fatfs);
+static IN_DMA_SECTION(FATFS fatfs);
#ifdef SDLOG_NEED_QUEUE
static size_t logMessageLen(const LogMessage *lm);
@@ -156,6 +174,8 @@ static SdioError sdLoglaunchThread(void);
static SdioError sdLogStopThread(void);
static thread_t *sdLogThd = NULL;
static SdioError getNextFIL(FileDes *fd);
+static void removeFromQueue(const size_t nbMsgToRFemov);
+static void cleanQueue(const bool allQueue);
#if (CH_KERNEL_MAJOR > 2)
static void thdSdLog(void *arg) ;
@@ -165,9 +185,6 @@ static msg_t thdSdLog(void *arg) ;
#endif // SDLOG_NEED_QUEUE
-
-
-
static int32_t uiGetIndexOfLogFile(const char *prefix, const char *fileName) ;
static inline SdioError flushWriteByteBuffer(const FileDes fd);
@@ -175,11 +192,12 @@ SdioError sdLogInit(uint32_t *freeSpaceInKo)
{
DWORD clusters = 0;
FATFS *fsp = NULL;
+ nbBytesWritten = 0;
// if init is already done, return ERROR
if (sdLogThd != NULL) {
*freeSpaceInKo = 0;
- return SDLOG_WAS_LAUNCHED;
+ return storageStatus = SDLOG_WAS_LAUNCHED;
}
#ifdef SDLOG_NEED_QUEUE
@@ -187,7 +205,7 @@ SdioError sdLogInit(uint32_t *freeSpaceInKo)
#endif
if (!sdc_lld_is_card_inserted(NULL)) {
- return SDLOG_NOCARD;
+ return storageStatus = SDLOG_NOCARD;
}
@@ -195,8 +213,8 @@ SdioError sdLogInit(uint32_t *freeSpaceInKo)
chThdSleepMilliseconds(10);
sdio_disconnect();
- if (sdio_connect() == false) {
- return SDLOG_NOCARD;
+ if (sdio_connect() == FALSE) {
+ return storageStatus = SDLOG_NOCARD;
}
#if _FATFS < 8000
@@ -206,7 +224,7 @@ SdioError sdLogInit(uint32_t *freeSpaceInKo)
#endif
if (rc != FR_OK) {
- return SDLOG_FATFS_ERROR;
+ return storageStatus = SDLOG_FATFS_ERROR;
}
if (freeSpaceInKo != NULL) {
@@ -215,16 +233,17 @@ SdioError sdLogInit(uint32_t *freeSpaceInKo)
}
#ifdef SDLOG_NEED_QUEUE
- for (uint8_t i = 0; i < SDLOG_NUM_BUFFER; i++) {
+ for (uint8_t i = 0; i < SDLOG_NUM_FILES; i++) {
fileDes[i].inUse = fileDes[i].tagAtClose = false;
fileDes[i].writeByteCache = NULL;
fileDes[i].writeByteSeek = 0;
}
- return sdLoglaunchThread();
+ storageStatus = sdLoglaunchThread();
#else
- return SDLOG_OK;
+ storageStatus = SDLOG_OK;
#endif
+ return storageStatus;
}
@@ -237,21 +256,21 @@ SdioError sdLogFinish(void)
FRESULT rc = f_mount(NULL, "", 0);
#endif
if (rc != FR_OK) {
- return SDLOG_FATFS_ERROR;
+ return storageStatus = SDLOG_FATFS_ERROR;
}
// if we mount, unmount, don't disconnect sdio
- /* if (sdio_disconnect () == false) */
+ /* if (sdio_disconnect () == FALSE) */
/* return SDLOG_NOCARD; */
- return SDLOG_OK ;
+ return storageStatus = SDLOG_OK;
}
#ifdef SDLOG_NEED_QUEUE
SdioError sdLogOpenLog(FileDes *fd, const char *directoryName, const char *prefix,
- bool appendTagAtClose)
+ const uint32_t autoFlushPeriod, const bool appendTagAtClose)
{
FRESULT rc; /* fatfs result code */
SdioError sde; /* sdio result code */
@@ -261,43 +280,49 @@ SdioError sdLogOpenLog(FileDes *fd, const char *directoryName, const char *prefi
sde = getNextFIL(fd);
if (sde != SDLOG_OK) {
+ storageStatus = sde;
return sde;
}
sde = getFileName(prefix, directoryName, fileName, sizeof(fileName), +1);
if (sde != SDLOG_OK) {
// sd card is not inserted, so logging task can be deleted
- return SDLOG_FATFS_ERROR;
+ return storageStatus = SDLOG_FATFS_ERROR;
}
rc = f_open(&fileDes[*fd].fil, fileName, FA_WRITE | FA_CREATE_ALWAYS);
if (rc) {
fileDes[*fd].inUse = false;
- return SDLOG_FATFS_ERROR;
+ return storageStatus = SDLOG_FATFS_ERROR;
} else {
fileDes[*fd].tagAtClose = appendTagAtClose;
+ fileDes[*fd].autoFlushPeriod = autoFlushPeriod;
+ fileDes[*fd].lastFlushTs = 0;
}
- return SDLOG_OK;
+ return storageStatus = SDLOG_OK;
}
-
SdioError sdLogCloseAllLogs(bool flush)
{
FRESULT rc = 0; /* Result code */
-
-
// do not flush what is in ram, close as soon as possible
if (flush == false) {
+ UINT bw;
// stop worker thread then close file
+ cleanQueue(true);
sdLogStopThread();
- for (FileDes fd = 0; fd < SDLOG_NUM_BUFFER; fd++) {
- if (fileDes[fd].inUse) {
- FIL *fileObject = &fileDes[fd].fil;
- FRESULT trc = f_close(fileObject);
+ for (FileDes fd = 0; fd < SDLOG_NUM_FILES; fd++) {
+ if (fileDes[fd].inUse) {
+ FIL *fo = &fileDes[fd].fil;
+ if (fileDes[fd].tagAtClose) {
+ f_write(fo, "\r\nEND_OF_LOG\r\n", 14, &bw);
+ nbBytesWritten += bw;
+ }
+ FRESULT trc = f_close(fo);
fileDes[fd].inUse = false;
if (!rc) {
rc = trc;
@@ -306,18 +331,18 @@ SdioError sdLogCloseAllLogs(bool flush)
}
if (rc) {
- return SDLOG_FATFS_ERROR;
+ return storageStatus = SDLOG_FATFS_ERROR;
}
// flush ram buffer then close
} else { // flush == true
if (sdLogThd == NULL) {
// something goes wrong, log thread is no more working
- return SDLOG_NOTHREAD;
+ return storageStatus = SDLOG_NOTHREAD;
}
// queue flush + close order, then stop worker thread
- for (FileDes fd = 0; fd < SDLOG_NUM_BUFFER; fd++) {
+ for (FileDes fd = 0; fd < SDLOG_NUM_FILES; fd++) {
if (fileDes[fd].inUse) {
flushWriteByteBuffer(fd);
sdLogCloseLog(fd);
@@ -326,31 +351,65 @@ SdioError sdLogCloseAllLogs(bool flush)
LogMessage *lm = tlsf_malloc_r(&HEAP_DEFAULT, sizeof(LogMessage));
if (lm == NULL) {
- return SDLOG_QUEUEFULL;
+ return storageStatus = SDLOG_MEMFULL;
}
lm->op.fcntl = FCNTL_EXIT;
if (msgqueue_send(&messagesQueue, lm, sizeof(LogMessage), MsgQueue_REGULAR) < 0) {
- return SDLOG_QUEUEFULL;
+ return storageStatus = SDLOG_QUEUEFULL;
} else {
chThdWait(sdLogThd);
sdLogThd = NULL;
}
}
- return SDLOG_OK;
+ return storageStatus = SDLOG_OK;
+}
+
+SdioError sdLogFlushAllLogs(void)
+{
+ SdioError status = SDLOG_OK;
+ if (sdLogThd == NULL) {
+ // something goes wrong, log thread is no more working
+ return storageStatus = SDLOG_NOTHREAD;
+ }
+
+ // queue flush + close order, then stop worker thread
+ for (FileDes fd = 0; fd < SDLOG_NUM_FILES; fd++) {
+ if (fileDes[fd].inUse) {
+ status = sdLogFlushLog(fd);
+ if (status != SDLOG_OK) {
+ break;
+ }
+ }
+ }
+
+ return storageStatus = status;
}
-#define FD_CHECK(fd) if ((fd < 0) || (fd >= SDLOG_NUM_BUFFER) \
- || (fileDes[fd].inUse == false)) \
- return SDLOG_FATFS_ERROR
+#define FD_CHECK(fd) if ((fd < 0) || (fd >= SDLOG_NUM_FILES) \
+ || (fileDes[fd].inUse == false)) \
+ return SDLOG_FATFS_ERROR
+
+
+SdioError sdLogExpandLogFile(const FileDes fd, const size_t sizeInMo,
+ const bool preallocate)
+{
+ FD_CHECK(fd);
+
+ // expand with opt=1 : pre allocate file now
+ const FRESULT rc = f_expand(&fileDes[fd].fil, sizeInMo * 1024 * 1024, preallocate);
+ return (rc == FR_OK) ? SDLOG_OK : SDLOG_CANNOT_EXPAND;
+}
SdioError sdLogWriteLog(const FileDes fd, const char *fmt, ...)
{
FD_CHECK(fd);
+
const SdioError status = flushWriteByteBuffer(fd);
+ storageStatus = status;
if (status != SDLOG_OK) {
return status;
}
@@ -361,7 +420,7 @@ SdioError sdLogWriteLog(const FileDes fd, const char *fmt, ...)
LogMessage *lm = tlsf_malloc_r(&HEAP_DEFAULT, LOG_MESSAGE_PREBUF_LEN);
if (lm == NULL) {
va_end(ap);
- return SDLOG_QUEUEFULL;
+ return storageStatus = SDLOG_MEMFULL;
}
lm->op.fcntl = FCNTL_WRITE;
@@ -374,11 +433,11 @@ SdioError sdLogWriteLog(const FileDes fd, const char *fmt, ...)
const size_t msgLen = logMessageLen(lm);
lm = tlsf_realloc_r(&HEAP_DEFAULT, lm, msgLen);
if (lm == NULL) {
- return SDLOG_QUEUEFULL;
+ return storageStatus = SDLOG_MEMFULL;
}
if (msgqueue_send(&messagesQueue, lm, msgLen, MsgQueue_REGULAR) < 0) {
- return SDLOG_QUEUEFULL;
+ return storageStatus = SDLOG_QUEUEFULL;
}
return SDLOG_OK;
@@ -389,20 +448,24 @@ SdioError sdLogFlushLog(const FileDes fd)
FD_CHECK(fd);
const SdioError status = flushWriteByteBuffer(fd);
+ storageStatus = status;
if (status != SDLOG_OK) {
return status;
}
+ // give room to send a flush order if the queue is full
+ cleanQueue(false);
+
LogMessage *lm = tlsf_malloc_r(&HEAP_DEFAULT, sizeof(LogMessage));
if (lm == NULL) {
- return SDLOG_QUEUEFULL;
+ return storageStatus = SDLOG_MEMFULL;
}
lm->op.fcntl = FCNTL_FLUSH;
lm->op.fd = fd & 0x1f;
if (msgqueue_send(&messagesQueue, lm, sizeof(LogMessage), MsgQueue_REGULAR) < 0) {
- return SDLOG_QUEUEFULL;
+ return storageStatus = SDLOG_QUEUEFULL;
}
return SDLOG_OK;
@@ -412,19 +475,20 @@ SdioError sdLogCloseLog(const FileDes fd)
{
FD_CHECK(fd);
+ cleanQueue(false);
LogMessage *lm = tlsf_malloc_r(&HEAP_DEFAULT, sizeof(LogMessage));
if (lm == NULL) {
- return SDLOG_QUEUEFULL;
+ return storageStatus = SDLOG_MEMFULL;
}
lm->op.fcntl = FCNTL_CLOSE;
lm->op.fd = fd & 0x1f;
if (msgqueue_send(&messagesQueue, lm, sizeof(LogMessage), MsgQueue_REGULAR) < 0) {
- return SDLOG_QUEUEFULL;
+ return storageStatus = SDLOG_QUEUEFULL;
}
- return SDLOG_OK;
+ return storageStatus = SDLOG_OK;
}
@@ -439,26 +503,26 @@ static inline SdioError flushWriteByteBuffer(const FileDes fd)
if (msgqueue_send(&messagesQueue, fileDes[fd].writeByteCache,
sizeof(LogMessage) + fileDes[fd].writeByteSeek,
MsgQueue_REGULAR) < 0) {
- return SDLOG_QUEUEFULL;
+ return storageStatus = SDLOG_QUEUEFULL;
}
fileDes[fd].writeByteCache = NULL;
}
- return SDLOG_OK;
+ return storageStatus = SDLOG_OK;
}
SdioError sdLogWriteRaw(const FileDes fd, const uint8_t *buffer, const size_t len)
{
FD_CHECK(fd);
-
const SdioError status = flushWriteByteBuffer(fd);
+ storageStatus = status;
if (status != SDLOG_OK) {
return status;
}
LogMessage *lm = tlsf_malloc_r(&HEAP_DEFAULT, logRawLen(len));
if (lm == NULL) {
- return SDLOG_QUEUEFULL;
+ return storageStatus = SDLOG_MEMFULL;
}
lm->op.fcntl = FCNTL_WRITE;
@@ -466,7 +530,7 @@ SdioError sdLogWriteRaw(const FileDes fd, const uint8_t *buffer, const size_t le
memcpy(lm->mess, buffer, len);
if (msgqueue_send(&messagesQueue, lm, logRawLen(len), MsgQueue_REGULAR) < 0) {
- return SDLOG_QUEUEFULL;
+ return storageStatus = SDLOG_QUEUEFULL;
}
return SDLOG_OK;
@@ -476,27 +540,27 @@ SdioError sdLogAllocSDB(SdLogBuffer **sdb, const size_t len)
{
*sdb = tlsf_malloc_r(&HEAP_DEFAULT, logRawLen(len));
if (*sdb == NULL) {
- return SDLOG_QUEUEFULL;
+ return storageStatus = SDLOG_MEMFULL;
}
LogMessage *lm = tlsf_malloc_r(&HEAP_DEFAULT, logRawLen(len));
if (lm == NULL) {
tlsf_free_r(&HEAP_DEFAULT, *sdb);
- return SDLOG_QUEUEFULL;
+ return storageStatus = SDLOG_MEMFULL;
}
(*sdb)->lm = lm;
(*sdb)->len = len;
(*sdb)->offset = 0;
- return SDLOG_OK;
+ return storageStatus = SDLOG_OK;
}
char *sdLogGetBufferFromSDB(SdLogBuffer *sdb)
{
- return sdb->lm->mess + sdb->offset;
+ return sdb->lm->mess + sdb->offset;
}
-bool sdLogSeekBufferFromSDB(SdLogBuffer *sdb, uint32_t offset)
+bool sdLogSeekBufferFromSDB(SdLogBuffer *sdb, uint32_t offset)
{
if ((sdb->offset + offset) < sdb->len) {
sdb->offset += offset;
@@ -515,7 +579,7 @@ SdioError sdLogWriteSDB(const FileDes fd, SdLogBuffer *sdb)
{
SdioError status = SDLOG_OK;
- if ((fd < 0) || (fd >= SDLOG_NUM_BUFFER) || (fileDes[fd].inUse == false)) {
+ if ((fd < 0) || (fd >= SDLOG_NUM_FILES) || (fileDes[fd].inUse == false)) {
status = SDLOG_FATFS_ERROR;
goto fail;
}
@@ -525,6 +589,7 @@ SdioError sdLogWriteSDB(const FileDes fd, SdLogBuffer *sdb)
goto fail;
}
+
sdb->lm->op.fcntl = FCNTL_WRITE;
sdb->lm->op.fd = fd & 0x1f;
@@ -541,11 +606,12 @@ fail:
exit:
tlsf_free_r(&HEAP_DEFAULT, sdb);
- return status;
+ return storageStatus = status;
}
+
SdioError sdLogWriteByte(const FileDes fd, const uint8_t value)
{
FD_CHECK(fd);
@@ -554,7 +620,7 @@ SdioError sdLogWriteByte(const FileDes fd, const uint8_t value)
if (fileDes[fd].writeByteCache == NULL) {
lm = tlsf_malloc_r(&HEAP_DEFAULT, sizeof(LogMessage) + WRITE_BYTE_CACHE_SIZE);
if (lm == NULL) {
- return SDLOG_QUEUEFULL;
+ return storageStatus = SDLOG_MEMFULL;
}
lm->op.fcntl = FCNTL_WRITE;
@@ -574,30 +640,36 @@ SdioError sdLogWriteByte(const FileDes fd, const uint8_t value)
// instead of freeing buffer, we just reset cache seek.
if (status == SDLOG_QUEUEFULL) {
fileDes[fd].writeByteSeek = 0;
- return status;
+ return storageStatus = SDLOG_QUEUEFULL;
}
}
-
- return SDLOG_OK;
+ return storageStatus = SDLOG_OK;
}
+/*
+ if fatfs use stack for working buffers, stack size should be reserved accordingly
+ */
+#define WA_LOG_BASE_SIZE 1024
+#if _USE_LFN == 2
+#if _FS_EXFAT
+static THD_WORKING_AREA(waThdSdLog, WA_LOG_BASE_SIZE+((_MAX_LFN+1)*2)+(19*32));
+#else
+static THD_WORKING_AREA(waThdSdLog, WA_LOG_BASE_SIZE+((_MAX_LFN+1)*2));
+#endif
+#else
+static THD_WORKING_AREA(waThdSdLog, WA_LOG_BASE_SIZE);
+#endif
-
-
-/* enregistrer les fichiers ouverts de manière à les fermer
- si necessaire
- */
-static THD_WORKING_AREA(waThdSdLog, 1024);
-SdioError sdLoglaunchThread()
+SdioError sdLoglaunchThread ()
{
chThdSleepMilliseconds(100);
sdLogThd = chThdCreateStatic(waThdSdLog, sizeof(waThdSdLog),
NORMALPRIO + 1, thdSdLog, NULL);
if (sdLogThd == NULL) {
- return SDLOG_INTERNAL_ERROR;
+ return storageStatus = SDLOG_INTERNAL_ERROR;
} else {
- return SDLOG_OK;
+ return storageStatus = SDLOG_OK;
}
}
@@ -605,33 +677,33 @@ SdioError sdLogStopThread(void)
{
SdioError retVal = SDLOG_OK;
+ storageStatus = retVal;
if (sdLogThd == NULL) {
- return SDLOG_NOTHREAD;
+ return storageStatus = SDLOG_NOTHREAD;
}
LogMessage lm;
- // ask for closing (after flushing) all opened files
- for (uint8_t i = 0; i < SDLOG_NUM_BUFFER; i++) {
- if (fileDes[i].inUse) {
- flushWriteByteBuffer(i);
- lm.op.fcntl = FCNTL_CLOSE;
- lm.op.fd = i & 0x1f;
- if (msgqueue_copy_send(&messagesQueue, &lm, sizeof(LogMessage), MsgQueue_OUT_OF_BAND) < 0) {
- retVal = SDLOG_QUEUEFULL;
- }
- }
- }
+ /* // ask for closing (after flushing) all opened files */
+ /* for (uint8_t i=0; i 2)
static void thdSdLog(void *arg)
#else
@@ -804,22 +913,17 @@ static msg_t thdSdLog(void *arg)
{
(void) arg;
struct PerfBuffer {
- uint8_t buffer[SDLOG_WRITE_BUFFER_SIZE];
+ // each element of buffer should be word aligned for sdio efficient write
+ ALIGNED_VAR(4) uint8_t buffer[SDLOG_WRITE_BUFFER_SIZE] ;
uint16_t size;
} ;
UINT bw;
- static IN_STD_SECTION(struct PerfBuffer perfBuffers[SDLOG_NUM_BUFFER]) = {
- [0 ... SDLOG_NUM_BUFFER - 1] = {.buffer = {0}, .size = 0}
- };
-
- // FIXME above initialization doesn't seem to work for all GCC version
- // for now, also doing the good old way.
- memset(perfBuffers, 0, SDLOG_NUM_BUFFER * sizeof(struct PerfBuffer));
-
+ static IN_STD_SECTION_CLEAR(struct PerfBuffer perfBuffers[SDLOG_NUM_FILES]);
+ storageStatus = SDLOG_OK;
chRegSetThreadName("thdSdLog");
- while (!chThdShouldTerminateX()) {
- LogMessage *lm;
+ while (true) {
+ LogMessage *lm = NULL;
const int32_t retLen = (int32_t)(msgqueue_pop(&messagesQueue, (void **) &lm));
if (retLen > 0) {
FIL *fo = &fileDes[lm->op.fd].fil;
@@ -833,6 +937,7 @@ static msg_t thdSdLog(void *arg)
if (fileDes[lm->op.fd].inUse) {
if (curBufFill) {
f_write(fo, perfBuffer, curBufFill, &bw);
+ nbBytesWritten += bw;
perfBuffers[lm->op.fd].size = 0;
}
if (lm->op.fcntl == FCNTL_FLUSH) {
@@ -840,6 +945,7 @@ static msg_t thdSdLog(void *arg)
} else { // close
if (fileDes[lm->op.fd].tagAtClose) {
f_write(fo, "\r\nEND_OF_LOG\r\n", 14, &bw);
+ nbBytesWritten += bw;
}
f_close(fo);
fileDes[lm->op.fd].inUse = false; // store that file is closed
@@ -849,7 +955,8 @@ static msg_t thdSdLog(void *arg)
break;
case FCNTL_EXIT:
- chThdExit(SDLOG_OK);
+ tlsf_free_r(&HEAP_DEFAULT, lm); // to avoid a memory leak
+ chThdExit(storageStatus = SDLOG_NOTHREAD);
break; /* To exit from thread when asked : chThdTerminate
then send special message with FCNTL_EXIT */
@@ -867,11 +974,21 @@ static msg_t thdSdLog(void *arg)
const int32_t stayLen = SDLOG_WRITE_BUFFER_SIZE - curBufFill;
memcpy(&(perfBuffer[curBufFill]), lm->mess, (size_t)(stayLen));
FRESULT rc = f_write(fo, perfBuffer, SDLOG_WRITE_BUFFER_SIZE, &bw);
- f_sync(fo);
+ nbBytesWritten += bw;
+ // if there an autoflush period specified, flush to the mass storage media
+ // if timer has expired and rearm.
+ if (fileDes[lm->op.fd].autoFlushPeriod) {
+ const systime_t now = chVTGetSystemTimeX();
+ if ((now - fileDes[lm->op.fd].lastFlushTs) >
+ (fileDes[lm->op.fd].autoFlushPeriod * CH_CFG_ST_FREQUENCY)) {
+ f_sync(fo);
+ fileDes[lm->op.fd].lastFlushTs = now;
+ }
+ }
if (rc) {
- chThdExit(SDLOG_FATFS_ERROR);
+ chThdExit(storageStatus = SDLOG_FATFS_ERROR);
} else if (bw != SDLOG_WRITE_BUFFER_SIZE) {
- chThdExit(SDLOG_FSFULL);
+ chThdExit(storageStatus = SDLOG_FSFULL);
}
memcpy(perfBuffer, &(lm->mess[stayLen]), (uint32_t)(messLen - stayLen));
@@ -882,7 +999,7 @@ static msg_t thdSdLog(void *arg)
}
tlsf_free_r(&HEAP_DEFAULT, lm);
} else {
- chThdExit(SDLOG_INTERNAL_ERROR);
+ chThdExit(storageStatus = SDLOG_INTERNAL_ERROR);
}
}
#if (CH_KERNEL_MAJOR == 2)
@@ -905,7 +1022,7 @@ static SdioError getNextFIL(FileDes *fd)
// if there is a free slot in fileDes, use it
// else, if all slots are buzy, maximum open files limit
// is reach.
- for (FileDes i = 0; i < SDLOG_NUM_BUFFER; i++) {
+ for (FileDes i = 0; i < SDLOG_NUM_FILES; i++) {
if (fileDes[i].inUse == false) {
*fd = i;
fileDes[i].inUse = true;
@@ -915,4 +1032,15 @@ static SdioError getNextFIL(FileDes *fd)
return SDLOG_FDFULL;
}
+size_t sdLogGetNbBytesWrittenToStorage(void)
+{
+ return nbBytesWritten;
+}
+
+SdioError sdLogGetStorageStatus(void)
+{
+ return storageStatus;
+}
+
+
#endif
diff --git a/sw/airborne/modules/loggers/sdlog_chibios/sdLog.h b/sw/airborne/modules/loggers/sdlog_chibios/sdLog.h
index bc59bdd9d0..4422ebf5b8 100644
--- a/sw/airborne/modules/loggers/sdlog_chibios/sdLog.h
+++ b/sw/airborne/modules/loggers/sdlog_chibios/sdLog.h
@@ -29,7 +29,6 @@
#include "std.h"
#include "mcuconf.h"
-//#include "ff.h"
#include
#define NUMBERLEN 4
@@ -44,29 +43,53 @@ extern "C" {
This module is highly coupled with fatfs, and mcuconf.h
several MACRO should be defined before use
- FATFS (ffconf.h) :
- ° _FS_LOCK : number of simultaneously open file
- ° _FS_REENTRANT : If you need to open / close file during log, this should be set to 1 at
- the expense of more used cam and cpu.
- If you open all files prior to log data on them, it should be left to 0
+ FATFS (ffconf.h)
- MCUCONF.H (or any other header included before sdLog.h
+
+ mcuconf.h (or any other header included before sdLog.h
° SDLOG_ALL_BUFFERS_SIZE : (in bytes) cache buffer size shared between all opened log file
+ minumum size by opened log file should be at least 512 and
+ should be a POWER OF TWO
° SDLOG_MAX_MESSAGE_LEN : (in bytes) maximum length of a message
- ° SDLOG_QUEUE_BUCKETS : number of entries in queue
+ ° SDLOG_QUEUE_BUCKETS : number of entries in bufering queue
+ ° SDLOG_NUM_FILES : number of simultaneous opened log files
+
+ EXAMPLE:
+ #define SDLOG_QUEUE_BUCKETS 1024
+ #define SDLOG_MAX_MESSAGE_LEN 252
+ #define SDLOG_NUM_FILES 1
+ #define SDLOG_ALL_BUFFERS_SIZE (SDLOG_NUM_FILES*4096)
+
+
use of the api :
sdLogInit (initialize peripheral, verify sdCard availibility)
sdLogOpenLog : open file
- sdLogWriteXXX
- sdLogFlushLog : flush buffer (optional)
- sdLogCloseLog
- sdLogFinish
+ sdLogExpandLogFile : reserve contiguous space on storage
+ sdLogWriteXXX : write log using one off the many function of the API
+ sdLogCloseLog : close log
+ sdLogFinish : terminate logging thread
+
and asynchronous emergency close (power outage detection by example) :
sdLogCloseAllLogs
sdLogFinish
+ + ADVICE for maximizing throughtput by order of inportance
+ ° define STM32_SDC_SDIO_UNALIGNED_SUPPORT to FALSE in mcuconf.h
+ ° do not use sdLogFlushXXX API but instead give a flush period of 10 in sdLogOpenLog
+ ° SDLOG_ALL_BUFFERS_SIZE/SDLOG_NUM_FILES should be around 8192 and a power of two
+ ° reserve contiguous room for your entire log file using sdLogExpandLogFile
+ just after opening log
+ ° use class 10 SD card
+
+ + ADVICE for maximizing reliability
+ ° survey power loss, and call sdLogCloseAllLogs (false) when power loss is detected
+ after having powered off all you can (LEDs or anything draining power from MCU pins)
+ ° always check return status of function (sdLogOpenLog will fail if filesystem is dirty)
+ ° always check filesystem health with fsck (linux) or CHKDSK (windows) when
+ mounting sd card on a computer
+
*/
@@ -90,10 +113,12 @@ typedef enum {
SDLOG_FSFULL,
SDLOG_FDFULL,
SDLOG_QUEUEFULL,
+ SDLOG_MEMFULL,
SDLOG_NOTHREAD,
SDLOG_INTERNAL_ERROR,
+ SDLOG_CANNOT_EXPAND,
SDLOG_LOGNUM_ERROR,
- SDLOG_WAS_LAUNCHED
+ SDLOG_WAS_LAUNCHED,
} SdioError;
typedef struct _SdLogBuffer SdLogBuffer;
@@ -108,7 +133,7 @@ typedef int8_t FileDes;
* This function is available even without thread login facility : even
* if SDLOG_XXX macro are zeroed
* @param[out] freeSpaceInKo : if pointer in nonnull, return free space on filesystem
- * @return status (always check status)
+ * @return status (always check status)
*/
SdioError sdLogInit(uint32_t *freeSpaceInKo);
@@ -121,10 +146,10 @@ SdioError sdLogInit(uint32_t *freeSpaceInKo);
* if SDLOG_XXX macro are zeroed
* @param[in] prefix : the pattern for the file : example LOG_
* @param[in] directoryName : root directory where to find file
- * @param[out] nextFileName : file with path ready to be used for f_open system call
+ * @param[out] nextFileName : file with path ready to be used for f_open system call
* @param[in] nameLength : length of previous buffer
* @param[in] indexOffset : use 0 to retrieve last existent filename, 1 for next filename
- * @return status (always check status)
+ * @return status (always check status)
*/
SdioError getFileName(const char *prefix, const char *directoryName,
char *nextFileName, const size_t nameLength, const int indexOffset);
@@ -141,16 +166,16 @@ SdioError getFileName(const char *prefix, const char *directoryName,
* @param[in] prefix : the pattern for the file : example LOG_
* @param[in] directoryName : root directory where to find file
* @param[in] sizeConsideredEmpty : file whose size is less or equal to that value will be removed
- * @return status (always check status)
+ * @return status (always check status)
*/
SdioError removeEmptyLogs(const char *directoryName, const char *prefix,
const size_t sizeConsideredEmpty);
/**
* @brief unmount filesystem
* @details unmount filesystem, free sdio peripheral
- * This function is available even without thread login facility : even
- * if SDLOG_XXX macro are zeroed
- * @return status (always check status)
+ * This function is available even without thread login facility : even
+ * if SDLOG_XXX macro are zeroed
+ * @return status (always check status)
*/
SdioError sdLogFinish(void);
@@ -159,40 +184,68 @@ SdioError sdLogFinish(void);
/**
* @brief open new log file
* @details always open new file with numeric index
- * @param[out] fileObject : file descriptor : small integer between 0 and _FS_REENTRANT-1
+ * @param[out] fileObject : file descriptor : small integer between 0 and _FS_REENTRANT-1
* @param[in] directoryName : name of directory just under ROOT, created if nonexistant
* @param[in] fileName : the name will be appended with 3 digits number
+ * @param[in] autoFlushPeriod : if non 0, period in second at which flush to mass storage is done
+ * if 0, no autoflush is done.
* @param[in] appendTagAtClose : at close, a marker will be added to prove that the file is complete
- * and not corrupt. useful for text logging purpose, but probably not wanted fort binary
- * files.
- * @return status (always check status)
+ * and not corrupt. useful for text logging purpose, but probably not wanted for binary
+ * files.
+ * @return status (always check status)
*/
SdioError sdLogOpenLog(FileDes *fileObject, const char *directoryName, const char *fileName,
- bool appendTagAtClose);
+ const uint32_t autoFlushPeriod,
+ const bool appendTagAtClose);
+
+
+/**
+ * @brief expand underlying file to maximise throughtput
+ * @details ask underlying file system to prepare a contiguous data area to the file.
+ * if expand fail, file system is still avalaible but performance may suffer
+ * @param[in] fileObject : file descriptor returned by sdLogOpenLog
+ * @param[in] sizeInMo : size of the contiguous storage
+ * @param[in] preallocate : if true, the file is preallocated at asked size, more efficient
+ * but take room on storage ans is not easy to manipulate afterward because of big files
+ * even if no log id recorded on file
+ * @return status (always check status)
+ */
+SdioError sdLogExpandLogFile(const FileDes fileObject, const size_t sizeInMo,
+ const bool preallocate);
/**
* @brief flush ram buffer associated with file to sdCard
+ * @details *WARNING* this lower throughtput by a factor of ten or more,
+ * @details leading to lost messages if writing rate is high
* @param[in] fileObject : file descriptor returned by sdLogOpenLog
- * @return status (always check status)
+ * @return status (always check status)
*/
SdioError sdLogFlushLog(const FileDes fileObject);
+/**
+ * @brief flush all ram buffers to sdCard
+ * @details *WARNING* this lower throughtput by a factor of ten or more,
+ * @details leading to lost messages if writing rate is high
+ * @return status (always check status)
+ */
+SdioError sdLogFlushAllLogs(void);
+
/**
* @brief flush ram buffer then close file.
* @param[in] fileObject : file descriptor returned by sdLogOpenLog
- * @return status (always check status)
+ * @return status (always check status)
*/
SdioError sdLogCloseLog(const FileDes fileObject);
/**
* @brief close all opened logs then stop worker thread
* @param[in] flush : if true : flush all ram buffers before closing (take more time)
- * if false : close imediatly files without flushing buffers,
- * more chance to keep filesystem integrity in case of
- * emergency close after power outage is detected
- * @return status (always check status)
+ * if false : close imediatly files without flushing buffers,
+ * more chance to keep filesystem integrity in case of
+ * emergency close after power outage is detected
+ * @return status (always check status)
*/
SdioError sdLogCloseAllLogs(bool flush);
@@ -201,7 +254,7 @@ SdioError sdLogCloseAllLogs(bool flush);
* @brief log text
* @param[in] fileObject : file descriptor returned by sdLogOpenLog
* @param[in] fmt : format and args in printf convention
- * @return status (always check status)
+ * @return status (always check status)
*/
SdioError sdLogWriteLog(const FileDes fileObject, const char *fmt, ...);
@@ -211,24 +264,25 @@ SdioError sdLogWriteLog(const FileDes fileObject, const char *fmt, ...);
* @param[in] fileObject : file descriptor returned by sdLogOpenLog
* @param[in] buffer : memory pointer on buffer
* @param[in] len : number of bytes to write
- * @return status (always check status)
+ * @return status (always check status)
*/
SdioError sdLogWriteRaw(const FileDes fileObject, const uint8_t *buffer, const size_t len);
+
/**
* @brief log binary data limiting buffer copy by preallocating space
* @param[in] len : number of bytes to write
- * @param[out] sdb : pointer to opaque object pointer containing buffer
- * there is two accessor functions (below) to access
- * buffer ptr and buffer len.
- * @details usage of the set of 4 functions :
- * SdLogBuffer *sdb;
- * sdLogAllocSDB (&sdb, 100);
- * memcpy (getBufferFromSDB(sdb), SOURCE, offset);
- * sdLogSeekBufferFromSDB (sdb, offset);
- * sdLogWriteSDB (file, sdb);
- * @return status (always check status)
- */
+ * @param[out] sdb : pointer to opaque object pointer containing buffer
+ * there is two accessor functions (below) to access
+ * buffer ptr and buffer len.
+ * @details usage of the set of 4 functions :
+ * SdLogBuffer *sdb;
+ * sdLogAllocSDB (&sdb, 100);
+ * memcpy (getBufferFromSDB(sdb), SOURCE, offset);
+ * sdLogSeekBufferFromSDB (sdb, offset);
+ * sdLogWriteSDB (file, sdb);
+ * @return status (always check status)
+*/
SdioError sdLogAllocSDB(SdLogBuffer **sdb, const size_t len);
/**
@@ -236,38 +290,38 @@ SdioError sdLogAllocSDB(SdLogBuffer **sdb, const size_t len);
* message + offset managed by sdLogSeekBufferFromSDB
* @param[in] sdb : pointer to opaque object containing buffer
* and previously filled by sdLogAllocSDB
- * @return pointer to writable area
- */
-char *sdLogGetBufferFromSDB(SdLogBuffer *sdb);
+ * @return pointer to writable area
+*/
+char *sdLogGetBufferFromSDB(SdLogBuffer *sdb);
/**
* @brief manage internal offset in user buffer
* @param[in] sdb : pointer to opaque object containing buffer
- * and previously filled by sdLogAllocSDB
- * offset : increment internal offset with this value
- * @return true if offset is withing internal buffer boundary
- * false if offset is NOT withing internal buffer boundary, in this case,
- * no keek is done
- */
-bool sdLogSeekBufferFromSDB(SdLogBuffer *sdb, uint32_t offset);
+ * and previously filled by sdLogAllocSDB
+ * offset : increment internal offset with this value
+ * @return true if offset is withing internal buffer boundary
+ false if offset is NOT withing internal buffer boundary, in this case,
+ no seek is done
+*/
+bool sdLogSeekBufferFromSDB(SdLogBuffer *sdb, uint32_t offset);
/**
* @brief return len of the writable area of a preallocated message (this take into account
- * the offset)
+ * the offset)
* @param[in] sdb : pointer to opaque object containing buffer
- * and previously filled by sdLogAllocSDB
- * @return len of writable area
- */
+ * and previously filled by sdLogAllocSDB
+ * @return len of writable area
+*/
size_t sdLogGetBufferLenFromSDB(SdLogBuffer *sdb);
/**
* @brief send a preallocted message after it has been filled
* @param[in] fileObject : file descriptor returned by sdLogOpenLog
* @param[in] sdb : pointer to opaque object containing buffer
- * and previously filled by sdLogAllocSDB
- * @return status (always check status)
+ * and previously filled by sdLogAllocSDB
+ * @return status (always check status)
*/
SdioError sdLogWriteSDB(const FileDes fd, SdLogBuffer *sdb);
@@ -276,9 +330,24 @@ SdioError sdLogWriteSDB(const FileDes fd, SdLogBuffer *sdb);
* @brief log one byte of binary data
* @param[in] fileObject : file descriptor returned by sdLogOpenLog
* @param[in] value : byte to log
- * @return status (always check status)
+ * @return status (always check status)
*/
SdioError sdLogWriteByte(const FileDes fileObject, const uint8_t value);
+
+/**
+ * @brief return number of bytes actually written to the mass storage
+ * @return number of bytes actually written to the mass storage (due to buffering, this can be
+ different than number of byte sent to the logger)
+*/
+size_t sdLogGetNbBytesWrittenToStorage(void);
+
+/**
+ * @brief return storage backend status
+ * @return storage backend status
+*/
+SdioError sdLogGetStorageStatus(void);
+
+
#endif
diff --git a/sw/airborne/modules/loggers/sdlog_chibios/usbStorage.c b/sw/airborne/modules/loggers/sdlog_chibios/usbStorage.c
index a843423f4d..8c6b04eafe 100644
--- a/sw/airborne/modules/loggers/sdlog_chibios/usbStorage.c
+++ b/sw/airborne/modules/loggers/sdlog_chibios/usbStorage.c
@@ -36,198 +36,21 @@
#include "mcu_periph/sdio.h"
#include "led.h"
-static uint8_t nibbleToHex(uint8_t nibble);
-static void populateSerialNumberDescriptorData(void);
static void thdUsbStorage(void *arg);
static thread_t *usbStorageThreadPtr = NULL;
/* USB mass storage driver */
-static USBMassStorageDriver UMSD1;
static bool isRunning = false;
-/* endpoint index */
-#define USB_MS_DATA_EP 1
-
-/* USB device descriptor */
-static const uint8_t deviceDescriptorData[] = {
- USB_DESC_DEVICE
- (
- 0x0200, /* supported USB version (2.0) */
- 0x00, /* device class (none, specified in interface) */
- 0x00, /* device sub-class (none, specified in interface) */
- 0x00, /* device protocol (none, specified in interface) */
- 64, /* max packet size of control end-point */
- 0x0483, /* vendor ID (STMicroelectronics!) */
- 0x5740, /* product ID (STM32F407) */
- 0x0100, /* device release number */
- 1, /* index of manufacturer string descriptor */
- 2, /* index of product string descriptor */
- 3, /* index of serial number string descriptor */
- 1 /* number of possible configurations */
- )
-};
-static const USBDescriptor deviceDescriptor = {
- sizeof(deviceDescriptorData),
- deviceDescriptorData
-};
-
-/* configuration descriptor */
-static const uint8_t configurationDescriptorData[] = {
- /* configuration descriptor */
- USB_DESC_CONFIGURATION
- (
- 32, /* total length */
- 1, /* number of interfaces */
- 1, /* value that selects this configuration */
- 0, /* index of string descriptor describing this configuration */
- 0xC0, /* attributes (self-powered) */
- 50 /* max power (100 mA) */
- ),
-
- /* interface descriptor */
- USB_DESC_INTERFACE
- (
- 0, /* interface number */
- 0, /* value used to select alternative setting */
- 2, /* number of end-points used by this interface */
- 0x08, /* interface class (Mass Storage) */
- 0x06, /* interface sub-class (SCSI Transparent Storage) */
- 0x50, /* interface protocol (Bulk Only) */
- 0 /* index of string descriptor describing this interface */
- ),
-
- /* end-point descriptor */
- USB_DESC_ENDPOINT
- (
- USB_MS_DATA_EP | 0x80, /* address (end point index | OUT direction) */
- USB_EP_MODE_TYPE_BULK, /* attributes (bulk) */
- 64, /* max packet size */
- 0x05 /* polling interval (ignored for bulk end-points) */
- ),
-
- /* end-point descriptor */
- USB_DESC_ENDPOINT
- (
- USB_MS_DATA_EP | 0x00, /* address (end point index | IN direction) */
- USB_EP_MODE_TYPE_BULK, /* attributes (bulk) */
- 64, /* max packet size */
- 0x05 /* polling interval (ignored for bulk end-points) */
- )
-};
-static const USBDescriptor configurationDescriptor = {
- sizeof(configurationDescriptorData),
- configurationDescriptorData
-};
-
-/* Language descriptor */
-static const uint8_t languageDescriptorData[] = {
- USB_DESC_BYTE(4),
- USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
- USB_DESC_WORD(0x0409) /* U.S. english */
-};
-static const USBDescriptor languageDescriptor = {
- sizeof(languageDescriptorData),
- languageDescriptorData
-};
-
-/* Vendor descriptor */
-static const uint8_t vendorDescriptorData[] = {
- USB_DESC_BYTE(20),
- USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
- 'P', 0, 'a', 0, 'p', 0, 'a', 0, 'r', 0, 'a', 0, 'z', 0, 'z', 0, 'i', 0
-};
-static const USBDescriptor vendorDescriptor = {
- sizeof(vendorDescriptorData),
- vendorDescriptorData
-};
-
-/* Product descriptor */
-static const uint8_t productDescriptorData[] = {
- USB_DESC_BYTE(20),
- USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
- 'A', 0, 'u', 0, 't', 0, 'o', 0, 'p', 0, 'i', 0, 'l', 0, 'o', 0, 't', 0
-};
-static const USBDescriptor productDescriptor = {
- sizeof(productDescriptorData),
- productDescriptorData
-};
-
-/* Serial number descriptor from stm32 uniq id */
-/* uniq id is 12 bytes which gives 24 char which require 50 bytes for usb description */
-/* this array is the only one in ram (others in flash), and should be populated before */
-/* usb initialisation */
-uint8_t serialNumberDescriptorData[50] = {
- USB_DESC_BYTE(50),
- USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
- 0
-};
-static const USBDescriptor serialNumberDescriptor = {
- sizeof(serialNumberDescriptorData),
- serialNumberDescriptorData
-};
-
-/* Handles GET_DESCRIPTOR requests from the USB host */
-static const USBDescriptor *getDescriptor(USBDriver *usbp, uint8_t type, uint8_t index, uint16_t lang)
-{
- (void)usbp;
- (void)lang;
-
- switch (type) {
- case USB_DESCRIPTOR_DEVICE:
- return &deviceDescriptor;
-
- case USB_DESCRIPTOR_CONFIGURATION:
- return &configurationDescriptor;
-
- case USB_DESCRIPTOR_STRING:
- switch (index) {
- case 0: return &languageDescriptor;
- case 1: return &vendorDescriptor;
- case 2: return &productDescriptor;
- case 3: return &serialNumberDescriptor;
- }
- }
-
- return 0;
-}
-
-/* Handles global events of the USB driver */
-static void usbEvent(USBDriver *usbp, usbevent_t event)
-{
- (void) usbp;
-
- switch (event) {
- case USB_EVENT_CONFIGURED:
- chSysLockFromISR();
- msdConfigureHookI(&UMSD1);
- chSysUnlockFromISR();
- break;
-
- case USB_EVENT_RESET:
- case USB_EVENT_ADDRESS:
- case USB_EVENT_SUSPEND:
- case USB_EVENT_WAKEUP:
- case USB_EVENT_STALLED:
- default:
- break;
- }
-}
-
-/* Configuration of the USB driver */
-const USBConfig usbConfig = {
- usbEvent,
- getDescriptor,
- msdRequestsHook,
- 0
-};
/* Turns on a LED when there is I/O activity on the USB port */
static void usbActivity(bool active __attribute__((unused)))
{
#ifdef SDLOG_USB_LED
- if (active)
+ if (active) {
LED_ON(SDLOG_USB_LED);
- else
+ } else {
LED_OFF(SDLOG_USB_LED);
+ }
#endif
}
@@ -237,16 +60,15 @@ static USBMassStorageConfig msdConfig = {
(BaseBlockDevice *) &SDCD1,
USB_MS_DATA_EP,
&usbActivity,
- "DPprz_sd",
- "DApogee",
- "0.1"
+ "Pprz_sd",
+ "AutoPilot",
+ "0.2"
};
static THD_WORKING_AREA(waThdUsbStorage, 1024);
void usbStorageStartPolling(void)
{
- populateSerialNumberDescriptorData();
usbStorageThreadPtr = chThdCreateStatic(waThdUsbStorage, sizeof(waThdUsbStorage),
NORMALPRIO + 2, thdUsbStorage, NULL);
@@ -279,12 +101,6 @@ static void thdUsbStorage(void *arg)
uint antiBounce = 5;
event_listener_t connected;
- // Should use EXTI interrupt instead of active polling,
- // but in the chibios_opencm3 implementation, since EXTI is
- // used via libopencm3, ISR are routed on pprz/opencm3 and cannot
- // be used concurrently by chibios api
- // Should be fixed when using chibios-rt branch
- // FIXME: Is the comment still relevant?
while (!chThdShouldTerminateX() && antiBounce) {
const bool usbConnected = palReadPad(SDLOG_USB_VBUS_PORT, SDLOG_USB_VBUS_PIN);
if (usbConnected) {
@@ -299,7 +115,8 @@ static void thdUsbStorage(void *arg)
chRegSetThreadName("UsbStorage:connected");
/* Stop the logs*/
- sdlog_chibios_finish(false);
+ // it's not a powerloss, wa have time to flush the ram buffer
+ sdlog_chibios_finish(true);
/* connect sdcard sdc interface sdio */
@@ -308,19 +125,10 @@ static void thdUsbStorage(void *arg)
}
/* initialize the USB mass storage driver */
- msdInit(&UMSD1);
-
- /* start the USB mass storage service */
- msdStart(&UMSD1, &msdConfig);
-
- /* start the USB driver */
- usbDisconnectBus(&USBD1);
- chThdSleepMilliseconds(1000);
- usbStart(&USBD1, &usbConfig);
- usbConnectBus(&USBD1);
+ init_msd_driver(NULL, &msdConfig);
/* wait for a real usb storage connexion before shutting down autopilot */
- chEvtRegisterMask(&UMSD1.evt_connected, &connected, EVENT_MASK(1));
+ msd_register_evt_connected(&connected, EVENT_MASK(1));
chEvtWaitOne(EVENT_MASK(1));
/* stop autopilot */
@@ -331,15 +139,11 @@ static void thdUsbStorage(void *arg)
chThdSleepMilliseconds(10);
}
+ deinit_msd_driver();
- /* then close open descriptors and reboot autopilot */
- usbDisconnectBus(&USBD1);
chThdSleepMilliseconds(500);
- msdStop(&UMSD1);
- sdio_disconnect();
mcu_reset();
- return;
}
bool usbStorageIsItRunning(void)
@@ -347,24 +151,3 @@ bool usbStorageIsItRunning(void)
return isRunning;
}
-static uint8_t nibbleToHex(uint8_t nibble)
-{
- nibble &= 0x0F;
- return nibble < 10 ? nibble + '0' : nibble + 'A' - 10;
-}
-
-
-static void populateSerialNumberDescriptorData(void)
-{
- const uint8_t *UniqProcessorId = (uint8_t *) 0x1FFF7A10;
- const uint8_t UniqProcessorIdLen = 12;
-
- uint8_t *baseDdPtr = &serialNumberDescriptorData[2];
- for (uint32_t i = 0; i < UniqProcessorIdLen; i++) {
- *baseDdPtr++ = nibbleToHex(UniqProcessorId[i] >> 4);
- *baseDdPtr++ = 0;
- *baseDdPtr++ = nibbleToHex(UniqProcessorId[i]);
- *baseDdPtr++ = 0;
- }
-}
-
diff --git a/sw/airborne/modules/loggers/sdlog_chibios/usb_msd.c b/sw/airborne/modules/loggers/sdlog_chibios/usb_msd.c
index 35d15d22ff..c32f7ea8b4 100644
--- a/sw/airborne/modules/loggers/sdlog_chibios/usb_msd.c
+++ b/sw/airborne/modules/loggers/sdlog_chibios/usb_msd.c
@@ -26,6 +26,10 @@
#include "modules/loggers/sdlog_chibios/usb_msd.h"
+
+static THD_WORKING_AREA(mass_storage_thread_wa, 1024);
+
+static USBMassStorageDriver UMSD;
/* Request types */
#define MSD_REQ_RESET 0xFF
#define MSD_GET_MAX_LUN 0xFE
@@ -93,6 +97,15 @@
#define SCSI_ASENSEQ_INITIALIZING_COMMAND_REQUIRED 0x02
#define SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07
+
+
+static void mass_storage_thread(void *arg);
+void debug_snd_evt_i(eventmask_t evt);
+void debug_snd_evt_inl(eventmask_t evt);
+void debug_snd_evt_nl(eventmask_t evt);
+
+
+thread_t *dbg_printer = NULL;
/**
* @brief Response to a READ_CAPACITY_10 SCSI command
*/
@@ -119,22 +132,23 @@ static uint8_t rw_buf[2][512];
typedef uint32_t DWORD __attribute__((__may_alias__));;
typedef uint16_t WORD __attribute__((__may_alias__));
-
/**
* @brief Byte-swap a 32 bits unsigned integer
*/
-static inline DWORD swap_uint32(DWORD val);
-static inline DWORD swap_uint32(DWORD val)
+static inline DWORD swap_uint32(const DWORD val)
{
- val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
- return ((val << 16) & 0xFFFF0000) | ((val >> 16) & 0x0000FFFF);
+ DWORD v = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
+ return ((v << 16) & 0xFFFF0000) | ((v >> 16) & 0x0000FFFF);
}
/**
* @brief Byte-swap a 16 bits unsigned integer
*/
-#define swap_uint16(x) (((((WORD)(x)) >> 8) & 0xff) | ((((WORD)(x)) & 0xff) << 8))
+static inline WORD swap_uint16(const WORD val)
+{
+ return (((val >> 8) & 0xff) | ((val & 0xff) << 8));
+}
static void msd_handle_end_point_notification(USBDriver *usbp, usbep_t ep);
/**
@@ -174,6 +188,8 @@ void msdConfigureHookI(USBMassStorageDriver *msdp)
{
usbInitEndpointI(msdp->config->usbp, msdp->config->bulk_ep, &ep_data_config);
chBSemSignalI(&msdp->bsem);
+ SEM_RELEASED;
+ debug_snd_evt_inl(EVT_SEM_RELEASED);
chEvtBroadcastI(&msdp->evt_connected);
}
@@ -207,11 +223,39 @@ bool msdRequestsHook(USBDriver *usbp)
return false;
}
- /* reset all endpoints */
- /* TODO!*/
+ /*
+ As required by the BOT specification, the Bulk-only mass storage reset request (classspecific
+ request) is implemented. This request is used to reset the mass storage device and
+ its associated interface. This class-specific request should prepare the device for the next
+ CBW from the host.
+ To generate the BOT Mass Storage Reset, the host must send a device request on the
+ default pipe of:
+ • bmRequestType: Class, interface, host to device
+ • bRequest field set to 255 (FFh)
+ • wValue field set to ‘0’
+ • wIndex field set to the interface number
+ • wLength field set to ‘0’
+ */
+ UMSD.bot_reset = true;
+ chSysLockFromISR();
+
+ /* release and abandon current transmission */
+ chBSemResetI(&UMSD.bsem, false);
+ usbStallReceiveI(usbp, UMSD.config->bulk_ep);
+ usbStallTransmitI(usbp, UMSD.config->bulk_ep);
/* The device shall NAK the status stage of the device request until
* the Bulk-Only Mass Storage Reset is complete.
- */
+ * NAK EP1 in and out */
+ UMSD.config->usbp->otg->ie[UMSD.config->bulk_ep].DIEPCTL = DIEPCTL_SNAK;
+ UMSD.config->usbp->otg->oe[UMSD.config->bulk_ep].DOEPCTL = DOEPCTL_SNAK;
+
+ chSysUnlockFromISR();
+ UMSD.state = MSD_BOT_RESET;
+
+ /* response to this request using EP0 */
+ usbSetupTransfer(usbp, 0, 0, NULL);
+ debug_snd_evt_i(EVT_BOT_RESET);
+
return true;
case MSD_GET_MAX_LUN:
/* check that it is a DEV2HOST request */
@@ -239,10 +283,11 @@ bool msdRequestsHook(USBDriver *usbp)
*/
static void msd_wait_for_isr(USBMassStorageDriver *msdp)
{
-
/* sleep until it completes */
chSysLock();
chBSemWaitS(&msdp->bsem);
+ debug_snd_evt_inl(EVT_SEM_TAKEN);
+ SEM_TAKEN;
chSysUnlock();
}
@@ -253,10 +298,9 @@ static void msd_handle_end_point_notification(USBDriver *usbp, usbep_t ep)
{
(void)usbp;
- (void)ep;
-
chSysLockFromISR();
chBSemSignalI(&((USBMassStorageDriver *)usbp->in_params[ep])->bsem);
+ SEM_RELEASED;
chSysUnlockFromISR();
}
@@ -265,7 +309,11 @@ static void msd_handle_end_point_notification(USBDriver *usbp, usbep_t ep)
*/
static void msd_start_transmit(USBMassStorageDriver *msdp, const uint8_t *buffer, size_t size)
{
+
chSysLock();
+ if (msdp->bot_reset) {
+ msdp->config->usbp->transmitting = 0;
+ }
usbStartTransmitI(msdp->config->usbp, msdp->config->bulk_ep, buffer, size);
chSysUnlock();
}
@@ -275,7 +323,11 @@ static void msd_start_transmit(USBMassStorageDriver *msdp, const uint8_t *buffer
*/
static void msd_start_receive(USBMassStorageDriver *msdp, uint8_t *buffer, size_t size)
{
+
chSysLock();
+ if (msdp->bot_reset) {
+ msdp->config->usbp->receiving = 0;
+ }
usbStartReceiveI(msdp->config->usbp, msdp->config->bulk_ep, buffer, size);
chSysUnlock();
}
@@ -296,6 +348,8 @@ static inline void msd_scsi_set_sense(USBMassStorageDriver *msdp, uint8_t key, u
bool msd_scsi_process_inquiry(USBMassStorageDriver *msdp)
{
+ debug_snd_evt_nl(EVT_SCSI_PROC_INQ);
+
msd_cbw_t *cbw = &(msdp->cbw);
/* check the EVPD bit (Vital Product Data) */
@@ -309,7 +363,6 @@ bool msd_scsi_process_inquiry(USBMassStorageDriver *msdp)
uint8_t response[] = {'0'}; /* TODO */
msd_start_transmit(msdp, response, sizeof(response));
msdp->result = true;
-
/* wait for ISR */
return true;
}
@@ -352,7 +405,7 @@ bool msd_scsi_process_request_sense(USBMassStorageDriver *msdp)
*/
bool msd_scsi_process_read_capacity_10(USBMassStorageDriver *msdp)
{
-
+ debug_snd_evt_nl(EVT_SCSI_REQ_READ_CAP10);
static msd_scsi_read_capacity_10_response_t response;
response.block_size = swap_uint32(msdp->block_dev_info.blk_size);
@@ -370,7 +423,6 @@ bool msd_scsi_process_read_capacity_10(USBMassStorageDriver *msdp)
*/
bool msd_scsi_process_send_diagnostic(USBMassStorageDriver *msdp)
{
-
msd_cbw_t *cbw = &(msdp->cbw);
if (!(cbw->scsi_cmd_data[1] & (1 << 2))) {
@@ -395,7 +447,7 @@ bool msd_scsi_process_send_diagnostic(USBMassStorageDriver *msdp)
*/
bool msd_scsi_process_start_read_write_10(USBMassStorageDriver *msdp)
{
-
+ debug_snd_evt_nl(EVT_SCSI_REQ_SENSE10);
msd_cbw_t *cbw = &(msdp->cbw);
if ((cbw->scsi_cmd_data[0] == SCSI_CMD_WRITE_10) && blkIsWriteProtected(msdp->config->bbdp)) {
@@ -534,7 +586,7 @@ bool msd_scsi_process_start_stop_unit(USBMassStorageDriver *msdp)
*/
bool msd_scsi_process_mode_sense_6(USBMassStorageDriver *msdp)
{
-
+ debug_snd_evt_nl(EVT_SCSI_REQ_SENSE6);
static uint8_t response[4] = {
0x03, /* number of bytes that follow */
0x00, /* medium type is SBC */
@@ -555,6 +607,7 @@ bool msd_scsi_process_mode_sense_6(USBMassStorageDriver *msdp)
bool msd_scsi_process_read_format_capacities(USBMassStorageDriver *msdp)
{
+ debug_snd_evt_nl(EVT_SCSI_REQ_READ_FMT_CAP);
msd_scsi_read_format_capacities_response_t response;
response.capacity_list_length = 1;
response.block_count = swap_uint32(msdp->block_dev_info.blk_num);
@@ -572,10 +625,15 @@ bool msd_scsi_process_read_format_capacities(USBMassStorageDriver *msdp)
*/
bool msd_scsi_process_test_unit_ready(USBMassStorageDriver *msdp)
{
-
+ debug_snd_evt_nl(EVT_SCSI_REQ_TEST_UNIT_READY);
if (blkIsInserted(msdp->config->bbdp)) {
/* device inserted and ready */
msdp->result = true;
+ /* device not present or not ready */
+ msd_scsi_set_sense(msdp,
+ SCSI_SENSE_KEY_RECOVERED_ERROR,
+ SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
+ SCSI_ASENSEQ_NO_QUALIFIER);
} else {
/* device not present or not ready */
msd_scsi_set_sense(msdp,
@@ -594,8 +652,10 @@ bool msd_scsi_process_test_unit_ready(USBMassStorageDriver *msdp)
*/
bool msd_wait_for_command_block(USBMassStorageDriver *msdp)
{
+ debug_snd_evt_nl(EVT_WAIT_FOR_COMMAND_BLOCK);
msd_start_receive(msdp, (uint8_t *)&msdp->cbw, sizeof(msdp->cbw));
+
msdp->state = MSD_READ_COMMAND_BLOCK;
/* wait for ISR */
@@ -613,6 +673,7 @@ bool msd_read_command_block(USBMassStorageDriver *msdp)
/* by default transition back to the idle state */
msdp->state = MSD_IDLE;
+
/* check the command */
if ((cbw->signature != MSD_CBW_SIGNATURE) ||
(cbw->lun > 0) ||
@@ -626,12 +687,24 @@ bool msd_read_command_block(USBMassStorageDriver *msdp)
usbStallTransmitI(msdp->config->usbp, msdp->config->bulk_ep);
chSysUnlock();
+ msd_scsi_set_sense(msdp,
+ SCSI_SENSE_KEY_ILLEGAL_REQUEST,
+ SCSI_ASENSE_INVALID_FIELD_IN_CDB,
+ SCSI_ASENSEQ_NO_QUALIFIER);
+
/* don't wait for ISR */
+ msdp->result = false;
return false;
}
bool sleep = false;
+
+ /* check the command */
+ if (cbw->signature != MSD_CBW_SIGNATURE) {
+ sleep = msd_scsi_process_test_unit_ready(msdp);
+ }
+ //if (msdp->result == true)
/* check the command */
switch (cbw->scsi_cmd_data[0]) {
case SCSI_CMD_INQUIRY:
@@ -706,7 +779,7 @@ bool msd_read_command_block(USBMassStorageDriver *msdp)
}
/* wait for ISR if needed */
- if (sleep) {
+ if (sleep & !msdp->bot_reset) {
msd_wait_for_isr(msdp);
}
@@ -719,7 +792,7 @@ bool msd_read_command_block(USBMassStorageDriver *msdp)
usbStallTransmitI(msdp->config->usbp, msdp->config->bulk_ep);
chSysUnlock();
- /*return false;*/
+ return false;
}
/* update the command status wrapper and send it to the host */
@@ -734,47 +807,6 @@ bool msd_read_command_block(USBMassStorageDriver *msdp)
return true;
}
-/**
- * @brief Mass storage thread that processes commands
- */
-static THD_WORKING_AREA(mass_storage_thread_wa, 1024);
-static void mass_storage_thread(void *arg)
-{
-
- USBMassStorageDriver *msdp = (USBMassStorageDriver *)arg;
-
- chRegSetThreadName("USB-MSD");
-
- bool wait_for_isr = false;
-
- /* wait for the usb to be initialised */
- msd_wait_for_isr(msdp);
-
- while (!chThdShouldTerminateX()) {
- wait_for_isr = false;
-
- /* wait on data depending on the current state */
- switch (msdp->state) {
- case MSD_IDLE:
- wait_for_isr = msd_wait_for_command_block(msdp);
- break;
- case MSD_READ_COMMAND_BLOCK:
- wait_for_isr = msd_read_command_block(msdp);
- break;
- case MSD_EJECTED:
- /* disconnect usb device */
- usbDisconnectBus(msdp->config->usbp);
- usbStop(msdp->config->usbp);
- chThdExit(0);
- }
-
- /* wait until the ISR wakes thread */
- if (wait_for_isr) {
- msd_wait_for_isr(msdp);
- }
- }
-
-}
/**
* @brief Initializse a USB mass storage driver
@@ -782,8 +814,9 @@ static void mass_storage_thread(void *arg)
void msdInit(USBMassStorageDriver *msdp)
{
- chDbgAssert(msdp != NULL, "msdInit");
-
+ chDbgCheck(msdp != NULL);
+ msdp->bot_reset = false;
+ msdp->reconfigured_or_reset_event = false;
msdp->config = NULL;
msdp->thread = NULL;
msdp->state = MSD_IDLE;
@@ -794,6 +827,7 @@ void msdInit(USBMassStorageDriver *msdp)
/* initialise the binary semaphore as taken */
chBSemObjectInit(&msdp->bsem, true);
+ debug_snd_evt_i(EVT_SEM_TAKEN);
/* initialise the sense data structure */
size_t i;
@@ -820,9 +854,9 @@ void msdInit(USBMassStorageDriver *msdp)
void msdStart(USBMassStorageDriver *msdp, const USBMassStorageConfig *config)
{
- chDbgAssert(msdp != NULL, "msdStart");
- chDbgAssert(config != NULL, "msdStart");
- chDbgAssert(msdp->thread == NULL, "msdStart");
+ chDbgCheck(msdp != NULL);
+ chDbgCheck(config != NULL);
+ chDbgCheck(msdp->thread == NULL);
/* save the configuration */
msdp->config = config;
@@ -856,8 +890,7 @@ void msdStart(USBMassStorageDriver *msdp, const USBMassStorageConfig *config)
config->usbp->out_params[config->bulk_ep] = (void *)msdp;
/* run the thread */
- msdp->thread = chThdCreateStatic(mass_storage_thread_wa, sizeof(mass_storage_thread_wa), NORMALPRIO + 1,
- mass_storage_thread, msdp);
+ msdp->thread = chThdCreateStatic(mass_storage_thread_wa, sizeof(mass_storage_thread_wa), NORMALPRIO, mass_storage_thread, msdp);
}
/**
@@ -866,7 +899,7 @@ void msdStart(USBMassStorageDriver *msdp, const USBMassStorageConfig *config)
void msdStop(USBMassStorageDriver *msdp)
{
- chDbgAssert(msdp->thread != NULL, "msdStop");
+ chDbgCheck(msdp->thread != NULL);
/* notify the thread that it's over */
chThdTerminate(msdp->thread);
@@ -880,3 +913,310 @@ void msdStop(USBMassStorageDriver *msdp)
msdp->config->usbp->in_params[msdp->config->bulk_ep] = NULL;
msdp->config->usbp->out_params[msdp->config->bulk_ep] = NULL;
}
+
+
+
+
+void debug_snd_evt_i(eventmask_t evt)
+{
+ if (dbg_printer != NULL) {
+ chSysLockFromISR();
+ chEvtSignalI(dbg_printer, evt);
+ chSysUnlockFromISR();
+ }
+}
+
+void debug_snd_evt_inl(eventmask_t evt)
+{
+ if (dbg_printer != NULL) {
+ chEvtSignalI(dbg_printer, evt);
+ }
+}
+
+void debug_snd_evt_nl(eventmask_t evt)
+{
+ if (dbg_printer != NULL) {
+ chEvtSignal(dbg_printer, evt);
+ }
+}
+
+/* Handles global events of the USB driver */
+static void usbEvent(USBDriver *usbp, usbevent_t event)
+{
+ (void) usbp;
+ switch (event) {
+ case USB_EVENT_CONFIGURED:
+ chSysLockFromISR();
+ UMSD.reconfigured_or_reset_event = true;
+ msdConfigureHookI(&UMSD);
+ chSysUnlockFromISR();
+ break;
+
+ case USB_EVENT_RESET:
+ debug_snd_evt_i(EVT_USB_RESET);
+ UMSD.reconfigured_or_reset_event = true;
+ break;
+ case USB_EVENT_ADDRESS:
+ case USB_EVENT_SUSPEND:
+ case USB_EVENT_WAKEUP:
+ case USB_EVENT_STALLED:
+ break;
+ default:
+ break;
+ }
+}
+
+/* USB device descriptor */
+static const uint8_t deviceDescriptorData[] = {
+ USB_DESC_DEVICE
+ (
+ 0x0200, /* supported USB version (2.0) */
+ 0x00, /* interface class */
+ 0x00, /* interface sub-class */
+ 0x00, /* interface protocol */
+ 64, /* max packet size of control end-point */
+ 0x0483, /* vendor ID (ST) */
+ 0xBABE, /* product ID (Babe) */
+ 0x0100, /* device release number */
+ 1, /* index of manufacturer string descriptor */
+ 2, /* index of product string descriptor */
+ 3, /* index of serial number string descriptor */
+ 1 /* number of possible configurations */
+ )
+};
+static const USBDescriptor deviceDescriptor = {
+ sizeof(deviceDescriptorData),
+ deviceDescriptorData
+};
+
+/* configuration descriptor */
+static const uint8_t configurationDescriptorData[] = {
+ /* configuration descriptor */
+ USB_DESC_CONFIGURATION
+ (
+ 32, /* total length */
+ 1, /* number of interfaces */
+ 1, /* value that selects this configuration */
+ 0, /* index of string descriptor describing this configuration */
+ 0xC0, /* attributes (self-powered) */
+ 100 /* max power (100 mA) */
+ ),
+
+ /* interface descriptor */
+ USB_DESC_INTERFACE
+ (
+ 0, /* interface number */
+ 0, /* value used to select alternative setting */
+ 2, /* number of end-points used by this interface */
+ 0x08, /* interface class (Mass Storage) */
+ 0x06, /* interface sub-class (SCSI Transparent Storage) */
+ 0x50, /* interface protocol (Bulk Only) */
+ 0 /* index of string descriptor describing this interface */
+ ),
+
+ /* end-point descriptor */
+ USB_DESC_ENDPOINT
+ (
+ USB_MS_DATA_EP | 0x80, /* address (end point index | OUT direction) */
+ USB_EP_MODE_TYPE_BULK, /* attributes (bulk) */
+ 64, /* max packet size */
+ 0x05 /* polling interval (ignored for bulk end-points) */
+ ),
+
+ /* end-point descriptor */
+ USB_DESC_ENDPOINT
+ (
+ USB_MS_DATA_EP | 0x00, /* address (end point index | IN direction) */
+ USB_EP_MODE_TYPE_BULK, /* attributes (bulk) */
+ 64, /* max packet size */
+ 0x05 /* polling interval (ignored for bulk end-points) */
+ )
+};
+static const USBDescriptor configurationDescriptor = {
+ sizeof(configurationDescriptorData),
+ configurationDescriptorData
+};
+
+/* Language descriptor */
+static const uint8_t languageDescriptorData[] = {
+ USB_DESC_BYTE(4),
+ USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
+ USB_DESC_WORD(0x0409) /* U.S. english */
+};
+static const USBDescriptor languageDescriptor = {
+ sizeof(languageDescriptorData),
+ languageDescriptorData
+};
+
+/* Vendor descriptor */
+static const uint8_t vendorDescriptorData[] = {
+ USB_DESC_BYTE(22),
+ USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
+ 'S', 0, 'T', 0, 'M', 0, 'i', 0, 'c', 0, 'r', 0, 'o', 0, 'M', 0, 'S', 0, 'D', 0
+};
+static const USBDescriptor vendorDescriptor = {
+ sizeof(vendorDescriptorData),
+ vendorDescriptorData
+};
+
+/* Product descriptor */
+static const uint8_t productDescriptorData[] = {
+ USB_DESC_BYTE(24),
+ USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
+ 'M', 0, 'S', 0, 'D', 0, ' ', 0, 'E', 0, 'x', 0, 'a', 0, 'm', 0, 'p', 0, 'l', 0, 'e', 0
+};
+static const USBDescriptor productDescriptor = {
+ sizeof(productDescriptorData),
+ productDescriptorData
+};
+
+/* Serial number descriptor */
+static const uint8_t serialNumberDescriptorData[] = {
+ USB_DESC_BYTE(26),
+ USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
+ '0', 0, '1', 0, '4', 0, '2', 0, '3', 0, '0', 0, 'F', 0, 'K', 0, '0', 0, '0', 0, '0', 0, '1', 0
+};
+static const USBDescriptor serialNumberDescriptor = {
+ sizeof(serialNumberDescriptorData),
+ serialNumberDescriptorData
+};
+
+
+/* Handles GET_DESCRIPTOR requests from the USB host */
+static const USBDescriptor *getDescriptor(USBDriver *usbp, uint8_t type, uint8_t index, uint16_t lang)
+{
+ (void)usbp;
+ (void)lang;
+
+ switch (type) {
+ case USB_DESCRIPTOR_DEVICE:
+ return &deviceDescriptor;
+
+ case USB_DESCRIPTOR_CONFIGURATION:
+ return &configurationDescriptor;
+
+ case USB_DESCRIPTOR_STRING:
+ switch (index) {
+ case 0: return &languageDescriptor;
+ case 1: return &vendorDescriptor;
+ case 2: return &productDescriptor;
+ case 3: return &serialNumberDescriptor;
+ }
+ }
+
+ return 0;
+}
+
+/* Configuration of the USB driver */
+static const USBConfig usbConfig = {
+ usbEvent,
+ getDescriptor,
+ msdRequestsHook,
+ 0
+};
+
+
+
+void deinit_msd_driver(void)
+{
+ msdStop(&UMSD);
+}
+
+void init_msd_driver(void *dbgThreadPtr, USBMassStorageConfig *msdConfig)
+{
+ msdInit(&UMSD);
+ /* start the USB mass storage service */
+ msdStart(&UMSD, msdConfig);
+
+ dbg_printer = (thread_t *)dbgThreadPtr;
+
+ /* start the USB driver */
+ usbDisconnectBus(&USBD);
+ chThdSleepMilliseconds(1000);
+ usbStop(&USBD);
+ usbStart(&USBD, &usbConfig);
+ usbConnectBus(&USBD);
+}
+
+void msd_register_evt_connected(event_listener_t *elp, eventmask_t mask)
+{
+ chEvtRegisterMask(&UMSD.evt_connected, elp, mask);
+}
+
+void msd_register_evt_ejected(event_listener_t *elp, eventmask_t mask)
+{
+ chEvtRegisterMask(&UMSD.evt_ejected, elp, mask);
+}
+
+
+/**
+ * @brief Mass storage thread that processes commands
+ */
+static void mass_storage_thread(void *arg)
+{
+
+ USBMassStorageDriver *msdp = (USBMassStorageDriver *)arg;
+
+ chRegSetThreadName("USB-MSD");
+
+ bool wait_for_isr = false;
+
+ /* wait for the usb to be initialised */
+ msd_wait_for_isr(msdp);
+
+ while (!chThdShouldTerminateX()) {
+
+ if (msdp->reconfigured_or_reset_event) {
+ /*If the devices is unplugged and re-plugged but did not have a CPU reset,
+ * we must set the state back to idle.*/
+ msdp->reconfigured_or_reset_event = false;
+ msdp->state = MSD_IDLE;
+ msd_scsi_set_sense(msdp,
+ SCSI_SENSE_KEY_GOOD,
+ SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
+ SCSI_ASENSEQ_NO_QUALIFIER);
+ }
+
+
+
+ wait_for_isr = false;
+
+ /* wait on data depending on the current state */
+ switch (msdp->state) {
+ case MSD_IDLE:
+ wait_for_isr = msd_wait_for_command_block(msdp);
+ break;
+ case MSD_READ_COMMAND_BLOCK:
+ wait_for_isr = msd_read_command_block(msdp);
+ break;
+ case MSD_EJECTED:
+ /* disconnect usb device */
+ usbDisconnectBus(msdp->config->usbp);
+ usbStop(msdp->config->usbp);
+ chThdExit(0);
+ return;
+ case MSD_BOT_RESET:
+ chThdSleepMilliseconds(100);
+ chSysLock();
+ usb_lld_disable_endpoints(msdp->config->usbp);
+ chSysUnlock();
+ chThdSleepMilliseconds(100);
+ chSysLock();
+ msdp->config->usbp->epc[USB_MS_DATA_EP] = &ep_data_config;
+ usb_lld_init_endpoint(msdp->config->usbp, USB_MS_DATA_EP);
+ chBSemReset(&msdp->bsem, false);
+ chSysUnlock();
+
+ msdp->state = MSD_READ_COMMAND_BLOCK;
+ wait_for_isr = true;
+ break;
+ }
+
+ /* wait until the ISR wakes thread */
+ if (wait_for_isr) {
+ msd_wait_for_isr(msdp);
+ }
+ }
+
+ return;
+}
diff --git a/sw/airborne/modules/loggers/sdlog_chibios/usb_msd.h b/sw/airborne/modules/loggers/sdlog_chibios/usb_msd.h
index 1b9d78c053..f2788d429f 100644
--- a/sw/airborne/modules/loggers/sdlog_chibios/usb_msd.h
+++ b/sw/airborne/modules/loggers/sdlog_chibios/usb_msd.h
@@ -26,21 +26,39 @@
#pragma once
-#include
-#include
-#include "std.h"
-#ifndef PACK_STRUCT_BEGIN
-#define PACK_STRUCT_BEGIN
-#endif
+#include "ch.h"
+#include "hal.h"
+#include "chdebug.h"
+#include "modules/loggers/sdlog_chibios/usb_msd.h"
-#ifndef PACK_STRUCT_END
-#define PACK_STRUCT_END
-#endif
-
-#ifndef PACK_STRUCT_STRUCT
#define PACK_STRUCT_STRUCT __attribute__((packed))
-#endif
+#define PACK_STRUCT_BEGIN
+#define PACK_STRUCT_END
+
+/* endpoint index */
+#define USB_MS_DATA_EP 1
+
+
+
+#define USBD USBD1
+
+#define SEM_TAKEN
+#define SEM_RELEASED
+
+#define EVT_USB_RESET (1 << 0)
+#define EVT_BOT_RESET (1 << 1)
+#define EVT_SEM_TAKEN (1 << 2)
+#define EVT_SEM_RELEASED (1 << 3)
+#define EVT_USB_CONFIGURED (1 << 4)
+#define EVT_SCSI_REQ_TEST_UNIT_READY (1 << 5)
+#define EVT_SCSI_REQ_READ_FMT_CAP (1 << 6)
+#define EVT_SCSI_REQ_SENSE6 (1 << 7)
+#define EVT_SCSI_REQ_SENSE10 (1 << 8)
+#define EVT_WAIT_FOR_COMMAND_BLOCK (1 << 9)
+#define EVT_SCSI_REQ_SEND_DIAGNOSTIC (1 << 10)
+#define EVT_SCSI_REQ_READ_CAP10 (1 << 11)
+#define EVT_SCSI_PROC_INQ (1 << 12)
/**
* @brief Command Block Wrapper structure
@@ -95,7 +113,8 @@ PACK_STRUCT_BEGIN typedef struct {
typedef enum {
MSD_IDLE,
MSD_READ_COMMAND_BLOCK,
- MSD_EJECTED
+ MSD_EJECTED,
+ MSD_BOT_RESET
} msd_state_t;
/**
@@ -103,44 +122,44 @@ typedef enum {
*/
typedef struct {
/**
- * @brief USB driver to use for communication
- */
+ * @brief USB driver to use for communication
+ */
USBDriver *usbp;
/**
- * @brief Block device to use for storage
- */
+ * @brief Block device to use for storage
+ */
BaseBlockDevice *bbdp;
/**
- * @brief Index of the USB endpoint to use for transfers
- */
+ * @brief Index of the USB endpoint to use for transfers
+ */
usbep_t bulk_ep;
/**
- * @brief Optional callback that will be called whenever there is
- * read/write activity
- * @note The callback is called with argument true when activity starts,
- * and false when activity stops.
- */
+ * @brief Optional callback that will be called whenever there is
+ * read/write activity
+ * @note The callback is called with argument true when activity starts,
+ * and false when activity stops.
+ */
void (*rw_activity_callback)(bool);
/**
- * @brief Short vendor identification
- * @note ASCII characters only, maximum 8 characters (pad with zeroes).
- */
+ * @brief Short vendor identification
+ * @note ASCII characters only, maximum 8 characters (pad with zeroes).
+ */
uint8_t short_vendor_id[8];
/**
- * @brief Short product identification
- * @note ASCII characters only, maximum 16 characters (pad with zeroes).
- */
+ * @brief Short product identification
+ * @note ASCII characters only, maximum 16 characters (pad with zeroes).
+ */
uint8_t short_product_id[16];
/**
- * @brief Short product revision
- * @note ASCII characters only, maximum 4 characters (pad with zeroes).
- */
+ * @brief Short product revision
+ * @note ASCII characters only, maximum 4 characters (pad with zeroes).
+ */
uint8_t short_product_version[4];
} USBMassStorageConfig;
@@ -161,7 +180,9 @@ typedef struct {
msd_csw_t csw;
msd_scsi_sense_response_t sense;
msd_scsi_inquiry_response_t inquiry;
+ bool reconfigured_or_reset_event;
bool result;
+ bool bot_reset;
} USBMassStorageDriver;
#ifdef __cplusplus
@@ -214,8 +235,25 @@ void msdConfigureHookI(USBMassStorageDriver *msdp);
*/
bool msdRequestsHook(USBDriver *usbp);
+
+void init_msd_driver(void *dbgThreadPtr, USBMassStorageConfig *msdConfig);
+void deinit_msd_driver(void);
+
+/**
+ * @brief register connected event source in local event mask
+ * @details This function is a stub to chEvtRegisterMask
+ */
+void msd_register_evt_connected(event_listener_t *elp, eventmask_t mask);
+
+/**
+ * @brief register ejected event source in local event mask
+ * @details This function is a stub to chEvtRegisterMask
+ * ejected event is a logical event : when host unmount the filesystem,
+ * not a physical event (event is not sent in case of unplugged usb wire)
+ */
+void msd_register_evt_ejected(event_listener_t *elp, eventmask_t mask);
+
+
#ifdef __cplusplus
}
#endif
-
-
diff --git a/sw/ext/chibios b/sw/ext/chibios
index 0db56fc105..9a3437d8f0 160000
--- a/sw/ext/chibios
+++ b/sw/ext/chibios
@@ -1 +1 @@
-Subproject commit 0db56fc105f39b7652254199e754fba58bb3b1f6
+Subproject commit 9a3437d8f0a4b9b16db1d838f597da50d3ec75f2
diff --git a/sw/ext/fatfs b/sw/ext/fatfs
index 169a1acbfc..26da8b2457 160000
--- a/sw/ext/fatfs
+++ b/sw/ext/fatfs
@@ -1 +1 @@
-Subproject commit 169a1acbfceb730a3e7bcc1b7e368b0cbb9de424
+Subproject commit 26da8b2457df4a2ce0e763dfb07296d7044da564
diff --git a/sw/ext/pprzlink b/sw/ext/pprzlink
index cb329c22a3..229ed4a445 160000
--- a/sw/ext/pprzlink
+++ b/sw/ext/pprzlink
@@ -1 +1 @@
-Subproject commit cb329c22a354202ab8425aaafe2d17bbad5d2d8d
+Subproject commit 229ed4a445c54e18285b12dab1fbc7c703bf7021
diff --git a/sw/ext/tlsf/tlsf.c b/sw/ext/tlsf/tlsf.c
index 0b3cd774cf..233146f68b 100644
--- a/sw/ext/tlsf/tlsf.c
+++ b/sw/ext/tlsf/tlsf.c
@@ -377,11 +377,11 @@ static block_header_t* search_suitable_block(control_t* control, int* fli, int*
** First, search for a block in the list associated with the given
** fl/sl index.
*/
- unsigned int sl_map = control->sl_bitmap[fl] & (~0 << sl);
+ unsigned int sl_map = control->sl_bitmap[fl] & (~0U << sl);
if (!sl_map)
{
/* No block exists. Search in the next largest first-level list. */
- const unsigned int fl_map = control->fl_bitmap & (~0 << (fl + 1));
+ const unsigned int fl_map = control->fl_bitmap & (~0U << (fl + 1));
if (!fl_map)
{
/* No free blocks available, memory has been exhausted. */