1818#include "memfault/core/math.h"
1919#include "memfault/core/platform/core.h"
2020#include "memfault/core/platform/device_info.h"
21+ #include "memfault/core/platform/system_time.h"
2122#include "memfault/core/reboot_tracking.h"
2223#include "memfault/core/self_test.h"
2324#include "memfault/core/trace_event.h"
@@ -76,7 +77,7 @@ static bool is_field_valid(const char *str, eDeviceInfoField field) {
7677 }
7778 // First validate min and max length
7879 // Max + 1 needed determine if we exceeded bounds before NULL found
79- size_t len = strnlen (str , MEMFAULT_DEVICE_INFO_MAX_STRING_SIZE + 1 );
80+ size_t len = memfault_strnlen (str , MEMFAULT_DEVICE_INFO_MAX_STRING_SIZE + 1 );
8081 if ((len < 1 ) || (len > MEMFAULT_DEVICE_INFO_MAX_STRING_SIZE )) {
8182 MEMFAULT_LOG_ERROR ("Invalid length %zu for %s" , len , s_device_info_field_names [field ]);
8283 return false;
@@ -311,6 +312,72 @@ uint32_t memfault_self_test_reboot_reason_test_verify(void) {
311312 return success ? 0 : 1 ;
312313}
313314
315+ // Use MEMFAULT_NO_OPT to prevent busy loop from being removed
316+ MEMFAULT_NO_OPT static uint32_t prv_get_time_since_boot_test (void ) {
317+ uint64_t start_time_ms = memfault_platform_get_time_since_boot_ms ();
318+
319+ if (start_time_ms == 0 ) {
320+ MEMFAULT_LOG_ERROR ("Time since boot reported as 0" );
321+ return (1 << 0 );
322+ }
323+
324+ // Force a 100ms delay to ensure enough time has passed to yield a different timestamp
325+ memfault_self_test_platform_delay (100 );
326+
327+ uint64_t end_time_ms = memfault_platform_get_time_since_boot_ms ();
328+ if ((end_time_ms <= start_time_ms )) {
329+ MEMFAULT_LOG_ERROR ("Time since boot not monotonically increasing: start[%" PRIu64
330+ "] vs end[%" PRIu64 "]" ,
331+ start_time_ms , end_time_ms );
332+ return (1 << 1 );
333+ }
334+
335+ MEMFAULT_LOG_INFO ("Time since boot test succeeded" );
336+ return 0 ;
337+ }
338+
339+ // Arbitrary point in recent history
340+ // The time test did not exist before 2024/01/29 UTC
341+ #define MEMFAULT_SELF_TEST_TIMESTAMP_ANCHOR (1706486400)
342+
343+ static uint32_t prv_platform_time_get_current_test (void ) {
344+ sMemfaultCurrentTime time = {
345+ .type = kMemfaultCurrentTimeType_Unknown ,
346+ .info = {
347+ .unix_timestamp_secs = 0 ,
348+ },
349+ };
350+ bool result = memfault_platform_time_get_current (& time );
351+ if (!result ) {
352+ MEMFAULT_LOG_ERROR ("Current timestamp could not be recovered" );
353+ return (1 << 2 );
354+ }
355+
356+ if (time .type != kMemfaultCurrentTimeType_UnixEpochTimeSec ) {
357+ MEMFAULT_LOG_ERROR ("Invalid time type returned: %u" , time .type );
358+ return (1 << 3 );
359+ }
360+
361+ if (time .info .unix_timestamp_secs < MEMFAULT_SELF_TEST_TIMESTAMP_ANCHOR ) {
362+ MEMFAULT_LOG_ERROR ("Timestamp too far in the past: %" PRIu64 , time .info .unix_timestamp_secs );
363+ return (1 << 4 );
364+ }
365+
366+ MEMFAULT_LOG_INFO ("Verify received timestamp for accuracy. Timestamp received %" PRIu64 ,
367+ time .info .unix_timestamp_secs );
368+ return 0 ;
369+ }
370+
371+ uint32_t memfault_self_test_time_test (void ) {
372+ MEMFAULT_SELF_TEST_PRINT_HEADER ("Time Test" );
373+
374+ uint32_t result = prv_get_time_since_boot_test ();
375+ result |= prv_platform_time_get_current_test ();
376+
377+ MEMFAULT_LOG_INFO (MEMFAULT_SELF_TEST_END_OUTPUT );
378+ return result ;
379+ }
380+
314381#endif // defined(MEMFAULT_UNITTEST_SELF_TEST)
315382
316383int memfault_self_test_run (uint32_t run_flags ) {
@@ -333,5 +400,8 @@ int memfault_self_test_run(uint32_t run_flags) {
333400 if (run_flags & kMemfaultSelfTestFlag_RebootReasonVerify ) {
334401 result = memfault_self_test_reboot_reason_test_verify ();
335402 }
403+ if (run_flags & kMemfaultSelfTestFlag_PlatformTime ) {
404+ result |= memfault_self_test_time_test ();
405+ }
336406 return (result == 0 ) ? 0 : 1 ;
337407}
0 commit comments