diff --git a/src/main/common/time.c b/src/main/common/time.c index 3541f237e8..c6044e178d 100644 --- a/src/main/common/time.c +++ b/src/main/common/time.c @@ -30,6 +30,8 @@ #include "common/printf.h" #include "common/time.h" +#include "drivers/persistent.h" + #include "pg/pg_ids.h" #include "drivers/time.h" @@ -262,4 +264,31 @@ bool rtcSetDateTime(dateTime_t *dt) return rtcSet(&t); } +void rtcPersistWrite(int16_t offsetMinutes) +{ + rtcTime_t workTime; + uint32_t highLongWord = 0; + uint32_t lowLongWord = 0; + if (rtcGet(&workTime)) { + workTime += (offsetMinutes * 60 * MILLIS_PER_SECOND); + highLongWord = (uint32_t)(workTime >> 32); + lowLongWord = (uint32_t)(workTime & 0xffffffff); + } + persistentObjectWrite(PERSISTENT_OBJECT_RTC_HIGH, highLongWord); + persistentObjectWrite(PERSISTENT_OBJECT_RTC_LOW, lowLongWord); +} + +bool rtcPersistRead(rtcTime_t *t) +{ + const uint32_t highLongWord = persistentObjectRead(PERSISTENT_OBJECT_RTC_HIGH); + const uint32_t lowLongWord = persistentObjectRead(PERSISTENT_OBJECT_RTC_LOW); + + if ((highLongWord != 0) || (lowLongWord != 0)) { + *t = ((uint64_t)highLongWord << 32) + lowLongWord; + return true; + } else { + return false; + } +} + #endif diff --git a/src/main/common/time.h b/src/main/common/time.h index b93860b56f..988422bba4 100644 --- a/src/main/common/time.h +++ b/src/main/common/time.h @@ -40,6 +40,9 @@ typedef uint32_t timeUs_t; #define TIMEUS_MAX UINT32_MAX #endif +#define TIMEZONE_OFFSET_MINUTES_MIN -780 // -13 hours +#define TIMEZONE_OFFSET_MINUTES_MAX 780 // +13 hours + static inline timeDelta_t cmpTimeUs(timeUs_t a, timeUs_t b) { return (timeDelta_t)(a - b); } #define FORMATTED_DATE_TIME_BUFSIZE 30 @@ -95,4 +98,6 @@ bool rtcSet(rtcTime_t *t); bool rtcGetDateTime(dateTime_t *dt); bool rtcSetDateTime(dateTime_t *dt); +void rtcPersistWrite(int16_t offsetMinutes); +bool rtcPersistRead(rtcTime_t *t); #endif diff --git a/src/main/drivers/persistent.h b/src/main/drivers/persistent.h index 90f0568d3f..aaf4f7535f 100644 --- a/src/main/drivers/persistent.h +++ b/src/main/drivers/persistent.h @@ -30,6 +30,8 @@ typedef enum { PERSISTENT_OBJECT_HSE_VALUE, PERSISTENT_OBJECT_OVERCLOCK_LEVEL, PERSISTENT_OBJECT_BOOTLOADER_REQUEST, + PERSISTENT_OBJECT_RTC_HIGH, // high 32 bits of rtcTime_t + PERSISTENT_OBJECT_RTC_LOW, // low 32 bits of rtcTime_t PERSISTENT_OBJECT_COUNT, } persistentObjectId_e; diff --git a/src/main/drivers/usb_msc.h b/src/main/drivers/usb_msc.h index d2467894a0..66f94e57e4 100644 --- a/src/main/drivers/usb_msc.h +++ b/src/main/drivers/usb_msc.h @@ -31,4 +31,4 @@ bool mscCheckBoot(void); uint8_t mscStart(void); bool mscCheckButton(void); void mscWaitForButton(void); -void systemResetToMsc(void); +void systemResetToMsc(int timezoneOffsetMinutes); diff --git a/src/main/drivers/usb_msc_f4xx.c b/src/main/drivers/usb_msc_f4xx.c index 52e2b6043a..de0257cfdc 100644 --- a/src/main/drivers/usb_msc_f4xx.c +++ b/src/main/drivers/usb_msc_f4xx.c @@ -159,11 +159,18 @@ void mscWaitForButton(void) } } -void systemResetToMsc(void) +void systemResetToMsc(int timezoneOffsetMinutes) { *((uint32_t *)0x2001FFF0) = MSC_MAGIC; __disable_irq(); + + // Persist the RTC across the reboot to use as the file timestamp +#ifdef USE_PERSISTENT_MSC_RTC + rtcPersistWrite(timezoneOffsetMinutes); +#else + UNUSED(timezoneOffsetMinutes); +#endif NVIC_SystemReset(); } #endif diff --git a/src/main/drivers/usb_msc_f7xx.c b/src/main/drivers/usb_msc_f7xx.c index 9e104f70f1..5f0029dc1c 100644 --- a/src/main/drivers/usb_msc_f7xx.c +++ b/src/main/drivers/usb_msc_f7xx.c @@ -164,11 +164,18 @@ void mscWaitForButton(void) } } -void systemResetToMsc(void) +void systemResetToMsc(int timezoneOffsetMinutes) { *((__IO uint32_t*) BKPSRAM_BASE + 16) = MSC_MAGIC; __disable_irq(); + + // Persist the RTC across the reboot to use as the file timestamp +#ifdef USE_PERSISTENT_MSC_RTC + rtcPersistWrite(timezoneOffsetMinutes); +#else + UNUSED(timezoneOffsetMinutes); +#endif NVIC_SystemReset(); } #endif diff --git a/src/main/fc/init.c b/src/main/fc/init.c index b03782c7be..016214ef9e 100644 --- a/src/main/fc/init.c +++ b/src/main/fc/init.c @@ -58,6 +58,7 @@ #include "drivers/light_led.h" #include "drivers/mco.h" #include "drivers/nvic.h" +#include "drivers/persistent.h" #include "drivers/pwm_esc_detect.h" #include "drivers/pwm_output.h" #include "drivers/rx/rx_pwm.h" @@ -89,6 +90,10 @@ #include "interface/cli.h" #include "interface/msp.h" +#ifdef USE_PERSISTENT_MSC_RTC +#include "msc/usbd_storage.h" +#endif + #include "msp/msp_serial.h" #include "pg/adc.h" @@ -428,6 +433,12 @@ void init(void) } #endif +#ifdef USE_PERSISTENT_MSC_RTC + // if we didn't enter MSC mode then clear the persistent RTC value + persistentObjectWrite(PERSISTENT_OBJECT_RTC_HIGH, 0); + persistentObjectWrite(PERSISTENT_OBJECT_RTC_LOW, 0); +#endif + #ifdef USE_I2C i2cHardwareConfigure(i2cConfig(0)); diff --git a/src/main/interface/cli.c b/src/main/interface/cli.c index 711bd6b8e9..aeb7c9b8cf 100644 --- a/src/main/interface/cli.c +++ b/src/main/interface/cli.c @@ -4483,16 +4483,27 @@ static void cliDiff(char *cmdline) #if defined(USE_USB_MSC) static void cliMsc(char *cmdline) { - UNUSED(cmdline); - if (mscCheckFilesystemReady()) { +#ifdef USE_RTC_TIME + int timezoneOffsetMinutes = timeConfig()->tz_offsetMinutes; + if (!isEmpty(cmdline)) { + timezoneOffsetMinutes = atoi(cmdline); + if ((timezoneOffsetMinutes < TIMEZONE_OFFSET_MINUTES_MIN) || (timezoneOffsetMinutes > TIMEZONE_OFFSET_MINUTES_MAX)) { + cliPrintErrorLinef("INVALID TIMEZONE OFFSET"); + return; + } + } +#else + int timezoneOffsetMinutes = 0; + UNUSED(cmdline); +#endif cliPrintHashLine("Restarting in mass storage mode"); cliPrint("\r\nRebooting"); bufWriterFlush(cliWriter); waitForSerialPortToFinishTransmitting(cliPort); stopPwmAllMotors(); - systemResetToMsc(); + systemResetToMsc(timezoneOffsetMinutes); } else { cliPrintHashLine("Storage not present or failed to initialize!"); } @@ -4598,7 +4609,11 @@ const clicmd_t cmdTable[] = { #endif CLI_COMMAND_DEF("motor", "get/set motor", " []", cliMotor), #ifdef USE_USB_MSC +#ifdef USE_RTC_TIME + CLI_COMMAND_DEF("msc", "switch into msc mode", "[]", cliMsc), +#else CLI_COMMAND_DEF("msc", "switch into msc mode", NULL, cliMsc), +#endif #endif CLI_COMMAND_DEF("name", "name of craft", NULL, cliName), #ifndef MINIMAL_CLI diff --git a/src/main/interface/msp.c b/src/main/interface/msp.c index 32dadcccea..55a900c754 100644 --- a/src/main/interface/msp.c +++ b/src/main/interface/msp.c @@ -138,6 +138,7 @@ enum { MSP_REBOOT_FIRMWARE = 0, MSP_REBOOT_BOOTLOADER, MSP_REBOOT_MSC, + MSP_REBOOT_MSC_UTC, MSP_REBOOT_COUNT, }; @@ -253,8 +254,14 @@ static void mspRebootFn(serialPort_t *serialPort) break; #if defined(USE_USB_MSC) case MSP_REBOOT_MSC: - systemResetToMsc(); - + case MSP_REBOOT_MSC_UTC: { +#ifdef USE_RTC_TIME + const int16_t timezoneOffsetMinutes = (rebootMode == MSP_REBOOT_MSC) ? timeConfig()->tz_offsetMinutes : 0; + systemResetToMsc(timezoneOffsetMinutes); +#else + systemResetToMsc(0); +#endif + } break; #endif default: diff --git a/src/main/interface/settings.c b/src/main/interface/settings.c index eff9fa81d9..73c7417b47 100644 --- a/src/main/interface/settings.c +++ b/src/main/interface/settings.c @@ -30,6 +30,7 @@ #include "cms/cms.h" #include "common/utils.h" +#include "common/time.h" #include "drivers/adc.h" #include "drivers/bus_i2c.h" @@ -1266,6 +1267,11 @@ const clivalue_t valueTable[] = { { "spektrum_spi_mfg_id", VAR_UINT8 | MASTER_VALUE | MODE_ARRAY, .config.array.length = 4, PG_RX_SPEKTRUM_SPI_CONFIG, offsetof(spektrumConfig_t, mfgId) }, { "spektrum_spi_num_channels", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, DSM_MAX_CHANNEL_COUNT }, PG_RX_SPEKTRUM_SPI_CONFIG, offsetof(spektrumConfig_t, numChannels) }, #endif + +// PG_TIMECONFIG +#ifdef USE_RTC_TIME + { "timezone_offset_minutes", VAR_INT16 | MASTER_VALUE, .config.minmax = { TIMEZONE_OFFSET_MINUTES_MIN, TIMEZONE_OFFSET_MINUTES_MAX }, PG_TIME_CONFIG, offsetof(timeConfig_t, tz_offsetMinutes) }, +#endif }; const uint16_t valueTableEntryCount = ARRAYLEN(valueTable); diff --git a/src/main/msc/emfat_file.c b/src/main/msc/emfat_file.c index fdb8eb5f24..c1d5d69dc1 100644 --- a/src/main/msc/emfat_file.c +++ b/src/main/msc/emfat_file.c @@ -22,14 +22,18 @@ * Author: jflyper@github.com */ -#include "common/utils.h" -#include "common/printf.h" - +#include "platform.h" #include "emfat.h" #include "emfat_file.h" +#include "common/printf.h" +#include "common/time.h" +#include "common/utils.h" + #include "io/flashfs.h" +#include "msc/usbd_storage.h" + #define FILESYSTEM_SIZE_MB 256 #define USE_EMFAT_AUTORUN @@ -269,6 +273,14 @@ static emfat_entry_t entries[EMFAT_MAX_ENTRY]; static char logNames[EMFAT_MAX_LOG_ENTRY][8+3]; emfat_t emfat; +static uint32_t cmaTime = CMA_TIME; + +static void emfat_set_entry_cma(emfat_entry_t *entry) +{ + entry->cma_time[0] = cmaTime; + entry->cma_time[1] = cmaTime; + entry->cma_time[2] = cmaTime; +} static void emfat_add_log(emfat_entry_t *entry, int number, uint32_t offset, uint32_t size) { @@ -278,10 +290,8 @@ static void emfat_add_log(emfat_entry_t *entry, int number, uint32_t offset, uin entry->offset = offset; entry->curr_size = size; entry->max_size = entry->curr_size; - entry->cma_time[0] = CMA_TIME; - entry->cma_time[1] = CMA_TIME; - entry->cma_time[2] = CMA_TIME; entry->readcb = bblog_read_proc; + emfat_set_entry_cma(entry); } static int emfat_find_log(emfat_entry_t *entry, int maxCount) @@ -327,8 +337,17 @@ void emfat_init_files(void) emfat_entry_t *entry; memset(entries, 0, sizeof(entries)); +#ifdef USE_PERSISTENT_MSC_RTC + rtcTime_t mscRebootRtc; + if (rtcPersistRead(&mscRebootRtc)) { + const int32_t rtcSeconds = rtcTimeGetSeconds(&mscRebootRtc); + cmaTime = emfat_cma_time_from_unix((uint32_t)rtcSeconds); + } +#endif + for (size_t i = 0 ; i < PREDEFINED_ENTRY_COUNT ; i++) { entries[i] = entriesPredefined[i]; + emfat_set_entry_cma(&entries[i]); } // Detect and create entries for each individual log @@ -343,6 +362,7 @@ void emfat_init_files(void) entry = &entries[entryIndex]; entry->curr_size = flashfsIdentifyStartOfFreeSpace(); entry->max_size = entry->curr_size; + emfat_set_entry_cma(entry); ++entryIndex; } @@ -352,6 +372,7 @@ void emfat_init_files(void) // used space is doubled because of the individual files plus the single complete file entry->curr_size = (FILESYSTEM_SIZE_MB * 1024 * 1024) - (flashfsIdentifyStartOfFreeSpace() * 2); entry->max_size = entry->curr_size; + emfat_set_entry_cma(entry); emfat_init(&emfat, "BETAFLT", entries); } diff --git a/src/main/msc/usbd_storage.c b/src/main/msc/usbd_storage.c index 4312120699..769cf34841 100644 --- a/src/main/msc/usbd_storage.c +++ b/src/main/msc/usbd_storage.c @@ -21,6 +21,9 @@ /* * Author: jflyper (https://github.com/jflyper) */ + +#include "platform.h" +#include "common/time.h" #ifdef USE_HAL_DRIVER #include "usbd_msc.h" diff --git a/src/main/msc/usbd_storage.h b/src/main/msc/usbd_storage.h index f77d326cde..afc8c0925b 100644 --- a/src/main/msc/usbd_storage.h +++ b/src/main/msc/usbd_storage.h @@ -27,6 +27,8 @@ #include "usbd_msc_core.h" #endif +#include "common/time.h" + #ifdef USE_HAL_DRIVER extern USBD_StorageTypeDef *USBD_STORAGE_fops; #ifdef USE_SDCARD_SDIO diff --git a/src/main/target/common_post.h b/src/main/target/common_post.h index 726ac8c6ab..8fa15bf231 100644 --- a/src/main/target/common_post.h +++ b/src/main/target/common_post.h @@ -223,3 +223,7 @@ #define SPI_PREINIT_COUNT 16 // 2 x 8 (GYROx2, BARO, MAG, MAX, FLASHx2, RX) #endif #endif + +#if (!defined(USE_FLASHFS) || !defined(USE_RTC_TIME) || !defined(USE_USB_MSC)) +#undef USE_PERSISTENT_MSC_RTC +#endif diff --git a/src/main/target/common_pre.h b/src/main/target/common_pre.h index 7cdc119313..80e5be0b4e 100644 --- a/src/main/target/common_pre.h +++ b/src/main/target/common_pre.h @@ -59,6 +59,7 @@ #define USE_ADC_INTERNAL #define USE_USB_CDC_HID #define USE_USB_MSC +#define USE_PERSISTENT_MSC_RTC #if defined(STM32F40_41xxx) || defined(STM32F411xE) #define USE_OVERCLOCK @@ -78,6 +79,7 @@ #define USE_ADC_INTERNAL #define USE_USB_CDC_HID #define USE_USB_MSC +#define USE_PERSISTENT_MSC_RTC #define USE_MCO #endif diff --git a/src/test/unit/osd_unittest.cc b/src/test/unit/osd_unittest.cc index 1161c2bae1..86e2578674 100644 --- a/src/test/unit/osd_unittest.cc +++ b/src/test/unit/osd_unittest.cc @@ -37,6 +37,7 @@ extern "C" { #include "common/time.h" #include "drivers/max7456_symbols.h" + #include "drivers/persistent.h" #include "drivers/serial.h" #include "fc/config.h" @@ -1080,4 +1081,6 @@ extern "C" { bool failsafeIsActive(void) { return false; } bool gpsRescueIsConfigured(void) { return false; } int8_t calculateThrottlePercent(void) { return 0; } + uint32_t persistentObjectRead(persistentObjectId_e) { return 0; } + void persistentObjectWrite(persistentObjectId_e, uint32_t) {} }