#pragma once /*************************************** threads.h Multithreading for AVR8 yield() must be called with enabled interrupts! (SEI) ***************************************/ #include #include #include #include #include #include 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);