合作式调度器
优缺点:
- 同一时间只有一个任务运行
- 容易调试,任务好管理
缺点:
- 任务阻塞可能会饿死其他任务
- 只适合小型项目
代码解析:
句柄数据结构:
1 2 3 4 5 6 7 8 9 10
| #define SCH_MAX_TASKS 5
typedef struct { uint8_t run; uint16_t TimeCount; uint16_t TimeRload; void (*pTaskFunc)(void); } TaskStruct_t;
|
调度器:
调度器本身是一个中断函数,先设定一定的时基,比如100us进一次中断,累计中断次数就知道过了多少时间了。然后判断TimeCount 是否为0,若为0则表示时间到开始运行任务,否则继续递减。TimeRload表示若任务需要隔一段时间运行,则该变量储存这段时间的具体值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| void SCH_inter() { for (uint8_t i = 0; i < SCH_MAX_TASKS; i++) { if(TaskNum[i].TimeCount > 0) { TaskNum[i].TimeCount--; if(TaskNum[i].TimeCount == 0) { TaskNum[i].run = 1; if(TaskNum[i].TimeRload > 0) { TaskNum[i].TimeCount = TaskNum[i].TimeRload; } } } } }
|
最后,在while(1)中循环的是管理器,它用来执行任务并准备好下一次的运行。
1 2 3 4 5 6 7 8 9 10 11 12
| void SCH_update() { for(uint8_t i=0;i<SCH_MAX_TASKS;i++) { if(TaskNum[i].run == 1) { TaskNum[i].run = 0; TaskNum[i].pTaskFunc(); } } }
|
最后是添加任务到消息队列,若对某个i,函数地址为空,则表示队列里面有空闲位置可以加入函数,只需要更改制定数据结构即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| void SCH_addTask(void (*pFunction)(void), uint32_t delay, uint32_t period) { for(uint8_t i=0;i<SCH_MAX_TASKS;i++) { if(TaskNum[i].pTaskFunc == 0) { TaskNum[i].pTaskFunc = pFunction; TaskNum[i].TimeCount = delay; TaskNum[i].TimeRload = period; TaskNum[i].run = 0; break; } } }
|
同时,我把printf函数重定向到串口,只需要初始化(我给的是PA9和PA10)
1 2 3 4 5 6 7 8 9
|
#include <stdio.h>
int fputc(int ch, FILE *f) { send_data((uint8_t)ch); return ch; }
|
即可在使用printf函数的时候自动输出到端口。
简单运用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| #include "stm32f10x.h" #include "timer.h" #include "scheduler.h" #include "uart.h"
void test_task(void); void task_2s(void);
int main(){
uart_init(); Timer_Init(); printf("A\r\n"); SCH_addTask(test_task,10000,10000); SCH_addTask(task_2s,20000,20000); while(1){ SCH_update(); }; }
void TIM2_IRQHandler() { if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); SCH_inter(); } }
void test_task(void) { printf("this is a time of 1s test task\r\n"); }
void task_2s(void) { printf("this is a time of 2s test task\r\n"); }
|