LCOV - code coverage report
Current view: top level - asyncFreeRtos/include/async - TaskInitializer.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 52 53 98.1 %
Date: 2025-08-28 06:39:11 Functions: 26 26 100.0 %

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

Generated by: LCOV version 1.14