FreeRTOS Task Interface
- FreeRTOS Task Interface Design Document
- Location
- Type
- Background
- Overview
- Detailed Design
- API
- Static Allocation of Tasks
- Initialization
- Inheriting the Task Interface class
- Suspending and Resuming a Task
- Removing a Task
- Configuring Execution Frequency
- Additional Helper Functions
- Caveats
- Future Advancements
Location
systems
Type
Interface
Background
The Task
interface is an abstraction layer for FreeRTOS tasks.
Information regarding FreeRTOS tasks can be found here.
Overview
Tasks that are scheduled and managed by the
TaskScheduler
.
Task objects must inherit the Task
interface.
Detailed Design
API
class TaskInterface
{
public:
virtual TaskSchedulerInterface & GetTaskScheduler() const = 0;
virtual bool Setup() = 0;
virtual bool PreRun() = 0;
virtual bool Run() = 0;
virtual void Suspend() const = 0;
virtual void Resume() const = 0;
virtual void Delete() const = 0;
virtual const char * GetName() const = 0;
virtual Priority GetPriority() const = 0;
virtual size_t GetStackSize() const = 0;
virtual void SetHandle(TaskHandle_t * handle) = 0;
virtual TaskHandle_t * GetHandle() = 0;
virtual StaticTask_t * GetTaskBuffer() = 0;
virtual StackType_t * GetStack() = 0;
virtual void SetDelayTime(uint32_t time) = 0;
virtual uint32_t GetDelayTime() const = 0;
};
template <size_t kStackSize>
class Task : public TaskInterface
{
public:
TaskSchedulerInterface & GetTaskScheduler() const override;
bool Setup() override;
bool PreRun() override;
void Suspend() const override;
void Resume() const override;
void Delete() const override;
const char * GetName() const override;
Priority GetPriority() const override;
size_t GetStackSize() const override;
void SetHandle(TaskHandle_t * handle) override;
TaskHandle_t * GetHandle() override;
StaticTask_t * GetTaskBuffer() override;
StackType_t * GetStack() override;
void SetDelayTime(uint32_t time) override;
uint32_t GetDelayTime() const override;
virtual ~Task() {}
protected:
explicit constexpr Task(const char * name,
Priority priority,
TaskSchedulerInterface & task_scheduler);
bool DeclaredOnStackCheck() const;
TaskSchedulerInterface & task_scheduler_;
const char * const kName;
const Priority kPriority;
TaskHandle_t handle_;
uint32_t delay_time_;
StaticTask_t task_buffer_;
StackType_t stack_[kStackSize];
};
Static Allocation of Tasks
Tasks are statically allocated and the FreeRTOS task handle is created and
managed by the TaskScheduler
. To enable the static allocation of tasks, the
configSUPPORT_STATIC_ALLOCATION
definition is set to 1 in
FreeRTOSConfig.h and the
implementation of vApplicationGetIdleTaskMemory()
must also be provided to
statically allocate memory for the FreeRTOS idle task when
vTaskStartScheduler()
is invoked.
Note: Static allocation for FreeRTOS is enabled by default in SJSU-Dev2.
static StaticTask_t idle_task_tcb;
static StackType_t idle_task_stack[configMINIMAL_STACK_SIZE];
extern "C" void vApplicationGetIdleTaskMemory(
StaticTask_t ** ppx_idle_task_tcb_buffer,
StackType_t ** ppx_idle_task_stack_buffer,
uint32_t * pul_idle_task_stack_size)
{
*ppx_idle_task_tcb_buffer = &idle_task_tcb;
*ppx_idle_task_stack_buffer = idle_task_stack;
*pul_idle_task_stack_size = std::size(idle_task_stack);
}
More information regarding static allocation of FreeRTOS objects can be found here.
Initialization
bool DeclaredOnStack()
The DeclaredOnStack()
method checks if the address position of the Task
object is within the bounds of the heap or the .bss and data segments. A fatal
error is asserted if the tasks exists on the stack.
explicit constexpr Task(const char *, Priority, TaskSchedulerInterface &)
The following is performed when the task is constructed:
- Store the specified name, priority, and designated
TaskScheduler
. - Set the initial delay time to 0.
- Invoke
DeclaredOnStack()
to check the task exists in the heap or is declared globally. - Add the task to the specified
task_scheduler
. This scheduler will be responsible for creating and managing this task.
Inheriting the Task Interface class
When a task begins, the methods Setup(), PreRun(), and Run() are invoked in the following order:
- Setup()
- PreRun()
- Run()
These methods should be overridden in the inheriting class to provide any initialization and/or execution code that are performed by the task.
void Setup() override
Setup is performed when Start()
of the TaskScheduler is invoked. If the
Setup()
of a scheduler task fails to complete, the scheduler will not start
and a fatal error will be asserted. The function should be overridden with any
initialization code that the task requires.
void PreRun() override
PreRun() is invoked after starting the task scheduler once before Run()
is
ever called. PreRun()
is performed after Setup()
of all scheduled Tasks are
complete. Therefore, this method should be overridden if the task requires a
different Task
to be setup first.
void Run() override
Continuously invoked until the task has been temporarily suspended by
Suspend()
or terminated.
The Run()
method MUST be overridden with the desired task execution code.
Suspending and Resuming a Task
void Suspend() const override
Suspends the task until resumed by Resume()
.
void Resume() const override
Resumes the task if the task was suspended by Suspend()
.
Removing a Task
void Delete() override
Suspends the task if it is running and invokes the TaskScheduler
’s
RemoveTask()
method to remove this task from the scheduler.
Configuring Execution Frequency
A task can be configured to be executed at a constant desired frequency through
the SetDelayTime()
function.
void SetDelayTime(uint32_t time) override
Sets the delay time in FreeRTOS ticks to ensure Run()
is called at a desired
frequency for periodic tasks. For example, if time = 1000 and the rtos tick
period is 1ms, then Run()
will be invoked every 1 second.
const uint32_t GetDelayTime() const override
Returns the delay time that was set by SetDelayTime() in milliseconds.
Additional Helper Functions
const char * GetName() const override
Returns the name used to identify the task.
Priority GetPriority() const override
Returns the priority of the task.
size_t GetStackSize() const override
Returns the pre-allocated stack size for the task in bytes.
void SetHandle(TaskHandle_t * handle) override
This method is used by the TaskScheduler
to set the task FreeRTOS task handle
when the task is created. This handle is used for suspending, resuming, or
deleting the task.
TaskHandle_t * GetHandle() override
Returns a pointer reference of the task's handle.
StaticTask_t * GetTaskBuffer() override
Returns a pointer reference to the task's Task Control Block (TCB);
StackType_t * GetStack() override
Returns a pointer reference of the task's pre-allocated stack.
Caveats
The TaskInterface
class is used to provide a generalization for the Task
class since the Task
class takes in a template argument.
Future Advancements
N/A