Skip to content

Support static allocation in Freertos example #651

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ These examples require you to set the `FREERTOS_KERNEL_PATH` to point to the Fre

App|Description
---|---
[hello_freertos](freertos/hello_freertos) | Examples that demonstrate how run FreeRTOS and tasks on 1 or 2 cores.
[hello_freertos_one_core](freertos/hello_freertos) | Demonstrates how run FreeRTOS and tasks on one core
[hello_freertos_two_cores](freertos/hello_freertos) | Demonstrates how run FreeRTOS and tasks on two cores.
[hello_freertos_static_allocation](freertos/hello_freertos) | Demonstrates how run FreeRTOS on two cores with static RAM allocation.

### GPIO

Expand Down
4 changes: 4 additions & 0 deletions freertos/FreeRTOSConfig_examples_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,12 @@
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t

/* Memory allocation related definitions. */
#ifndef configSUPPORT_STATIC_ALLOCATION
#define configSUPPORT_STATIC_ALLOCATION 0
#endif
#ifndef configSUPPORT_DYNAMIC_ALLOCATION
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#endif
#define configTOTAL_HEAP_SIZE (128*1024)
#define configAPPLICATION_ALLOCATED_HEAP 0

Expand Down
64 changes: 48 additions & 16 deletions freertos/hello_freertos/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,42 +1,74 @@
set(TARGET_NAME hello_freertos1)
add_executable(${TARGET_NAME}
# Example running FreeRTOS on 1 core
add_executable(hello_freertos_one_core
hello_freertos.c
)
target_include_directories(${TARGET_NAME} PRIVATE
target_include_directories(hello_freertos_one_core PRIVATE
${CMAKE_CURRENT_LIST_DIR}/..
)
target_link_libraries(${TARGET_NAME} PRIVATE
# Linking to FreeRTOS-Kernel-Heap4 means we use a dynamic heap for allocations
target_link_libraries(hello_freertos_one_core PRIVATE
pico_async_context_freertos
FreeRTOS-Kernel-Heap4
pico_stdlib
)
# Set the nunber of cores to 1.
# This defaults to 2 in FreeRTOSConfig_examples_common.h if not defined in here
target_compile_definitions(hello_freertos_one_core PRIVATE
configNUMBER_OF_CORES=1
)
if(PICO_CYW43_SUPPORTED)
# For led support on pico_w
target_link_libraries(${TARGET_NAME} PRIVATE
target_link_libraries(hello_freertos_one_core PRIVATE
pico_cyw43_arch_none
)
)
endif()
target_compile_definitions(${TARGET_NAME} PRIVATE
configNUMBER_OF_CORES=1
)
pico_add_extra_outputs(${TARGET_NAME})
pico_add_extra_outputs(hello_freertos_one_core)

set(TARGET_NAME hello_freertos2)
add_executable(${TARGET_NAME}
# Example running FreeRTOS on 2 cores
add_executable(hello_freertos_two_cores
hello_freertos.c
)
target_include_directories(${TARGET_NAME} PRIVATE
target_include_directories(hello_freertos_two_cores PRIVATE
${CMAKE_CURRENT_LIST_DIR}/..
)
target_link_libraries(${TARGET_NAME} PRIVATE
# Linking to FreeRTOS-Kernel-Heap4 to use a dynamic heap for allocations
target_link_libraries(hello_freertos_two_cores PRIVATE
pico_async_context_freertos
FreeRTOS-Kernel-Heap4
pico_stdlib
)
if(PICO_CYW43_SUPPORTED)
# For led support on pico_w
target_link_libraries(${TARGET_NAME} PRIVATE
target_link_libraries(hello_freertos_two_cores PRIVATE
pico_cyw43_arch_none
)
endif()
pico_add_extra_outputs(hello_freertos_two_cores)

# Example running FreeRTOS on 2 cores with static RAM allocation
add_executable(hello_freertos_static_allocation
hello_freertos.c
)
target_include_directories(hello_freertos_static_allocation PRIVATE
${CMAKE_CURRENT_LIST_DIR}/..
)
# Linking to FreeRTOS-Kernel-Static to use static memory instead of a dynamic heap for allocations
target_link_libraries(hello_freertos_static_allocation PRIVATE
pico_async_context_freertos
FreeRTOS-Kernel-Static
pico_stdlib
)
# Change the configuration to just use static RAM allocation
# If configSUPPORT_DYNAMIC_ALLOCATION is left undefined it will default to 1
# If configSUPPORT_STATIC_ALLOCATION is left undefined it will default to 0
target_compile_definitions(hello_freertos_static_allocation PRIVATE
configSUPPORT_STATIC_ALLOCATION=1
configSUPPORT_DYNAMIC_ALLOCATION=0
)
if(PICO_CYW43_SUPPORTED)
# For led support on pico_w
target_link_libraries(hello_freertos_static_allocation PRIVATE
pico_cyw43_arch_none
)
endif()
pico_add_extra_outputs(${TARGET_NAME})
pico_add_extra_outputs(hello_freertos_static_allocation)
37 changes: 28 additions & 9 deletions freertos/hello_freertos/hello_freertos.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,22 @@
static async_context_freertos_t async_context_instance;

// Create an async context
static async_context_t *example_async_context(void) {
static async_context_t *create_async_context(void) {
async_context_freertos_config_t config = async_context_freertos_default_config();
config.task_priority = WORKER_TASK_PRIORITY; // defaults to ASYNC_CONTEXT_DEFAULT_FREERTOS_TASK_PRIORITY
config.task_stack_size = WORKER_TASK_STACK_SIZE; // defaults to ASYNC_CONTEXT_DEFAULT_FREERTOS_TASK_STACK_SIZE
#if configSUPPORT_STATIC_ALLOCATION
static StackType_t async_context_freertos_task_stack[WORKER_TASK_STACK_SIZE];
config.task_stack = async_context_freertos_task_stack;
#endif
if (!async_context_freertos_init(&async_context_instance, &config))
return NULL;
return &async_context_instance.core;
}

#if USE_LED
// Turn led on or off
static void pico_set_led(bool led_on) {
static void set_led(bool led_on) {
#if defined PICO_DEFAULT_LED_PIN
gpio_put(PICO_DEFAULT_LED_PIN, led_on);
#elif defined(CYW43_WL_GPIO_LED_PIN)
Expand All @@ -68,20 +72,20 @@ static void pico_set_led(bool led_on) {
}

// Initialise led
static void pico_init_led(void) {
static void init_led(void) {
#if defined PICO_DEFAULT_LED_PIN
gpio_init(PICO_DEFAULT_LED_PIN);
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
#elif defined(CYW43_WL_GPIO_LED_PIN)
hard_assert(cyw43_arch_init() == PICO_OK);
pico_set_led(false); // make sure cyw43 is started
set_led(false); // make sure cyw43 is started
#endif
}

void blink_task(__unused void *params) {
bool on = false;
printf("blink_task starts\n");
pico_init_led();
init_led();
while (true) {
#if configNUMBER_OF_CORES > 1
static int last_core_id = -1;
Expand All @@ -90,7 +94,7 @@ void blink_task(__unused void *params) {
printf("blink task is on core %d\n", last_core_id);
}
#endif
pico_set_led(on);
set_led(on);
on = !on;

#if LED_BUSY_WAIT
Expand Down Expand Up @@ -122,13 +126,20 @@ static void do_work(async_context_t *context, async_at_time_worker_t *worker) {
async_at_time_worker_t worker_timeout = { .do_work = do_work };

void main_task(__unused void *params) {
async_context_t *context = example_async_context();
async_context_t *context = create_async_context();
// start the worker running
async_context_add_at_time_worker_in_ms(context, &worker_timeout, 0);
#if USE_LED
// start the led blinking
#if configSUPPORT_STATIC_ALLOCATION
static StackType_t blink_stack[BLINK_TASK_STACK_SIZE];
static StaticTask_t blink_buf;
xTaskCreateStatic(blink_task, "BlinkThread", BLINK_TASK_STACK_SIZE, NULL, BLINK_TASK_PRIORITY, blink_stack, &blink_buf);
#else
static_assert(configSUPPORT_DYNAMIC_ALLOCATION, "");
xTaskCreate(blink_task, "BlinkThread", BLINK_TASK_STACK_SIZE, NULL, BLINK_TASK_PRIORITY, NULL);
#endif
#endif // configSUPPORT_STATIC_ALLOCATION
#endif // USE_LED
int count = 0;
while(true) {
#if configNUMBER_OF_CORES > 1
Expand All @@ -146,11 +157,19 @@ void main_task(__unused void *params) {

void vLaunch( void) {
TaskHandle_t task;
#if configSUPPORT_STATIC_ALLOCATION
static StackType_t main_stack[MAIN_TASK_STACK_SIZE];
static StaticTask_t main_buf;
task = xTaskCreateStatic(main_task, "MainThread", MAIN_TASK_STACK_SIZE, NULL, MAIN_TASK_PRIORITY, main_stack, &main_buf);
#else
static_assert(configSUPPORT_DYNAMIC_ALLOCATION, "");
xTaskCreate(main_task, "MainThread", MAIN_TASK_STACK_SIZE, NULL, MAIN_TASK_PRIORITY, &task);

#endif // configSUPPORT_STATIC_ALLOCATION
#if configUSE_CORE_AFFINITY && configNUMBER_OF_CORES > 1
// we must bind the main task to one core (well at least while the init is called)
vTaskCoreAffinitySet(task, 1);
#else
(void)task;
#endif

/* Start the tasks and timer running. */
Expand Down