一、基于事件的任务调度器
1.事件任务调度器数据结构
typedef unsigned char bit_t;typedef unsigned char u1_t;typedef signed char s1_t;typedef unsigned short u2_t;typedef short s2_t;typedef unsigned int u4_t;typedef int s4_t;typedef unsigned long long u8_t;typedef long long s8_t;typedef unsigned int uint;typedef const char* str_t;typedef s4_t ostime_t;struct osjob_t; typedef void (*osjobcb_t) (struct osjob_t*);struct osjob_t { struct osjob_t* next;//链表 ostime_t deadline;//任务执行事件 osjobcb_t func; //任务函数};TYPEDEF_xref2osjob_t;// RUNTIME STATE 用于记录当前即时任务及计划任务;即时任务添加进即时任务链表后即时运行;计划任务则为计时时间到则运行。static struct { osjob_t* scheduledjobs; /* 计划任务 */ osjob_t* runnablejobs; /* 即时任务 */} OS;
任务的添加和删除工作,都以回调的形式完成。
2.OS初始化及时基
/* 系统初始化,如定时器、中断等 */void os_init () {/* hal_init(); */} /* 获取系统时间,需要消耗MCU一个定时器来实现OS系统时基 */ostime_t os_getTime () { return hal_ticks();}
3.任务及任务链表
任务链表分两个,一个为即时任务链表,一个为定时任务链表;删除时需要从两个表中寻找并删除。
从任务链表中删除指定任务
static u1_t unlinkjob (osjob_t** pnext, osjob_t* job) { for( ; *pnext; pnext = &((*pnext)->next)) { if(*pnext == job) { // unlink *pnext = job->next; return 1; } } return 0;}// clear scheduled jobvoid os_clearCallback (osjob_t* job) { hal_disableIRQs(); unlinkjob(&OS.scheduledjobs, job) || unlinkjob(&OS.runnablejobs, job); hal_enableIRQs();}
添加任务至即时任务链表
// schedule immediately runnable jobvoid os_setCallback (osjob_t* job, osjobcb_t cb) { osjob_t** pnext; hal_disableIRQs(); // remove if job was already queued os_clearCallback(job); // fill-in job job->func = cb; job->next = NULL; // add to end of run queue for(pnext=&OS.runnablejobs; *pnext; pnext=&((*pnext)->next)); *pnext = job; hal_enableIRQs();}
添加任务至计划任务链表
// schedule timed jobvoid os_setTimedCallback (osjob_t* job, ostime_t time, osjobcb_t cb) { osjob_t** pnext; hal_disableIRQs(); // remove if job was already queued os_clearCallback(job); // fill-in job job->deadline = time; job->func = cb; job->next = NULL; // insert into schedule for(pnext=&OS.scheduledjobs; *pnext; pnext=&((*pnext)->next)) { if((*pnext)->deadline - time > 0) { // (cmp diff, not abs!) // enqueue before next element and stop job->next = *pnext; break; } } *pnext = job; hal_enableIRQs();}
4.任务后台
优先从即时任务中提取任务运行,即时任务运行完成后,才会再运行计划任务。所以,计划任务一般给对实时性无要求的任务,有时候为了保证即时任务,需要将一些任务设定为计划任务,如:点灯任务。
// execute jobs from timer and from run queuevoid os_runloop () { while(1) { osjob_t* j = NULL; hal_disableIRQs(); // check for runnable jobs if(OS.runnablejobs) { j = OS.runnablejobs; OS.runnablejobs = j->next; } else if(OS.scheduledjobs && hal_checkTimer(OS.scheduledjobs->deadline)) { // check for expired timed jobs j = OS.scheduledjobs; OS.scheduledjobs = j->next; } else { // nothing pending hal_sleep(); // wake by irq (timer already restarted) } hal_enableIRQs(); if(j) { // run job callback j->func(j); } }}
5.任务调度实例
static void immediatelyfunc (osjob_t* j) {/*TODO*/}static void scheduledfunc (osjob_t* j) {/*TODO*/}// application entry pointint main () { osjob_t immediatelyjob; osjob_t scheduledjob; // initialize runtime env os_init(); // setup initial job 添加即时任务 os_setCallback(&immediatelyjob, immediatelyfunc); // execute scheduled jobs and events os_setTimedCallback (&scheduledjob, 1000, scheduledfunc) os_runloop();// (not reached) return 0;}