stm32f1xx_HBL/srv/task.h

169 lines
7.7 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------------------------------------------------------------
enum TaskTrigger {
TASK_TRIGGER_ANY,
TASK_TRIGGER_STK,
TASK_TRIGGER_RTC,
TASK_TRIGGER_BOTH,
};
struct TaskState {
uint32_t timestamp;
uint8_t count:5;
enum TaskTrigger trigger:2;
uint8_t timeout_mode:1;
};
typedef void(*TaskFunction)(struct TaskState*, uint32_t);
struct Task {
TaskFunction function;
struct TaskState state;
};
//--functions-------------------------------------------------------------------
#define TASK(fct_name) void fct_name(struct TaskState* restrict __task_state, \
uint32_t __task_time)
#define TASK_ENTRY \
_TASK_COUNT_INIT; \
(void*) __task_time; \
switch (__task_state->count) {
#define TASK_CLEANUP \
case (_TASK_COUNT_CLEANUP): \
/* fall through */
#define TASK_EXIT \
} \
__task_state->count = _TASK_COUNT_EXIT & 0x1F; \
return;
#define TASK_TIMEOUT (__task_state->timeout == 0)
#define TASK_YIELD() _TASK_YIELD(_TASK_COUNT_INCR)
#define TASK_PAUSE(delay_ms) _TASK_PAUSE(delay_ms, _TASK_COUNT_INCR)
#define TASK_SLEEP(delay_s) _TASK_SLEEP(delay_s, _TASK_COUNT_INCR)
#define TASK_YIELD_UNTIL(cond) _TASK_YIELD_UNTIL(cond, _TASK_COUNT_INCR)
#define TASK_PAUSE_UNTIL(cond, delay_ms) \
_TASK_PAUSE_UNTIL(cond, delay_ms, _TASK_COUNT_INCR)
#define TASK_SLEEP_UNTIL(cond, delay_s) \
_TASK_SLEEP_UNTIL(cond, delay_s, _TASK_COUNT_INCR)
#define TASK_EXECUTE(task) _TASK_EXECUTE(task, _TASK_COUNT_INCR)
void task_start_scheduler(void);
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 & 0x3F)
#define _TASK_COUNT_CLEANUP (UINT8_MAX - 1)
#define _TASK_YIELD(count_val) do { \
__task_state->count = count_val; \
__task_state->trigger = TASK_TRIGGER_ANY; \
return; \
case (count_val): \
/* fall through */ \
} while (0)
#define _TASK_PAUSE(delay_ms, count_val) do { \
__task_state->count = count_val; \
__task_state->timestamp = __task_time + delay_ms; \
__task_state->trigger = TASK_TRIGGER_STK; \
return; \
case (count_val): \
/* fall through */ \
} while (0)
#define _TASK_SLEEP(delay_s, count_val) do { \
__task_state->count = count_val; \
__task_state->timestamp = __task_time + delay_s * 1000; \
__task_state->trigger = TASK_TRIGGER_RTC; \
return; \
case (count_val): \
/* fall through */ \
} while (0)
#define _TASK_YIELD_UNTIL(cond, count_val) do { \
__task_state->count = count_val; \
__task_state->trigger = TASK_TRIGGER_ANY; \
case (count_val): \
if (!(cond)) { \
return; \
} \
/* fall through */ \
} while (0)
#define _TASK_PAUSE_UNTIL(cond, delay_ms, count_val) do { \
__task_state->count = count_val; \
__task_state->timestamp = __task_time + delay_ms; \
__task_state->trigger = TASK_TRIGGER_STK; \
__task_state->timeout_mode = true; \
} \
case (count_val): \
if (!(cond) && __task_state->timestamp != 0) { \
return; \
} else { \
__task_state->timeout_mode = false; \
} \
/* fall through */ \
} while (0)
#define _TASK_SLEEP_UNTIL(cond, delay_s, count_val) do { \
__task_state->count = count_val; \
__task_state->timestamp = __taks_time + delay_s * 1000; \
__task_state->trigger = TASK_TRIGGER_RTC; \
__task_state->timeout_mode = true; \
} \
case (count_val): \
if (!(cond) && __task_state->timestamp != 0) { \
return; \
} else { \
__task_state->timeout_mode = false; \
} \
/* fall through */ \
} while (0)
#define _TASK_EXECUTE(task, count_val) do { \
__task_state->count = count_val; \
__task_state->trigger = TASK_TRIGGER_ANY; \
task_start(Task task); \
return; \
case (count_val): \
if (task_is_running(task)) { \
return; \
} \
/* fall through */ \
} while (0)
#endif //_task_h_