179 lines
3.9 KiB
C
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);
|
|
|
|
|
|
|