Skip to content

Commit 968d67b

Browse files
committed
async_context_freertos: Add support for configSUPPORT_STATIC_ALLOCATION
The implementation of async_context_freertos currently assumes that FreeRTOS has been configured with `configSUPPORT_DYNAMIC_ALLOCATION`, which causes it to allocate semaphores, timers and tasks from the heap. However, some projects may prefer `configSUPPORT_STATIC_ALLOCATION`, which requires memory to be allocated ahead of time. This change allows async_context_freertos to support either static or dynamic allocation. The way this works is when `configSUPPORT_STATIC_ALLOCATION` is enabled, `async_context_freertos` struct will reserve extra space for the static objects (e.g. `StaticSemaphore_t`) and it will prefer to use the static creation functions (e.g. `xSemaphoreCreateBinaryStatic()`). For the task creation, the user will be responsible for allocating the stack memory and setting the task_stack field in `async_context_freertos_config_t`. For convenience, The `cyw43_arch_init_default_async_context()` function will reserve `CYW43_TASK_STACK_SIZE` words of stack space in static memory.
1 parent 65a8907 commit 968d67b

File tree

3 files changed

+56
-2
lines changed

3 files changed

+56
-2
lines changed

src/rp2_common/pico_async_context/async_context_freertos.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,19 +109,45 @@ bool async_context_freertos_init(async_context_freertos_t *self, async_context_f
109109
self->core.type = &template;
110110
self->core.flags = ASYNC_CONTEXT_FLAG_CALLBACK_FROM_NON_IRQ;
111111
self->core.core_num = get_core_num();
112+
#if configSUPPORT_STATIC_ALLOCATION
113+
self->lock_mutex = xSemaphoreCreateRecursiveMutexStatic(&self->lock_mutex_buf);
114+
self->work_needed_sem = xSemaphoreCreateBinaryStatic(&self->work_needed_sem_buf);
115+
self->timer_handle = xTimerCreateStatic( "async_context_timer", // Just a text name, not used by the kernel.
116+
portMAX_DELAY,
117+
pdFALSE, // The timers will auto-reload themselves when they expire.
118+
self,
119+
timer_handler,
120+
&self->timer_buf);
121+
122+
if (config->task_stack) {
123+
self->task_handle = xTaskCreateStatic( async_context_task,
124+
"async_context_task",
125+
config->task_stack_size,
126+
self,
127+
config->task_priority,
128+
config->task_stack,
129+
&self->task_buf);
130+
}
131+
#else
112132
self->lock_mutex = xSemaphoreCreateRecursiveMutex();
113133
self->work_needed_sem = xSemaphoreCreateBinary();
114134
self->timer_handle = xTimerCreate( "async_context_timer", // Just a text name, not used by the kernel.
115135
portMAX_DELAY,
116136
pdFALSE, // The timers will auto-reload themselves when they expire.
117137
self,
118138
timer_handler);
139+
#endif
119140

120141
if (!self->lock_mutex ||
121142
!self->work_needed_sem ||
122143
!self->timer_handle ||
123-
pdPASS != xTaskCreate(async_context_task, "async_context_task", config->task_stack_size, self,
124-
config->task_priority, &self->task_handle)) {
144+
#if configSUPPORT_STATIC_ALLOCATION
145+
!self->task_handle
146+
#else
147+
pdPASS == xTaskCreate(async_context_task, "async_context_task", config->task_stack_size, self,
148+
config->task_priority, &self->task_handle)
149+
#endif
150+
) {
125151
async_context_deinit(&self->core);
126152
return false;
127153
}
@@ -179,6 +205,9 @@ void async_context_freertos_lock_check(__unused async_context_t *self_base) {
179205
typedef struct sync_func_call{
180206
async_when_pending_worker_t worker;
181207
SemaphoreHandle_t sem;
208+
#if configSUPPORT_STATIC_ALLOCATION
209+
StaticSemaphore_t sem_buf;
210+
#endif
182211
uint32_t (*func)(void *param);
183212
void *param;
184213
uint32_t rc;
@@ -197,7 +226,11 @@ uint32_t async_context_freertos_execute_sync(async_context_t *self_base, uint32_
197226
call.worker.do_work = handle_sync_func_call;
198227
call.func = func;
199228
call.param = param;
229+
#if configSUPPORT_STATIC_ALLOCATION
230+
call.sem = xSemaphoreCreateBinaryStatic(&call.sem_buf);
231+
#else
200232
call.sem = xSemaphoreCreateBinary();
233+
#endif
201234
async_context_add_when_pending_worker(self_base, &call.worker);
202235
async_context_set_work_pending(self_base, &call.worker);
203236
xSemaphoreTake(call.sem, portMAX_DELAY);

src/rp2_common/pico_async_context/include/pico/async_context_freertos.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ typedef struct async_context_freertos_config {
5656
* \brief Stack size for the async_context task
5757
*/
5858
configSTACK_DEPTH_TYPE task_stack_size;
59+
/**
60+
* \brief Pointer to stack memory for the async_context task.
61+
* If this is not provided, then a stack will be allocated from the
62+
* freertos heap.
63+
*/
64+
#if configSUPPORT_STATIC_ALLOCATION
65+
StackType_t *task_stack;
66+
#endif
5967
/**
6068
* \brief the core ID (see \ref portGET_CORE_ID()) to pin the task to.
6169
* This is only relevant in SMP mode.
@@ -71,6 +79,12 @@ struct async_context_freertos {
7179
SemaphoreHandle_t work_needed_sem;
7280
TimerHandle_t timer_handle;
7381
TaskHandle_t task_handle;
82+
#if configSUPPORT_STATIC_ALLOCATION
83+
StaticSemaphore_t lock_mutex_buf;
84+
StaticSemaphore_t work_needed_sem_buf;
85+
StaticTimer_t timer_buf;
86+
StaticTask_t task_buf;
87+
#endif
7488
uint8_t nesting;
7589
volatile bool task_should_exit;
7690
};

src/rp2_common/pico_cyw43_arch/cyw43_arch_freertos.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,20 @@
2525

2626
static async_context_freertos_t cyw43_async_context_freertos;
2727

28+
#if configSUPPORT_STATIC_ALLOCATION
29+
static StackType_t cyw43_async_context_freertos_task_stack[CYW43_TASK_STACK_SIZE];
30+
#endif
31+
2832
async_context_t *cyw43_arch_init_default_async_context(void) {
2933
async_context_freertos_config_t config = async_context_freertos_default_config();
3034
#ifdef CYW43_TASK_PRIORITY
3135
config.task_priority = CYW43_TASK_PRIORITY;
3236
#endif
3337
#ifdef CYW43_TASK_STACK_SIZE
3438
config.task_stack_size = CYW43_TASK_STACK_SIZE;
39+
#endif
40+
#if configSUPPORT_STATIC_ALLOCATION
41+
config.task_stack = cyw43_async_context_freertos_task_stack;
3542
#endif
3643
if (async_context_freertos_init(&cyw43_async_context_freertos, &config))
3744
return &cyw43_async_context_freertos.core;

0 commit comments

Comments
 (0)