Files
lab-rv32i-freertos-static-task/include/freertos/task_storage.hpp
T

184 lines
5.4 KiB
C++

#ifndef FREERTOS_CPP_TASK_STORAGE_HPP
#define FREERTOS_CPP_TASK_STORAGE_HPP
#include <stddef.h>
#include <stdint.h>
#include <type_traits>
extern "C"
{
#include "FreeRTOS.h"
#include "task.h"
}
#ifndef FREERTOS_STORAGE_CHECKPOINT
#define FREERTOS_STORAGE_CHECKPOINT( point, object ) \
do \
{ \
( void ) ( point ); \
( void ) ( object ); \
} while( 0 )
#endif
namespace freertos
{
enum class StorageTaskState : uint8_t
{
constructed,
ready,
running,
completed,
start_failed
};
template< typename Derived >
class DynamicTask
{
public:
constexpr DynamicTask( const char * name,
configSTACK_DEPTH_TYPE stack_words,
UBaseType_t priority ) noexcept
: name_ { name }, stack_words_ { stack_words }, priority_ { priority }
{
}
DynamicTask( const DynamicTask & ) = delete;
DynamicTask & operator=( const DynamicTask & ) = delete;
DynamicTask( DynamicTask && ) = delete;
DynamicTask & operator=( DynamicTask && ) = delete;
bool start() noexcept
{
static_assert( std::is_base_of< DynamicTask< Derived >,
Derived >::value );
if( state_ != StorageTaskState::constructed )
{
return false;
}
state_ = StorageTaskState::ready;
const BaseType_t result = xTaskCreate(
&DynamicTask::trampoline, name_, stack_words_,
static_cast< Derived * >( this ), priority_, &handle_ );
if( result != pdPASS )
{
handle_ = nullptr;
state_ = StorageTaskState::start_failed;
return false;
}
FREERTOS_STORAGE_CHECKPOINT( 2U, this );
return true;
}
TaskHandle_t native_handle() const noexcept { return handle_; }
StorageTaskState state() const noexcept { return state_; }
private:
static void trampoline( void * context )
{
auto * const derived = static_cast< Derived * >( context );
auto & base = *static_cast< DynamicTask * >( derived );
base.state_ = StorageTaskState::running;
FREERTOS_STORAGE_CHECKPOINT( 5U, derived );
derived->run();
base.state_ = StorageTaskState::completed;
base.handle_ = nullptr;
FREERTOS_STORAGE_CHECKPOINT( 7U, derived );
vTaskDelete( nullptr );
for( ;; ) {}
}
TaskHandle_t handle_ {};
const char * const name_;
const configSTACK_DEPTH_TYPE stack_words_;
const UBaseType_t priority_;
volatile StorageTaskState state_ { StorageTaskState::constructed };
};
template< size_t StackWords >
struct StaticTaskStorage final
{
StaticTask_t tcb {};
StackType_t stack[ StackWords ] {};
};
template< typename Derived, size_t StackWords >
class StaticTask
{
public:
static_assert( StackWords > 0U, "static task needs stack storage" );
constexpr StaticTask( const char * name,
UBaseType_t priority,
StaticTaskStorage< StackWords > & storage ) noexcept
: name_ { name }, priority_ { priority }, storage_ { storage }
{
}
StaticTask( const StaticTask & ) = delete;
StaticTask & operator=( const StaticTask & ) = delete;
StaticTask( StaticTask && ) = delete;
StaticTask & operator=( StaticTask && ) = delete;
bool start() noexcept
{
static_assert( std::is_base_of< StaticTask< Derived, StackWords >,
Derived >::value );
if( state_ != StorageTaskState::constructed )
{
return false;
}
state_ = StorageTaskState::ready;
handle_ = xTaskCreateStatic(
&StaticTask::trampoline,
name_,
static_cast< configSTACK_DEPTH_TYPE >( StackWords ),
static_cast< Derived * >( this ),
priority_,
storage_.stack,
&storage_.tcb );
if( handle_ == nullptr )
{
state_ = StorageTaskState::start_failed;
return false;
}
FREERTOS_STORAGE_CHECKPOINT( 4U, this );
return true;
}
TaskHandle_t native_handle() const noexcept { return handle_; }
StorageTaskState state() const noexcept { return state_; }
const StaticTask_t * tcb_storage() const noexcept { return &storage_.tcb; }
const StackType_t * stack_storage() const noexcept { return storage_.stack; }
static constexpr size_t stack_words() noexcept { return StackWords; }
static constexpr size_t stack_bytes() noexcept
{
return StackWords * sizeof( StackType_t );
}
private:
static void trampoline( void * context )
{
auto * const derived = static_cast< Derived * >( context );
auto & base = *static_cast< StaticTask * >( derived );
base.state_ = StorageTaskState::running;
FREERTOS_STORAGE_CHECKPOINT( 6U, derived );
derived->run();
base.state_ = StorageTaskState::completed;
base.handle_ = nullptr;
FREERTOS_STORAGE_CHECKPOINT( 8U, derived );
vTaskDelete( nullptr );
for( ;; ) {}
}
TaskHandle_t handle_ {};
const char * const name_;
const UBaseType_t priority_;
StaticTaskStorage< StackWords > & storage_;
volatile StorageTaskState state_ { StorageTaskState::constructed };
};
} // namespace freertos
#endif