mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-14 06:42:58 +08:00
fix(freertos): notifiy-based sync can be initialized from any task (#6692)
This commit is contained in:
parent
c46f6b0a41
commit
0bd8cbcc9e
@ -50,11 +50,11 @@ static void prvMutexInit(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 prvCheckCondInit(lv_thread_sync_t * pxCond);
|
||||
|
||||
#if !USE_FREERTOS_TASK_NOTIFY
|
||||
static void prvTestAndDecrement(lv_thread_sync_t * pxCond,
|
||||
uint32_t ulLocalWaitingThreads);
|
||||
#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 * xAttr)
|
||||
{
|
||||
pxThread->xTaskArg = xAttr;
|
||||
pxThread->pTaskArg = xAttr;
|
||||
pxThread->pvStartRoutine = pvStartRoutine;
|
||||
|
||||
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)
|
||||
{
|
||||
#if USE_FREERTOS_TASK_NOTIFY
|
||||
/* Store the handle of the calling task. */
|
||||
pxCond->xTaskToNotify = xTaskGetCurrentTaskHandle();
|
||||
#else
|
||||
/* If the cond is uninitialized, perform initialization. */
|
||||
prvCheckCondInit(pxCond);
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
#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. */
|
||||
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. */
|
||||
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)
|
||||
{
|
||||
#if USE_FREERTOS_TASK_NOTIFY
|
||||
/* Send a notification to the task waiting. */
|
||||
xTaskNotifyGive(pxCond->xTaskToNotify);
|
||||
#else
|
||||
/* If the cond is uninitialized, perform initialization. */
|
||||
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. */
|
||||
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)
|
||||
{
|
||||
#if USE_FREERTOS_TASK_NOTIFY
|
||||
LV_UNUSED(pxCond);
|
||||
#else
|
||||
#if !USE_FREERTOS_TASK_NOTIFY
|
||||
/* Cleanup all resources used by the cond. */
|
||||
vSemaphoreDelete(pxCond->xCondWaitSemaphore);
|
||||
vSemaphoreDelete(pxCond->xSyncMutex);
|
||||
pxCond->ulWaitingThreads = 0;
|
||||
pxCond->xSyncSignal = pdFALSE;
|
||||
pxCond->xIsInitialized = pdFALSE;
|
||||
#endif
|
||||
pxCond->xIsInitialized = pdFALSE;
|
||||
|
||||
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)
|
||||
{
|
||||
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. */
|
||||
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();
|
||||
|
||||
@ -393,7 +426,7 @@ static void prvRunThread(void * pxArg)
|
||||
lv_thread_t * pxThread = (lv_thread_t *)pxArg;
|
||||
|
||||
/* Run the thread routine. */
|
||||
pxThread->pvStartRoutine((void *)pxThread->xTaskArg);
|
||||
pxThread->pvStartRoutine((void *)pxThread->pTaskArg);
|
||||
|
||||
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)
|
||||
{
|
||||
pxCond->xIsInitialized = pdTRUE;
|
||||
pxCond->xSyncSignal = pdFALSE;
|
||||
|
||||
#if USE_FREERTOS_TASK_NOTIFY
|
||||
pxCond->xTaskToNotify = NULL;
|
||||
#else
|
||||
pxCond->xCondWaitSemaphore = xSemaphoreCreateCounting(ulMAX_COUNT, 0U);
|
||||
|
||||
/* Ensure that the FreeRTOS semaphore was successfully created. */
|
||||
@ -455,14 +493,11 @@ static void prvCondInit(lv_thread_sync_t * pxCond)
|
||||
|
||||
/* Condition variable successfully created. */
|
||||
pxCond->ulWaitingThreads = 0;
|
||||
pxCond->xSyncSignal = pdFALSE;
|
||||
pxCond->xIsInitialized = pdTRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void prvCheckCondInit(lv_thread_sync_t * pxCond)
|
||||
{
|
||||
BaseType_t xSemCreateStatus = pdTRUE;
|
||||
|
||||
/* Check if the condition variable needs to be initialized. */
|
||||
if(pxCond->xIsInitialized == pdFALSE) {
|
||||
/* 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,
|
||||
uint32_t ulLocalWaitingThreads)
|
||||
{
|
||||
|
@ -51,7 +51,7 @@ extern "C" {
|
||||
|
||||
typedef struct {
|
||||
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. */
|
||||
} lv_thread_t;
|
||||
|
||||
@ -61,15 +61,15 @@ typedef struct {
|
||||
} lv_mutex_t;
|
||||
|
||||
typedef struct {
|
||||
#if USE_FREERTOS_TASK_NOTIFY
|
||||
TaskHandle_t xTaskToNotify;
|
||||
#else
|
||||
BaseType_t
|
||||
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. */
|
||||
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. */
|
||||
BaseType_t xSyncSignal; /**< Set to pdTRUE if the thread is signaled, pdFALSE otherwise. */
|
||||
#endif
|
||||
} lv_thread_sync_t;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user