diff --git a/ports/mimxrt/fatfs_port.c b/ports/mimxrt/fatfs_port.c index 7b7008667f..5d3b90c28d 100644 --- a/ports/mimxrt/fatfs_port.c +++ b/ports/mimxrt/fatfs_port.c @@ -26,14 +26,12 @@ */ #include "lib/oofatfs/ff.h" -#include "fsl_snvs_lp.h" - +#include "shared/timeutils/timeutils.h" +#include "modmachine.h" MP_WEAK DWORD get_fattime(void) { - snvs_lp_srtc_datetime_t srtcDate; - - SNVS_LP_SRTC_GetDatetime(SNVS, &srtcDate); - - return ((srtcDate.year - 1980) << 25) | (srtcDate.month << 21) | (srtcDate.day << 16) | - (srtcDate.hour << 11) | ((srtcDate.minute << 5) | (srtcDate.second / 2)); + uint64_t seconds = machine_rtc_get_seconds(); + timeutils_struct_time_t tm; + timeutils_seconds_since_epoch_to_struct_time(seconds, &tm); + return ((tm.tm_year - 1980) << 25) | ((tm.tm_mon) << 21) | ((tm.tm_mday) << 16) | ((tm.tm_hour) << 11) | ((tm.tm_min) << 5) | (tm.tm_sec / 2); } diff --git a/ports/mimxrt/machine_rtc.c b/ports/mimxrt/machine_rtc.c index b025e39261..3b7aa6ed86 100644 --- a/ports/mimxrt/machine_rtc.c +++ b/ports/mimxrt/machine_rtc.c @@ -73,18 +73,33 @@ void machine_rtc_alarm_on() { machine_rtc_alarm_set_en(); } -uint32_t machine_rtc_get_seconds() { - uint32_t seconds = 0; - uint32_t tmp = 0; +// Returned ticks are in units of 1/32768 seconds. +uint64_t machine_rtc_get_ticks(void) { + uint64_t ticks = 0; + uint64_t tmp = 0; // Do consecutive reads until value is correct + uint32_t state = disable_irq(); do { - seconds = tmp; - tmp = (SNVS->LPSRTCMR << 17U); - tmp |= (SNVS->LPSRTCLR >> 15U); - } while (tmp != seconds); + ticks = tmp; + tmp = (uint64_t)SNVS->LPSRTCMR << 32U; + tmp |= SNVS->LPSRTCLR; + } while (tmp != ticks); + enable_irq(state); - return seconds; + return ticks; +} + +uint64_t machine_rtc_get_seconds(void) { + return machine_rtc_get_ticks() / 32768U; +} + +// Input ticks are in units of 1/32768 seconds. +static void machine_rtc_set_ticks(uint64_t ticks) { + SNVS_LP_SRTC_StopTimer(SNVS); + SNVS->LPSRTCMR = (uint32_t)(ticks >> 32U); + SNVS->LPSRTCLR = (uint32_t)ticks; + SNVS_LP_SRTC_StartTimer(SNVS); } void machine_rtc_alarm_helper(int seconds, bool repeat) { @@ -164,18 +179,9 @@ void machine_rtc_start(void) { SNVS_LP_SRTC_StartTimer(SNVS); // If the date is not set, set it to a more recent start date, // MicroPython's first commit. - snvs_lp_srtc_datetime_t srtc_date; - SNVS_LP_SRTC_GetDatetime(SNVS, &srtc_date); - if (srtc_date.year <= 1970) { - srtc_date = (snvs_lp_srtc_datetime_t) { - .year = 2013, - .month = 10, - .day = 14, - .hour = 19, - .minute = 53, - .second = 11, - }; - SNVS_LP_SRTC_SetDatetime(SNVS, &srtc_date); + if (machine_rtc_get_ticks() < 10) { + mp_timestamp_t seconds = timeutils_seconds_since_epoch(2013, 10, 14, 19, 53, 11); + machine_rtc_set_ticks((uint64_t)seconds * 32768ULL); } } @@ -190,39 +196,34 @@ static mp_obj_t machine_rtc_make_new(const mp_obj_type_t *type, size_t n_args, s static mp_obj_t machine_rtc_datetime_helper(size_t n_args, const mp_obj_t *args, int hour_index) { if (n_args == 1) { // Get date and time. - snvs_lp_srtc_datetime_t srtc_date; - SNVS_LP_SRTC_GetDatetime(SNVS, &srtc_date); - + uint64_t ticks = machine_rtc_get_ticks(); + timeutils_struct_time_t tm; + timeutils_seconds_since_epoch_to_struct_time(ticks / 32768U, &tm); mp_obj_t tuple[8] = { - mp_obj_new_int(srtc_date.year), - mp_obj_new_int(srtc_date.month), - mp_obj_new_int(srtc_date.day), - mp_obj_new_int(timeutils_calc_weekday(srtc_date.year, srtc_date.month, srtc_date.day)), - mp_obj_new_int(srtc_date.hour), - mp_obj_new_int(srtc_date.minute), - mp_obj_new_int(srtc_date.second), - mp_obj_new_int(0), + mp_obj_new_int(tm.tm_year), + mp_obj_new_int(tm.tm_mon), + mp_obj_new_int(tm.tm_mday), + mp_obj_new_int(tm.tm_wday), + mp_obj_new_int(tm.tm_hour), + mp_obj_new_int(tm.tm_min), + mp_obj_new_int(tm.tm_sec), + mp_obj_new_int((ticks % 32768) * 15625U / 512U), }; return mp_obj_new_tuple(8, tuple); } else { // Set date and time. mp_obj_t *items; - mp_int_t year; mp_obj_get_array_fixed_n(args[1], 8, &items); - - snvs_lp_srtc_datetime_t srtc_date; - year = mp_obj_get_int(items[0]); - srtc_date.year = year >= 100 ? year : year + 2000; // allow 21 for 2021 - srtc_date.month = mp_obj_get_int(items[1]); - srtc_date.day = mp_obj_get_int(items[2]); - // Ignore weekday at items[3] - srtc_date.hour = mp_obj_get_int(items[hour_index]); - srtc_date.minute = mp_obj_get_int(items[hour_index + 1]); - srtc_date.second = mp_obj_get_int(items[hour_index + 2]); - if (SNVS_LP_SRTC_SetDatetime(SNVS, &srtc_date) != kStatus_Success) { - mp_raise_ValueError(NULL); - } - + timeutils_struct_time_t tm = { + .tm_year = mp_obj_get_int(items[0]), + .tm_mon = mp_obj_get_int(items[1]), + .tm_mday = mp_obj_get_int(items[2]), + .tm_hour = mp_obj_get_int(items[4]), + .tm_min = mp_obj_get_int(items[5]), + .tm_sec = mp_obj_get_int(items[6]), + }; + uint32_t seconds = timeutils_seconds_since_epoch(tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); + machine_rtc_set_ticks((uint64_t)seconds * 32768ULL); return mp_const_none; } } diff --git a/ports/mimxrt/mbedtls/mbedtls_port.c b/ports/mimxrt/mbedtls/mbedtls_port.c index 230e264bf9..fa2d81001b 100644 --- a/ports/mimxrt/mbedtls/mbedtls_port.c +++ b/ports/mimxrt/mbedtls/mbedtls_port.c @@ -30,8 +30,8 @@ #include "mbedtls_config_port.h" #if defined(MBEDTLS_HAVE_TIME) || defined(MBEDTLS_HAVE_TIME_DATE) -#include "fsl_snvs_lp.h" #include "shared/timeutils/timeutils.h" +#include "modmachine.h" #include "mbedtls/platform_time.h" #endif @@ -49,9 +49,7 @@ int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t #if defined(MBEDTLS_HAVE_TIME) time_t mimxrt_rtctime_seconds(time_t *timer) { // Get date and date in CPython order. - snvs_lp_srtc_datetime_t date; - SNVS_LP_SRTC_GetDatetime(SNVS, &date); - return timeutils_seconds_since_epoch(date.year, date.month, date.day, date.hour, date.minute, date.second); + return machine_rtc_get_seconds(); } mbedtls_ms_time_t mbedtls_ms_time(void) { diff --git a/ports/mimxrt/modmachine.h b/ports/mimxrt/modmachine.h index 34e93260f2..398dfb2260 100644 --- a/ports/mimxrt/modmachine.h +++ b/ports/mimxrt/modmachine.h @@ -42,6 +42,8 @@ void mimxrt_sdram_init(void); void machine_i2s_init0(); void machine_i2s_deinit_all(void); void machine_rtc_start(void); +uint64_t machine_rtc_get_ticks(void); +uint64_t machine_rtc_get_seconds(void); void machine_rtc_alarm_helper(int seconds, bool repeat); void machine_uart_set_baudrate(mp_obj_t uart, uint32_t baudrate); diff --git a/ports/mimxrt/modtime.c b/ports/mimxrt/modtime.c index fe77b8a733..4b439bb17d 100644 --- a/ports/mimxrt/modtime.c +++ b/ports/mimxrt/modtime.c @@ -25,30 +25,17 @@ * THE SOFTWARE. */ -#include "py/obj.h" #include "shared/timeutils/timeutils.h" -#include "fsl_snvs_lp.h" +#include "modmachine.h" // Get the localtime. static void mp_time_localtime_get(timeutils_struct_time_t *tm) { // Get current date and time. - snvs_lp_srtc_datetime_t t; - SNVS_LP_SRTC_GetDatetime(SNVS, &t); - tm->tm_year = t.year; - tm->tm_mon = t.month; - tm->tm_mday = t.day; - tm->tm_hour = t.hour; - tm->tm_min = t.minute; - tm->tm_sec = t.second; - tm->tm_wday = timeutils_calc_weekday(t.year, t.month, t.day); - tm->tm_yday = timeutils_year_day(t.year, t.month, t.day); + uint64_t seconds = machine_rtc_get_seconds(); + timeutils_seconds_since_epoch_to_struct_time(seconds, tm); } // Return the number of seconds since the Epoch. static mp_obj_t mp_time_time_get(void) { - snvs_lp_srtc_datetime_t t; - SNVS_LP_SRTC_GetDatetime(SNVS, &t); - return timeutils_obj_from_timestamp( - timeutils_seconds_since_epoch(t.year, t.month, t.day, t.hour, t.minute, t.second) - ); + return timeutils_obj_from_timestamp(machine_rtc_get_seconds()); } diff --git a/ports/mimxrt/mphalport.c b/ports/mimxrt/mphalport.c index c3802be30f..67612229ae 100644 --- a/ports/mimxrt/mphalport.c +++ b/ports/mimxrt/mphalport.c @@ -34,7 +34,7 @@ #include "extmod/misc.h" #include "ticks.h" #include "tusb.h" -#include "fsl_snvs_lp.h" +#include "modmachine.h" #ifndef MICROPY_HW_STDIN_BUFFER_LEN #define MICROPY_HW_STDIN_BUFFER_LEN 512 @@ -96,10 +96,12 @@ mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { } uint64_t mp_hal_time_ns(void) { - snvs_lp_srtc_datetime_t t; - SNVS_LP_SRTC_GetDatetime(SNVS, &t); - uint64_t s = timeutils_seconds_since_epoch(t.year, t.month, t.day, t.hour, t.minute, t.second); - return s * 1000000000ULL; + uint64_t ticks = machine_rtc_get_ticks(); + // Need to compute: + // nanoseconds = ticks * 1_000_000_000 / 32768 + // = ticks * 5**9 / 64 + // but split it into upper and lower 32-bit values so the multiplication doesn't overflow. + return (((ticks >> 32U) * 1953125ULL) << 26U) + (((ticks & 0xffffffff) * 1953125ULL) >> 6U); } /*******************************************************************************/