diff --git a/ports/nrf/modules/machine/rtcounter.c b/ports/nrf/modules/machine/rtcounter.c index 08d31f61d0..c1ef1b4dd9 100644 --- a/ports/nrf/modules/machine/rtcounter.c +++ b/ports/nrf/modules/machine/rtcounter.c @@ -27,6 +27,7 @@ #include "py/nlr.h" #include "py/runtime.h" +#include "mphalport.h" #include "rtcounter.h" #include "nrfx_rtc.h" #include "nrf_clock.h" @@ -182,9 +183,7 @@ static mp_obj_t machine_rtc_make_new(const mp_obj_type_t *type, size_t n_args, s } // 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); - } + mp_nrf_start_lfclk(); // Make sure it's uninitialized. nrfx_rtc_uninit(self->p_rtc); diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index 2a1a4cb13b..06c6ba5cc2 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -40,6 +40,36 @@ #include "nrf_clock.h" #endif +#if !defined(USE_WORKAROUND_FOR_ANOMALY_132) && \ + (defined(NRF52832_XXAA) || defined(NRF52832_XXAB)) +// ANOMALY 132 - LFCLK needs to avoid frame from 66us to 138us after LFCLK stop. +#define USE_WORKAROUND_FOR_ANOMALY_132 1 +#endif + +#if USE_WORKAROUND_FOR_ANOMALY_132 +#include "soc/nrfx_coredep.h" +#endif + +void mp_nrf_start_lfclk(void) { + if (!nrf_clock_lf_start_task_status_get(NRF_CLOCK)) { + // Check if the clock was recently stopped but is still running. + #if USE_WORKAROUND_FOR_ANOMALY_132 + bool was_running = nrf_clock_lf_is_running(NRF_CLOCK); + // If so, wait for it to stop. This ensures that the delay for anomaly 132 workaround does + // not land us in the middle of the forbidden interval. + while (nrf_clock_lf_is_running(NRF_CLOCK)) { + } + // If the clock just stopped, we can start it again right away as we are certainly before + // the forbidden 66-138us interval. Otherwise, apply a delay of 138us to make sure we are + // after the interval. + if (!was_running) { + nrfx_coredep_delay_us(138); + } + #endif + nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_LFCLKSTART); + } +} + #if MICROPY_PY_TIME_TICKS // Use RTC1 for time ticks generation (ms and us) with 32kHz tick resolution @@ -99,9 +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); - } + 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); diff --git a/ports/nrf/mphalport.h b/ports/nrf/mphalport.h index 1ba4b6e70f..7efe05a15f 100644 --- a/ports/nrf/mphalport.h +++ b/ports/nrf/mphalport.h @@ -54,6 +54,8 @@ void mp_hal_delay_us(mp_uint_t us); const char *nrfx_error_code_lookup(uint32_t err_code); +void mp_nrf_start_lfclk(void); + #define MP_HAL_PIN_FMT "%q" #define mp_hal_pin_obj_t const pin_obj_t * #define mp_hal_get_pin_obj(o) pin_find(o)