diff --git a/Kconfig.defaults b/Kconfig.defaults index 3e98206f..c07438d6 100644 --- a/Kconfig.defaults +++ b/Kconfig.defaults @@ -110,6 +110,9 @@ config FILE_SYSTEM config FAT_FILESYSTEM_ELM default y +config FS_FATFS_HAS_RTC + default y + config FS_FATFS_LFN default y choice FS_FATFS_LFN_MODE diff --git a/prj.conf b/prj.conf index 6e2a1100..1a0a04c0 100644 --- a/prj.conf +++ b/prj.conf @@ -172,6 +172,7 @@ CONFIG_SDHC=y CONFIG_LOG=y CONFIG_FILE_SYSTEM=y CONFIG_FAT_FILESYSTEM_ELM=y +CONFIG_FS_FATFS_HAS_RTC=y # Enable SDHC interface CONFIG_DISK_DRIVERS=y diff --git a/prj_fota.conf b/prj_fota.conf index 6b7263a0..0aee2b1b 100644 --- a/prj_fota.conf +++ b/prj_fota.conf @@ -188,6 +188,7 @@ CONFIG_SDHC=y CONFIG_LOG=y CONFIG_FILE_SYSTEM=y CONFIG_FAT_FILESYSTEM_ELM=y +CONFIG_FS_FATFS_HAS_RTC=y # Enable SDHC interface CONFIG_DISK_DRIVERS=y diff --git a/src/SD_Card/SD_Card_Manager/CMakeLists.txt b/src/SD_Card/SD_Card_Manager/CMakeLists.txt index d93a7c09..ae3bf3a0 100644 --- a/src/SD_Card/SD_Card_Manager/CMakeLists.txt +++ b/src/SD_Card/SD_Card_Manager/CMakeLists.txt @@ -1,4 +1,5 @@ target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/SD_Card_Manager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/fatfs_time.c ) diff --git a/src/SD_Card/SD_Card_Manager/fatfs_time.c b/src/SD_Card/SD_Card_Manager/fatfs_time.c new file mode 100644 index 00000000..1e862792 --- /dev/null +++ b/src/SD_Card/SD_Card_Manager/fatfs_time.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include + +#include "time_sync.h" + +#define FAT_YEAR_MIN 1980U +#define FAT_YEAR_MAX 2107U +#define UNIX_US_PER_SECOND 1000000ULL +#define TM_YEAR_BASE 1900U /* struct tm.tm_year stores years since 1900. */ + +/* 2022-01-01 matches FatFs/Zephyr's no-RTC fallback date and is used until phone time sync is available. */ +#define FATFS_FALLBACK_TIME \ + (((DWORD)(2022U - FAT_YEAR_MIN) << 25) | ((DWORD)1U << 21) | ((DWORD)1U << 16)) + + +DWORD get_fattime(void) +{ + + uint64_t now_us; + uint64_t now_seconds; + + if (!time_sync_is_synced()) { + return FATFS_FALLBACK_TIME; + } + + now_us = get_current_time_us(); + now_seconds = now_us / UNIX_US_PER_SECOND; + + + time_t now = (time_t)now_seconds; + struct tm calendar; + + if ((uint64_t)now != now_seconds || gmtime_r(&now, &calendar) == NULL) { + return FATFS_FALLBACK_TIME; + } + + uint32_t year = (uint32_t)calendar.tm_year + TM_YEAR_BASE; + + if (year < FAT_YEAR_MIN || year > FAT_YEAR_MAX) { + return FATFS_FALLBACK_TIME; + } + + /* + * FAT directory entries store timestamps as packed date/time fields. + * FatFs asks the application for that packed value via get_fattime(). + */ + return (((DWORD)(year - FAT_YEAR_MIN) << 25) | + ((DWORD)(calendar.tm_mon + 1) << 21) | + ((DWORD)calendar.tm_mday << 16) | + ((DWORD)calendar.tm_hour << 11) | + ((DWORD)calendar.tm_min << 5) | + ((DWORD)(calendar.tm_sec / 2))); +} diff --git a/src/time_sync/time_sync.c b/src/time_sync/time_sync.c index f1841e4e..4d8a0c16 100644 --- a/src/time_sync/time_sync.c +++ b/src/time_sync/time_sync.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -40,6 +41,7 @@ struct __packed time_sync_packet { }; int64_t time_offset_us = 0; +static atomic_t time_synced; bool notify_rtt_enabled = false; @@ -137,6 +139,7 @@ static ssize_t write_time_offset( int64_t delta; memcpy(&delta, buf, sizeof(delta)); time_offset_us += delta; + atomic_set(&time_synced, 1); LOG_DBG("Received time offset update: %lld us, new time offset: %lld us", delta, time_offset_us); return len; @@ -152,7 +155,11 @@ int init_time_sync(void) { return 0; } -inline uint64_t get_current_time_us() { +bool time_sync_is_synced(void) { + return atomic_get(&time_synced) != 0; +} + +uint64_t get_current_time_us(void) { uint64_t base_u = get_time_since_boot_us(); int64_t base_s = (base_u > (uint64_t)INT64_MAX) ? INT64_MAX : (int64_t)base_u; int64_t now_s = base_s + time_offset_us; @@ -167,7 +174,7 @@ inline uint64_t get_current_time_us() { return (uint64_t)now_s; } -inline uint64_t get_time_since_boot_us() { +uint64_t get_time_since_boot_us(void) { return k_ticks_to_us_floor64(k_uptime_ticks()); } diff --git a/src/time_sync/time_sync.h b/src/time_sync/time_sync.h index a9ee8cd3..f4fe3ed1 100644 --- a/src/time_sync/time_sync.h +++ b/src/time_sync/time_sync.h @@ -4,19 +4,26 @@ extern "C" { #endif +#include #include /** * @brief Get time since boot in microseconds. * @return Time since boot in microseconds. */ -uint64_t get_time_since_boot_us(); +uint64_t get_time_since_boot_us(void); /** * @brief Get the current synchronized time in microseconds (since 1. January 1970). * @return Current synchronized time in microseconds. */ -uint64_t get_current_time_us(); +uint64_t get_current_time_us(void); + +/** + * @brief Check whether the wall-clock time has been synchronized. + * @return True after the Time Offset characteristic has been written. + */ +bool time_sync_is_synced(void); /** * @brief Initialize the time synchronization module. @@ -27,4 +34,4 @@ int init_time_sync(); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif