diff --git a/epicardium/drivers/sleep.c b/epicardium/drivers/sleep.c index 70ded1925d767a36f5e9245fd232ce2e93da87a5..8370d47be7643760a43b8912ca00452fbbeacba3 100644 --- a/epicardium/drivers/sleep.c +++ b/epicardium/drivers/sleep.c @@ -210,5 +210,5 @@ void sleep_deepsleep(void) void epic_sleep(uint32_t ms) { - vTaskDelay(ms); + vTaskDelay(pdMS_TO_TICKS(ms)); } diff --git a/pycardium/mphalport.c b/pycardium/mphalport.c index ab3e0857c7d132f67c4c9b5f08530f06563d9a3d..d7fc93c9a9179a5f945dafaa4b8e172ed4561567 100644 --- a/pycardium/mphalport.c +++ b/pycardium/mphalport.c @@ -21,7 +21,8 @@ #include <string.h> // Smallest interval which can be reached exactly -#define SYSTICK_INTERVAL_US 15625ULL +// * 8 to allow up to 100 ms epic calls +#define SYSTICK_INTERVAL_US (15625ULL * 8ULL) #define SYSTICK_FREQ_HZ (1000000 / SYSTICK_INTERVAL_US) /* @@ -225,51 +226,6 @@ static void systick_delay_precise(uint32_t us) } } -static void systick_delay_sleep(uint32_t us) -{ - uint64_t final_time = systick_get_us() + (uint64_t)us - 2; - - while (1) { - uint64_t now = systick_get_us(); - - if ((now + SYSTICK_INTERVAL_US) > final_time) { - break; - } - - /* - * Sleep with WFI if more than SYSTICK_INTERVAL_US of delay - * is remaining. The SysTick interrupt is guaranteed to - * happen within any timespan of SYSTICK_INTERVAL_US. - * - * Use a critical section encompassing both the check and the - * WFI to prevent a race-condition where the interrupt happens - * just in between the check and WFI. - */ - uint32_t irqsaved = __get_PRIMASK(); - __set_PRIMASK(0); - if ((now + SYSTICK_INTERVAL_US) < final_time) { - __WFI(); - } - __set_PRIMASK(irqsaved); - - /* - * Handle pending MicroPython 'interrupts'. This call could - * potentially not return here when a handler raises an - * exception. Those will propagate outwards and thus make the - * delay return early. - * - * One example of this happeing is the KeyboardInterrupt - * (CTRL+C) which will abort the running code and exit to REPL. - */ - mp_handle_pending(true); - } - - uint64_t now = systick_get_us(); - if (now < final_time) { - systick_delay_precise(final_time - now); - } -} - static void systick_delay(uint32_t us) { if (us == 0) @@ -277,15 +233,35 @@ static void systick_delay(uint32_t us) /* * For very short delays, use the systick_delay_precise() function which - * delays with a microsecond accuracy. For anything >SYSTICK_INTERVAL_US, use + * delays with a microsecond accuracy. For anything > SYSTICK_INTERVAL_US, use * systick_delay_sleep() which puts the CPU to sleep when nothing is * happening and also checks for MicroPython interrupts every now and * then. */ - if (us < SYSTICK_INTERVAL_US) { + if (us < 1000) { systick_delay_precise(us); } else { - systick_delay_sleep(us); + uint64_t now = systick_get_us(); + uint64_t final_time = now + us; + + while (final_time - systick_get_us() > SYSTICK_INTERVAL_US) { + uint32_t sleep_time = + (final_time - systick_get_us()) / 1000; + if (sleep_time > 100) + sleep_time = 100; + epic_sleep(sleep_time); + mp_handle_pending(true); + } + + now = systick_get_us(); + if (final_time - now > 1000) { + epic_sleep((final_time - now) / 1000); + } + + now = systick_get_us(); + if (final_time > now) { + systick_delay_precise(final_time - now); + } } }