Skip to content

Commit b2495c7

Browse files
Merge pull request #5595 from nvlsianpu/bugfix/nordic_critical_section
fix nordic critical section
2 parents 62a7ecd + ae41c7d commit b2495c7

File tree

1 file changed

+72
-27
lines changed

1 file changed

+72
-27
lines changed

targets/TARGET_NORDIC/TARGET_NRF5/nordic_critical.c

Lines changed: 72 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,43 +15,88 @@
1515
* limitations under the License.
1616
*/
1717

18-
#include <stdint.h> // uint32_t, UINT32_MAX
19-
#include <assert.h> // uint32_t, UINT32_MAX
20-
#include "cmsis.h"
21-
#include "nrf_soc.h"
22-
#include "nrf_sdm.h"
23-
#include "nrf_nvic.h"
18+
#include <stdint.h>
19+
#include "app_util_platform.h"
2420

25-
static uint8_t _sd_state = 0;
26-
static volatile uint32_t _entry_count = 0;
21+
#if defined(SOFTDEVICE_PRESENT)
22+
static volatile uint32_t nordic_cr_nested = 0;
23+
24+
static void nordic_nvic_critical_region_enter(void);
25+
static void nordic_nvic_critical_region_exit(void);
26+
#endif
2727

2828
void core_util_critical_section_enter()
2929
{
30-
// if a critical section has already been entered, just update the counter
31-
if (_entry_count) {
32-
++_entry_count;
33-
return;
34-
}
35-
36-
// in this path, a critical section has never been entered
37-
// routine of SD V11 work even if the softdevice is not active
38-
sd_nvic_critical_region_enter(&_sd_state);
30+
#ifdef NRF52
31+
ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get())
32+
#endif
3933

40-
assert(_entry_count == 0); // entry count should always be equal to 0 at this point
41-
++_entry_count;
34+
#if defined(SOFTDEVICE_PRESENT)
35+
/* return value can be safely ignored */
36+
nordic_nvic_critical_region_enter();
37+
#else
38+
app_util_disable_irq();
39+
#endif
4240
}
4341

4442
void core_util_critical_section_exit()
4543
{
46-
assert(_entry_count > 0);
47-
--_entry_count;
44+
#ifdef NRF52
45+
ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get())
46+
#endif
47+
48+
#if defined(SOFTDEVICE_PRESENT)
49+
/* return value can be safely ignored */
50+
nordic_nvic_critical_region_exit();
51+
#else
52+
app_util_enable_irq();
53+
#endif
54+
}
55+
56+
#if defined(SOFTDEVICE_PRESENT)
57+
/**@brief Enters critical region.
58+
*
59+
* @post Application interrupts will be disabled.
60+
* @sa nordic_nvic_critical_region_exit
61+
*/
62+
static inline void nordic_nvic_critical_region_enter(void)
63+
{
64+
int was_masked = __sd_nvic_irq_disable();
4865

49-
// If their is other segments which have entered the critical section, just leave
50-
if (_entry_count) {
51-
return;
66+
if (nordic_cr_nested == 0) {
67+
nrf_nvic_state.__irq_masks[0] = ( NVIC->ICER[0] & __NRF_NVIC_APP_IRQS_0 );
68+
NVIC->ICER[0] = __NRF_NVIC_APP_IRQS_0;
69+
#ifdef NRF52
70+
nrf_nvic_state.__irq_masks[1] = ( NVIC->ICER[1] & __NRF_NVIC_APP_IRQS_1 );
71+
NVIC->ICER[1] = __NRF_NVIC_APP_IRQS_1;
72+
#endif
5273
}
5374

54-
// This is the last segment of the critical section, state should be restored as before entering
55-
// the critical section
56-
sd_nvic_critical_region_exit(_sd_state);
75+
nordic_cr_nested++;
76+
77+
if (!was_masked) {
78+
__sd_nvic_irq_enable();
79+
}
80+
}
81+
82+
/**@brief Exit critical region.
83+
*
84+
* @pre Application has entered a critical region using ::nordic_nvic_critical_region_enter.
85+
* @post If not in a nested critical region, the application interrupts will restored to the state before ::nordic_nvic_critical_region_enter was called.
86+
*/
87+
static inline void nordic_nvic_critical_region_exit(void)
88+
{
89+
nordic_cr_nested--;
90+
91+
if (nordic_cr_nested == 0) {
92+
int was_masked = __sd_nvic_irq_disable();
93+
NVIC->ISER[0] = nrf_nvic_state.__irq_masks[0];
94+
#ifdef NRF52
95+
NVIC->ISER[1] = nrf_nvic_state.__irq_masks[1];
96+
#endif
97+
if (!was_masked) {
98+
__sd_nvic_irq_enable();
99+
}
100+
}
57101
}
102+
#endif

0 commit comments

Comments
 (0)