LCOV - code coverage report
Current view: top level - libs/bsw/asyncFreeRtos/include/async - TaskInitializer.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 98.4 % 62 61
Test Date: 2026-06-18 08:29:03 Functions: 100.0 % 50 50

            Line data    Source code
       1              : /********************************************************************************
       2              :  * Copyright (c) 2024 Accenture
       3              :  *
       4              :  * This program and the accompanying materials are made available under the
       5              :  * terms of the Apache License Version 2.0 which is available at
       6              :  * https://www.apache.org/licenses/LICENSE-2.0
       7              :  *
       8              :  * SPDX-License-Identifier: Apache-2.0
       9              :  ********************************************************************************/
      10              : 
      11              : #pragma once
      12              : 
      13              : #include "async/StaticRunnable.h"
      14              : #include "async/Types.h"
      15              : 
      16              : #include <etl/array.h>
      17              : #include <etl/error_handler.h>
      18              : #include <etl/memory.h>
      19              : #include <etl/span.h>
      20              : 
      21              : #include <FreeRTOS.h>
      22              : #include <task.h>
      23              : #include <timers.h>
      24              : 
      25              : namespace async
      26              : {
      27              : namespace internal
      28              : {
      29              : 
      30            4 : constexpr size_t adjustStackSize(size_t const stackSize)
      31              : {
      32              : #if (defined(MINIMUM_STACK_SIZE)) && (MINIMUM_STACK_SIZE != 0)
      33            4 :     return (stackSize != 0U) && (stackSize < MINIMUM_STACK_SIZE) ? MINIMUM_STACK_SIZE : stackSize;
      34              : #else
      35              :     return stackSize;
      36              : #endif // (defined(MINIMUM_STACK_SIZE)) && (MINIMUM_STACK_SIZE != 0)
      37              : }
      38              : 
      39           38 : inline ::etl::span<uint8_t> align(size_t const alignment, ::etl::span<uint8_t> s)
      40              : {
      41           38 :     auto const mod = reinterpret_cast<size_t>(s.data()) % alignment;
      42           38 :     if (mod != 0)
      43              :     {
      44            0 :         return s.subspan(alignment - mod);
      45              :     }
      46              :     else
      47              :     {
      48           38 :         return s;
      49              :     }
      50              : }
      51              : 
      52              : template<size_t StackSize>
      53              : using Stack = ::etl::array<
      54              :     StackType_t,
      55              :     (adjustStackSize(StackSize) + sizeof(StackType_t) - 1) / sizeof(StackType_t)>;
      56              : 
      57              : /**
      58              :  * The TaskInitializer struct centralizes the initialization of tasks within the application.
      59              :  *
      60              :  * This struct provides a standardized way to set up tasks, defining key types and handling
      61              :  * configuration and setup of task and timer objects. It uses a specified Adapter type
      62              :  * for flexibility, allowing for different configurations.
      63              :  *
      64              :  * \tparam Adapter The adapter type used to provide specific task configuration types and functions.
      65              :  */
      66              : template<typename Adapter>
      67              : struct TaskInitializer : public StaticRunnable<TaskInitializer<Adapter>>
      68              : {
      69              :     using AdapterType      = Adapter;
      70              :     using StackSliceType   = ::etl::span<StackType_t>;
      71              :     using TaskConfigType   = typename AdapterType::TaskConfigType;
      72              :     using TaskFunctionType = typename AdapterType::TaskFunctionType;
      73              :     using TaskObjectType   = StaticTask_t;
      74              : 
      75              :     /**
      76              :      * Creates and initializes a task with the specified parameters.
      77              :      *
      78              :      * This function handles task creation by allocating memory for the object,
      79              :      * setting up the context, stack, and configuration,
      80              :      * and linking them to the specified task and timer objects.
      81              :      *
      82              :      * \tparam T The type of the stack used by the task.
      83              :      * \param context The execution context of the task.
      84              :      * \param name The name of the task.
      85              :      * \param task The static task object to initialize.
      86              :      * \param timer The static timer object associated with the task.
      87              :      * \param stack The stack to use for the task's execution.
      88              :      * \param taskFunction The function that the task will execute.
      89              :      * \param config Configuration settings for the task.
      90              :      */
      91              :     template<typename T>
      92              :     static void create(
      93              :         ContextType context,
      94              :         char const* name,
      95              :         TaskObjectType& task,
      96              :         T& stack,
      97              :         TaskFunctionType taskFunction,
      98              :         TaskConfigType const& config);
      99              : 
     100              : private:
     101              :     TaskInitializer(
     102              :         ContextType context,
     103              :         char const* name,
     104              :         TaskObjectType& task,
     105              :         StackSliceType const& stack,
     106              :         TaskFunctionType taskFunction,
     107              :         TaskConfigType const& config);
     108              : 
     109              : public:
     110              :     /// Executes task object initialization.
     111              :     void execute();
     112              : 
     113              :     /// The stack slice used for task execution.
     114              :     StackSliceType _stack;
     115              : 
     116              :     /// The function assigned for the task's execution.
     117              :     TaskFunctionType _taskFunction;
     118              : 
     119              :     /// Reference to the static task object.
     120              :     TaskObjectType& _task;
     121              :     /// The name of the task.
     122              :     char const* _name;
     123              : 
     124              :     /// The context in which the task will execute.
     125              :     ContextType _context;
     126              : 
     127              :     /// The configuration settings for the task.
     128              :     TaskConfigType _config;
     129              : };
     130              : 
     131              : /**
     132              :  * Primary template class that serves as a container for task-related objects and
     133              :  * configuration.
     134              :  *
     135              :  * TaskImpl provides a structure to hold essential components for tasks, such as the stack, task
     136              :  * object, and timer object, along with configuration settings. It serves as a base for derived task
     137              :  * classes (e.g., Task, IdleTask) and is designed for integration with FreeRTOS, using the Adapter
     138              :  * type for flexibility.
     139              :  *
     140              :  * \tparam Adapter The adapter type that supplies specific task configuration types and functions.
     141              :  * \tparam Context The context in which the task operates.
     142              :  * \tparam StackSize The size of the stack allocated for the task.
     143              :  */
     144              : template<class Adapter, ContextType Context, size_t StackSize = 0U>
     145              : class TaskImpl
     146              : {
     147              : public:
     148              :     using AdapterType      = Adapter;
     149              :     using StackSliceType   = ::etl::span<StackType_t>;
     150              :     using TaskConfigType   = typename AdapterType::TaskConfigType;
     151              :     using TaskFunctionType = typename AdapterType::TaskFunctionType;
     152              :     using TaskObjectType   = StaticTask_t;
     153              : 
     154              :     TaskImpl(char const* name, TaskFunctionType taskFunction, TaskConfigType const& taskConfig);
     155              : 
     156              : protected:
     157              :     ~TaskImpl() = default;
     158              : 
     159              : private:
     160              :     Stack<StackSize> _stack;
     161              :     TaskObjectType _task;
     162              : };
     163              : 
     164              : template<class Adapter, ContextType Context>
     165              : class TaskImpl<Adapter, Context, 0U>
     166              : {
     167              : public:
     168              :     using AdapterType      = Adapter;
     169              :     using StackSliceType   = ::etl::span<StackType_t>;
     170              :     using TaskConfigType   = typename AdapterType::TaskConfigType;
     171              :     using TaskFunctionType = typename AdapterType::TaskFunctionType;
     172              :     using TaskObjectType   = StaticTask_t;
     173              : 
     174              :     template<typename T>
     175              :     TaskImpl(
     176              :         char const* name,
     177              :         T& stack,
     178              :         TaskFunctionType taskFunction,
     179              :         TaskConfigType const& taskConfig);
     180              : 
     181              : protected:
     182              :     ~TaskImpl() = default;
     183              : 
     184              : private:
     185              :     TaskObjectType _task;
     186              : };
     187              : 
     188              : template<class Adapter, size_t StackSize = 0U>
     189              : struct IdleTask : public TaskImpl<Adapter, Adapter::TASK_IDLE, StackSize>
     190              : {
     191              :     using TaskFunctionType = typename Adapter::TaskFunctionType;
     192              :     using TaskConfigType   = typename Adapter::TaskConfigType;
     193              : 
     194              :     IdleTask(char const* name, TaskConfigType const& taskConfig = TaskConfigType());
     195              : 
     196              :     IdleTask(
     197              :         char const* name,
     198              :         TaskFunctionType taskFunction,
     199              :         TaskConfigType const& taskConfig = TaskConfigType());
     200              : };
     201              : 
     202              : template<class Adapter>
     203              : struct IdleTask<Adapter, 0U> : public TaskImpl<Adapter, Adapter::TASK_IDLE>
     204              : {
     205              :     using TaskFunctionType = typename Adapter::TaskFunctionType;
     206              :     using TaskConfigType   = typename Adapter::TaskConfigType;
     207              : 
     208              :     template<typename T>
     209              :     IdleTask(char const* name, T& stack, TaskConfigType const& taskConfig = TaskConfigType());
     210              : 
     211              :     template<typename T>
     212              :     IdleTask(
     213              :         char const* name,
     214              :         T& stack,
     215              :         TaskFunctionType taskFunction,
     216              :         TaskConfigType const& taskConfig = TaskConfigType());
     217              : };
     218              : 
     219              : template<class Adapter, size_t StackSize = 0U>
     220              : struct TimerTask : public TaskImpl<Adapter, Adapter::TASK_TIMER, StackSize>
     221              : {
     222              :     using TaskConfigType = typename Adapter::TaskConfigType;
     223              : 
     224              :     explicit TimerTask(char const* name, TaskConfigType const& taskConfig = TaskConfigType());
     225              : };
     226              : 
     227              : template<class Adapter>
     228              : struct TimerTask<Adapter, 0U> : public TaskImpl<Adapter, Adapter::TASK_TIMER>
     229              : {
     230              :     using TaskConfigType = typename Adapter::TaskConfigType;
     231              : 
     232              :     template<typename T>
     233              :     TimerTask(char const* name, T& stack, TaskConfigType const& taskConfig = TaskConfigType());
     234              : };
     235              : 
     236              : template<class Adapter, ContextType Context, size_t StackSize = 0U>
     237              : struct Task : public TaskImpl<Adapter, Context, StackSize>
     238              : {
     239              :     using TaskFunctionType = typename Adapter::TaskFunctionType;
     240              :     using TaskConfigType   = typename Adapter::TaskConfigType;
     241              : 
     242              :     explicit Task(char const* name, TaskConfigType const& taskConfig = TaskConfigType());
     243              : 
     244              :     Task(
     245              :         char const* name,
     246              :         TaskFunctionType taskFunction,
     247              :         TaskConfigType const& taskConfig = TaskConfigType());
     248              : };
     249              : 
     250              : template<class Adapter, ContextType Context>
     251              : struct Task<Adapter, Context, 0U> : public TaskImpl<Adapter, Context>
     252              : {
     253              :     using TaskFunctionType = typename Adapter::TaskFunctionType;
     254              :     using TaskConfigType   = typename Adapter::TaskConfigType;
     255              : 
     256              :     template<typename T>
     257              :     explicit Task(char const* name, T& stack, TaskConfigType const& taskConfig = TaskConfigType());
     258              : 
     259              :     template<typename T>
     260              :     Task(
     261              :         char const* name,
     262              :         T& stack,
     263              :         TaskFunctionType taskFunction,
     264              :         TaskConfigType const& taskConfig = TaskConfigType());
     265              : };
     266              : 
     267              : template<class Adapter>
     268              : template<typename T>
     269           19 : void TaskInitializer<Adapter>::create(
     270              :     ContextType const context,
     271              :     char const* const name,
     272              :     TaskObjectType& task,
     273              :     T& stack,
     274              :     TaskFunctionType const taskFunction,
     275              :     TaskConfigType const& config)
     276              : {
     277           19 :     auto const stackSliceRaw = ::etl::make_span(stack).template reinterpret_as<uint8_t>();
     278           19 :     auto const stackSlice
     279           19 :         = align(alignof(StackType_t), stackSliceRaw).template reinterpret_as<StackType_t>();
     280           19 :     auto const taskInitializerSlice = align(alignof(TaskInitializer), stackSliceRaw);
     281           19 :     ETL_ASSERT(
     282              :         taskInitializerSlice.size() >= sizeof(TaskInitializer),
     283              :         ETL_ERROR_GENERIC("stack must be big enough to hold a task initializer object"));
     284           18 :     new (taskInitializerSlice.data())
     285              :         TaskInitializer(context, name, task, stackSlice, taskFunction, config);
     286           18 : }
     287              : 
     288              : template<class Adapter>
     289           18 : TaskInitializer<Adapter>::TaskInitializer(
     290              :     ContextType const context,
     291              :     char const* const name,
     292              :     TaskObjectType& task,
     293              :     StackSliceType const& stack,
     294              :     TaskFunctionType const taskFunction,
     295              :     TaskConfigType const& config)
     296           18 : : _stack(stack)
     297           18 : , _taskFunction(taskFunction)
     298           18 : , _task(task)
     299           18 : , _name(name)
     300           18 : , _context(context)
     301           18 : , _config(config)
     302           18 : {}
     303              : 
     304              : template<class Adapter>
     305           18 : void TaskInitializer<Adapter>::execute()
     306              : {
     307           18 :     Adapter::initTask(*this);
     308           18 : }
     309              : 
     310              : template<class Adapter, ContextType Context, size_t StackSize>
     311           14 : TaskImpl<Adapter, Context, StackSize>::TaskImpl(
     312              :     char const* const name, TaskFunctionType const taskFunction, TaskConfigType const& taskConfig)
     313              : {
     314           14 :     TaskInitializer<Adapter>::create(Context, name, _task, _stack, taskFunction, taskConfig);
     315           13 : }
     316              : 
     317              : template<class Adapter, ContextType Context>
     318              : template<typename T>
     319            5 : TaskImpl<Adapter, Context, 0U>::TaskImpl(
     320              :     char const* const name,
     321              :     T& stack,
     322              :     TaskFunctionType const taskFunction,
     323              :     TaskConfigType const& taskConfig)
     324              : {
     325            5 :     TaskInitializer<Adapter>::create(Context, name, _task, stack, taskFunction, taskConfig);
     326            5 : }
     327              : 
     328              : template<class Adapter, size_t StackSize>
     329            1 : IdleTask<Adapter, StackSize>::IdleTask(char const* const name, TaskConfigType const& taskConfig)
     330            1 : : TaskImpl<Adapter, Adapter::TASK_IDLE, StackSize>(name, TaskFunctionType(), taskConfig)
     331            1 : {}
     332              : 
     333              : template<class Adapter, size_t StackSize>
     334            2 : IdleTask<Adapter, StackSize>::IdleTask(
     335              :     char const* const name, TaskFunctionType const taskFunction, TaskConfigType const& taskConfig)
     336            2 : : TaskImpl<Adapter, Adapter::TASK_IDLE, StackSize>(name, taskFunction, taskConfig)
     337            2 : {}
     338              : 
     339              : template<class Adapter>
     340              : template<typename T>
     341            1 : IdleTask<Adapter, 0U>::IdleTask(char const* const name, T& stack, TaskConfigType const& taskConfig)
     342            1 : : TaskImpl<Adapter, Adapter::TASK_IDLE>(name, stack, TaskFunctionType(), taskConfig)
     343            1 : {}
     344              : 
     345              : template<class Adapter>
     346              : template<typename T>
     347            1 : IdleTask<Adapter, 0U>::IdleTask(
     348              :     char const* const name,
     349              :     T& stack,
     350              :     TaskFunctionType const taskFunction,
     351              :     TaskConfigType const& taskConfig)
     352            1 : : TaskImpl<Adapter, Adapter::TASK_IDLE>(name, stack, taskFunction, taskConfig)
     353            1 : {}
     354              : 
     355              : template<class Adapter, size_t StackSize>
     356            2 : TimerTask<Adapter, StackSize>::TimerTask(char const* const name, TaskConfigType const& taskConfig)
     357              : : TaskImpl<Adapter, Adapter::TASK_TIMER, StackSize>(
     358            2 :     name, typename Adapter::TaskFunctionType(), taskConfig)
     359            2 : {}
     360              : 
     361              : template<class Adapter>
     362              : template<typename T>
     363            1 : TimerTask<Adapter, 0U>::TimerTask(
     364              :     char const* const name, T& stack, TaskConfigType const& taskConfig)
     365              : : TaskImpl<Adapter, Adapter::TASK_TIMER>(
     366            1 :     name, stack, typename Adapter::TaskFunctionType(), taskConfig)
     367            1 : {}
     368              : 
     369              : template<class Adapter, ContextType Context, size_t StackSize>
     370            5 : Task<Adapter, Context, StackSize>::Task(char const* const name, TaskConfigType const& taskConfig)
     371            5 : : TaskImpl<Adapter, Context, StackSize>(name, TaskFunctionType(), taskConfig)
     372            4 : {}
     373              : 
     374              : template<class Adapter, ContextType Context, size_t StackSize>
     375            4 : Task<Adapter, Context, StackSize>::Task(
     376              :     char const* const name, TaskFunctionType const taskFunction, TaskConfigType const& taskConfig)
     377            4 : : TaskImpl<Adapter, Context, StackSize>(name, taskFunction, taskConfig)
     378            4 : {}
     379              : 
     380              : template<class Adapter, ContextType Context>
     381              : template<typename T>
     382            1 : Task<Adapter, Context, 0U>::Task(char const* const name, T& stack, TaskConfigType const& taskConfig)
     383            1 : : TaskImpl<Adapter, Context>(name, stack, typename Adapter::TaskFunctionType(), taskConfig)
     384            1 : {}
     385              : 
     386              : template<class Adapter, ContextType Context>
     387              : template<typename T>
     388            1 : Task<Adapter, Context, 0U>::Task(
     389              :     char const* const name,
     390              :     T& stack,
     391              :     TaskFunctionType const taskFunction,
     392              :     TaskConfigType const& taskConfig)
     393            1 : : TaskImpl<Adapter, Context>(name, stack, taskFunction, taskConfig)
     394            1 : {}
     395              : 
     396              : } // namespace internal
     397              : } // namespace async
        

Generated by: LCOV version 2.0-1