avr-fw-modules/core/include/sys/threads.h

179 lines
3.9 KiB
C

#pragma once
/***************************************
threads.h
Multithreading for AVR8
yield() must be called with enabled interrupts! (SEI)
***************************************/
#include <stdint.h>
#include <hwo/stack.h>
#include <hwo/systick.h>
#include <sys/atomic.h>
#include <sys/types.h>
#include <util/list.h>
typedef void (*threadstart)(void *arg);
/* Thread Priorities */
#define TP_HIGH 0x00
#define TP_NORMAL 0x01
#define TP_LOW 0x02
#define TP_IDLE 0x03
// thread flags...
#define THREAD_HALT 0x0001
#define THREAD_WAIT 0x0002
#define THREAD_IDLE 0x0100
#define THREAD_REMOVE 0x0200
struct _hwo_thread
{
list_t list; // Thread Liste
list_t list_queue; // Priority Liste
list_t list_periodic; // Liste aller periodisch geplanten Threads
threadstart start;
void* arg;
union {
uint16_t flags;
struct {
uint16_t halt:1;
uint16_t wait:1;
uint16_t reserve0:6;
uint16_t idle:1;
uint16_t remove:1;
uint16_t periodic_miss:1;
uint16_t warn_stack:1;
uint16_t reserve1:2;
uint16_t priority:2;
};
};
struct {
int size;
uint8_t *base;
uint8_t *stackpointer;
int16_t min_free; // Kleinster festgestellter verfügbarer Stackspeicher
} stack;
struct {
systick_t timeout; // Zeitpunkt um aus tfWAIT zu erwachen...
int32_t periodic; // [us]
int32_t periode; // Periode Counter (periodic..0)
};
struct {
int32_t scheduled,
periodic_misses;
sched_time_t
scheduled_time;
} statistic;
};
typedef struct _hwo_thread THREAD;
#define THREAD(ptr) ((THREAD*)ptr)
typedef struct _hwo_thread thread_t;
#define thread_t(ptr) ((thread_t*)ptr)
/* _threading_threads: Global Thread List*/
extern list_t _threading_threads;
/* _threading_queues: Thread Queues by Priority */
extern list_t _threading_queues[4];
/* _threading_current: Currently active/scheduled Thread */
extern THREAD* _threading_current;
#define current_thread() (_threading_current)
void schedule_thread(THREAD *thread); // Thread einplanen
void unschedule_thread(THREAD *thread); // Thread aus Planung entfernen
void st_schedule(void); // SysTick: periodische Threadplaung
void ctxswitch(void); // context switcher
uint8_t* ctxsched(uint8_t* oldstack); // scheduler
void ctx_add_thread(THREAD* t);
void ctx_remove_thread(THREAD* t);
THREAD* thread_alloc(threadstart start,void* arg,uint16_t stacksize);
void thread_starter(void);
int thread_kill(THREAD* t);
void thread_sleep_irq(THREAD* thread);
void thread_wake(THREAD* thread);
void thread_set_periodic(THREAD* thread,int32_t us);
void thread_set_priority(THREAD* thread,uint8_t prio);
void yield(void);
static inline void thread_sleep(THREAD* thread)
{
ATOMIC
thread_sleep_irq(thread);
yield();
};
#define avrThread THREAD
/* @brief Auflösung des Systick Timers */
extern int32_t _ts_timer_resolution;
/* @brief CPU Takte pro Systick Timer Inkrement */
extern int32_t _ts_timer_cycles_per_increment;
/* @brief Letzter gemeldeter Zählerstand*/
extern int32_t _ts_timer_last_counter_value;
/* @brief Systick Timer Inkrmenente / Sekunde */
extern int32_t _ts_timer_increments_per_second;
/* @brief Rechenzeit für Systick */
extern sched_time_t _ts_sys_time,
_ts_irq_time;
extern int16_t _st_lag_current,
_st_lag_min,
_st_lag_max;
#ifndef _st_counter
#define _st_counter() 0
#endif // _st_counter
/* @brief retrieve momentary systick counter value
*/
static inline uint32_t st_current_counter(void){
int32_t cv = _st_counter();
if (_ts_timer_last_counter_value > cv){
cv += _ts_timer_resolution;
};
_ts_timer_last_counter_value = cv;
return cv;
};
static inline void st_reset_last_counter(void){
_ts_timer_last_counter_value = 0;
};
void thread_stat_schedule (sched_time_t *sched_time);
void thread_stat_unschedule (sched_time_t *sched_time);
void thread_stat_systick (sched_time_t *sched_time);