diff --git a/hal/src/nRF52840/sleep_hal.cpp b/hal/src/nRF52840/sleep_hal.cpp index a143a0dac3..5dd31a4d30 100644 --- a/hal/src/nRF52840/sleep_hal.cpp +++ b/hal/src/nRF52840/sleep_hal.cpp @@ -51,40 +51,62 @@ using namespace particle; -typedef struct WakeupSourcePriorityCache { +namespace { + +struct WakeupSourcePriorityCache { + WakeupSourcePriorityCache() { + memset((uint8_t*)this, 0xFF, sizeof(WakeupSourcePriorityCache)); + } + uint32_t gpiotePriority; uint32_t rtc2Priority; uint32_t blePriority; uint32_t lpcompPriority; uint32_t usart0Priority; uint32_t usart1Priority; -} WakeupSourcePriorityCache; +}; + +constexpr uint32_t INVALID_INT_PRIORITY = 0xFFFFFFFF; + +} static void bumpWakeupSourcesPriority(const hal_wakeup_source_base_t* wakeupSources, WakeupSourcePriorityCache* priority, uint32_t newPriority) { auto source = wakeupSources; while (source) { if (source->type == HAL_WAKEUP_SOURCE_TYPE_GPIO) { - priority->gpiotePriority = NVIC_GetPriority(GPIOTE_IRQn); + if (priority->gpiotePriority == INVALID_INT_PRIORITY) { + priority->gpiotePriority = NVIC_GetPriority(GPIOTE_IRQn); + } NVIC_SetPriority(GPIOTE_IRQn, newPriority); } else if (source->type == HAL_WAKEUP_SOURCE_TYPE_RTC) { - priority->rtc2Priority = NVIC_GetPriority(RTC2_IRQn); + if (priority->rtc2Priority == INVALID_INT_PRIORITY) { + priority->rtc2Priority = NVIC_GetPriority(RTC2_IRQn); + } NVIC_SetPriority(RTC2_IRQn, newPriority); } else if (source->type == HAL_WAKEUP_SOURCE_TYPE_BLE) { - priority->blePriority = NVIC_GetPriority(SD_EVT_IRQn); + if (priority->blePriority == INVALID_INT_PRIORITY) { + priority->blePriority = NVIC_GetPriority(SD_EVT_IRQn); + } NVIC_SetPriority(SD_EVT_IRQn, newPriority); NVIC_EnableIRQ(SD_EVT_IRQn); } else if (source->type == HAL_WAKEUP_SOURCE_TYPE_LPCOMP) { - priority->lpcompPriority = NVIC_GetPriority(COMP_LPCOMP_IRQn); + if (priority->lpcompPriority == INVALID_INT_PRIORITY) { + priority->lpcompPriority = NVIC_GetPriority(COMP_LPCOMP_IRQn); + } NVIC_SetPriority(COMP_LPCOMP_IRQn, newPriority); NVIC_EnableIRQ(COMP_LPCOMP_IRQn); } else if (source->type == HAL_WAKEUP_SOURCE_TYPE_USART) { - priority->usart0Priority = NVIC_GetPriority(UARTE0_UART0_IRQn); + if (priority->usart0Priority == INVALID_INT_PRIORITY) { + priority->usart0Priority = NVIC_GetPriority(UARTE0_UART0_IRQn); + } NVIC_SetPriority(UARTE0_UART0_IRQn, newPriority); nrf_uarte_int_enable(NRF_UARTE0, NRF_UARTE_INT_RXDRDY_MASK); } else if (source->type == HAL_WAKEUP_SOURCE_TYPE_NETWORK) { auto network = reinterpret_cast(source); if (!(network->flags & HAL_SLEEP_NETWORK_FLAG_INACTIVE_STANDBY)) { - priority->usart1Priority = NVIC_GetPriority(UARTE1_IRQn); + if (priority->usart1Priority == INVALID_INT_PRIORITY) { + priority->usart1Priority = NVIC_GetPriority(UARTE1_IRQn); + } NVIC_SetPriority(UARTE1_IRQn, newPriority); nrf_uarte_int_enable(NRF_UARTE1, NRF_UARTE_INT_RXDRDY_MASK); } @@ -93,15 +115,24 @@ static void bumpWakeupSourcesPriority(const hal_wakeup_source_base_t* wakeupSour } } -static void unbumpWakeupSourcesPriority(const hal_wakeup_source_base_t* wakeupSources, const WakeupSourcePriorityCache* priority) { +static void unbumpWakeupSourcesPriority(const hal_wakeup_source_base_t* wakeupSources, WakeupSourcePriorityCache* priority) { auto source = wakeupSources; while (source) { if (source->type == HAL_WAKEUP_SOURCE_TYPE_GPIO) { - NVIC_SetPriority(GPIOTE_IRQn, priority->gpiotePriority); + if (priority->gpiotePriority != INVALID_INT_PRIORITY) { + NVIC_SetPriority(GPIOTE_IRQn, priority->gpiotePriority); + priority->gpiotePriority = INVALID_INT_PRIORITY; + } } else if (source->type == HAL_WAKEUP_SOURCE_TYPE_RTC) { - NVIC_SetPriority(RTC2_IRQn, priority->rtc2Priority); + if (priority->rtc2Priority != INVALID_INT_PRIORITY) { + NVIC_SetPriority(RTC2_IRQn, priority->rtc2Priority); + priority->rtc2Priority = INVALID_INT_PRIORITY; + } } else if (source->type == HAL_WAKEUP_SOURCE_TYPE_BLE) { - NVIC_SetPriority(SD_EVT_IRQn, priority->blePriority); + if (priority->blePriority != INVALID_INT_PRIORITY) { + NVIC_SetPriority(SD_EVT_IRQn, priority->blePriority); + priority->blePriority = INVALID_INT_PRIORITY; + } NVIC_DisableIRQ(SD_EVT_IRQn); } else if (source->type == HAL_WAKEUP_SOURCE_TYPE_LPCOMP) { // FIXME: dirty hack, since we nowhere implemented the IRQ handler. @@ -111,14 +142,23 @@ static void unbumpWakeupSourcesPriority(const hal_wakeup_source_base_t* wakeupSo nrf_lpcomp_event_clear(NRF_LPCOMP_EVENT_CROSS); NVIC_DisableIRQ(COMP_LPCOMP_IRQn); NVIC_ClearPendingIRQ(COMP_LPCOMP_IRQn); - NVIC_SetPriority(COMP_LPCOMP_IRQn, priority->lpcompPriority); + if (priority->lpcompPriority != INVALID_INT_PRIORITY) { + NVIC_SetPriority(COMP_LPCOMP_IRQn, priority->lpcompPriority); + priority->lpcompPriority = INVALID_INT_PRIORITY; + } } else if (source->type == HAL_WAKEUP_SOURCE_TYPE_USART) { - NVIC_SetPriority(UARTE0_UART0_IRQn, priority->usart0Priority); + if (priority->usart0Priority != INVALID_INT_PRIORITY) { + NVIC_SetPriority(UARTE0_UART0_IRQn, priority->usart0Priority); + priority->usart0Priority = INVALID_INT_PRIORITY; + } nrf_uarte_int_disable(NRF_UARTE0, NRF_UARTE_INT_RXDRDY_MASK); } else if (source->type == HAL_WAKEUP_SOURCE_TYPE_NETWORK) { auto network = reinterpret_cast(source); if (!(network->flags & HAL_SLEEP_NETWORK_FLAG_INACTIVE_STANDBY)) { - NVIC_SetPriority(UARTE1_IRQn, priority->usart1Priority); + if (priority->usart1Priority != INVALID_INT_PRIORITY) { + NVIC_SetPriority(UARTE1_IRQn, priority->usart1Priority); + priority->usart1Priority = INVALID_INT_PRIORITY; + } nrf_uarte_int_disable(NRF_UARTE1, NRF_UARTE_INT_RXDRDY_MASK); } } @@ -227,20 +267,6 @@ static const hal_wakeup_source_base_t* findWakeupSource(const hal_wakeup_source_ } static void configGpioWakeupSource(const hal_wakeup_source_base_t* wakeupSources) { - uint32_t curIntenSet = NRF_GPIOTE->INTENSET; - nrf_gpiote_int_disable(curIntenSet); - // Clear events and interrupts - nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_IN_0); - nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_IN_1); - nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_IN_2); - nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_IN_3); - nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_IN_4); - nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_IN_5); - nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_IN_6); - nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_IN_7); - nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT); - NVIC_ClearPendingIRQ(GPIOTE_IRQn); - uint32_t gpioIntenSet = 0; Hal_Pin_Info* halPinMap = HAL_Pin_Map(); @@ -307,6 +333,21 @@ static void configGpioWakeupSource(const hal_wakeup_source_base_t* wakeupSources source = source->next; } if (gpioIntenSet > 0) { + uint32_t curIntenSet = NRF_GPIOTE->INTENSET; + nrf_gpiote_int_disable(curIntenSet); + + // Clear events and interrupts + nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_IN_0); + nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_IN_1); + nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_IN_2); + nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_IN_3); + nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_IN_4); + nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_IN_5); + nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_IN_6); + nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_IN_7); + nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT); + NVIC_ClearPendingIRQ(GPIOTE_IRQn); + nrf_gpiote_int_enable(gpioIntenSet); NVIC_EnableIRQ(GPIOTE_IRQn); } diff --git a/hal/src/stm32f2xx/sleep_hal.cpp b/hal/src/stm32f2xx/sleep_hal.cpp index 0840e1e890..fd0c32ffda 100644 --- a/hal/src/stm32f2xx/sleep_hal.cpp +++ b/hal/src/stm32f2xx/sleep_hal.cpp @@ -34,9 +34,12 @@ // anonymous namespace namespace { -static constexpr uint8_t extiChannelNum = 16; +constexpr uint16_t EXTI9_5_BITS_MASK = 0x03E0; +constexpr uint16_t EXTI15_10_BITS_MASK = 0xFC00; -static constexpr uint8_t GPIO_IRQn[extiChannelNum] = { +constexpr uint8_t extiChannelNum = 16; + +constexpr uint8_t GPIO_IRQn[extiChannelNum] = { EXTI0_IRQn, //0 EXTI1_IRQn, //1 EXTI2_IRQn, //2 @@ -55,6 +58,9 @@ static constexpr uint8_t GPIO_IRQn[extiChannelNum] = { EXTI15_10_IRQn //15 }; +// Bitmask +uint16_t extiPriorityBumped = 0x0000; + }; static int constructGpioWakeupReason(hal_wakeup_source_base_t** wakeupReason, pin_t pin) { @@ -175,7 +181,17 @@ static int configGpioWakeupSource(const hal_wakeup_source_base_t* wakeupSources, Hal_Pin_Info* pinMap = HAL_Pin_Map(); uint8_t pinSource = pinMap[gpioWakeup->pin].gpio_pin_source; - extiPriorities[pinSource] = NVIC_GetPriority(static_cast(GPIO_IRQn[pinSource])); + if (!(extiPriorityBumped >> pinSource) & 0x0001) { + extiPriorities[pinSource] = NVIC_GetPriority(static_cast(GPIO_IRQn[pinSource])); + if (pinSource <= 4) { + extiPriorityBumped |= (0x0001 << pinSource); + } + if (pinSource >= 5 && pinSource <= 9) { + extiPriorityBumped |= EXTI9_5_BITS_MASK; + } else if (pinSource >= 10 && pinSource <= 15) { + extiPriorityBumped |= EXTI15_10_BITS_MASK; + } + } NVIC_SetPriority(static_cast(GPIO_IRQn[pinSource]), 1); } source = source->next; @@ -692,11 +708,18 @@ static int enterStopBasedSleep(const hal_sleep_config_t* config, hal_wakeup_sour } else if (wakeupSource->type == HAL_WAKEUP_SOURCE_TYPE_GPIO) { auto gpioWakeup = reinterpret_cast(wakeupSource); HAL_Interrupts_Detach_Ext(gpioWakeup->pin, 1, nullptr); - - Hal_Pin_Info* pinMap = HAL_Pin_Map(); - uint8_t pinSource = pinMap[gpioWakeup->pin].gpio_pin_source; - extiPriority[pinSource] = NVIC_GetPriority(static_cast(GPIO_IRQn[pinSource])); - NVIC_SetPriority(static_cast(GPIO_IRQn[pinSource]), extiPriority[pinSource]); + uint8_t pinSource = halPinMap[gpioWakeup->pin].gpio_pin_source; + if ((extiPriorityBumped >> pinSource) & 0x0001) { + NVIC_SetPriority(static_cast(GPIO_IRQn[pinSource]), extiPriority[pinSource]); + if (pinSource <= 4) { + extiPriorityBumped &= ~(0x0001 << pinSource); + } + if (pinSource >= 5 && pinSource <= 9) { + extiPriorityBumped &= ~EXTI9_5_BITS_MASK; + } else if (pinSource >= 10 && pinSource <= 15) { + extiPriorityBumped &= ~EXTI15_10_BITS_MASK; + } + } } else if (wakeupSource->type == HAL_WAKEUP_SOURCE_TYPE_USART) { auto usartWakeup = reinterpret_cast(wakeupSource); // Enabled unwanted interrupts and unbump the interrupt priority