3030#include "supervisor/board.h"
3131#include "supervisor/port.h"
3232
33+ #include "supervisor/samd_prevent_sleep.h"
34+
3335// ASF 4
3436#include "atmel_start_pins.h"
3537#include "peripheral_clk_config.h"
114116#if CIRCUITPY_PEW
115117#include "common-hal/_pew/PewPew.h"
116118#endif
117- static volatile bool sleep_ok = true ;
119+ static volatile size_t sleep_disable_count = 0 ;
118120
119121#ifdef SAMD21
120122static uint8_t _tick_event_channel = EVSYS_SYNCH_NUM ;
@@ -126,12 +128,16 @@ static bool tick_enabled(void) {
126128// Sleeping requires a register write that can stall interrupt handling. Turning
127129// off sleeps allows for more accurate interrupt timing. (Python still thinks
128130// it is sleeping though.)
129- void rtc_start_pulse (void ) {
130- sleep_ok = false ;
131+ void samd_prevent_sleep (void ) {
132+ sleep_disable_count ++ ;
131133}
132134
133- void rtc_end_pulse (void ) {
134- sleep_ok = true;
135+ void samd_allow_sleep (void ) {
136+ if (sleep_disable_count == 0 ) {
137+ // We should never reach this!
138+ return ;
139+ }
140+ sleep_disable_count -- ;
135141}
136142#endif // SAMD21
137143
@@ -651,7 +657,11 @@ void port_interrupt_after_ticks(uint32_t ticks) {
651657 return ;
652658 }
653659 #ifdef SAMD21
654- if (!sleep_ok ) {
660+ if (sleep_disable_count > 0 ) {
661+ // "wake" immediately even if sleep_disable_count is set to 0 between
662+ // now and when port_idle_until_interrupt is called. Otherwise we may
663+ // sleep too long.
664+ _woken_up = true;
655665 return ;
656666 }
657667 #endif
@@ -687,7 +697,7 @@ void port_idle_until_interrupt(void) {
687697 }
688698 #endif
689699 common_hal_mcu_disable_interrupts ();
690- if (!background_callback_pending () && sleep_ok && !_woken_up ) {
700+ if (!background_callback_pending () && sleep_disable_count == 0 && !_woken_up ) {
691701 __DSB ();
692702 __WFI ();
693703 }
0 commit comments