Skip to content

Commit 691969c

Browse files
committed
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.
1 parent bb6af4d commit 691969c

File tree

2 files changed

+77
-44
lines changed
  • features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/hal_patch
  • targets/TARGET_NORDIC/TARGET_MCU_NRF51822

2 files changed

+77
-44
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2006-2013 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include "sleep_api.h"
17+
#include "cmsis.h"
18+
#include "mbed_interface.h"
19+
#include "softdevice_handler.h"
20+
#include "nrf_soc.h"
21+
22+
// Mask of reserved bits of the register ICSR in the System Control Block peripheral
23+
// In this case, bits which are equal to 0 are the bits reserved in this register
24+
#define SCB_ICSR_RESERVED_BITS_MASK 0x9E43F03F
25+
26+
void sleep(void)
27+
{
28+
// ensure debug is disconnected if semihost is enabled....
29+
30+
// Trigger an event when an interrupt is pending. This allows to wake up
31+
// the processor from disabled interrupts.
32+
SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
33+
34+
// If the SoftDevice is enabled, its API must be used to go to sleep.
35+
if (softdevice_handler_isEnabled()) {
36+
sd_power_mode_set(NRF_POWER_MODE_LOWPWR);
37+
sd_app_evt_wait();
38+
} else {
39+
NRF_POWER->TASKS_LOWPWR = 1;
40+
41+
// Note: it is not sufficient to just use WFE here, since the internal
42+
// event register may be already set from an event that occurred in the
43+
// past (like an SVC call to the SoftDevice) and in such case WFE will
44+
// just clear the register and continue execution.
45+
// Therefore, the strategy here is to first clear the event register
46+
// by using SEV/WFE pair, and then execute WFE again, unless there is
47+
// a pending interrupt.
48+
49+
// Set an event and wake up whatsoever, this will clear the event
50+
// register from all previous events set (SVC call included)
51+
__SEV();
52+
__WFE();
53+
54+
// Test if there is an interrupt pending (mask reserved regions)
55+
if (SCB->ICSR & (SCB_ICSR_RESERVED_BITS_MASK)) {
56+
// Ok, there is an interrut pending, no need to go to sleep
57+
return;
58+
} else {
59+
// next event will wakeup the CPU
60+
// If an interrupt occured between the test of SCB->ICSR and this
61+
// instruction, WFE will just not put the CPU to sleep
62+
__WFE();
63+
}
64+
}
65+
}
66+
67+
void deepsleep(void)
68+
{
69+
sleep();
70+
// NRF_POWER->SYSTEMOFF=1;
71+
}

targets/TARGET_NORDIC/TARGET_MCU_NRF51822/sleep.c

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -16,55 +16,17 @@
1616
#include "sleep_api.h"
1717
#include "cmsis.h"
1818
#include "mbed_interface.h"
19-
#include "softdevice_handler.h"
20-
#include "nrf_soc.h"
19+
#include "toolchain.h"
2120

22-
// Mask of reserved bits of the register ICSR in the System Control Block peripheral
23-
// In this case, bits which are equal to 0 are the bits reserved in this register
24-
#define SCB_ICSR_RESERVED_BITS_MASK 0x9E43F03F
25-
26-
void sleep(void)
21+
MBED_WEAK void sleep(void)
2722
{
2823
// ensure debug is disconnected if semihost is enabled....
29-
30-
// Trigger an event when an interrupt is pending. This allows to wake up
31-
// the processor from disabled interrupts.
32-
SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
33-
34-
// If the SoftDevice is enabled, its API must be used to go to sleep.
35-
if (softdevice_handler_isEnabled()) {
36-
sd_power_mode_set(NRF_POWER_MODE_LOWPWR);
37-
sd_app_evt_wait();
38-
} else {
39-
NRF_POWER->TASKS_LOWPWR = 1;
40-
41-
// Note: it is not sufficient to just use WFE here, since the internal
42-
// event register may be already set from an event that occurred in the
43-
// past (like an SVC call to the SoftDevice) and in such case WFE will
44-
// just clear the register and continue execution.
45-
// Therefore, the strategy here is to first clear the event register
46-
// by using SEV/WFE pair, and then execute WFE again, unless there is
47-
// a pending interrupt.
48-
49-
// Set an event and wake up whatsoever, this will clear the event
50-
// register from all previous events set (SVC call included)
51-
__SEV();
52-
__WFE();
53-
54-
// Test if there is an interrupt pending (mask reserved regions)
55-
if (SCB->ICSR & (SCB_ICSR_RESERVED_BITS_MASK)) {
56-
// Ok, there is an interrut pending, no need to go to sleep
57-
return;
58-
} else {
59-
// next event will wakeup the CPU
60-
// If an interrupt occured between the test of SCB->ICSR and this
61-
// instruction, WFE will just not put the CPU to sleep
62-
__WFE();
63-
}
64-
}
24+
NRF_POWER->TASKS_LOWPWR = 1;
25+
// wait for interrupt
26+
__WFE();
6527
}
6628

67-
void deepsleep(void)
29+
MBED_WEAK void deepsleep(void)
6830
{
6931
sleep();
7032
// NRF_POWER->SYSTEMOFF=1;

0 commit comments

Comments
 (0)