Commit c4fe452c authored by schneider's avatar schneider
Browse files

feat(pycardium): Use epic_sleep() call while sleeping

parent 679bf054
......@@ -210,5 +210,5 @@ void sleep_deepsleep(void)
void epic_sleep(uint32_t ms)
{
vTaskDelay(ms);
vTaskDelay(pdMS_TO_TICKS(ms));
}
......@@ -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);
}
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment