这个任务调度模块的实现是形成于毕设项目中的,用在STM32
中,断断续续跨度2个月实现了一些基本功能,可能后面再做其他项目时会一点点完善起来,也会多学习相关知识来强化模块的实用性和高效性,毕竟用自己自主实现出来的功能还是蛮舒心的。
整体上的结构属于线性结构
,结合链表
和定时器
来实现,我使用的是sysTick
这个滴答时钟,1ms
的频率,功能比较简单,容易理解。
分片的模式,主要体现在函数分片
和时间分片
在我之前就有使用在函数中,主要的思路是,把函数功能切片
,分为几个小部分,每次执行时按次序执行小部分,对于没有时序要求的函数来说,可以把一个占用CPU
大的功能分摊开来实现,从而避免有些地方耗时长的问题。对于时间分片
,其实就是定时器的一种应用,实际上,函数分片
在执行的时候已经是一种时间分片
了,不过现在加上人为的控制在里面了。 下面是函数分片
的一般结构:
(资料图片仅供参考)
void func(char *fos,...){ static char step=0;//顺序控制变量,自由度比较高,可乱序,可循环,可延迟执行 switch(step){ case 0:{ //... step++; break; } case 1:{ //... step++; break; } //... default:{ //step++;//可以借助default实现延时的效果,即跳过几次空白step break; } } return;}
其中添加的参数变量*fos
是必要的,因为就是通过传入每个任务的这个标志位来判断是否运行结束,而其他的参数,就得基于具体任务做不一样的处理了。
可以看到这个框图是一个头尾相连的闭环结构
,从头节点依次运行到尾节点后再从头循环往复执行下去。
void loop_task(void){static Task_Obj *tasknode;tasknode=task_curnode->next;//repoint the curnode to the nextif(tasknode==NULL){//tasknode is null,only the headnode have the attrreturn;//express the task space is none}else if(tasknode->task_type==TYPE_HEAD){//tasknode is headnodetask_curnode=tasknode;return;}else{if(tasknode->run_type == RUN_WAIT){ //等待型任务,通过ready标志来确定是否执行,否则就跳过if(!tasknode->ready){if(task_curnode->next !=NULL){task_curnode=task_curnode->next;return;}}}if(tasknode->task_status==STATUS_INIT){tasknode->tickstart=HAL_GetTick();//获取ticktasknode->task_status=STATUS_RUN;}else if(tasknode->task_status==STATUS_RUN){if((HAL_GetTick() - tasknode->tickstart) > (uint32_t)tasknode->task_tick){tasknode->task_name(&(tasknode->task_fos));//run the step task,transfer the fostasknode->tickstart+=(uint32_t)tasknode->task_tick;//update the tickstart}}}if(tasknode->task_fos==FOS_FLAG){tasknode->ready=0;if(tasknode->waittask!=NULL){ //置位该任务绑定的等待的任务准备运行标志位,标识可以准备运行了tasknode->waittask->ready=1;} //运行结束就删掉该任务delete_task(tasknode);}else if(tasknode->task_fos==FOC_FLAG){ //循环运行该任务tasknode->task_status=STATUS_INIT;//continue running from starttasknode->task_fos=0;//RESET fos}if(task_curnode->next !=NULL){if(task_curnode->next->run_type==RUN_FORCE) return;//force-type"s taskelse task_curnode=task_curnode->next;}}
其中有几个运行态和标志位
#define FOS_FLAG 99//运行结束标志#define FOC_FLAG 100//运行结束后再次执行,相当于循环运行#define TYPE_NOMAL 0//标识一般任务类型#define TYPE_HEAD 1//标识头任务类型#define TYPE_END 2//标识尾任务类型#define RUN_NORMAL 0//一般轮询模式#define RUN_FORCE 1//强制运行该任务,运行结束才继续下一个任务#define RUN_WAIT 2//等待指定的任务结束,才可以被运行#define STATUS_INIT 0//任务的准备阶段,用于获取起始时间#define STATUS_RUN 1//任务运行阶段#define STATUS_UNVAILED 2//无效状态
运行时对时间间隔tick
的把握还有点问题,这个等待后面有机会优化下。
typedef struct TASK_CLASS{void (*task_name)(char *taskfos,...);//任务函数int task_tick;//任务的时间分片间隔uint32_t tickstart;//起始时间点,每次执行完须加上一个tickchar task_fos;//运行结束标志char task_type;//任务类型变量char task_status;//任务状态char run_type;//运行状态char ready;//准备运行标志位struct TASK_CLASS *next;//下一任务struct TASK_CLASS *waittask;//等待执行的任务} Task_Obj;
添加任务
add_taskvoid add_task(void (*taskname)(char *,...),int tasktick,int runtype){//可变参,这里未做处理Task_Obj *tasknode,*tmpnode;char i;tasknode = (Task_Obj*)malloc(sizeof(Task_Obj));tasknode->task_name=taskname;tasknode->task_tick=tasktick;tasknode->task_fos=0;tasknode->task_status=STATUS_INIT;//initial statustasknode->task_type=TYPE_END; //set the new node to endnodetasknode->run_type=runtype;tasknode->next=&task_headnode;//the endnode point to the headnodetmpnode=&task_headnode;if(task_num==0){tmpnode->next=tasknode;task_num++;return;}for(i=0;inext;//reach the endnode}tmpnode->task_type=TYPE_NOMAL;//turn the last endnode to the normal nodetmpnode->next=tasknode;task_num++;}
add_wait_taskvoid add_wait_task(void (*taskname)(char *),void (*waitname)(char *),int tasktick){Task_Obj *tmpnode,*tasknode;char i,pos;tmpnode=&task_headnode;for(i=0;inext;//reach the endnodeif(tmpnode->task_name==taskname){pos=i;//获取要等待任务的位置break;}}tasknode = (Task_Obj*)malloc(sizeof(Task_Obj));tasknode->task_name=waitname;tasknode->task_tick=tasktick;tasknode->task_fos=0;tasknode->task_status=STATUS_INIT;//initial statustasknode->task_type=TYPE_END; //set the new node to endnodetasknode->run_type=RUN_WAIT;//任务为等待运行tasknode->ready=0;tasknode->next=&task_headnode;//the endnode point to the headnodetmpnode->waittask=tasknode;//获取新建的等待执行的任务地址,在运行结束后把等待执行的任务的准备运行标志位置1tmpnode=&task_headnode;if(task_num==0){tmpnode->next=tasknode;task_num++;return;}for(i=0;inext;//reach the endnode}tmpnode->task_type=TYPE_NOMAL;//turn the last endnode to the normal nodetmpnode->next=tasknode;task_num++;}
删除任务
delete_task(局限性大,只针对当前运行的任务而言)void delete_task(Task_Obj *taskobj){if(task_curnode->task_type==TYPE_HEAD && task_num < 2){//if curnode is headnode,and tasknum=1task_curnode->next=NULL;}else{task_curnode->next=taskobj->next;//repoint the curnode next}free(taskobj);//free the space of where the taskobj pointedtask_num--;}
delete_task_withname(删除指定任务名的任务)void delete_task_withname(void (*taskname)(char *)){Task_Obj *tmpnode,*tmpnode2;char i,pos;tmpnode=&task_headnode;for(i=0;inext;//reach the endnodeif(tmpnode->task_name==taskname){pos=i;break;}}if(i==task_num) return;tmpnode=&task_headnode;for(i=0;inext;}if(tmpnode->next==NULL){//if tmpnode is endnodetmpnode2->next=&task_headnode;}else{tmpnode2->next=tmpnode->next;//repoint the curnode next}task_num--;free(tmpnode);}
初始化任务空间
void non_task(char *taskfos){return;}void init_taskspace(void){task_headnode.task_name=non_task;task_headnode.task_type=TYPE_HEAD;task_headnode.task_status=STATUS_UNVAILED;task_headnode.next=NULL;task_curnode=&task_headnode;//头节点是没有任务需要执行的task_num=0;}
调用实例add_task(task1,500,RUN_NORMAL);//500ms执行一次task1任务add_wait_task(task1,task2,500);//task2等待task1结束才会执行,运行的时间间隔为500msdelete_task_withname(task1);//删除task1任务while(1){ //... loop_task();//任务轮询}
结语整体实现说难不难,说简单不简单,但也是我第一次尝试这种偏向系统级应用的代码,而且都没有参照任何其他的资料和代码,完全以自己的对任务的理解和具体项目的需求来一点点实现,希望后面会把这个调度的代码进一步完善成一个通用型的调度方式,也方便后面项目的使用了。
X 关闭
X 关闭
5月20日,在建的广西最长跨海大桥——龙门大桥东主塔顺利封顶。至此,龙门大桥东、西两岸主塔全部实现封顶,标志着该桥进入缆索系统施工阶
中新网上海3月30日电 (记者 陈静)上海正面临常态化防控以来疫情形势最严峻复杂的挑战,单日新增阳性感染者数量不断刷新纪录。记者30日获
中新网3月30日电 据国家地震台网官方微博消息,中国地震台网正式测定:3月30日18时14分在新疆和田地区皮山县(北纬36 01度,东经77 89度)发
上海市委常委会今天上午(3月30日)举行会议,听取当前疫情应急处置和核酸筛查相关工作汇报,研究部署下一步疫情防控重点工作。市委书记
(抗击新冠肺炎)江苏无锡一男子隐匿行程轨迹被警方立案侦查 中新网无锡3月30日电 (记者 孙权)3月30日,无锡市在“应检尽检”人员核
(抗击新冠肺炎)官方称吉林市疫情扩散势头得到遏制 中新网吉林3月30日电 (记者 石洪宇)记者30日从吉林市政府新闻办召开的疫情防控
中新网唐山3月30日电 (白云水 孟潮)3月30日,河北省唐山市召开新冠肺炎疫情防控工作新闻发布会通报称,3月29日0时至24时,唐山市新增
浙江省嘉兴市秀洲区新型冠状病毒感染肺炎疫情防控指挥部办公室发布通告: 3月30日上午,秀洲区发现1例新冠肺炎阳性感染者,该感染者
今天(3月30日)下午,新疆乌鲁木齐市人民政府新闻办公室召开疫情防控新闻发布会,通报乌鲁木齐市新冠肺炎疫情和疫情防控最新情况。会上
中新网天津3月30日电 (记者 王君妍)记者30日从天津市水务局获悉,为充分发挥河湖长制优势,近日,天津市将南水北调中线天津干线(天津