From 89a9c09af596a3ef57a8279acdc2bcb9879aa299 Mon Sep 17 00:00:00 2001 From: Jaden Weiss Date: Sat, 27 Jun 2020 14:03:15 -0400 Subject: [PATCH] runtime (atsamd51): allow interrupts to wake the scheduler --- src/runtime/runtime_atsamd51.go | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/runtime/runtime_atsamd51.go b/src/runtime/runtime_atsamd51.go index dd9da121..0a581430 100644 --- a/src/runtime/runtime_atsamd51.go +++ b/src/runtime/runtime_atsamd51.go @@ -249,7 +249,9 @@ func sleepTicks(d timeUnit) { for d != 0 { ticks() // update timestamp ticks := uint32(d) - timerSleep(ticks) + if !timerSleep(ticks) { + return + } d -= timeUnit(ticks) } } @@ -266,7 +268,9 @@ func ticks() timeUnit { } // ticks are in microseconds -func timerSleep(ticks uint32) { +// Returns true if the timer completed. +// Returns false if another interrupt occured which requires an early return to scheduler. +func timerSleep(ticks uint32) bool { timerWakeup.Set(0) if ticks < 8 { // due to delay waiting for the register value to sync, the minimum sleep value @@ -287,8 +291,20 @@ func timerSleep(ticks uint32) { // enable IRQ for CMP0 compare sam.RTC_MODE0.INTENSET.SetBits(sam.RTC_MODE0_INTENSET_CMP0) - for timerWakeup.Get() == 0 { - arm.Asm("wfi") +wait: + arm.Asm("wfe") + if timerWakeup.Get() != 0 { + return true + } + if hasScheduler { + // The interurpt may have awoken a goroutine, so bail out early. + // Disable IRQ for CMP0 compare. + sam.RTC_MODE0.INTENCLR.SetBits(sam.RTC_MODE0_INTENSET_CMP0) + return false + } else { + // This is running without a scheduler. + // The application expects this to sleep the whole time. + goto wait } }