|
13 | 13 |
|
14 | 14 | LOG_MODULE_REGISTER(lite_buttons, CONFIG_LITE_BUTTONS_LOG_LEVEL);
|
15 | 15 |
|
| 16 | +/* Local implementation of critical section enter/exit support. */ |
| 17 | + |
| 18 | +#include <stdint.h> |
| 19 | +#include <nrf.h> |
| 20 | + |
| 21 | +static uint32_t inside_critical_section; |
| 22 | + |
| 23 | +static void lite_irq_disable(void) |
| 24 | +{ |
| 25 | + __disable_irq(); |
| 26 | + inside_critical_section++; |
| 27 | +} |
| 28 | + |
| 29 | +static void lite_irq_enable(void) |
| 30 | +{ |
| 31 | + inside_critical_section--; |
| 32 | + if (inside_critical_section == 0) { |
| 33 | + __enable_irq(); |
| 34 | + } |
| 35 | +} |
| 36 | + |
| 37 | +static void lite_critical_section_enter(uint8_t *nested) |
| 38 | +{ |
| 39 | +#if defined(CONFIG_SOFTDEVICE) |
| 40 | + /* return value can be safely ignored */ |
| 41 | + (void) sd_nvic_critical_region_enter(nested); |
| 42 | +#else |
| 43 | + lite_irq_disable(); |
| 44 | +#endif |
| 45 | +} |
| 46 | + |
| 47 | +static void lite_critical_section_exit(uint8_t nested) |
| 48 | +{ |
| 49 | +#if defined(CONFIG_SOFTDEVICE) |
| 50 | + /* return value can be safely ignored */ |
| 51 | + (void) sd_nvic_critical_region_exit(nested); |
| 52 | +#else |
| 53 | + lite_irq_enable(); |
| 54 | +#endif |
| 55 | +} |
| 56 | + |
| 57 | +/**@brief Macro for entering a critical section. |
| 58 | + * |
| 59 | + * @note Due to implementation details, there must exist one and only one call to |
| 60 | + * CRITICAL_SECTION_EXIT() for each call to CRITICAL_SECTION_ENTER(), and they must be located |
| 61 | + * in the same scope. |
| 62 | + */ |
| 63 | +#ifdef SOFTDEVICE_PRESENT |
| 64 | +#define LITE_CRITICAL_SECTION_ENTER() \ |
| 65 | + { \ |
| 66 | + uint8_t __CS_NESTED = 0; \ |
| 67 | + lite_critical_section_enter(&__CS_NESTED); |
| 68 | +#else |
| 69 | +#define LITE_CRITICAL_SECTION_ENTER() lite_critical_section_enter(NULL) |
| 70 | +#endif |
| 71 | + |
| 72 | +/**@brief Macro for leaving a critical section. |
| 73 | + * |
| 74 | + * @note Due to implementation details, there must exist one and only one call to |
| 75 | + * CRITICAL_SECTION_EXIT() for each call to CRITICAL_SECTION_ENTER(), and they must be located |
| 76 | + * in the same scope. |
| 77 | + */ |
| 78 | +#ifdef SOFTDEVICE_PRESENT |
| 79 | +#define LITE_CRITICAL_SECTION_EXIT() \ |
| 80 | + lite_critical_section_exit(__CS_NESTED); \ |
| 81 | + } |
| 82 | +#else |
| 83 | +#define LITE_CRITICAL_SECTION_EXIT() lite_critical_section_exit(0) |
| 84 | +#endif |
| 85 | + |
| 86 | +/* End of local implementation of critical section enter/exit support. */ |
| 87 | + |
16 | 88 | #define GPIOTE_INST 0
|
17 | 89 | #define IRQ_PRIO 3
|
18 | 90 | #define BITS_PER_PIN 4
|
@@ -114,7 +186,9 @@ static void evt_handle(uint8_t pin, uint8_t value)
|
114 | 186 | if (value) {
|
115 | 187 | LOG_DBG("Pin %d idle->armed", pin);
|
116 | 188 | state_set(pin, BUTTON_PRESS_ARMED);
|
| 189 | + LITE_CRITICAL_SECTION_ENTER(); |
117 | 190 | global.pin_active |= 1ULL << pin;
|
| 191 | + LITE_CRITICAL_SECTION_EXIT(); |
118 | 192 | } else {
|
119 | 193 | /* stay in IDLE */
|
120 | 194 | }
|
@@ -146,7 +220,9 @@ static void evt_handle(uint8_t pin, uint8_t value)
|
146 | 220 | } else {
|
147 | 221 | state_set(pin, BUTTON_IDLE);
|
148 | 222 | user_event(pin, LITE_BUTTONS_RELEASE);
|
| 223 | + LITE_CRITICAL_SECTION_ENTER(); |
149 | 224 | global.pin_active &= ~(1ULL << pin);
|
| 225 | + LITE_CRITICAL_SECTION_EXIT(); |
150 | 226 | }
|
151 | 227 | LOG_DBG("Pin %d release_detected->%s", pin, value ? "pressed" : "idle");
|
152 | 228 | break;
|
@@ -176,7 +252,9 @@ static int buttons_disable(void)
|
176 | 252 | nrfx_gpiote_trigger_enable(&gpio_instance, global.configs[i].pin_number, false);
|
177 | 253 | }
|
178 | 254 |
|
| 255 | + LITE_CRITICAL_SECTION_ENTER(); |
179 | 256 | global.pin_active = 0;
|
| 257 | + LITE_CRITICAL_SECTION_EXIT(); |
180 | 258 |
|
181 | 259 | return 0;
|
182 | 260 | }
|
|
0 commit comments