From 7e8aeadfdc2878076ea88612fdf06432436b0931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C5=82=C4=85bek=2C=20Andrzej?= Date: Thu, 29 Sep 2016 13:24:20 +0200 Subject: [PATCH 1/8] TARGET_NRF5: changed 'sleep()' implementation to the one used in mbedOS 3. --- .../hal/TARGET_NORDIC/TARGET_NRF5/sleep.c | 46 ++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/sleep.c b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/sleep.c index 3c5ab7dbae..459d3b6753 100644 --- a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/sleep.c +++ b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/sleep.c @@ -16,13 +16,55 @@ #include "sleep_api.h" #include "cmsis.h" #include "mbed_interface.h" +#include "nrf_soc.h" +#include "nrf_sdm.h" + +// Mask of reserved bits of the register ICSR in the System Control Block peripheral +// In this case, bits which are equal to 0 are the bits reserved in this register +#define SCB_ICSR_RESERVED_BITS_MASK 0x9E43F03F void sleep(void) { // ensure debug is disconnected if semihost is enabled.... NRF_POWER->TASKS_LOWPWR = 1; - // wait for interrupt - __WFE(); + + SCB->SCR |= SCB_SCR_SEVONPEND_Msk; /* send an event when an interrupt is pending. + * This helps with the wakeup from the following app_evt_wait(). */ + + uint8_t sd_enabled; + + // look if exceptions are enabled or not, if they are, it is possible to make an SVC call + // and check if the soft device is running + if ((__get_PRIMASK() == 0) && (sd_softdevice_is_enabled(&sd_enabled) == NRF_SUCCESS) && (sd_enabled == 1)) { + // soft device is enabled, use the primitives from the soft device to go to sleep + sd_app_evt_wait(); + } else { + // Note: it is not possible to just use WFE at this stage because WFE + // will read the event register (not accessible) and if an event occured, + // in the past, it will just clear the event register and continue execution. + // SVC call like sd_softdevice_is_enabled set the event register to 1. + // This means that a making an SVC call followed by WFE will never put the + // CPU to sleep. + // Our startegy here is to clear the event register then, if there is any + // interrupt, return from here. If no interrupts are pending, just call + // WFE. + + // Set an event and wake up whatsoever, this will clear the event + // register from all previous events set (SVC call included) + __SEV(); + __WFE(); + + // Test if there is an interrupt pending (mask reserved regions) + if (SCB->ICSR & (SCB_ICSR_RESERVED_BITS_MASK)) { + // Ok, there is an interrut pending, no need to go to sleep + return; + } else { + // next event will wakeup the CPU + // If an interrupt occured between the test of SCB->ICSR and this + // instruction, WFE will just not put the CPU to sleep + __WFE(); + } + } } void deepsleep(void) From eb5fdf05c626ef0013a284f544fea9a5d535211e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C5=82=C4=85bek=2C=20Andrzej?= Date: Thu, 29 Sep 2016 13:31:14 +0200 Subject: [PATCH 2/8] TARGET_NRF5: corrected 'sleep()' to make it work properly on NRF52 as well. --- hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/sleep.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/sleep.c b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/sleep.c index 459d3b6753..98c2815dd3 100644 --- a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/sleep.c +++ b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/sleep.c @@ -26,7 +26,6 @@ void sleep(void) { // ensure debug is disconnected if semihost is enabled.... - NRF_POWER->TASKS_LOWPWR = 1; SCB->SCR |= SCB_SCR_SEVONPEND_Msk; /* send an event when an interrupt is pending. * This helps with the wakeup from the following app_evt_wait(). */ @@ -37,8 +36,11 @@ void sleep(void) // and check if the soft device is running if ((__get_PRIMASK() == 0) && (sd_softdevice_is_enabled(&sd_enabled) == NRF_SUCCESS) && (sd_enabled == 1)) { // soft device is enabled, use the primitives from the soft device to go to sleep + sd_power_mode_set(NRF_POWER_MODE_LOWPWR); sd_app_evt_wait(); } else { + NRF_POWER->TASKS_LOWPWR = 1; + // Note: it is not possible to just use WFE at this stage because WFE // will read the event register (not accessible) and if an event occured, // in the past, it will just clear the event register and continue execution. From 1f208f69169f7c0b8267671d159d1ddad59bc9ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C5=82=C4=85bek=2C=20Andrzej?= Date: Thu, 29 Sep 2016 13:32:19 +0200 Subject: [PATCH 3/8] Enabled flow control feature for NRF51_DK and NRF52_DK targets. --- hal/targets.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hal/targets.json b/hal/targets.json index dffaa479ba..23af151ec3 100644 --- a/hal/targets.json +++ b/hal/targets.json @@ -1986,7 +1986,7 @@ "supported_form_factors": ["ARDUINO"], "inherits": ["MCU_NRF51_32K_UNIFIED"], "progen": {"target": "nrf51-dk"}, - "device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], + "device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], "release_versions": ["2", "5"] }, "NRF51_DONGLE": { @@ -2057,7 +2057,7 @@ "NRF52_PAN_62", "NRF52_PAN_63" ], - "device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], + "device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], "release_versions": ["2", "5"] }, "DELTA_DFBM_NQ620": { From 4b8d5e006af49775de452bce7245a56646f1e2f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C5=82=C4=85bek=2C=20Andrzej?= Date: Thu, 29 Sep 2016 14:16:54 +0200 Subject: [PATCH 4/8] TARGET_NRF5: Corrected gpio_api to make P0.31 usable on NRF52. --- .../TARGET_MCU_NRF52832/TARGET_NRF52_DK/PinNames.h | 1 + hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/gpio_api.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/TARGET_MCU_NRF52832/TARGET_NRF52_DK/PinNames.h b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/TARGET_MCU_NRF52832/TARGET_NRF52_DK/PinNames.h index 0ce5babca4..2b86eca485 100644 --- a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/TARGET_MCU_NRF52832/TARGET_NRF52_DK/PinNames.h +++ b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/TARGET_MCU_NRF52832/TARGET_NRF52_DK/PinNames.h @@ -120,6 +120,7 @@ typedef enum { P0_28 = p28, P0_29 = p29, P0_30 = p30, + P0_31 = p31, LED1 = p17, LED2 = p18, diff --git a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/gpio_api.c b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/gpio_api.c index 4c1586c0c3..163a4ac4af 100644 --- a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/gpio_api.c +++ b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/gpio_api.c @@ -20,7 +20,11 @@ #include "nrf_drv_gpiote.h" -#define GPIO_PIN_COUNT 31 +#if defined(TARGET_MCU_NRF51822) + #define GPIO_PIN_COUNT 31 +#else + #define GPIO_PIN_COUNT 32 +#endif typedef struct { bool used_as_gpio : 1; From 1b593b125a24898e702b3fdf4795aeabb026f61d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C5=82=C4=85bek=2C=20Andrzej?= Date: Wed, 5 Oct 2016 09:10:29 +0200 Subject: [PATCH 5/8] TARGET_NORDIC: simplified the checking if SD is enabled in 'sleep()', used the new implementation in legacy HAL for NRF51822. --- .../TARGET_NORDIC/TARGET_MCU_NRF51822/sleep.c | 48 +++++++++++++++++-- targets/TARGET_NORDIC/TARGET_NRF5/sleep.c | 36 +++++++------- 2 files changed, 62 insertions(+), 22 deletions(-) diff --git a/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/sleep.c b/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/sleep.c index 3c5ab7dbae..ab074b149a 100644 --- a/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/sleep.c +++ b/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/sleep.c @@ -16,13 +16,55 @@ #include "sleep_api.h" #include "cmsis.h" #include "mbed_interface.h" +#include "softdevice_handler.h" +#include "nrf_soc.h" + +// Mask of reserved bits of the register ICSR in the System Control Block peripheral +// In this case, bits which are equal to 0 are the bits reserved in this register +#define SCB_ICSR_RESERVED_BITS_MASK 0x9E43F03F void sleep(void) { // ensure debug is disconnected if semihost is enabled.... - NRF_POWER->TASKS_LOWPWR = 1; - // wait for interrupt - __WFE(); + + // Trigger an event when an interrupt is pending. This allows to wake up + // the processor from disabled interrupts. + SCB->SCR |= SCB_SCR_SEVONPEND_Msk; + + // If the SoftDevice is enabled, its API must be used to go to sleep. + if (softdevice_handler_isEnabled()) + { + sd_power_mode_set(NRF_POWER_MODE_LOWPWR); + sd_app_evt_wait(); + } + else + { + NRF_POWER->TASKS_LOWPWR = 1; + + // Note: it is not sufficient to just use WFE here, since the internal + // event register may be already set from an event that occurred in the + // past (like an SVC call to the SoftDevice) and in such case WFE will + // just clear the register and continue execution. + // Therefore, the strategy here is to first clear the event register + // by using SEV/WFE pair, and then execute WFE again, unless there is + // a pending interrupt. + + // Set an event and wake up whatsoever, this will clear the event + // register from all previous events set (SVC call included) + __SEV(); + __WFE(); + + // Test if there is an interrupt pending (mask reserved regions) + if (SCB->ICSR & (SCB_ICSR_RESERVED_BITS_MASK)) { + // Ok, there is an interrut pending, no need to go to sleep + return; + } else { + // next event will wakeup the CPU + // If an interrupt occured between the test of SCB->ICSR and this + // instruction, WFE will just not put the CPU to sleep + __WFE(); + } + } } void deepsleep(void) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5/sleep.c b/targets/TARGET_NORDIC/TARGET_NRF5/sleep.c index 98c2815dd3..ab074b149a 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5/sleep.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5/sleep.c @@ -16,8 +16,8 @@ #include "sleep_api.h" #include "cmsis.h" #include "mbed_interface.h" +#include "softdevice_handler.h" #include "nrf_soc.h" -#include "nrf_sdm.h" // Mask of reserved bits of the register ICSR in the System Control Block peripheral // In this case, bits which are equal to 0 are the bits reserved in this register @@ -27,29 +27,27 @@ void sleep(void) { // ensure debug is disconnected if semihost is enabled.... - SCB->SCR |= SCB_SCR_SEVONPEND_Msk; /* send an event when an interrupt is pending. - * This helps with the wakeup from the following app_evt_wait(). */ + // Trigger an event when an interrupt is pending. This allows to wake up + // the processor from disabled interrupts. + SCB->SCR |= SCB_SCR_SEVONPEND_Msk; - uint8_t sd_enabled; - - // look if exceptions are enabled or not, if they are, it is possible to make an SVC call - // and check if the soft device is running - if ((__get_PRIMASK() == 0) && (sd_softdevice_is_enabled(&sd_enabled) == NRF_SUCCESS) && (sd_enabled == 1)) { - // soft device is enabled, use the primitives from the soft device to go to sleep + // If the SoftDevice is enabled, its API must be used to go to sleep. + if (softdevice_handler_isEnabled()) + { sd_power_mode_set(NRF_POWER_MODE_LOWPWR); sd_app_evt_wait(); - } else { + } + else + { NRF_POWER->TASKS_LOWPWR = 1; - // Note: it is not possible to just use WFE at this stage because WFE - // will read the event register (not accessible) and if an event occured, - // in the past, it will just clear the event register and continue execution. - // SVC call like sd_softdevice_is_enabled set the event register to 1. - // This means that a making an SVC call followed by WFE will never put the - // CPU to sleep. - // Our startegy here is to clear the event register then, if there is any - // interrupt, return from here. If no interrupts are pending, just call - // WFE. + // Note: it is not sufficient to just use WFE here, since the internal + // event register may be already set from an event that occurred in the + // past (like an SVC call to the SoftDevice) and in such case WFE will + // just clear the register and continue execution. + // Therefore, the strategy here is to first clear the event register + // by using SEV/WFE pair, and then execute WFE again, unless there is + // a pending interrupt. // Set an event and wake up whatsoever, this will clear the event // register from all previous events set (SVC call included) From f62d7e5cfd1aeed5c3f4908c47d7583e0ceea053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C5=82=C4=85bek=2C=20Andrzej?= Date: Wed, 5 Oct 2016 14:32:07 +0200 Subject: [PATCH 6/8] Revert "Enabled flow control feature for NRF51_DK and NRF52_DK targets." This reverts commit 1f208f69169f7c0b8267671d159d1ddad59bc9ca. # Conflicts: # hal/targets.json --- targets/targets.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/targets.json b/targets/targets.json index 14a445299f..d5c9df6b1e 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -1989,7 +1989,7 @@ "supported_form_factors": ["ARDUINO"], "inherits": ["MCU_NRF51_32K_UNIFIED"], "progen": {"target": "nrf51-dk"}, - "device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], + "device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], "release_versions": ["2", "5"] }, "NRF51_DONGLE": { @@ -2060,7 +2060,7 @@ "NRF52_PAN_62", "NRF52_PAN_63" ], - "device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], + "device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], "release_versions": ["2", "5"] }, "DELTA_DFBM_NQ620": { From bb6af4d8a62324c47eb95b57c7acd2dfd4401f67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C5=82=C4=85bek=2C=20Andrzej?= Date: Wed, 5 Oct 2016 14:51:22 +0200 Subject: [PATCH 7/8] TARGET_NORDIC: editorial corrections in 'sleep()' implementations to better fit mbed coding style. --- targets/TARGET_NORDIC/TARGET_MCU_NRF51822/sleep.c | 7 ++----- targets/TARGET_NORDIC/TARGET_NRF5/sleep.c | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/sleep.c b/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/sleep.c index ab074b149a..efb46699ee 100644 --- a/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/sleep.c +++ b/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/sleep.c @@ -32,13 +32,10 @@ void sleep(void) SCB->SCR |= SCB_SCR_SEVONPEND_Msk; // If the SoftDevice is enabled, its API must be used to go to sleep. - if (softdevice_handler_isEnabled()) - { + if (softdevice_handler_isEnabled()) { sd_power_mode_set(NRF_POWER_MODE_LOWPWR); sd_app_evt_wait(); - } - else - { + } else { NRF_POWER->TASKS_LOWPWR = 1; // Note: it is not sufficient to just use WFE here, since the internal diff --git a/targets/TARGET_NORDIC/TARGET_NRF5/sleep.c b/targets/TARGET_NORDIC/TARGET_NRF5/sleep.c index ab074b149a..efb46699ee 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5/sleep.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5/sleep.c @@ -32,13 +32,10 @@ void sleep(void) SCB->SCR |= SCB_SCR_SEVONPEND_Msk; // If the SoftDevice is enabled, its API must be used to go to sleep. - if (softdevice_handler_isEnabled()) - { + if (softdevice_handler_isEnabled()) { sd_power_mode_set(NRF_POWER_MODE_LOWPWR); sd_app_evt_wait(); - } - else - { + } else { NRF_POWER->TASKS_LOWPWR = 1; // Note: it is not sufficient to just use WFE here, since the internal From 691969c3157c5d9ca3a7f56befbee429a0d6e579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C5=82=C4=85bek=2C=20Andrzej?= Date: Thu, 6 Oct 2016 11:51:41 +0200 Subject: [PATCH 8/8] TARGET_NORDIC: restored old 'sleep()' implementation in legacy HAL, moved the new one to FEATURE_BLE, so it is picked only when SoftDevice is in use. --- .../TARGET_MCU_NRF51822/hal_patch/sleep.c | 71 +++++++++++++++++++ .../TARGET_NORDIC/TARGET_MCU_NRF51822/sleep.c | 50 ++----------- 2 files changed, 77 insertions(+), 44 deletions(-) create mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/hal_patch/sleep.c diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/hal_patch/sleep.c b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/hal_patch/sleep.c new file mode 100644 index 0000000000..efb46699ee --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/hal_patch/sleep.c @@ -0,0 +1,71 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "sleep_api.h" +#include "cmsis.h" +#include "mbed_interface.h" +#include "softdevice_handler.h" +#include "nrf_soc.h" + +// Mask of reserved bits of the register ICSR in the System Control Block peripheral +// In this case, bits which are equal to 0 are the bits reserved in this register +#define SCB_ICSR_RESERVED_BITS_MASK 0x9E43F03F + +void sleep(void) +{ + // ensure debug is disconnected if semihost is enabled.... + + // Trigger an event when an interrupt is pending. This allows to wake up + // the processor from disabled interrupts. + SCB->SCR |= SCB_SCR_SEVONPEND_Msk; + + // If the SoftDevice is enabled, its API must be used to go to sleep. + if (softdevice_handler_isEnabled()) { + sd_power_mode_set(NRF_POWER_MODE_LOWPWR); + sd_app_evt_wait(); + } else { + NRF_POWER->TASKS_LOWPWR = 1; + + // Note: it is not sufficient to just use WFE here, since the internal + // event register may be already set from an event that occurred in the + // past (like an SVC call to the SoftDevice) and in such case WFE will + // just clear the register and continue execution. + // Therefore, the strategy here is to first clear the event register + // by using SEV/WFE pair, and then execute WFE again, unless there is + // a pending interrupt. + + // Set an event and wake up whatsoever, this will clear the event + // register from all previous events set (SVC call included) + __SEV(); + __WFE(); + + // Test if there is an interrupt pending (mask reserved regions) + if (SCB->ICSR & (SCB_ICSR_RESERVED_BITS_MASK)) { + // Ok, there is an interrut pending, no need to go to sleep + return; + } else { + // next event will wakeup the CPU + // If an interrupt occured between the test of SCB->ICSR and this + // instruction, WFE will just not put the CPU to sleep + __WFE(); + } + } +} + +void deepsleep(void) +{ + sleep(); + // NRF_POWER->SYSTEMOFF=1; +} diff --git a/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/sleep.c b/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/sleep.c index efb46699ee..be8d69d1e8 100644 --- a/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/sleep.c +++ b/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/sleep.c @@ -16,55 +16,17 @@ #include "sleep_api.h" #include "cmsis.h" #include "mbed_interface.h" -#include "softdevice_handler.h" -#include "nrf_soc.h" +#include "toolchain.h" -// Mask of reserved bits of the register ICSR in the System Control Block peripheral -// In this case, bits which are equal to 0 are the bits reserved in this register -#define SCB_ICSR_RESERVED_BITS_MASK 0x9E43F03F - -void sleep(void) +MBED_WEAK void sleep(void) { // ensure debug is disconnected if semihost is enabled.... - - // Trigger an event when an interrupt is pending. This allows to wake up - // the processor from disabled interrupts. - SCB->SCR |= SCB_SCR_SEVONPEND_Msk; - - // If the SoftDevice is enabled, its API must be used to go to sleep. - if (softdevice_handler_isEnabled()) { - sd_power_mode_set(NRF_POWER_MODE_LOWPWR); - sd_app_evt_wait(); - } else { - NRF_POWER->TASKS_LOWPWR = 1; - - // Note: it is not sufficient to just use WFE here, since the internal - // event register may be already set from an event that occurred in the - // past (like an SVC call to the SoftDevice) and in such case WFE will - // just clear the register and continue execution. - // Therefore, the strategy here is to first clear the event register - // by using SEV/WFE pair, and then execute WFE again, unless there is - // a pending interrupt. - - // Set an event and wake up whatsoever, this will clear the event - // register from all previous events set (SVC call included) - __SEV(); - __WFE(); - - // Test if there is an interrupt pending (mask reserved regions) - if (SCB->ICSR & (SCB_ICSR_RESERVED_BITS_MASK)) { - // Ok, there is an interrut pending, no need to go to sleep - return; - } else { - // next event will wakeup the CPU - // If an interrupt occured between the test of SCB->ICSR and this - // instruction, WFE will just not put the CPU to sleep - __WFE(); - } - } + NRF_POWER->TASKS_LOWPWR = 1; + // wait for interrupt + __WFE(); } -void deepsleep(void) +MBED_WEAK void deepsleep(void) { sleep(); // NRF_POWER->SYSTEMOFF=1;