From 9d625a1ccb302e6fd26a6b3a8a45db49b47c3bfe Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sat, 1 Aug 2020 18:31:48 +0200 Subject: [PATCH] nrf: call sd_app_evt_wait when the SoftDevice is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reduces current consumption from 500-1000µA to very low (<10µA) current consumption. This change is important for battery powered devices, especially devices that may be running for long periods of time. --- src/runtime/arch_cortexm.go | 4 --- src/runtime/runtime_atsamd21.go | 4 +++ src/runtime/runtime_atsamd51.go | 4 +++ src/runtime/runtime_cortexm_qemu.go | 4 +++ src/runtime/runtime_nrf_bare.go | 9 ++++++ src/runtime/runtime_nrf_softdevice.go | 40 +++++++++++++++++++++++++++ src/runtime/runtime_nxpmk66f18.go | 4 +++ src/runtime/runtime_stm32.go | 6 ++++ 8 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 src/runtime/runtime_nrf_bare.go create mode 100644 src/runtime/runtime_nrf_softdevice.go diff --git a/src/runtime/arch_cortexm.go b/src/runtime/arch_cortexm.go index 1ccdd96c..3359eb66 100644 --- a/src/runtime/arch_cortexm.go +++ b/src/runtime/arch_cortexm.go @@ -102,7 +102,3 @@ func procPin() { func procUnpin() { arm.EnableInterrupts(procPinnedMask) } - -func waitForEvents() { - arm.Asm("wfe") -} diff --git a/src/runtime/runtime_atsamd21.go b/src/runtime/runtime_atsamd21.go index 353ab488..a5f99293 100644 --- a/src/runtime/runtime_atsamd21.go +++ b/src/runtime/runtime_atsamd21.go @@ -345,3 +345,7 @@ func initADCClock() { sam.GCLK_CLKCTRL_CLKEN) waitForSync() } + +func waitForEvents() { + arm.Asm("wfe") +} diff --git a/src/runtime/runtime_atsamd51.go b/src/runtime/runtime_atsamd51.go index 201e2df0..2b8fe565 100644 --- a/src/runtime/runtime_atsamd51.go +++ b/src/runtime/runtime_atsamd51.go @@ -332,3 +332,7 @@ func initADCClock() { sam.GCLK.PCHCTRL[41].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN) } + +func waitForEvents() { + arm.Asm("wfe") +} diff --git a/src/runtime/runtime_cortexm_qemu.go b/src/runtime/runtime_cortexm_qemu.go index eed20156..20e9df9a 100644 --- a/src/runtime/runtime_cortexm_qemu.go +++ b/src/runtime/runtime_cortexm_qemu.go @@ -50,3 +50,7 @@ var stdoutWrite = (*volatile.Register8)(unsafe.Pointer(uintptr(0x4000c000))) func putchar(c byte) { stdoutWrite.Set(uint8(c)) } + +func waitForEvents() { + arm.Asm("wfe") +} diff --git a/src/runtime/runtime_nrf_bare.go b/src/runtime/runtime_nrf_bare.go new file mode 100644 index 00000000..97300410 --- /dev/null +++ b/src/runtime/runtime_nrf_bare.go @@ -0,0 +1,9 @@ +// +build nrf,!softdevice + +package runtime + +import "device/arm" + +func waitForEvents() { + arm.Asm("wfe") +} diff --git a/src/runtime/runtime_nrf_softdevice.go b/src/runtime/runtime_nrf_softdevice.go new file mode 100644 index 00000000..03ec2be3 --- /dev/null +++ b/src/runtime/runtime_nrf_softdevice.go @@ -0,0 +1,40 @@ +// +build nrf,softdevice + +package runtime + +import ( + "device/arm" + "device/nrf" +) + +//export sd_app_evt_wait +func sd_app_evt_wait() + +func waitForEvents() { + // Call into the SoftDevice to sleep. This is necessary here because a + // normal wfe will not put the chip in low power mode (it still consumes + // 500µA-1mA). It is really needed to call sd_app_evt_wait for low power + // consumption. + + // First check whether the SoftDevice is enabled. Unfortunately, + // sd_app_evt_wait cannot be called when the SoftDevice is not enabled. + var enabled uint8 + arm.SVCall1(0x12, &enabled) // sd_softdevice_is_enabled + + if enabled != 0 { + // Now pick the appropriate SVCall number. Hopefully they won't change + // in the future with a different SoftDevice version. + if nrf.DEVICE == "nrf51" { + // sd_app_evt_wait: SOC_SVC_BASE_NOT_AVAILABLE + 29 + arm.SVCall0(0x2B + 29) + } else if nrf.DEVICE == "nrf52" || nrf.DEVICE == "nrf52840" { + // sd_app_evt_wait: SOC_SVC_BASE_NOT_AVAILABLE + 21 + arm.SVCall0(0x2C + 21) + } else { + sd_app_evt_wait() + } + } else { + // SoftDevice is disabled so we can sleep normally. + arm.Asm("wfe") + } +} diff --git a/src/runtime/runtime_nxpmk66f18.go b/src/runtime/runtime_nxpmk66f18.go index 84d421b7..a46aa11e 100644 --- a/src/runtime/runtime_nxpmk66f18.go +++ b/src/runtime/runtime_nxpmk66f18.go @@ -265,3 +265,7 @@ func abort() { machine.PollUART(&machine.UART2) } } + +func waitForEvents() { + arm.Asm("wfe") +} diff --git a/src/runtime/runtime_stm32.go b/src/runtime/runtime_stm32.go index 029d94ce..4eaafe20 100644 --- a/src/runtime/runtime_stm32.go +++ b/src/runtime/runtime_stm32.go @@ -2,6 +2,8 @@ package runtime +import "device/arm" + type timeUnit int64 func postinit() {} @@ -12,3 +14,7 @@ func main() { run() abort() } + +func waitForEvents() { + arm.Asm("wfe") +}