Отличная штука, давно пользую для AVR, PIC, STM32. Вот несколько полезных макросов и простейший диспетчер (старт/стоп + по одному миллисекундному таймеру на задачу). Еще есть программный 1-wire и I2C, оптимизорованные под Protothreads (могут обслуживать параллельно несколько шин).
#ifndef UL_PTX_H_
#define UL_PTX_H_
#include "ul_other.h"
#include "pt.h"
/** Execute statement cmd and wait until condition becames true */
#define PTX_EXEC_WAIT_UNTIL(cmd, cond) { cmd; }; PT_WAIT_UNTIL(pt, cond)
/** delay, ms using millisecond timer */
#define PTX_DELAY(tmr, time) PTX_EXEC_WAIT_UNTIL((tmr) += (time), (tmr) == 0);
/** delay using thread millisecond timer */
#define PTX_DELAY_MS(time) PTX_DELAY(ptx->tmr, time)
/** decrement timer if flag is set */
#define PTX_TIMER_DEC(flag, tmr) if ((flag) && (tmr)) (tmr)--
/** decrement millisecond timer */
#define PTX_TIMER_MS_DEC(tmr) PTX_TIMER_DEC(t_1000, tmr)
/** thread structure */
struct ptx {
struct pt pt; /**< protothread data */
char (*pf)(struct pt *pt, struct ptx *ptx); /**< thread function pointer */
U16 tmr; /**< thread timer */
U8 run; /**< thread run/stop flag */
void *data; /**< pointer to thread data */
};
/** threads queue */
extern struct ptx ptx_queue[PTX_MAX];
/** add new thread to queue */
struct ptx *ptx_add( char (*pf)(struct pt *pt, struct ptx *ptx), void *data, U8 run );
/** run started threads */
void ptx_dispatch( void );
#endif /* UL_PTX_H_ */
#include <stddef.h>
#include "ul_ptx.h"
#include "ul_timing.h"
struct ptx ptx_queue[PTX_MAX];
U8 ptx_cnt;
struct ptx *ptx_add( char (*pf)(struct pt *pt, struct ptx *ptx), void *data, U8 run ) {
if (ptx_cnt < (PTX_MAX)) {
struct ptx *ptx = &ptx_queue[ptx_cnt];
ptx->pf = pf;
ptx->data = data;
PT_INIT( &ptx->pt );
ptx->tmr = 0;
ptx->run = run;
ptx_cnt++;
return ptx;
}
return NULL;
}
void ptx_dispatch( void ) {
if (ptx_cnt > 0) {
struct ptx *ptx = &ptx_queue[0];
for (U8 cnt=0; cnt<ptx_cnt; cnt++, ptx++)
if (ptx->run) {
//decrement millisecond timer
PTX_TIMER_MS_DEC(ptx->tmr);
//call thread function
(ptx_queue[cnt].pf)(&ptx->pt, ptx);
}
}
}