From 5aa2fb1443c346b2995f317cf2e70f3a8fd90da8 Mon Sep 17 00:00:00 2001 From: h2zero Date: Wed, 13 Nov 2024 13:41:02 -0700 Subject: [PATCH] Refactor NimBLEUtils::taskWait to check notification value before blocking. Instead of incrementing the notificatin value via `xTaskNotifyGive` this will now set a specific bit in the task notification value which will be tested before blocking a task. This will prevent a task from blocking indefinitely if the event that calls `taskRelease` occurs before entering the blocked state. * Adds a config setting for the bit to set in the task notification value. --- Kconfig | 7 +++++++ src/NimBLEUtils.cpp | 20 +++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Kconfig b/Kconfig index db71798..2a603c6 100644 --- a/Kconfig +++ b/Kconfig @@ -76,6 +76,13 @@ config NIMBLE_CPP_DEBUG_ASSERT_ENABLED Enabling this option will add debug asserts to the NimBLE CPP library. This will use approximately 1kB of flash memory. +config NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT + int "FreeRTOS task block bit" + default 31 + help + Configure the bit to set in the task notification value when a task is blocked waiting for an event. + This should be set to a bit that is not used by other notifications in the system. + # # BT config # diff --git a/src/NimBLEUtils.cpp b/src/NimBLEUtils.cpp index d69cdee..f722be7 100644 --- a/src/NimBLEUtils.cpp +++ b/src/NimBLEUtils.cpp @@ -27,6 +27,10 @@ # include # include +# if defined INC_FREERTOS_H +constexpr uint32_t TASK_BLOCK_BIT = (1 << CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT); +# endif + static const char* LOG_TAG = "NimBLEUtils"; /** @@ -44,12 +48,14 @@ bool NimBLEUtils::taskWait(const NimBLETaskData& taskData, uint32_t timeout) { } # if defined INC_FREERTOS_H + uint32_t notificationValue; + xTaskNotifyWait(0, TASK_BLOCK_BIT, ¬ificationValue, 0); + if (notificationValue & TASK_BLOCK_BIT) { + return true; + } + taskData.m_pHandle = xTaskGetCurrentTaskHandle(); -# ifdef ulTaskNotifyValueClear - // Clear the task notification value to ensure we block - ulTaskNotifyValueClear(static_cast(taskData.m_pHandle), ULONG_MAX); -# endif - return ulTaskNotifyTake(pdTRUE, ticks) == pdTRUE; + return xTaskNotifyWait(0, TASK_BLOCK_BIT, nullptr, ticks) == pdTRUE; # else ble_npl_sem sem; @@ -73,10 +79,10 @@ bool NimBLEUtils::taskWait(const NimBLETaskData& taskData, uint32_t timeout) { * @param [in] flags A return value to set in the task data structure. */ void NimBLEUtils::taskRelease(const NimBLETaskData& taskData, int flags) { + taskData.m_flags = flags; if (taskData.m_pHandle != nullptr) { - taskData.m_flags = flags; # if defined INC_FREERTOS_H - xTaskNotifyGive(static_cast(taskData.m_pHandle)); + xTaskNotify(static_cast(taskData.m_pHandle), TASK_BLOCK_BIT, eSetBits); # else ble_npl_sem_release(static_cast(taskData.m_pHandle)); # endif