From 19789ab02452b6ddf7404e47355e4e3b8f8ac636 Mon Sep 17 00:00:00 2001 From: RetiredWizard Date: Wed, 27 Mar 2024 17:09:34 -0400 Subject: [PATCH 1/3] ports/nrf: Force push rebase attempt. Signed-off-by: RetiredWizard --- ports/nrf/Makefile | 1 + ports/nrf/modtime.c | 51 +++++++++ ports/nrf/modules/machine/modmachine.c | 6 ++ ports/nrf/modules/machine/modmachine.h | 4 + ports/nrf/modules/machine/rtc.c | 144 +++++++++++++++++++++++++ ports/nrf/modules/machine/rtc.h | 4 + ports/nrf/mpconfigport.h | 16 +++ ports/nrf/mphalport.c | 14 ++- ports/nrf/mphalport.h | 1 + 9 files changed, 237 insertions(+), 4 deletions(-) create mode 100644 ports/nrf/modtime.c create mode 100644 ports/nrf/modules/machine/rtc.c create mode 100644 ports/nrf/modules/machine/rtc.h diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 4fe921f0fad88..688c021233d49 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -267,6 +267,7 @@ DRIVERS_SRC_C += $(addprefix modules/,\ machine/pin.c \ machine/timer.c \ machine/rtcounter.c \ + machine/rtc.c \ machine/temp.c \ os/microbitfs.c \ board/modboard.c \ diff --git a/ports/nrf/modtime.c b/ports/nrf/modtime.c new file mode 100644 index 0000000000000..d1448a4141657 --- /dev/null +++ b/ports/nrf/modtime.c @@ -0,0 +1,51 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2023 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/obj.h" +#include "shared/timeutils/timeutils.h" +#include "ports/nrf/modules/machine/rtc.h" + +// Return the localtime as an 8-tuple. +static mp_obj_t mp_time_localtime_get(void) { + mp_int_t seconds = ticks_ms_64() / 1000; + timeutils_struct_time_t tm; + timeutils_seconds_since_epoch_to_struct_time(seconds, &tm); + mp_obj_t tuple[8] = { + tuple[0] = mp_obj_new_int(tm.tm_year), + tuple[1] = mp_obj_new_int(tm.tm_mon), + tuple[2] = mp_obj_new_int(tm.tm_mday), + tuple[3] = mp_obj_new_int(tm.tm_hour), + tuple[4] = mp_obj_new_int(tm.tm_min), + tuple[5] = mp_obj_new_int(tm.tm_sec), + tuple[6] = mp_obj_new_int(tm.tm_wday), + tuple[7] = mp_obj_new_int(tm.tm_yday), + }; + return mp_obj_new_tuple(8, tuple); +} + +static mp_obj_t mp_time_time_get(void) { + return mp_obj_new_int((ticks_ms_64() + rtc_offset[1]) / 1000); +} diff --git a/ports/nrf/modules/machine/modmachine.c b/ports/nrf/modules/machine/modmachine.c index de1d0e31246b4..1683da8410564 100644 --- a/ports/nrf/modules/machine/modmachine.c +++ b/ports/nrf/modules/machine/modmachine.c @@ -65,6 +65,12 @@ #define MICROPY_PY_MACHINE_RTCOUNTER_ENTRY #endif +#if MICROPY_PY_MACHINE_RTC +#define MICROPY_PY_MACHINE_RTC_ENTRY { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, +#else +#define MICROPY_PY_MACHINE_RTC_ENTRY +#endif + #if MICROPY_PY_MACHINE_TIMER_NRF #define MICROPY_PY_MACHINE_TIMER_ENTRY { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, #else diff --git a/ports/nrf/modules/machine/modmachine.h b/ports/nrf/modules/machine/modmachine.h index 4574dc00103c1..9f2b3d0791bec 100644 --- a/ports/nrf/modules/machine/modmachine.h +++ b/ports/nrf/modules/machine/modmachine.h @@ -30,6 +30,10 @@ #include "py/obj.h" +#if MICROPY_PY_MACHINE_RTC +extern const mp_obj_type_t machine_rtc_type; +#endif + void machine_init(void); #endif // __MICROPY_INCLUDED_NRF5_MODMACHINE_H__ diff --git a/ports/nrf/modules/machine/rtc.c b/ports/nrf/modules/machine/rtc.c new file mode 100644 index 0000000000000..369b0e1b5115c --- /dev/null +++ b/ports/nrf/modules/machine/rtc.c @@ -0,0 +1,144 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Nick Moore for Adafruit Industries + * Copyright (c) 2021 "Krzysztof Adamski" + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "modmachine.h" + +#if MICROPY_PY_MACHINE_RTC + +#include "py/mphal.h" +#include "shared/timeutils/timeutils.h" +#include "rtc.h" + + +// These values are placed before and after the current RTC count. They are +// used to determine if the RTC count is valid. These randomly-generated values +// will be set when the RTC value is set in order to mark the RTC as valid. If +// the system crashes or reboots, these values will remain undisturbed and the +// RTC offset will remain valid. +// +// If MicroPython is updated or these symbols shift around, the prefix and +// suffix will no longer match, and the time will no longer be valid. +#define RTC_OFFSET_CHECK_PREFIX 0x25ea7e2a +#define RTC_OFFSET_CHECK_SUFFIX 0x2b80b69e + +void rtc_offset_check(void) { + // If the prefix and suffix are not valid, zero-initialize the RTC offset. + if ((rtc_offset[0] != RTC_OFFSET_CHECK_PREFIX) || (rtc_offset[2] != RTC_OFFSET_CHECK_SUFFIX)) { + rtc_offset[1] = 0; + } +} + +void rtc_get_time(timeutils_struct_time_t *tm) { + uint64_t ticks_s = ticks_ms_64() / 1000; + timeutils_seconds_since_2000_to_struct_time(rtc_offset[1] + ticks_s, tm); +} + +void rtc_set_time(timeutils_struct_time_t *tm) { + uint64_t ticks_s = ticks_ms_64() / 1000; + uint32_t epoch_s = timeutils_seconds_since_2000( + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec + ); + rtc_offset[1] = epoch_s - ticks_s; + + // Set the prefix and suffix in order to indicate the time is valid. This + // must be done after the offset is updated, in case there is a crash or + // power failure. + rtc_offset[0] = RTC_OFFSET_CHECK_PREFIX; + rtc_offset[2] = RTC_OFFSET_CHECK_SUFFIX; +} + +typedef struct _machine_rtc_obj_t { + mp_obj_base_t base; +} machine_rtc_obj_t; + +// singleton RTC object +static const machine_rtc_obj_t machine_rtc_obj = {{&machine_rtc_type}}; + +static mp_obj_t machine_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + // check arguments + mp_arg_check_num(n_args, n_kw, 0, 0, false); + + // return constant object + return (mp_obj_t)&machine_rtc_obj; +} + +static mp_obj_t machine_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) { + if (n_args == 1) { + timeutils_struct_time_t t; + + rtc_get_time(&t); + + mp_obj_t tuple[8] = { + mp_obj_new_int(t.tm_year), + mp_obj_new_int(t.tm_mon), + mp_obj_new_int(t.tm_mday), + mp_obj_new_int(t.tm_wday), + mp_obj_new_int(t.tm_hour), + mp_obj_new_int(t.tm_min), + mp_obj_new_int(t.tm_sec), + mp_obj_new_int(0) + }; + + return mp_obj_new_tuple(8, tuple); + } else { + mp_obj_t *items; + + mp_obj_get_array_fixed_n(args[1], 8, &items); + + timeutils_struct_time_t t = { + .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]), + }; + // Deliberately ignore the weekday argument and compute the proper value + t.tm_wday = timeutils_calc_weekday(t.tm_year, t.tm_mon, t.tm_mday); + + rtc_set_time(&t); + + } + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_datetime_obj, 1, 2, machine_rtc_datetime); + +static const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_datetime), MP_ROM_PTR(&machine_rtc_datetime_obj) }, +}; +static MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + machine_rtc_type, + MP_QSTR_RTC, + MP_TYPE_FLAG_NONE, + make_new, machine_rtc_make_new, + locals_dict, &machine_rtc_locals_dict + ); + +#endif // MICROPY_PY_MACHINE_RTC diff --git a/ports/nrf/modules/machine/rtc.h b/ports/nrf/modules/machine/rtc.h new file mode 100644 index 0000000000000..ffdec83265364 --- /dev/null +++ b/ports/nrf/modules/machine/rtc.h @@ -0,0 +1,4 @@ +extern uint64_t ticks_ms_64(void); + +// This is the time in seconds since 2000 that the RTC was started. +__attribute__((section(".uninitialized"))) static uint32_t rtc_offset[3]; diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 37fbdf1eb3b29..d99c20b6d7615 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -234,10 +234,26 @@ #define MICROPY_PY_MACHINE_RTCOUNTER (0) #endif +#ifndef MICROPY_PY_MACHINE_RTC +#define MICROPY_PY_MACHINE_RTC (1) +#endif + #ifndef MICROPY_PY_TIME_TICKS #define MICROPY_PY_TIME_TICKS (1) #endif +#ifndef MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME +#define MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME (1) +#endif + +#ifndef MICROPY_PY_TIME_TIME_TIME_NS +#define MICROPY_PY_TIME_TIME_TIME_NS (1) +#endif + +#ifndef MICROPY_PY_TIME_INCLUDEFILE +#define MICROPY_PY_TIME_INCLUDEFILE "ports/nrf/modtime.c" +#endif + #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0) diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index 06c6ba5cc2e76..8db80538251bc 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -129,7 +129,10 @@ static void rtc_irq_time(nrfx_rtc_int_type_t event) { void rtc1_init_time_ticks(void) { // Start the low-frequency clock (if it hasn't been started already) - mp_nrf_start_lfclk(); + if (!nrf_clock_lf_is_running(NRF_CLOCK)) { + nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_LFCLKSTART); + rtc_offset_check(); + } // Uninitialize first, then set overflow IRQ and first CC event nrfx_rtc_uninit(&rtc1); nrfx_rtc_init(&rtc1, &rtc_config_time_ticks, rtc_irq_time); @@ -138,8 +141,7 @@ void rtc1_init_time_ticks(void) { nrfx_rtc_enable(&rtc1); } -mp_uint_t mp_hal_ticks_ms(void) { - // Compute: (rtc_overflows << 24 + COUNTER) * 1000 / 32768 +uint64_t ticks_ms_64(void) { // Compute: (rtc_overflows << 24 + COUNTER) * 1000 / 32768 // // Note that COUNTER * 1000 / 32768 would overflow during calculation, so use // the less obvious * 125 / 4096 calculation (overflow secure). @@ -151,7 +153,11 @@ mp_uint_t mp_hal_ticks_ms(void) { uint32_t counter; // guard against overflow irq RTC1_GET_TICKS_ATOMIC(rtc1, overflows, counter) - return (overflows << 9) * 1000 + (counter * 125 / 4096); + return ((uint64_t)overflows << 9) * 1000 + (counter * 125 / 4096); +} + +mp_uint_t mp_hal_ticks_ms(void) { + return ticks_ms_64(); } mp_uint_t mp_hal_ticks_us(void) { diff --git a/ports/nrf/mphalport.h b/ports/nrf/mphalport.h index 7efe05a15fc8e..6a1eb5bdd97e7 100644 --- a/ports/nrf/mphalport.h +++ b/ports/nrf/mphalport.h @@ -74,6 +74,7 @@ void rtc1_init_time_ticks(); mp_uint_t mp_hal_ticks_ms(void); #define mp_hal_ticks_us() (0) #endif +extern void rtc_offset_check(void); // TODO: empty implementation for now. Used by machine_spi.c:69 #define mp_hal_delay_us_fast(p) From cd6dbfa3f422469914d79b0da035bd142870e11e Mon Sep 17 00:00:00 2001 From: RetiredWizard Date: Wed, 27 Mar 2024 18:38:05 -0400 Subject: [PATCH 2/3] ports/nrf: Remove erroneous rebase change to LFCLK. Signed-off-by: RetiredWizard --- ports/nrf/mphalport.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index 8db80538251bc..366d7757569c2 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -129,10 +129,7 @@ static void rtc_irq_time(nrfx_rtc_int_type_t event) { void rtc1_init_time_ticks(void) { // Start the low-frequency clock (if it hasn't been started already) - if (!nrf_clock_lf_is_running(NRF_CLOCK)) { - nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_LFCLKSTART); - rtc_offset_check(); - } + mp_nrf_start_lfclk(); // Uninitialize first, then set overflow IRQ and first CC event nrfx_rtc_uninit(&rtc1); nrfx_rtc_init(&rtc1, &rtc_config_time_ticks, rtc_irq_time); From 57623bcee4664a91a701f33bf7482d068f0813ce Mon Sep 17 00:00:00 2001 From: RetiredWizard Date: Wed, 27 Mar 2024 19:15:15 -0400 Subject: [PATCH 3/3] ports/nrf: Add rtc_offset_chck to Anomaly 132 fix. Signed-off-by: RetiredWizard --- ports/nrf/mphalport.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index 366d7757569c2..4b4004188242c 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -67,6 +67,7 @@ void mp_nrf_start_lfclk(void) { } #endif nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_LFCLKSTART); + rtc_offset_check(); } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy