btstack_run_loop_freertos: implement execute on main thread

This commit is contained in:
Matthias Ringwald 2021-03-16 16:14:38 +01:00
parent 38b6e83679
commit c51a1d5a2d
2 changed files with 67 additions and 30 deletions

View File

@ -67,6 +67,7 @@
#include "task.h"
#include "queue.h"
#include "event_groups.h"
#include "semphr.h"
#endif
typedef struct function_call {
@ -90,10 +91,12 @@ typedef struct function_call {
#ifdef USE_STATIC_ALLOC
static StaticQueue_t btstack_run_loop_queue_object;
static uint8_t btstack_run_loop_queue_storage[ RUN_LOOP_QUEUE_LENGTH * RUN_LOOP_QUEUE_ITEM_SIZE ];
static StaticSemaphore_t btstack_run_loop_callback_mutex_object;
#endif
static QueueHandle_t btstack_run_loop_queue;
static TaskHandle_t btstack_run_loop_task;
static SemaphoreHandle_t btstack_run_loop_callbacks_mutex;
#ifndef HAVE_FREERTOS_TASK_NOTIFICATIONS
static EventGroupHandle_t btstack_run_loop_event_group;
@ -114,8 +117,7 @@ static void btstack_run_loop_freertos_set_timer(btstack_timer_source_t *ts, uint
ts->timeout = btstack_run_loop_freertos_get_time_ms() + timeout_in_ms + 1;
}
// schedules execution from regular thread
void btstack_run_loop_freertos_trigger(void){
static void btstack_run_loop_freertos_trigger_from_thread(void){
#ifdef HAVE_FREERTOS_TASK_NOTIFICATIONS
xTaskNotify(btstack_run_loop_task, EVENT_GROUP_FLAG_RUN_LOOP, eSetBits);
#else
@ -123,24 +125,6 @@ void btstack_run_loop_freertos_trigger(void){
#endif
}
void btstack_run_loop_freertos_execute_code_on_main_thread(void (*fn)(void *arg), void * arg){
// directly call function if already on btstack task
if (xTaskGetCurrentTaskHandle() == btstack_run_loop_task){
(*fn)(arg);
return;
}
function_call_t message;
message.fn = fn;
message.arg = arg;
BaseType_t res = xQueueSendToBack(btstack_run_loop_queue, &message, 0); // portMAX_DELAY);
if (res != pdTRUE){
log_error("Failed to post fn %p", fn);
}
btstack_run_loop_freertos_trigger();
}
#if defined(HAVE_FREERTOS_TASK_NOTIFICATIONS) || (INCLUDE_xEventGroupSetBitFromISR == 1)
static void btstack_run_loop_freertos_poll_data_sources_from_irq(void){
BaseType_t xHigherPriorityTaskWoken;
@ -157,19 +141,12 @@ static void btstack_run_loop_freertos_poll_data_sources_from_irq(void){
xEventGroupSetBitsFromISR(btstack_run_loop_event_group, EVENT_GROUP_FLAG_RUN_LOOP, &xHigherPriorityTaskWoken);
#endif
}
void btstack_run_loop_freertos_trigger_from_isr(void){
btstack_run_loop_freertos_trigger_from_isr();
}
#endif
static void btstack_run_loop_freertos_trigger_exit_internal(void){
run_loop_exit_requested = true;
}
void btstack_run_loop_freertos_trigger_exit(void){
btstack_run_loop_freertos_trigger_exit_internal();
}
/**
* Execute run_loop
*/
@ -183,7 +160,18 @@ static void btstack_run_loop_freertos_execute(void) {
// process data sources
btstack_run_loop_base_poll_data_sources();
// process registered function calls on run loop thread
// execute callbacks - protect list with mutex
while (1){
xSemaphoreTake(btstack_run_loop_callbacks_mutex, portMAX_DELAY);
btstack_context_callback_registration_t * callback_registration = (btstack_context_callback_registration_t *) btstack_linked_list_pop(&btstack_run_loop_base_callbacks);
xSemaphoreGive(btstack_run_loop_callbacks_mutex);
if (callback_registration == NULL){
break;
}
(*callback_registration->callback)(callback_registration->context);
}
// process registered function calls on run loop thread (deprecated)
while (true){
function_call_t message = { NULL, NULL };
BaseType_t res = xQueueReceive( btstack_run_loop_queue, &message, 0);
@ -197,7 +185,7 @@ static void btstack_run_loop_freertos_execute(void) {
uint32_t now = btstack_run_loop_freertos_get_time_ms();
btstack_run_loop_base_process_timers(now);
// exit triggered by btstack_run_loop_freertos_trigger_exit (from data source, timer, run on main thread)
// exit triggered by btstack_run_loop_trigger_exit (main thread or other thread)
if (run_loop_exit_requested) break;
// wait for timeout or event group/task notification
@ -217,13 +205,23 @@ static void btstack_run_loop_freertos_execute(void) {
}
}
static void btstack_run_loop_freertos_execute_on_main_thread(btstack_context_callback_registration_t * callback_registration){
// protect list with mutex
xSemaphoreTake(btstack_run_loop_callbacks_mutex, portMAX_DELAY);
btstack_run_loop_base_add_callback(callback_registration);
xSemaphoreGive(btstack_run_loop_callbacks_mutex);
btstack_run_loop_freertos_trigger_from_thread();
}
static void btstack_run_loop_freertos_init(void){
btstack_run_loop_base_init();
#ifdef USE_STATIC_ALLOC
btstack_run_loop_queue = xQueueCreateStatic(RUN_LOOP_QUEUE_LENGTH, RUN_LOOP_QUEUE_ITEM_SIZE, btstack_run_loop_queue_storage, &btstack_run_loop_queue_object);
btstack_run_loop_mutex = xSemaphoreCreateMutexStatic(&btstack_run_loop_callback_mutex_object);
#else
btstack_run_loop_queue = xQueueCreate(RUN_LOOP_QUEUE_LENGTH, RUN_LOOP_QUEUE_ITEM_SIZE);
btstack_run_loop_callbacks_mutex = xSemaphoreCreateMutex();
#endif
#ifndef HAVE_FREERTOS_TASK_NOTIFICATIONS
@ -258,10 +256,45 @@ static const btstack_run_loop_t btstack_run_loop_freertos = {
#else
NULL,
#endif
NULL,
btstack_run_loop_freertos_execute_on_main_thread,
&btstack_run_loop_freertos_trigger_exit_internal,
};
const btstack_run_loop_t * btstack_run_loop_freertos_get_instance(void){
return &btstack_run_loop_freertos;
}
// @deprecated functions
// schedules execution from regular thread
void btstack_run_loop_freertos_trigger(void){
btstack_run_loop_freertos_trigger_from_thread();
}
void btstack_run_loop_freertos_execute_code_on_main_thread(void (*fn)(void *arg), void * arg){
// directly call function if already on btstack task
if (xTaskGetCurrentTaskHandle() == btstack_run_loop_task){
(*fn)(arg);
return;
}
function_call_t message;
message.fn = fn;
message.arg = arg;
BaseType_t res = xQueueSendToBack(btstack_run_loop_queue, &message, 0); // portMAX_DELAY);
if (res != pdTRUE){
log_error("Failed to post fn %p", fn);
}
btstack_run_loop_freertos_trigger();
}
void btstack_run_loop_freertos_trigger_exit(void){
btstack_run_loop_freertos_trigger_exit_internal();
}
#if defined(HAVE_FREERTOS_TASK_NOTIFICATIONS) || (INCLUDE_xEventGroupSetBitFromISR == 1)
void btstack_run_loop_freertos_trigger_from_isr(void){
btstack_run_loop_freertos_trigger_from_isr();
}
#endif

View File

@ -58,12 +58,16 @@ const btstack_run_loop_t * btstack_run_loop_freertos_get_instance(void);
/**
* @brief Execute code on BTstack run loop. Can be used to control BTstack from a different thread
* @deprecated Please use btstack_run_loop_execute_on_main_thread() instead
*/
void btstack_run_loop_freertos_execute_code_on_main_thread(void (*fn)(void *arg), void * arg);
/**
* @brief Triggers processing of data sources from thread context.
* Has to be called after enabling a poll data source to wake-pup run loop.
*
* @deprecated Please use btstack_run_loop_execute_on_main_thread() instead
*/
void btstack_run_loop_freertos_trigger(void);