fix(freertos): notifiy-based sync can be initialized from any task (#6692)
This commit is contained in:
@@ -50,11 +50,11 @@ static void prvMutexInit(lv_mutex_t * pxMutex);
|
|||||||
|
|
||||||
static void prvCheckMutexInit(lv_mutex_t * pxMutex);
|
static void prvCheckMutexInit(lv_mutex_t * pxMutex);
|
||||||
|
|
||||||
#if !USE_FREERTOS_TASK_NOTIFY
|
|
||||||
static void prvCondInit(lv_thread_sync_t * pxCond);
|
static void prvCondInit(lv_thread_sync_t * pxCond);
|
||||||
|
|
||||||
static void prvCheckCondInit(lv_thread_sync_t * pxCond);
|
static void prvCheckCondInit(lv_thread_sync_t * pxCond);
|
||||||
|
|
||||||
|
#if !USE_FREERTOS_TASK_NOTIFY
|
||||||
static void prvTestAndDecrement(lv_thread_sync_t * pxCond,
|
static void prvTestAndDecrement(lv_thread_sync_t * pxCond,
|
||||||
uint32_t ulLocalWaitingThreads);
|
uint32_t ulLocalWaitingThreads);
|
||||||
#endif
|
#endif
|
||||||
@@ -87,7 +87,7 @@ lv_result_t lv_thread_init(lv_thread_t * pxThread, lv_thread_prio_t xSchedPriori
|
|||||||
void (*pvStartRoutine)(void *), size_t usStackSize,
|
void (*pvStartRoutine)(void *), size_t usStackSize,
|
||||||
void * xAttr)
|
void * xAttr)
|
||||||
{
|
{
|
||||||
pxThread->xTaskArg = xAttr;
|
pxThread->pTaskArg = xAttr;
|
||||||
pxThread->pvStartRoutine = pvStartRoutine;
|
pxThread->pvStartRoutine = pvStartRoutine;
|
||||||
|
|
||||||
BaseType_t xTaskCreateStatus = xTaskCreate(
|
BaseType_t xTaskCreateStatus = xTaskCreate(
|
||||||
@@ -182,13 +182,8 @@ lv_result_t lv_mutex_delete(lv_mutex_t * pxMutex)
|
|||||||
|
|
||||||
lv_result_t lv_thread_sync_init(lv_thread_sync_t * pxCond)
|
lv_result_t lv_thread_sync_init(lv_thread_sync_t * pxCond)
|
||||||
{
|
{
|
||||||
#if USE_FREERTOS_TASK_NOTIFY
|
|
||||||
/* Store the handle of the calling task. */
|
|
||||||
pxCond->xTaskToNotify = xTaskGetCurrentTaskHandle();
|
|
||||||
#else
|
|
||||||
/* If the cond is uninitialized, perform initialization. */
|
/* If the cond is uninitialized, perform initialization. */
|
||||||
prvCheckCondInit(pxCond);
|
prvCheckCondInit(pxCond);
|
||||||
#endif
|
|
||||||
|
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
}
|
}
|
||||||
@@ -197,17 +192,30 @@ lv_result_t lv_thread_sync_wait(lv_thread_sync_t * pxCond)
|
|||||||
{
|
{
|
||||||
lv_result_t lvRes = LV_RESULT_OK;
|
lv_result_t lvRes = LV_RESULT_OK;
|
||||||
|
|
||||||
#if USE_FREERTOS_TASK_NOTIFY
|
|
||||||
LV_UNUSED(pxCond);
|
|
||||||
|
|
||||||
/* Wait for other task to notify this task. */
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
||||||
#else
|
|
||||||
uint32_t ulLocalWaitingThreads;
|
|
||||||
|
|
||||||
/* If the cond is uninitialized, perform initialization. */
|
/* If the cond is uninitialized, perform initialization. */
|
||||||
prvCheckCondInit(pxCond);
|
prvCheckCondInit(pxCond);
|
||||||
|
|
||||||
|
#if USE_FREERTOS_TASK_NOTIFY
|
||||||
|
TaskHandle_t current_task_handle = xTaskGetCurrentTaskHandle();
|
||||||
|
|
||||||
|
_enter_critical();
|
||||||
|
BaseType_t signal_sent = pxCond->xSyncSignal;
|
||||||
|
pxCond->xSyncSignal = pdFALSE;
|
||||||
|
if(signal_sent == pdFALSE) {
|
||||||
|
/* The signal hasn't been sent yet. Tell the sender to notify this task */
|
||||||
|
pxCond->xTaskToNotify = current_task_handle;
|
||||||
|
}
|
||||||
|
/* If we have a signal from the other task, we should not ask to be notified */
|
||||||
|
_exit_critical();
|
||||||
|
|
||||||
|
if(signal_sent == pdFALSE) {
|
||||||
|
/* Wait for other task to notify this task. */
|
||||||
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
/* If the signal was received, no wait needs to be done */
|
||||||
|
#else
|
||||||
|
uint32_t ulLocalWaitingThreads;
|
||||||
|
|
||||||
/* Acquire the mutex. */
|
/* Acquire the mutex. */
|
||||||
xSemaphoreTake(pxCond->xSyncMutex, portMAX_DELAY);
|
xSemaphoreTake(pxCond->xSyncMutex, portMAX_DELAY);
|
||||||
|
|
||||||
@@ -264,13 +272,26 @@ lv_result_t lv_thread_sync_wait(lv_thread_sync_t * pxCond)
|
|||||||
|
|
||||||
lv_result_t lv_thread_sync_signal(lv_thread_sync_t * pxCond)
|
lv_result_t lv_thread_sync_signal(lv_thread_sync_t * pxCond)
|
||||||
{
|
{
|
||||||
#if USE_FREERTOS_TASK_NOTIFY
|
|
||||||
/* Send a notification to the task waiting. */
|
|
||||||
xTaskNotifyGive(pxCond->xTaskToNotify);
|
|
||||||
#else
|
|
||||||
/* If the cond is uninitialized, perform initialization. */
|
/* If the cond is uninitialized, perform initialization. */
|
||||||
prvCheckCondInit(pxCond);
|
prvCheckCondInit(pxCond);
|
||||||
|
|
||||||
|
#if USE_FREERTOS_TASK_NOTIFY
|
||||||
|
_enter_critical();
|
||||||
|
TaskHandle_t task_to_notify = pxCond->xTaskToNotify;
|
||||||
|
pxCond->xTaskToNotify = NULL;
|
||||||
|
if(task_to_notify == NULL) {
|
||||||
|
/* No task waiting to be notified. Send this signal for later */
|
||||||
|
pxCond->xSyncSignal = pdTRUE;
|
||||||
|
}
|
||||||
|
/* If a task is already waiting, there is no need to set the sync signal */
|
||||||
|
_exit_critical();
|
||||||
|
|
||||||
|
if(task_to_notify != NULL) {
|
||||||
|
/* There is a task waiting. Send a notification to it */
|
||||||
|
xTaskNotifyGive(task_to_notify);
|
||||||
|
}
|
||||||
|
/* If there was no task waiting to be notified, we sent a signal for it to see later. */
|
||||||
|
#else
|
||||||
/* Acquire the mutex. */
|
/* Acquire the mutex. */
|
||||||
xSemaphoreTake(pxCond->xSyncMutex, portMAX_DELAY);
|
xSemaphoreTake(pxCond->xSyncMutex, portMAX_DELAY);
|
||||||
|
|
||||||
@@ -308,16 +329,14 @@ lv_result_t lv_thread_sync_signal(lv_thread_sync_t * pxCond)
|
|||||||
|
|
||||||
lv_result_t lv_thread_sync_delete(lv_thread_sync_t * pxCond)
|
lv_result_t lv_thread_sync_delete(lv_thread_sync_t * pxCond)
|
||||||
{
|
{
|
||||||
#if USE_FREERTOS_TASK_NOTIFY
|
#if !USE_FREERTOS_TASK_NOTIFY
|
||||||
LV_UNUSED(pxCond);
|
|
||||||
#else
|
|
||||||
/* Cleanup all resources used by the cond. */
|
/* Cleanup all resources used by the cond. */
|
||||||
vSemaphoreDelete(pxCond->xCondWaitSemaphore);
|
vSemaphoreDelete(pxCond->xCondWaitSemaphore);
|
||||||
vSemaphoreDelete(pxCond->xSyncMutex);
|
vSemaphoreDelete(pxCond->xSyncMutex);
|
||||||
pxCond->ulWaitingThreads = 0;
|
pxCond->ulWaitingThreads = 0;
|
||||||
pxCond->xSyncSignal = pdFALSE;
|
pxCond->xSyncSignal = pdFALSE;
|
||||||
pxCond->xIsInitialized = pdFALSE;
|
|
||||||
#endif
|
#endif
|
||||||
|
pxCond->xIsInitialized = pdFALSE;
|
||||||
|
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
}
|
}
|
||||||
@@ -325,14 +344,28 @@ lv_result_t lv_thread_sync_delete(lv_thread_sync_t * pxCond)
|
|||||||
lv_result_t lv_thread_sync_signal_isr(lv_thread_sync_t * pxCond)
|
lv_result_t lv_thread_sync_signal_isr(lv_thread_sync_t * pxCond)
|
||||||
{
|
{
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
#if USE_FREERTOS_TASK_NOTIFY
|
|
||||||
/* Send a notification to the task waiting. */
|
|
||||||
vTaskNotifyGiveFromISR(pxCond->xTaskToNotify, &xHigherPriorityTaskWoken);
|
|
||||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
||||||
#else
|
|
||||||
/* If the cond is uninitialized, perform initialization. */
|
/* If the cond is uninitialized, perform initialization. */
|
||||||
prvCheckCondInit(pxCond);
|
prvCheckCondInit(pxCond);
|
||||||
|
|
||||||
|
#if USE_FREERTOS_TASK_NOTIFY
|
||||||
|
_enter_critical();
|
||||||
|
TaskHandle_t task_to_notify = pxCond->xTaskToNotify;
|
||||||
|
pxCond->xTaskToNotify = NULL;
|
||||||
|
if(task_to_notify == NULL) {
|
||||||
|
/* No task waiting to be notified. Send this signal for later */
|
||||||
|
pxCond->xSyncSignal = pdTRUE;
|
||||||
|
}
|
||||||
|
/* If a task is already waiting, there is no need to set the sync signal */
|
||||||
|
_exit_critical();
|
||||||
|
|
||||||
|
if(task_to_notify != NULL) {
|
||||||
|
/* There is a task waiting. Send a notification to it */
|
||||||
|
vTaskNotifyGiveFromISR(task_to_notify, &xHigherPriorityTaskWoken);
|
||||||
|
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||||
|
}
|
||||||
|
/* If there was no task waiting to be notified, we sent a signal for it to see later. */
|
||||||
|
#else
|
||||||
/* Enter critical section to prevent preemption. */
|
/* Enter critical section to prevent preemption. */
|
||||||
_enter_critical();
|
_enter_critical();
|
||||||
|
|
||||||
@@ -393,7 +426,7 @@ static void prvRunThread(void * pxArg)
|
|||||||
lv_thread_t * pxThread = (lv_thread_t *)pxArg;
|
lv_thread_t * pxThread = (lv_thread_t *)pxArg;
|
||||||
|
|
||||||
/* Run the thread routine. */
|
/* Run the thread routine. */
|
||||||
pxThread->pvStartRoutine((void *)pxThread->xTaskArg);
|
pxThread->pvStartRoutine((void *)pxThread->pTaskArg);
|
||||||
|
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
@@ -432,9 +465,14 @@ static void prvCheckMutexInit(lv_mutex_t * pxMutex)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !USE_FREERTOS_TASK_NOTIFY
|
|
||||||
static void prvCondInit(lv_thread_sync_t * pxCond)
|
static void prvCondInit(lv_thread_sync_t * pxCond)
|
||||||
{
|
{
|
||||||
|
pxCond->xIsInitialized = pdTRUE;
|
||||||
|
pxCond->xSyncSignal = pdFALSE;
|
||||||
|
|
||||||
|
#if USE_FREERTOS_TASK_NOTIFY
|
||||||
|
pxCond->xTaskToNotify = NULL;
|
||||||
|
#else
|
||||||
pxCond->xCondWaitSemaphore = xSemaphoreCreateCounting(ulMAX_COUNT, 0U);
|
pxCond->xCondWaitSemaphore = xSemaphoreCreateCounting(ulMAX_COUNT, 0U);
|
||||||
|
|
||||||
/* Ensure that the FreeRTOS semaphore was successfully created. */
|
/* Ensure that the FreeRTOS semaphore was successfully created. */
|
||||||
@@ -455,14 +493,11 @@ static void prvCondInit(lv_thread_sync_t * pxCond)
|
|||||||
|
|
||||||
/* Condition variable successfully created. */
|
/* Condition variable successfully created. */
|
||||||
pxCond->ulWaitingThreads = 0;
|
pxCond->ulWaitingThreads = 0;
|
||||||
pxCond->xSyncSignal = pdFALSE;
|
#endif
|
||||||
pxCond->xIsInitialized = pdTRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prvCheckCondInit(lv_thread_sync_t * pxCond)
|
static void prvCheckCondInit(lv_thread_sync_t * pxCond)
|
||||||
{
|
{
|
||||||
BaseType_t xSemCreateStatus = pdTRUE;
|
|
||||||
|
|
||||||
/* Check if the condition variable needs to be initialized. */
|
/* Check if the condition variable needs to be initialized. */
|
||||||
if(pxCond->xIsInitialized == pdFALSE) {
|
if(pxCond->xIsInitialized == pdFALSE) {
|
||||||
/* Cond initialization must be in a critical section to prevent two
|
/* Cond initialization must be in a critical section to prevent two
|
||||||
@@ -481,6 +516,7 @@ static void prvCheckCondInit(lv_thread_sync_t * pxCond)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !USE_FREERTOS_TASK_NOTIFY
|
||||||
static void prvTestAndDecrement(lv_thread_sync_t * pxCond,
|
static void prvTestAndDecrement(lv_thread_sync_t * pxCond,
|
||||||
uint32_t ulLocalWaitingThreads)
|
uint32_t ulLocalWaitingThreads)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ extern "C" {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void (*pvStartRoutine)(void *); /**< Application thread function. */
|
void (*pvStartRoutine)(void *); /**< Application thread function. */
|
||||||
void * xTaskArg; /**< Arguments for application thread function. */
|
void * pTaskArg; /**< Arguments for application thread function. */
|
||||||
TaskHandle_t xTaskHandle; /**< FreeRTOS task handle. */
|
TaskHandle_t xTaskHandle; /**< FreeRTOS task handle. */
|
||||||
} lv_thread_t;
|
} lv_thread_t;
|
||||||
|
|
||||||
@@ -61,15 +61,15 @@ typedef struct {
|
|||||||
} lv_mutex_t;
|
} lv_mutex_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
#if USE_FREERTOS_TASK_NOTIFY
|
|
||||||
TaskHandle_t xTaskToNotify;
|
|
||||||
#else
|
|
||||||
BaseType_t
|
BaseType_t
|
||||||
xIsInitialized; /**< Set to pdTRUE if this condition variable is initialized, pdFALSE otherwise. */
|
xIsInitialized; /**< Set to pdTRUE if this condition variable is initialized, pdFALSE otherwise. */
|
||||||
|
BaseType_t xSyncSignal; /**< Set to pdTRUE if the thread is signaled, pdFALSE otherwise. */
|
||||||
|
#if USE_FREERTOS_TASK_NOTIFY
|
||||||
|
TaskHandle_t xTaskToNotify; /**< The task waiting to be signalled. NULL if nothing is waiting. */
|
||||||
|
#else
|
||||||
SemaphoreHandle_t xCondWaitSemaphore; /**< Threads block on this semaphore in lv_thread_sync_wait. */
|
SemaphoreHandle_t xCondWaitSemaphore; /**< Threads block on this semaphore in lv_thread_sync_wait. */
|
||||||
uint32_t ulWaitingThreads; /**< The number of threads currently waiting on this condition variable. */
|
uint32_t ulWaitingThreads; /**< The number of threads currently waiting on this condition variable. */
|
||||||
SemaphoreHandle_t xSyncMutex; /**< Threads take this mutex before accessing the condition variable. */
|
SemaphoreHandle_t xSyncMutex; /**< Threads take this mutex before accessing the condition variable. */
|
||||||
BaseType_t xSyncSignal; /**< Set to pdTRUE if the thread is signaled, pdFALSE otherwise. */
|
|
||||||
#endif
|
#endif
|
||||||
} lv_thread_sync_t;
|
} lv_thread_sync_t;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user