This function used to return the raw current value, but that exposes the prescaling used internaly
142 lines
2.9 KiB
C
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_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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//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();
|
|
}
|