stm32f1xx_HBL/srv/task.c
Steins7 c09d2cda67 Remove priority parameter from tasks
In the end, priorities are only usefull in preemptive systems. Here, it would
only garentee the execution order, which we don't care about most of the time
2024-05-14 14:53:51 +02:00

146 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"
#include "debug.h"
//--local definitions-----------------------------------------------------------
#define MAX_TASK_NB 10
struct TaskContext {
Task function;
uint32_t delay_ms;
uint8_t state;
};
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;
bool task_runned = false;
for (uint8_t i = 0; i < task_nb; ++i) {
if (task_list[i].function != nullptr) {
if (task_list[i].delay_ms == 0) {
task_runned = true;
debug_trace("%u", 1);
debug_trace("%u", i + 2);
struct TaskReturn ret
= task_list[i].function(task_list[i].state);
debug_trace("%u", i + 2);
debug_trace("%u", 1);
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) {
debug_trace("%u", 1);
debug_trace("%u", 0);
stk_configure(delay * 1000, task_callback);
stk_start();
__asm("wfi");
stk_stop();
uint32_t stk_delay = stk_read_us();
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;
}
}
debug_trace("%u", 0);
debug_trace("%u", 1);
}
}
//never returns
}
void task_start(Task task)
{
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_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();
}