Files
lab-rv32i-freertos-task-wra…/include/freertos/task.hpp
T

135 lines
3.1 KiB
C++

#ifndef FREERTOS_CPP_EXPLICIT_TASK_HPP
#define FREERTOS_CPP_EXPLICIT_TASK_HPP
#include <stdint.h>
#include <type_traits>
extern "C"
{
#include "FreeRTOS.h"
#include "task.h"
}
#ifndef FREERTOS_TASK_CHECKPOINT
#define FREERTOS_TASK_CHECKPOINT( point, object ) \
do \
{ \
( void ) ( point ); \
( void ) ( object ); \
} while( 0 )
#endif
namespace freertos
{
enum class TaskState : uint8_t
{
constructed,
starting,
ready,
running,
completed,
start_failed
};
template< typename Derived >
class Task
{
public:
constexpr Task( const char * name,
configSTACK_DEPTH_TYPE stack_words,
UBaseType_t priority ) noexcept
: name_ { name },
stack_words_ { stack_words },
priority_ { priority }
{
}
Task( const Task & ) = delete;
Task & operator=( const Task & ) = delete;
Task( Task && ) = delete;
Task & operator=( Task && ) = delete;
bool start() noexcept
{
static_assert( std::is_base_of< Task< Derived >, Derived >::value,
"Derived must inherit Task<Derived>" );
if( state_ != TaskState::constructed )
{
return false;
}
state_ = TaskState::starting;
FREERTOS_TASK_CHECKPOINT( 2U, this );
/*
* Mark ready before entering the kernel: with a live scheduler a
* higher-priority new task may complete before xTaskCreate returns.
*/
state_ = TaskState::ready;
FREERTOS_TASK_CHECKPOINT( 3U, this );
const BaseType_t created = xTaskCreate(
&Task::trampoline,
name_,
stack_words_,
static_cast< Derived * >( this ),
priority_,
&handle_ );
if( created != pdPASS )
{
handle_ = nullptr;
state_ = TaskState::start_failed;
return false;
}
FREERTOS_TASK_CHECKPOINT( 4U, this );
return true;
}
TaskHandle_t native_handle() const noexcept
{
return handle_;
}
TaskState state() const noexcept
{
return state_;
}
const char * name() const noexcept
{
return name_;
}
private:
static void trampoline( void * context )
{
Derived * const derived = static_cast< Derived * >( context );
Task & base = *static_cast< Task * >( derived );
FREERTOS_TASK_CHECKPOINT( 6U, derived );
base.state_ = TaskState::running;
FREERTOS_TASK_CHECKPOINT( 7U, derived );
derived->run();
base.state_ = TaskState::completed;
base.handle_ = nullptr;
FREERTOS_TASK_CHECKPOINT( 10U, derived );
vTaskDelete( nullptr );
for( ;; )
{
}
}
TaskHandle_t handle_ {};
const char * const name_;
const configSTACK_DEPTH_TYPE stack_words_;
const UBaseType_t priority_;
volatile TaskState state_ { TaskState::constructed };
};
} // namespace freertos
#endif