125 lines
5.2 KiB
C
125 lines
5.2 KiB
C
/** @file task.h
|
|
* 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
|
|
*/
|
|
|
|
#ifndef _task_h_
|
|
#define _task_h_
|
|
|
|
//--includes--------------------------------------------------------------------
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
|
|
//--type definitions------------------------------------------------------------
|
|
|
|
struct TaskState {
|
|
int32_t delay;
|
|
uint8_t count:7;
|
|
uint8_t is_active:1;
|
|
};
|
|
|
|
typedef void(*TaskFunction)(struct TaskState*);
|
|
|
|
struct Task {
|
|
TaskFunction function;
|
|
struct TaskState state;
|
|
};
|
|
|
|
|
|
//--functions-------------------------------------------------------------------
|
|
|
|
#define TASK(fct_name) void fct_name(struct TaskState* restrict __task_state)
|
|
|
|
#define TASK_ENTRY \
|
|
_TASK_COUNT_INIT; \
|
|
switch (__task_state->count) {
|
|
|
|
#define TASK_CLEANUP \
|
|
case (_TASK_COUNT_CLEANUP): \
|
|
/* fall through */
|
|
|
|
#define TASK_EXIT \
|
|
} \
|
|
__task_state->count = _TASK_COUNT_EXIT; \
|
|
return;
|
|
|
|
#define TASK_TIMEOUT
|
|
|
|
#define TASK_YIELD() _TASK_YIELD(_TASK_COUNT_INCR)
|
|
#define TASK_SLEEP(delay_ms) _TASK_SLEEP(delay_ms, _TASK_COUNT_INCR)
|
|
#define TASK_YIELD_UNTIL(cond) _TASK_YIELD_UNTIL(cond, _TASK_COUNT_INCR)
|
|
#define TASK_SLEEP_UNTIL(cond, delay_ms) \
|
|
_TASK_SLEEP_UNTIL(cond, delay_ms, _TASK_COUNT_INCR)
|
|
#define TASK_EXECUTE(task) _TASK_EXECUTE(task, _TASK_COUNT_INCR)
|
|
|
|
void task_schedule(uint32_t elapsed_ms);
|
|
|
|
void task_declare();
|
|
|
|
void task_start(TaskFunction task);
|
|
void task_stop(TaskFunction task);
|
|
bool task_is_running(TaskFunction task);
|
|
|
|
|
|
//--internal_functions----------------------------------------------------------
|
|
|
|
#define _TASK_COUNT_INIT enum { TASK_COUNTER_BASE = __COUNTER__ }
|
|
#define _TASK_COUNT_INCR (uint8_t)(__COUNTER__ - TASK_COUNTER_BASE - 1)
|
|
#define _TASK_COUNT_EXIT (UINT8_MAX & 0x7F)
|
|
#define _TASK_COUNT_CLEANUP (UINT8_MAX - 1)
|
|
|
|
#define _TASK_YIELD(count_val) do { \
|
|
__task_state->count = count_val; \
|
|
return; \
|
|
case (count_val): \
|
|
/* fall through */ \
|
|
} while (0)
|
|
|
|
#define _TASK_SLEEP(delay_ms, count_val) do { \
|
|
__task_state->count = count_val; \
|
|
__task_state->delay = delay_ms; \
|
|
return; \
|
|
case (count_val): \
|
|
/* fall through */ \
|
|
} while (0)
|
|
|
|
#define _TASK_YIELD_UNTIL(cond, count_val) do { \
|
|
__task_state->count = count_val; \
|
|
case (count_val): \
|
|
if (!(cond)) { \
|
|
return; \
|
|
} \
|
|
/* fall through */ \
|
|
} while (0)
|
|
|
|
#define _TASK_SLEEP_UNTIL(cond, delay_ms, count_val) do { \
|
|
__task_state->count = count_val; \
|
|
__task_state->delay = delay_ms; \
|
|
__task_state->is_active = true; \
|
|
case (count_val): \
|
|
if (!(cond) && __task_state->delay >= 0) { \
|
|
return; \
|
|
} \
|
|
__task_state->is_active = false; \
|
|
/* fall through */ \
|
|
} while (0)
|
|
|
|
#define _TASK_EXECUTE(task, count_val) do { \
|
|
__task_state->count = count_val; \
|
|
task_start(Task task); \
|
|
return; \
|
|
case (count_val): \
|
|
if (task_is_running(task)) { \
|
|
return; \
|
|
} \
|
|
/* fall through */ \
|
|
} while (0)
|
|
|
|
#endif //_task_h_
|
|
|