stm32f1xx_HBL/srv/task.c
Steins7 432310a52d Implement task module
For now, most code is temporary to validate that the system can work as
envisionned. Optimisations and cleaning will be done shortly
2024-04-30 20:15:58 +02:00

142 lines
2.9 KiB
C

/** @file task.c
* Module handling the task creation and management
*
* The module provides an API to create, run and manage lightweight, stack-less
* threads (tasks). This system is based on protothreads,
* see https://dunkels.com/adam/pt/index.html
*/
//--includes--------------------------------------------------------------------
#include "task.h"
#include "../drv/stk.h"
#include "error.h"
//--local definitions-----------------------------------------------------------
#define MAX_TASK_NB 10
struct TaskContext {
Task function;
uint32_t delay_ms;
uint8_t state;
uint8_t priority;
};
void task_callback(void);
//--local variables-------------------------------------------------------------
static struct TaskContext task_list[MAX_TASK_NB];
static uint8_t task_nb;
//--public functions------------------------------------------------------------
void task_start_scheduler(void)
{
while (1) {
uint32_t delay = UINT32_MAX;
for (uint8_t priority = 0; priority < UINT8_MAX; ++priority) {
bool task_runned = false;
for (uint8_t i = 0; i < task_nb; ++i) {
if (task_list[i].function != nullptr) {
if (task_list[i].priority == priority) {
if (task_list[i].delay_ms == 0) {
task_runned = true;
struct TaskReturn ret
= task_list[i].function(task_list[i].state);
if (ret.state == _TASK_COUNT_EXIT) {
task_list[i].function = nullptr;
} else {
task_list[i].delay_ms = ret.delay_ms;
task_list[i].state = ret.state;
}
}
if (delay > task_list[i].delay_ms) {
delay = task_list[i].delay_ms;
}
}
}
}
if (task_runned) {
break;
}
}
if (delay > 0) {
stk_configure(delay * 1000, task_callback);
stk_start();
__asm("wfi");
stk_stop();
uint32_t stk_delay = stk_read();
if (stk_delay != 0) {
delay = stk_delay;
}
for (uint8_t i = 0; i < task_nb; ++i) {
if (task_list[i].function != nullptr) {
task_list[i].delay_ms -= delay;
}
}
}
}
//never returns
}
void task_start(Task task, uint8_t priority)
{
for (uint8_t i = 0; i < MAX_TASK_NB; ++i) {
if (task_list[i].function == nullptr) {
task_list[i].function = task;
task_list[i].delay_ms = 0;
task_list[i].state = 0;
task_list[i].priority = priority;
++task_nb;
return;
}
}
error_trigger("task list is full");
}
void task_stop(Task task)
{
for (uint8_t i = 0; i < task_nb; ++i) {
if (task_list[i].function == task) {
task_list[i].function(_TASK_COUNT_CLEANUP);
task_list[i].function = nullptr;
return;
}
}
error_trigger("task does not exist");
}
bool task_is_running(Task task)
{
for (uint8_t i = 0; i < task_nb; ++i) {
if (task_list[i].function == task) {
return true;
}
}
return false;
}
//--local functions-------------------------------------------------------------
void task_callback(void) {
stk_stop();
}