Commit ebe5578b authored by schneider's avatar schneider
Browse files

fix(pycardium): Account for imprecise epicardium sleeps

The clock source of epicardium is not very stable and can drift multiple
percent. This has an effect on epic_sleep() and can lead to sleeps which
are longer than anticipated. With this change we slowly move towards our
sleep goal using multiple calls. This is less efficient but leads to
precise results.
parent f4fa0af8
......@@ -236,40 +236,38 @@ 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 > 10 ms, 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 < 1000) {
if (us < 10000) {
systick_delay_precise(us);
} else {
uint64_t now = systick_get_us();
uint64_t final_time = now + us;
while (final_time - systick_get_us() > SYSTICK_INTERVAL_US) {
while (final_time - systick_get_us() > 10000) {
uint32_t sleep_time =
(final_time - systick_get_us()) / 1000;
/* We need to wake up at least in SYSTICK_INTERVAL_US to make
* sure we serve the systick interrupt.
* Add some error margin to avoid issues with the clock accuracy
* of epicardium */
if (sleep_time > SYSTICK_INTERVAL_US / 1000 / 2) {
sleep_time = SYSTICK_INTERVAL_US / 1000 / 2;
* sure we serve the systick interrupt. */
if (sleep_time > SYSTICK_INTERVAL_US / 1000) {
sleep_time = SYSTICK_INTERVAL_US / 1000;
}
epic_sleep(sleep_time);
/* Add some error margin to avoid issues with the clock accuracy
* of epicardium. We will account for the actual time via our
* (accurate) systick */
epic_sleep(sleep_time / 2);
/* epic_sleep() can return early if there was an interrupt
* coming from epicardium side.
* Give MP a chance to handle them. */
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