1 /* 2 * Copyright (c) 2022 Raspberry Pi (Trading) Ltd. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #ifndef _PICO_ASYNC_CONTEXT_FREERTOS_H 8 #define _PICO_ASYNC_CONTEXT_FREERTOS_H 9 10 /** \file pico/async_context.h 11 * \defgroup async_context_freertos async_context_freertos 12 * \ingroup pico_async_context 13 * 14 * \brief async_context_freertos provides an implementation of \ref async_context that handles asynchronous 15 * work in a separate FreeRTOS task. 16 */ 17 #include "pico/async_context.h" 18 19 // FreeRTOS includes 20 #include "FreeRTOS.h" 21 #include "semphr.h" 22 #include "timers.h" 23 24 #ifdef __cplusplus 25 extern "C" { 26 #endif 27 28 #ifndef ASYNC_CONTEXT_DEFAULT_FREERTOS_TASK_PRIORITY 29 #define ASYNC_CONTEXT_DEFAULT_FREERTOS_TASK_PRIORITY ( tskIDLE_PRIORITY + 4) 30 #endif 31 32 #ifndef ASYNC_CONTEXT_DEFAULT_FREERTOS_TASK_STACK_SIZE 33 #define ASYNC_CONTEXT_DEFAULT_FREERTOS_TASK_STACK_SIZE configMINIMAL_STACK_SIZE 34 #endif 35 36 typedef struct async_context_freertos async_context_freertos_t; 37 38 #if !defined(configNUMBER_OF_CORES) && defined(configNUM_CORES) 39 #if !portSUPPORT_SMP 40 #error configNUMBER_OF_CORES is the new name for configNUM_CORES 41 #else 42 // portSUPPORT_SMP was defined in old smp branch 43 #error configNUMBER_OF_CORES is the new name for configNUM_CORES, however it looks like you may need to define both as you are using an old SMP branch of FreeRTOS 44 #endif 45 #endif 46 47 /** 48 * \brief Configuration object for async_context_freertos instances. 49 */ 50 typedef struct async_context_freertos_config { 51 /** 52 * \brief Task priority for the async_context task 53 */ 54 UBaseType_t task_priority; 55 /** 56 * \brief Stack size for the async_context task 57 */ 58 configSTACK_DEPTH_TYPE task_stack_size; 59 /** 60 * \brief the core ID (see \ref portGET_CORE_ID()) to pin the task to. 61 * This is only relevant in SMP mode. 62 */ 63 #if configUSE_CORE_AFFINITY && configNUMBER_OF_CORES > 1 64 UBaseType_t task_core_id; 65 #endif 66 } async_context_freertos_config_t; 67 68 struct async_context_freertos { 69 async_context_t core; 70 SemaphoreHandle_t lock_mutex; 71 SemaphoreHandle_t work_needed_sem; 72 TimerHandle_t timer_handle; 73 TaskHandle_t task_handle; 74 uint8_t nesting; 75 volatile bool task_should_exit; 76 }; 77 78 /*! 79 * \brief Initialize an async_context_freertos instance using the specified configuration 80 * \ingroup async_context_freertos 81 * 82 * If this method succeeds (returns true), then the async_context is available for use 83 * and can be de-initialized by calling async_context_deinit(). 84 * 85 * \param self a pointer to async_context_freertos structure to initialize 86 * \param config the configuration object specifying characteristics for the async_context 87 * \return true if initialization is successful, false otherwise 88 */ 89 bool async_context_freertos_init(async_context_freertos_t *self, async_context_freertos_config_t *config); 90 91 /*! 92 * \brief Return a copy of the default configuration object used by \ref async_context_freertos_init_with_defaults() 93 * \ingroup async_context_freertos 94 * 95 * The caller can then modify just the settings it cares about, and call \ref async_context_freertos_init() 96 * \return the default configuration object 97 */ async_context_freertos_default_config(void)98 static inline async_context_freertos_config_t async_context_freertos_default_config(void) { 99 async_context_freertos_config_t config = { 100 .task_priority = ASYNC_CONTEXT_DEFAULT_FREERTOS_TASK_PRIORITY, 101 .task_stack_size = ASYNC_CONTEXT_DEFAULT_FREERTOS_TASK_STACK_SIZE, 102 #if configUSE_CORE_AFFINITY && configNUMBER_OF_CORES > 1 103 .task_core_id = (UBaseType_t)-1, // none 104 #endif 105 }; 106 return config; 107 108 } 109 110 /*! 111 * \brief Initialize an async_context_freertos instance with default values 112 * \ingroup async_context_freertos 113 * 114 * If this method succeeds (returns true), then the async_context is available for use 115 * and can be de-initialized by calling async_context_deinit(). 116 * 117 * \param self a pointer to async_context_freertos structure to initialize 118 * \return true if initialization is successful, false otherwise 119 */ async_context_freertos_init_with_defaults(async_context_freertos_t * self)120 static inline bool async_context_freertos_init_with_defaults(async_context_freertos_t *self) { 121 async_context_freertos_config_t config = async_context_freertos_default_config(); 122 return async_context_freertos_init(self, &config); 123 } 124 125 #ifdef __cplusplus 126 } 127 #endif 128 129 #endif 130