前两篇文档我一共讲述了3个裸机框架:(1)轮询系统;(2)前后台系统;(3)基于时间片的多任务系统;

今天再谈一谈单链表组成的裸机系统。此写法更加灵活,和时间片的概念类似,

(4)基于单链表的多任务系统

代码写法分为7步

【1】定义一个表示的任务的结构体类型

timeout表示超时时间,与定时器心跳比较,如果时间到,就执行*pTask指向的函数体

repeat用来周期设置,一般设置成timerout一样,如果设置为0,该任务只是执行一次

*pTask指向该任务要执行的函数体(一般也称为回调函数)

Task_t* next指向链表中的下一个任务节点

//定义一个表示的任务的结构体类型typedef struct Task_t{ unsigned int timeout; // 超时时间(用来与定时器心跳比较) unsigned int repeat;// 循环定时触发时间(周期定时设置),为0时代表单次定时 void (*pTask)(void); //任务的函数指针 struct Task_t* next;// 指向下一个定时器任务节点}Task_t;

【2】定义变量,包含task任务结构体和链表头以及心跳全局变量

//任务结构体变量Task_t task1;Task_t task2;Task_t task3;//表头struct Task_t* g_head_handle=NULL;//心跳计数器unsigned int g_task_ticks=0;

【3】心跳函数将心跳全局变量自加

void Task_Ticks(){ g_task_ticks++;}

【4】任务初始化

void Task_Init(Task_t* hTask, void(*pTask)(), unsigned int timeout, unsigned int repeat){hTask->timeout = g_task_ticks + timeout;hTask->repeat = repeat;hTask->pTask = pTask;}

【5】任务启动和停止函数

//链表中插入任务char Task_Start(Task_t* hTask){struct Task_t* target = g_head_handle;//检查链表中是否已经有该任务while(target) {if(target == hTask) return -1;//already exist.target = target->next;}//链表头部插入任务hTask->next = g_head_handle;g_head_handle = hTask;return 0;}//移除链表中的任务,相当于停止该任务void Task_Stop(Task_t* hTask){struct Task_t** curr;for(curr = &g_head_handle; *curr; ) {struct Task_t* entry = *curr;if (entry == hTask) {*curr = entry->next;} elsecurr = &entry->next;}}

【6】任务循环

//任务循环void Task_Process() { struct Task_t* target;for(target=g_head_handle; target; target=target->next) {if(g_task_ticks >= target->timeout) {if(target->repeat == 0) {Task_Stop(target);} else {target->timeout = g_task_ticks + target->repeat;}target->pTask();