From 5dfbf0747f13754d7a7252e198e073d969a2dfce Mon Sep 17 00:00:00 2001 From: Kirill Brezhnyev Date: Thu, 21 Nov 2024 15:43:45 +0100 Subject: [PATCH] Update documentation for asyncFreeRtos resolves: BS-2650 Change-Id: I7f3542ceea547ece3af5119826c41aa00fa65bc2 --- libs/bsw/asyncFreeRtos/doc/index.rst | 45 ++++---- .../asyncFreeRtos/doc/user/adapter_api.rst | 28 ----- libs/bsw/asyncFreeRtos/doc/user/async_api.rst | 29 ----- .../doc/user/asynchronous_execution.rst | 93 ++++++++++++++++ libs/bsw/asyncFreeRtos/doc/user/index.rst | 10 ++ .../asyncFreeRtos/doc/user/names_hooking.rst | 19 ++++ .../doc/user/scenarios/execute.rst | 38 ------- .../doc/user/scenarios/future.rst | 40 ------- .../doc/user/scenarios/index.rst | 37 ------ .../doc/user/scenarios/schedule.rst | 37 ------ .../doc/user/scenarios/startup.rst | 37 ------ .../doc/user/startup_sequence.rst | 65 +++++++++++ .../asyncFreeRtos/doc/user/static_config.rst | 30 ----- .../doc/user/synchornization_mechanisms.rst | 105 ++++++++++++++++++ .../include/async/FreeRtosAdapter.h | 76 +++++++++++++ .../include/async/FutureSupport.h | 35 ++++++ libs/bsw/asyncFreeRtos/include/async/Lock.h | 9 +- .../include/async/ModifiableLock.h | 11 ++ .../include/async/StaticContextHook.h | 7 ++ .../include/async/StaticRunnable.h | 11 +- .../include/async/StaticTickHook.h | 39 ------- .../asyncFreeRtos/include/async/TaskContext.h | 87 ++++++++++++++- .../include/async/TaskInitializer.h | 52 +++++++++ libs/bsw/asyncFreeRtos/include/async/Types.h | 5 + 24 files changed, 605 insertions(+), 340 deletions(-) delete mode 100644 libs/bsw/asyncFreeRtos/doc/user/adapter_api.rst delete mode 100644 libs/bsw/asyncFreeRtos/doc/user/async_api.rst create mode 100644 libs/bsw/asyncFreeRtos/doc/user/asynchronous_execution.rst create mode 100644 libs/bsw/asyncFreeRtos/doc/user/index.rst create mode 100644 libs/bsw/asyncFreeRtos/doc/user/names_hooking.rst delete mode 100644 libs/bsw/asyncFreeRtos/doc/user/scenarios/execute.rst delete mode 100644 libs/bsw/asyncFreeRtos/doc/user/scenarios/future.rst delete mode 100644 libs/bsw/asyncFreeRtos/doc/user/scenarios/index.rst delete mode 100644 libs/bsw/asyncFreeRtos/doc/user/scenarios/schedule.rst delete mode 100644 libs/bsw/asyncFreeRtos/doc/user/scenarios/startup.rst create mode 100644 libs/bsw/asyncFreeRtos/doc/user/startup_sequence.rst delete mode 100644 libs/bsw/asyncFreeRtos/doc/user/static_config.rst create mode 100644 libs/bsw/asyncFreeRtos/doc/user/synchornization_mechanisms.rst delete mode 100644 libs/bsw/asyncFreeRtos/include/async/StaticTickHook.h diff --git a/libs/bsw/asyncFreeRtos/doc/index.rst b/libs/bsw/asyncFreeRtos/doc/index.rst index 40b9a510e6..381a8b08ee 100644 --- a/libs/bsw/asyncFreeRtos/doc/index.rst +++ b/libs/bsw/asyncFreeRtos/doc/index.rst @@ -1,35 +1,36 @@ asyncFreeRtos ============= -Overview --------- +This module provides a collection of classes that serve as an intermediate layer +between the asynchronous operations API and their implementation in **FreeRTOS**. +The supported asynchronous operations include: -The module implements the generic ``async`` API for FreeRTOS. +* Non-blocking immediate execution +* Non-blocking scheduling of single-time execution +* Non-blocking scheduling of cyclic execution +* Thread synchronization using ``wait()`` and ``notify()`` mechanisms +* Secure sections with ``Lock`` + +The implementation of these asynchronous operations is achieved by wrapping native +**FreeRTOS** functions into classes like ``async::TaskContext`` and ``async::FutureSupport``. +Additional classes, such as ``async::FreeRtosAdapter`` and ``async::StaticRunnable``, +offer a public API for initializing tasks that can later be executed asynchronously. The main features of this implementation are: -* A configurable maximum number of tasks can be configured (as contexts) using simple - initialization types that also allocate tasks stacks statically -* A context maps to a FreeRTOS task -* A context can be represented by a number (starting with 0). A higher context number - indicates a higher prio of the corresponding task. -* The idle task has the reserved value (and priority) 0. -* The timer task is the task with the highest priority in the system. -* All other tasks priorities are between idle and timer task priority. -* All tasks can be configured by simple configuration objects that also statically - allocate the required stacks. -* A hook concept for registering to task switch events is available -* A simple interface for synchronizing FreeRTOS with interrupts is available -* Implementations of legacy interfaces `looper` and `ITimeoutManager2` are available - for each configured task (they can be optionally disabled) +* A single ``async::Task`` instance corresponds to a single **FreeRTOS** task (via TaskHandle_t, a pointer to the **FreeRTOS** structure). +* The ``async::Task`` context is represented by an integer ID. A higher context ID indicates a higher priority for the corresponding task. +* The idle task has a reserved context ID and priority of 0. +* The timer task is assigned the highest priority in the system. +* All other task priorities are assigned values between the idle and timer task priorities. +* Task configuration specifies both the context ID and the required stack size. +* A Runnable is executed within the context of one of the initialized instances of ``async::Task``. +* A hook mechanism is available for registering task switch events. +* An interface is provided for synchronizing **FreeRTOS** with interrupts. .. toctree:: :maxdepth: 1 :glob: - :hidden: - user/adapter_api - user/async_api - user/scenarios/index - user/static_config + */index diff --git a/libs/bsw/asyncFreeRtos/doc/user/adapter_api.rst b/libs/bsw/asyncFreeRtos/doc/user/adapter_api.rst deleted file mode 100644 index d25147d1fa..0000000000 --- a/libs/bsw/asyncFreeRtos/doc/user/adapter_api.rst +++ /dev/null @@ -1,28 +0,0 @@ -Adapter API -=========== - -Overview --------- - -The adapter API is designed to interface with FreeRTOS, a real-time operating system for -embedded devices, through a template class FreeRtosAdapter. - -Code generation ---------------- - -Not applicable - -Configuration -------------- - -Not applicable - -Calibration ------------ - -Not applicable - -Usage Examples and Integration ------------------------------- - -Should be synced together with a specific implementation ``asyncFreeRtos`` module. \ No newline at end of file diff --git a/libs/bsw/asyncFreeRtos/doc/user/async_api.rst b/libs/bsw/asyncFreeRtos/doc/user/async_api.rst deleted file mode 100644 index 57ff19a0ec..0000000000 --- a/libs/bsw/asyncFreeRtos/doc/user/async_api.rst +++ /dev/null @@ -1,29 +0,0 @@ -Async API -========= - -Overview --------- - -The async API is designed to interface with FreeRTOS, a real-time operating system by -providing interfaces for executing tasks asynchronously, scheduling them for later execution -and for setting them to run at fixed intervals. - -Code generation ---------------- - -Not applicable - -Configuration -------------- - -Not applicable - -Calibration ------------ - -Not applicable - -Usage Examples and Integration ------------------------------- - -Should be synced together with a specific implementation ``asyncFreeRtos`` module. \ No newline at end of file diff --git a/libs/bsw/asyncFreeRtos/doc/user/asynchronous_execution.rst b/libs/bsw/asyncFreeRtos/doc/user/asynchronous_execution.rst new file mode 100644 index 0000000000..afa3dc3a41 --- /dev/null +++ b/libs/bsw/asyncFreeRtos/doc/user/asynchronous_execution.rst @@ -0,0 +1,93 @@ +.. _async_execution: + +Asynchonous execution +===================== + +The asyncronous execution family consists of three functions: + +* ``async::execute()`` +* ``async::schedule()`` +* ``async::scheduleAtFixedRate()`` + +Each of the above function would call a corresponding non-blocking method from +``FreeRtosAdapter`` class. A more detailed description of the functions may be found in ``async`` module. + +Features +-------- + +Execute ++++++++ + +The following sequences illustrate the expected behavior of calls to execute from different contexts: + +* | **Execute in a higher-priority context than the current context.** + | The current task is expected to be immediately preempted to execute the higher-priority `runnable`. + +* | **Execute in the same context as the current context.** + | Even in this case, it is an asynchronous operation. The `runnable` is expected to be + executed only after the complete execution of the current `runnable`. + +* | **Execute in a lower-priority context than the current context.** + | The lower-priority `runnable` is expected to be executed only after the execution of all + higher-priority `runnables` has completed. + +Schedule +++++++++ + +The following sequences illustrate the expected behavior of calls to ``schedule`` or +``scheduleAtFixedRate`` from different contexts: + +* | **Schedule in a higher-priority context.** + | Timers of the higher-priority task are expected to be handled immediately, preempting the + lower-priority task. + +* | **Schedule in the same context.** + | Timers of the current context are expected to be handled after the execution of the current + `runnable`, avoiding immediate execution in this specific case. + +* | **Schedule in a lower-priority context.** + | Timer handling is expected to be triggered within the lower-priority context only after all + higher-priority handling has been completed. + +Related types ++++++++++++++ + +* ``async::FreeRtosAdapter`` +* ``async::TimeoutType`` + +Examples +++++++++ + +Define a class that implements the ``IRunnable`` interface: + +.. code-block:: cpp + + #include + + class RunnableImpl : public ::async::IRunnable + { + public: + void execute() override + { + fprintf(stdout, "Executing TestRunnable!\n"); + } + }; + +In client code allocate the runnable object and asynchronously execute it: + +.. code-block:: cpp + + static RunnableImpl runnable; + static ::async::TimeoutType timeout; + + void executeRunnable(::async::ContextType& context) + { + // asynchronously execute the runnable: + ::async::execute(context, runnable); + + // schedule the runnable for single-time execution after 1 second from now: + ::async::schedule(context, runnable, timeout, 1, ::async::TimeUnit::SECONDS); + + // schedule the runnable for cyclic execution with period 2 seconds: + ::async::scheduleAtFixedRate(context, runnable, timeout, 2, ::async::TimeUnit::SECONDS); + } \ No newline at end of file diff --git a/libs/bsw/asyncFreeRtos/doc/user/index.rst b/libs/bsw/asyncFreeRtos/doc/user/index.rst new file mode 100644 index 0000000000..ca91baf88d --- /dev/null +++ b/libs/bsw/asyncFreeRtos/doc/user/index.rst @@ -0,0 +1,10 @@ +User Documentation +================== + +.. toctree:: + :maxdepth: 1 + + startup_sequence + names_hooking + asynchronous_execution + synchornization_mechanisms \ No newline at end of file diff --git a/libs/bsw/asyncFreeRtos/doc/user/names_hooking.rst b/libs/bsw/asyncFreeRtos/doc/user/names_hooking.rst new file mode 100644 index 0000000000..fb8227429e --- /dev/null +++ b/libs/bsw/asyncFreeRtos/doc/user/names_hooking.rst @@ -0,0 +1,19 @@ +.. _names_hooking: + +Names hooking +============= + +The client of ``asyncFreeRtos`` module must provide implementation for the following functions, +that define certain macroses in the configuration file **FreeRTOSConfig.h** of **FreeRTOS**: + +* ``asyncEnterTask()`` +* ``asyncLeaveTask()`` +* ``asyncEnterIsrGroup()`` +* ``asyncLeaveIsrGroup()`` +* ``asyncTickHook()`` +* ``asyncInitialized()`` + +Related types +------------- + +* ``StaticContextHook`` \ No newline at end of file diff --git a/libs/bsw/asyncFreeRtos/doc/user/scenarios/execute.rst b/libs/bsw/asyncFreeRtos/doc/user/scenarios/execute.rst deleted file mode 100644 index 2a3c609d26..0000000000 --- a/libs/bsw/asyncFreeRtos/doc/user/scenarios/execute.rst +++ /dev/null @@ -1,38 +0,0 @@ -execute -======= - -Overview --------- - -The following sequences show the expected behavior of calls to ``execute`` -from different contexts. - - * Execute in higher prio context than the current context. It is expected that the - current task is immediately pre-empted in order to execute the higher-prio Runnable. - - * Execute in same context as the current context. It is important to note that also in this - case it is an asynchronous operation and the Runnable is expected to be - executed after complete execution of the current Runnable. - - * Execute in lower prio context than the current context. It is expected that the lower-prio - Runnable is first executed after all execution of higher-prio Runnables is terminated. - -Code generation ---------------- - -Not applicable - -Configuration -------------- - -Not applicable - -Calibration ------------ - -Not applicable - -Usage Examples and Integration ------------------------------- - -Should be synced together with a specific implementation ``asyncFreeRtos`` module. diff --git a/libs/bsw/asyncFreeRtos/doc/user/scenarios/future.rst b/libs/bsw/asyncFreeRtos/doc/user/scenarios/future.rst deleted file mode 100644 index 947ce23a94..0000000000 --- a/libs/bsw/asyncFreeRtos/doc/user/scenarios/future.rst +++ /dev/null @@ -1,40 +0,0 @@ -Future support -============== - -Overview --------- - -The following sequences shows how futures (which are deprecated) are -implemented in order to provide blocking behaviour for a given task. - - * Synchronous wait on event set by higher prio context. It is expected that the - waiting task is suspended (using a ``FutureSupport`` object) and giving all - other tasks the chance to process events. Here the context that signals the - event is of higher-prio therefore the waiting task will only be executed - after the higher-prio runnable has terminated its work. - - * Synchronous wait on event set by lower prio context. It is expected that the - waiting task is suspended (using a ``FutureSupport`` object) and giving all - other tasks the chance to process events. Here the context that signals the - event is of lower-prio therefore it will be pre-empted on setting the signal - and continues after the higher-prio task has finished its work. - -Code generation ---------------- - -Not applicable - -Configuration -------------- - -Not applicable - -Calibration ------------ - -Not applicable - -Usage Examples and Integration ------------------------------- - -Should be synced together with a specific implementation ``asyncFreeRtos`` module. \ No newline at end of file diff --git a/libs/bsw/asyncFreeRtos/doc/user/scenarios/index.rst b/libs/bsw/asyncFreeRtos/doc/user/scenarios/index.rst deleted file mode 100644 index 249d2f3afd..0000000000 --- a/libs/bsw/asyncFreeRtos/doc/user/scenarios/index.rst +++ /dev/null @@ -1,37 +0,0 @@ -Example Scenarios -================= - -Overview --------- - -The following chapters show the expected behaviour of ``asyncFreeRtos`` -for typical ``async`` use cases. - -.. toctree:: - :maxdepth: 1 - :glob: - - startup - execute - schedule - future - -Code generation ---------------- - -Not applicable - -Configuration -------------- - -Not applicable - -Calibration ------------ - -Not applicable - -Usage Examples and Integration ------------------------------- - -Should be synced together with a specific implementation ``asyncFreeRtos`` module. \ No newline at end of file diff --git a/libs/bsw/asyncFreeRtos/doc/user/scenarios/schedule.rst b/libs/bsw/asyncFreeRtos/doc/user/scenarios/schedule.rst deleted file mode 100644 index 52aaac5fbd..0000000000 --- a/libs/bsw/asyncFreeRtos/doc/user/scenarios/schedule.rst +++ /dev/null @@ -1,37 +0,0 @@ -schedule/scheduleAtFixedRate -============================ - -Overview --------- - -The following sequences show the expected behaviour of calls to ``schedule`` -or ``scheduleAtFixedRate`` from different contexts. - - * Schedule in higher prio context. It is expected that timers of the higher-prio task are - handled immediately by pre-empting the lower-prio task. - - * Schedule in same context. It is expected that timers of the context are handled after - the current ``Runnable``, avoiding immediate execution in this special case. - - * Schedule in lower prio context. It is expected that the timer handling is only triggered - within the lower-prio context once after all higher-prio handling is terminated. - -Code generation ---------------- - -Not applicable - -Configuration -------------- - -Not applicable - -Calibration ------------ - -Not applicable - -Usage Examples and Integration ------------------------------- - -Should be synced together with a specific implementation ``asyncFreeRtos`` module. \ No newline at end of file diff --git a/libs/bsw/asyncFreeRtos/doc/user/scenarios/startup.rst b/libs/bsw/asyncFreeRtos/doc/user/scenarios/startup.rst deleted file mode 100644 index ffb7ad67f5..0000000000 --- a/libs/bsw/asyncFreeRtos/doc/user/scenarios/startup.rst +++ /dev/null @@ -1,37 +0,0 @@ -Startup -======= - -Overview --------- - -Below is the startup sequence. - -* Initialization. The application initializes the FreeRTOS tasks (with one - applicational task, idle task and timer task) and the calls created by a call - to FreeRtosAdapter::init(). - -* Running the adapter. The application calls FreeRtosAdapter::run() to start - the FreeRTOS scheduler.Before running FreeRTOS typically an initial Runnable will be triggered - by the application. This will then be executed once FreeRTOS has started and the corresponding - task is executed first (depending on its priority). If all tasks have been started and waiting - for further events FreeRTOS triggers repeatedly the idle routine from within the idle task. - -Code generation ---------------- - -Not applicable - -Configuration -------------- - -Not applicable - -Calibration ------------ - -Not applicable - -Usage Examples and Integration ------------------------------- - -Should be synced together with a specific implementation ``asyncFreeRtos`` module. \ No newline at end of file diff --git a/libs/bsw/asyncFreeRtos/doc/user/startup_sequence.rst b/libs/bsw/asyncFreeRtos/doc/user/startup_sequence.rst new file mode 100644 index 0000000000..a611acece2 --- /dev/null +++ b/libs/bsw/asyncFreeRtos/doc/user/startup_sequence.rst @@ -0,0 +1,65 @@ +.. _tasks_startup: + +Startup Sequence +================ + +1. **Initialization** + + Application initializes the ``async::internal::Task`` task objects, the bare minimum are: + + - The idle task + - The timer task + + required by **FreeRTOS**. However, typically more tasks will be needed in the application, + e.g. communication (CAN, UDS, Ethernet), monitoring, SWC scheduler, + as well as lifecycle task managing desired order of modules start up and shut down. + This initialization is completed by calling ``async::FreeRtosAdapter::init()``, + which creates the corresponding **FreeRTOS** tasks. + +2. **Running the Adapter** + + The application starts the **FreeRTOS** scheduler by calling ``async::FreeRtosAdapter::run()``. + The `runnables` are executed according to their priority and designated time, + whether immediate or scheduled. + Refer to :ref:`async_execution` for more information about task priorities. + + If `runnables` are being executed or waiting for execution (scheduled `runnables`), + the application can use the idle task to perform low-priority routines, + such as monitoring console input/output. + +Related types +------------- + +* ``async::FreeRtosAdapter`` +* ``async::TaskInitializer`` +* ``async::StaticRunnable`` + +Examples +-------- + +Typical routine for creating, initializing, and starting a task: + +.. code-block:: cpp + + using AsyncAdapter = ::async::AsyncBinding::AdapterType; + + // assume the enumerator is defining the available tasks of RTOS: + enum + { + TASK_BSP, + TASK_UDS, + TASK_DEMO + }; + + // make decision about the stack size for the task: + const uint32_t STACK_SIZE = 1024; + + async::internal::Task demoTask{"demo"}; + + ... + + AsyncAdapter::init(); + + ... + + AsyncAdapter::run(); \ No newline at end of file diff --git a/libs/bsw/asyncFreeRtos/doc/user/static_config.rst b/libs/bsw/asyncFreeRtos/doc/user/static_config.rst deleted file mode 100644 index 830649154a..0000000000 --- a/libs/bsw/asyncFreeRtos/doc/user/static_config.rst +++ /dev/null @@ -1,30 +0,0 @@ -Static Configuration -==================== - -Overview --------- - -In order to have a deeply integrated async implementation the configuration for -a specific project is basically based on two files AsyncBinding.h and Config.h files -that are required to be provided by an application. - -Code generation ---------------- - -Not applicable - -Configuration -------------- - -Not applicable - -Calibration ------------ - -Not applicable - -Usage Examples and Integration ------------------------------- - -Should be synced together with a specific implementation ``asyncFreeRtos`` module. - diff --git a/libs/bsw/asyncFreeRtos/doc/user/synchornization_mechanisms.rst b/libs/bsw/asyncFreeRtos/doc/user/synchornization_mechanisms.rst new file mode 100644 index 0000000000..7d1174935f --- /dev/null +++ b/libs/bsw/asyncFreeRtos/doc/user/synchornization_mechanisms.rst @@ -0,0 +1,105 @@ +.. _synch_mechanisms: + +Synchrnonization mechanisms +=========================== + +The synchronization mechanisms allow synchronization of threads and ensure secure sections. + +Related classes + +* ``async::Lock`` +* ``async::ModifiableLock`` +* ``async::FutureSupport`` + +Examples +-------- + +Lock +++++ + +The ``async::Lock`` class implements the `RAII` idiom, meaning that declaring a ``async::Lock`` object in +the code blocks other threads until execution exits the scope of the ``async::Lock`` object. In the +example below, a global **counter** is presumably being incremented by two or more threads. To prevent +simultaneous modification of the counter, the `lock` object ensures that the increment operation is +performed by only one thread at a time, while others are paused and wait. + +.. code-block:: cpp + + uint32_t counter = 0; // global (shared) resource + + void callback() + { + // .. some code here + + { // visibility scope of the lock starts here + ::async::Lock const lock; + ++counter; + } // visibility scope of the lock ends here + + // .. some code here + } + +ModifiableLock +++++++++++++++ + +``async::ModifiableLock`` provides a secure section similar to ``async::Lock`` and is also an `RAII` object. +However, it additionally allows the client to unlock it on demand using the unlock function. + +.. code-block:: cpp + + uint32_t counter = 0; // global (shared) resource + + void callback() + { + // .. some code here + + ::async::ModifiableLock const lock; + ++counter; + // .. some code we want to be inside the secure section + + lock.unlock(); + + // .. some code outside the secure section + } + +FutureSupport ++++++++++++++ + +The ``async::FutureSupport`` class implements the ``async::IFutureSupport`` interface. +Calling the ``async::FutureSupport::wait()`` method pauses the current thread until the `future` object is ready. +This class synchronizes the main thread with the worker thread and can be compared to `barriers` or +`condition variables`. The ``async::FutureSupport::notify()`` function sets the bits of the `future` object, +allowing execution to return to the main thread. + +Let's introduce a runnable class AsyncCommandExecutor: + +.. code-block:: cpp + + #include "async/FutureSupport.h" + + // Asynchronous command executor + class AsyncCommandExecutor : private ::async::RunnableType + { + public: + AsyncCommandExecutor() : _future(0) {} // assume context ID is 0 + async::FutureSupport _future; + } + +Execute asynchronously, wait until its execution is complete and proceed. + +.. code-block:: cpp + + // synchronization of asynchronous execution + void AsyncCommandExecutor::execWithWait + { + ::async::execute(context, *this); // enqueue async execution + _future.wait(); // wait until the execution is done + + // .. some code that may only be processes after "execute" is finished + } + + void AsyncCommandExecutor::execute() + { + // Do something and notify when complete + _future.notify(); + } diff --git a/libs/bsw/asyncFreeRtos/include/async/FreeRtosAdapter.h b/libs/bsw/asyncFreeRtos/include/async/FreeRtosAdapter.h index 31b33d3e94..fe7eb780be 100644 --- a/libs/bsw/asyncFreeRtos/include/async/FreeRtosAdapter.h +++ b/libs/bsw/asyncFreeRtos/include/async/FreeRtosAdapter.h @@ -60,6 +60,16 @@ class TaskConfigHolder } // namespace internal +/** + * Adapter class bridging FreeRTOS functionalities with the application's binding. + * + * The `FreeRtosAdapter` class serves as a centralized interface for managing tasks, timers, + * and scheduling functionalities within a FreeRTOS environment. It utilizes the specified + * `Binding` type to adapt and configure task-related components, such as `TaskContext`, + * `TaskConfig`, and idle and timer tasks. + * + * \tparam Binding The binding type specifying application-specific configurations. + */ template class FreeRtosAdapter { @@ -90,6 +100,7 @@ class FreeRtosAdapter template using Task = internal::Task; + /// Struct representing the stack usage for a specific task. struct StackUsage { StackUsage(); @@ -98,6 +109,14 @@ class FreeRtosAdapter uint32_t _usedSize; }; + /** + * Retrieves memory pointers for a FreeRTOS task. + * + * \tparam Context The task context. + * \param ppxTaskTCBBuffer Pointer to the task control block buffer. + * \param ppxTaskStackBuffer Pointer to the task stack buffer. + * \param pulTaskStackSize Pointer to the task stack size. + */ template static void getTaskMemory( StaticTask_t** ppxTaskTCBBuffer, @@ -113,25 +132,61 @@ class FreeRtosAdapter static ContextType getCurrentTaskContext(); #ifndef ASYNC_TIMEOUTMANAGER2_DISABLE + /** + * Retrieves the timeout manager for a given context. + * + * \param context The task context. + * \return A reference to the timeout manager. + */ static ::common::ITimeoutManager2& getTimeoutManager(ContextType context); #endif // ASYNC_TIMEOUTMANAGER2_DISABLE #ifndef ASYNC_LOOPER_DISABLE + /** + * Retrieves the looper for a given context. + * + * \param context The task context. + * \return A reference to the looper. + */ static ::loop::looper& getLooper(ContextType context); #endif // ASYNC_LOOPER_DISABLE + /// Initializes the FreeRTOS adapter and associated tasks. static void init(); + /// Starts the FreeRTOS scheduler. static void run(); static void runningHook(); + /** + * Retrieves the stack usage for a specified task. + * + * \param taskIdx The index of the task. + * \param stackUsage A reference to the StackUsage struct to populate. + * \return True if stack usage information is successfully retrieved. + */ static bool getStackUsage(size_t taskIdx, StackUsage& stackUsage); static void callIdleTaskFunction(); + /** + * Executes a specified runnable within a given context. + * + * \param context The task context. + * \param runnable The runnable to execute. + */ static void execute(ContextType context, RunnableType& runnable); + /** + * Schedules a runnable to execute after a delay. + * + * \param context The task context. + * \param runnable The runnable to schedule. + * \param timeout The timeout associated with the runnable. + * \param delay The delay before execution. + * \param unit The time unit for the delay. + */ static void schedule( ContextType context, RunnableType& runnable, @@ -139,6 +194,15 @@ class FreeRtosAdapter uint32_t delay, TimeUnitType unit); + /** + * Schedules a runnable to execute at a fixed rate. + * + * \param context The task context. + * \param runnable The runnable to schedule. + * \param timeout The timeout associated with the runnable. + * \param delay The delay before the first execution. + * \param unit The time unit for the delay. + */ static void scheduleAtFixedRate( ContextType context, RunnableType& runnable, @@ -146,14 +210,26 @@ class FreeRtosAdapter uint32_t delay, TimeUnitType unit); + /** + * Cancels a scheduled runnable. + * + * \param timeout The timeout associated with the runnable to cancel. + */ static void cancel(TimeoutType& timeout); + /// Notifies the system of an interrupt entry. static void enterIsr(); + /// Notifies the system of an interrupt exit. static void leaveIsr(); + /** + * Exits the ISR without yielding control. + * \return True if yielding is not required after ISR. + */ static bool leaveIsrNoYield(); + /// \return A pointer to the task woken by the ISR. static BaseType_t* getHigherPriorityTaskWoken(); private: diff --git a/libs/bsw/asyncFreeRtos/include/async/FutureSupport.h b/libs/bsw/asyncFreeRtos/include/async/FutureSupport.h index 0620e11112..1cabb8997c 100644 --- a/libs/bsw/asyncFreeRtos/include/async/FutureSupport.h +++ b/libs/bsw/asyncFreeRtos/include/async/FutureSupport.h @@ -14,14 +14,49 @@ namespace async { +/** + * This class implements wait and notify + * functions to synchronize between threads. + * + */ class FutureSupport : public ::os::IFutureSupport { public: + /** + * Class constructor. + * + * \param context execution context. + */ explicit FutureSupport(ContextType context); + /** + * Wait function sets the thread into "waiting" state. + * + * \param context execution context. + */ void wait() override; + + /** + * Notify function wakes from "waiting" state. + * + * \param context execution context. + */ void notify() override; + + /** + * The function causes assertion if context assigned + * to this instance is not equal to actual context of + * FreeRTOS' task where functions of current instance are executed. + */ void assertTaskContext() override; + + /** + * The function checks if the context assigned to this instance + * corresponds to actual context of FreeRTOS' task + * where functions of current instance are executed. + * + * \return true if contexts match. + */ bool verifyTaskContext() override; private: diff --git a/libs/bsw/asyncFreeRtos/include/async/Lock.h b/libs/bsw/asyncFreeRtos/include/async/Lock.h index 710b9f94e8..92d24d3fb0 100644 --- a/libs/bsw/asyncFreeRtos/include/async/Lock.h +++ b/libs/bsw/asyncFreeRtos/include/async/Lock.h @@ -10,7 +10,14 @@ namespace async { - +/** + * A synchronization mechanism that blocks threads from accessing a resource. + * + * The Lock class ensures mutual exclusion, allowing only one thread to access a + * protected resource or function at a time. When a thread acquires the lock, + * any other thread attempting to acquire it is blocked until the lock is released. + * The lock is automatically released in the destructor (RAII idiom). + */ class Lock { public: diff --git a/libs/bsw/asyncFreeRtos/include/async/ModifiableLock.h b/libs/bsw/asyncFreeRtos/include/async/ModifiableLock.h index b99aaa47a3..d4eecbe2bb 100644 --- a/libs/bsw/asyncFreeRtos/include/async/ModifiableLock.h +++ b/libs/bsw/asyncFreeRtos/include/async/ModifiableLock.h @@ -10,6 +10,17 @@ namespace async { +/** + * A synchronization mechanism that blocks threads from accessing a resource. + * + * The `ModifiableLock` class ensures mutual exclusion, + * allowing only one thread to access a protected + * resource or function at a time. When a thread acquires the lock, + * any other thread attempting to acquire it is blocked until the lock is released. + * The lock can be acquired either in the constructor or on demand using the `lock` function. + * Similarly, the lock can be released either in the destructor or on demand using the `unlock` + * function. + */ class ModifiableLock final { public: diff --git a/libs/bsw/asyncFreeRtos/include/async/StaticContextHook.h b/libs/bsw/asyncFreeRtos/include/async/StaticContextHook.h index 91e1ac38a6..e4f3ba5f3f 100644 --- a/libs/bsw/asyncFreeRtos/include/async/StaticContextHook.h +++ b/libs/bsw/asyncFreeRtos/include/async/StaticContextHook.h @@ -10,6 +10,13 @@ namespace async { +/** + * A template class implementing static polymorphism + * for seamless wrapping of any class with corresponding + * method implementations. + * + * \tparam T The underlying type with method implementations. + */ template class StaticContextHook : public ::estd::singleton { diff --git a/libs/bsw/asyncFreeRtos/include/async/StaticRunnable.h b/libs/bsw/asyncFreeRtos/include/async/StaticRunnable.h index b31c942cc1..bd690a9353 100644 --- a/libs/bsw/asyncFreeRtos/include/async/StaticRunnable.h +++ b/libs/bsw/asyncFreeRtos/include/async/StaticRunnable.h @@ -11,6 +11,13 @@ namespace async { +/** + * This is a template class that acts as collecion (linked list) + * of Tasks to be added to the FreeRTOS system. + * + * \tparam T The underlying implementing execute function. + */ + template class StaticRunnable { @@ -32,7 +39,9 @@ template T* StaticRunnable::_first = nullptr; /** - * Inline implementation. + * Class constructor. + * On instance construction the new instance is added into + * the inked list by adjusting the pointers _first and _next. */ template StaticRunnable::StaticRunnable() : _next(_first) diff --git a/libs/bsw/asyncFreeRtos/include/async/StaticTickHook.h b/libs/bsw/asyncFreeRtos/include/async/StaticTickHook.h deleted file mode 100644 index 53a9bfb4ae..0000000000 --- a/libs/bsw/asyncFreeRtos/include/async/StaticTickHook.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2024 Accenture. - -/** - * \ingroup async - */ -#ifndef GUARD_7EF028C0_E8D7_4AF1_BA19_F09ECA423071 -#define GUARD_7EF028C0_E8D7_4AF1_BA19_F09ECA423071 - -#include "estd/singleton.h" - -namespace async -{ -template -class StaticTickHook : public ::estd::singleton -{ -public: - using InstanceType = T; - - StaticTickHook(T& instance); - - static void handleTick(); -}; - -/** - * Inline implementation. - */ -template -StaticTickHook::StaticTickHook(T& instance) : ::estd::singleton(instance) -{} - -template -inline void StaticTickHook::handleTick() -{ - ::estd::singleton::instance().handleTick(); -} - -} // namespace async - -#endif // GUARD_7EF028C0_E8D7_4AF1_BA19_F09ECA423071 diff --git a/libs/bsw/asyncFreeRtos/include/async/TaskContext.h b/libs/bsw/asyncFreeRtos/include/async/TaskContext.h index b4e576cf54..5c571aab6f 100644 --- a/libs/bsw/asyncFreeRtos/include/async/TaskContext.h +++ b/libs/bsw/asyncFreeRtos/include/async/TaskContext.h @@ -23,17 +23,48 @@ namespace async { +/** + * Provides an interface between application-specific Tasks and Timers + * and the FreeRTOS framework, managing FreeRTOS* task and timer callbacks. + * + * The TaskContext class facilitates seamless integration between the application's + * task and timer logic and FreeRTOS by invoking necessary FreeRTOS functions + * for task creation, scheduling and processing callbacks. + * + * \tparam Binding The specific binding type associated with the TaskContext. + */ template class TaskContext : public EventDispatcher<2U, LockType> { public: using TaskFunctionType = ::estd::function&)>; - using StackType = ::estd::slice; + + using StackType = ::estd::slice; TaskContext(); + /** + * Initializes a task with a specified context and task function. + * \param context The context associated with this task. + * \param taskFunction The function to execute in this task. + */ void initTask(ContextType context, TaskFunctionType taskFunction); + + /** + * Sets the FreeRTOS task handle for this context. + * \param taskHandle The handle to associate with the FreeRTOS task. + */ void initTaskHandle(TaskHandle_t taskHandle); + + /** + * Creates a FreeRTOS task with specific configuration. + * \param context The task's context. + * \param task The static task storage structure. + * \param name The name of the task. + * \param priority The priority of the task. + * \param stack The stack allocated for the task. + * \param taskFunction The function that the task will execute. + */ void createTask( ContextType context, StaticTask_t& task, @@ -41,26 +72,80 @@ class TaskContext : public EventDispatcher<2U, LockType> UBaseType_t priority, StackType const& stack, TaskFunctionType taskFunction); + + /** + * Creates a FreeRTOS timer. + * \param timer The static timer storage structure. + * \param name The name of the timer. + */ void createTimer(StaticTimer_t& timer, char const* name); char const* getName() const; + TaskHandle_t getTaskHandle() const; + uint32_t getUnusedStackSize() const; + /** + * Executes asynchronously the specified runnable within this task context. + * \param runnable The runnable to execute. + */ void execute(RunnableType& runnable); + + /** + * Schedules a runnable to execute after a delay. + * \param runnable The runnable to schedule. + * \param timeout The timeout associated with the runnable. + * \param delay The delay before execution. + * \param unit The time unit for the delay. + */ void schedule(RunnableType& runnable, TimeoutType& timeout, uint32_t delay, TimeUnitType unit); + + /** + * Schedules a runnable to execute at a fixed rate. + * \param runnable The runnable to schedule. + * \param timeout The timeout associated with the runnable. + * \param period The period between executions. + * \param unit The time unit for the period. + */ void scheduleAtFixedRate( RunnableType& runnable, TimeoutType& timeout, uint32_t period, TimeUnitType unit); + + /** + * Cancels a scheduled runnable. + * \param timeout The timeout associated with the runnable to cancel. + */ void cancel(TimeoutType& timeout); + /// Calls the task's assigned function. void callTaskFunction(); + + /// Dispatches events for processing within this context. void dispatch(); + + /// Stops event dispatching. void stopDispatch(); + + /// Dispatches events while runnable is executing. void dispatchWhileWork(); + /** + * Sets a timeout value in microseconds. + * \param timeInUs The timeout duration in microseconds. + */ void setTimeout(uint32_t timeInUs); + /** + * Retrieves the amount of unused stack space for a specified task. + * \param taskHandle The handle of the task. + * \return The amount of unused stack space. + */ static uint32_t getUnusedStackSize(TaskHandle_t taskHandle); + + /** + * Default function to be executed by a task within this context. + * \param taskContext The context in which the task executes. + */ static void defaultTaskFunction(TaskContext& taskContext); private: diff --git a/libs/bsw/asyncFreeRtos/include/async/TaskInitializer.h b/libs/bsw/asyncFreeRtos/include/async/TaskInitializer.h index e8ca8a4bd0..6eebd05439 100644 --- a/libs/bsw/asyncFreeRtos/include/async/TaskInitializer.h +++ b/libs/bsw/asyncFreeRtos/include/async/TaskInitializer.h @@ -33,6 +33,15 @@ using Stack = ::estd::array< StackType_t, (adjustStackSize(StackSize) + sizeof(StackType_t) - 1) / sizeof(StackType_t)>; +/** + * The TaskInitializer struct centralizes the initialization of tasks within the application. + * + * This struct provides a standardized way to set up tasks, defining key types and handling + * configuration and setup of task and timer objects. It uses a specified Adapter type + * for flexibility, allowing for different configurations. + * + * \tparam Adapter The adapter type used to provide specific task configuration types and functions. + */ template struct TaskInitializer : public StaticRunnable> { @@ -43,6 +52,22 @@ struct TaskInitializer : public StaticRunnable> using TaskObjectType = StaticTask_t; using TimerObjectType = StaticTimer_t; + /** + * Creates and initializes a task with the specified parameters. + * + * This function handles task creation by allocating memory for the object, + * setting up the context, stack, and configuration, + * and linking them to the specified task and timer objects. + * + * \tparam T The type of the stack used by the task. + * \param context The execution context of the task. + * \param name The name of the task. + * \param task The static task object to initialize. + * \param timer The static timer object associated with the task. + * \param stack The stack to use for the task's execution. + * \param taskFunction The function that the task will execute. + * \param config Configuration settings for the task. + */ template static void create( ContextType context, @@ -64,17 +89,44 @@ struct TaskInitializer : public StaticRunnable> TaskConfigType const& config); public: + /// Executes task object initialization. void execute(); + /// The stack slice used for task execution. StackSliceType _stack; + + /// The function assigned for the task's execution. TaskFunctionType _taskFunction; + + /// Reference to the static task object. TaskObjectType& _task; + + /// Reference to the static timer object associated with the task. TimerObjectType& _timer; + + /// The name of the task. char const* _name; + + /// The context in which the task will execute. ContextType _context; + + /// The configuration settings for the task. TaskConfigType _config; }; +/** + * Primary template class that serves as a container for task-related objects and + * configuration. + * + * TaskImpl provides a structure to hold essential components for tasks, such as the stack, task + * object, and timer object, along with configuration settings. It serves as a base for derived task + * classes (e.g., Task, IdleTask) and is designed for integration with FreeRTOS, using the Adapter + * type for flexibility. + * + * \tparam Adapter The adapter type that supplies specific task configuration types and functions. + * \tparam Context The context in which the task operates. + * \tparam StackSize The size of the stack allocated for the task. + */ template class TaskImpl { diff --git a/libs/bsw/asyncFreeRtos/include/async/Types.h b/libs/bsw/asyncFreeRtos/include/async/Types.h index fdf9777b70..03d4dfc8dc 100644 --- a/libs/bsw/asyncFreeRtos/include/async/Types.h +++ b/libs/bsw/asyncFreeRtos/include/async/Types.h @@ -24,6 +24,11 @@ using ModifiableLockType = ModifiableLock; ContextType const CONTEXT_INVALID = 0xFFU; +/** + * This class stores information about the Runnable + * object and its context, as well implements the + * "expired" function executed on timer time out. + */ struct TimeoutType : public ::timer::Timeout { public: