开源一个极简的定时调度器

shower 4月前 281

就俩文件,五个api:

ztask.h:

#ifndef _ZTASK_H
#define _ZTASK_H
#define ZT_MAX_TASKS 4
typedef void (*zt_func_t)(void);
// should be called in main loop
void zt_poll(void);
// timeout: repeat inteval;   en: start immediately or not
int zt_bind(zt_func_t func, int repeat, int en);
// should be called in systick_irqhandler
void zt_tick(void);
void zt_start(int id);
void zt_stop(int id);
#endif
复制代码
ztask.c:
#include "ztask.h"
typedef struct {
    zt_func_t func;
    unsigned long timeout, repeat;
    int en;
} zt_task_t;
static struct {
    unsigned long ticks;
    int num_tasks;
    zt_task_t tasks[ZT_MAX_TASKS];
} g;
void zt_tick(void)
{
    // overflow not handled. for 1ms tick, it could run 2^32 * 1ms = ~50 days.
    g.ticks++;
}
void zt_poll(void)
{
    int i;
    for(i = 0; i < g.num_tasks; i++) {
        if(g.ticks >= g.tasks[i].timeout) {
            g.tasks[i].timeout = g.ticks + g.tasks[i].repeat;
            if(g.tasks[i].en)
                g.tasks[i].func();
        }
    }
}
void zt_stop(int id)
{
    if(id < ZT_MAX_TASKS)
        g.tasks[id].en = 0;
}
void zt_start(int id)
{
    if(id < ZT_MAX_TASKS)
        g.tasks[id].en = 1;
}
int zt_bind(zt_func_t func, int repeat, int en)
{
    if(g.num_tasks < ZT_MAX_TASKS) {
        g.tasks[g.num_tasks].func = func;
        g.tasks[g.num_tasks].repeat = repeat;
        g.tasks[g.num_tasks].timeout = 0;
        g.tasks[g.num_tasks].en = en;
        return g.num_tasks++;
    }
    else
        return -1;
}


使用方法:

定义两个任务函数:

void blink(void)
{
    GPIOA->ODR |= GPIO_PIN_1;
    _delay_us(10);
    GPIOA->ODR &= ~GPIO_PIN_1;
}
void hello(void)
{
    printf("Hello, world.\n");
}


在进入主循环前:

 

 zt_bind(blink, 100, 1);      // 每100ms执行一次
   zt_bind(hello, 500, 1);     // 每500ms执行一次


最后在主循环里调用 zt_poll(), 在systick中断里调用zt_tick(), 就行了。

如果需要控制任务启动/停止, 需要用一个变量保存zt_bind的返回值,然后执行zt_start和zt_stop即可。


最新回复 [0]
返回