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-02-24 11:21:15 Functions: 100.0 % 50 50

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

Generated by: LCOV version 2.0-1