前几天,受一位物联网大神的影响,想写一个自己的合作式调度器,最近正好在学习状态机,
就按着状态机的思路自己写了一个。
首先来介绍下这个合作式调度器的思路。
1、任务插入就绪队列支持两个优先级,时间都是O(1),一个队尾,一个队首;
2、任务的调度时间为O(1);
3、任务返回false,则本任务不在自动加入队列;返回ture,则执行完毕后,任务自动加入到队尾;
4、任务池可自定义大小;
5、调度器返回false,表示空闲态,系统可以进入Sleep();
6、每个任务通过USER_NEW_FSM(__TASK,__PRAM,__PRIORITY)指定自己的下一个任务;
7、如果每个任务都是NONE-block的,并且都拆分成小的任务,那么这个调度器就是多任务的;
8、如果在main()里面调度一个,在一个定时中断里面调度一个,那么就可以实现真正的多任务;
9、没有任务栈,所以一些参量需要static;
来看下内核结构体:
//task heap
typedef struct core_task_t core_task_t;
struct core_task_t{
ptTask *pCallTask;
void *pRam;
core_task_t *ptNext;
};
用户接口:
//user/sys interface
#define USER_NEW_FSM(__TASK,__PRAM,__PRIORITY) add_task_fpfsm_core_t((__TASK),(__PRAM),(__PRIORITY))
#define SYS_CALL_SUB_FSM() scheduler_fpfsm_core_t()
#define SYS_INIT_FSM() do{\
init_fpfsm_core_t();\
}while(0)
#define USER_NEW_MEMORY_FSM(__MEMORY,__SIZE) add_memory_block_to_fpfsm_core_t_heap((__MEMORY),(__SIZE));
怎么用呢?
以一个灯为例:
void main(void)
{
DisINT()
IO_Init();
SYS_INIT_FSM();
USER_NEW_MEMORY_FSM(s_chTaskMemory,(FPFSM_TASK_TCB_SIZE * TASK_NUM));
EnINT()
task1_start(NULL);
while(1)
{
SYS_CALL_SUB_FSM();
}
}
/****************** TASK ******************/
enum{
TASK_DELAY_START = 0,
TASK_DELAY_WAIT,
TASK_DELAY_END
};
typedef struct{
uint8_t state;
uint16_t hwDelayTimer;
uint16_t hwDelayMS;
ptTask *PCallBack;
}tLEDTaskStack;
static bool task_delay(void* pTemp)
{
tLEDTaskStack *ptTaskStack = (tLEDTaskStack*)pTemp;
if(NULL == ptTaskStack){
return false;
}
switch(ptTaskStack->state){
case TASK_DELAY_START:
ptTaskStack->state = TASK_DELAY_WAIT;
ptTaskStack->hwDelayMS = DELAY_1MS;
//break;
case TASK_DELAY_WAIT:
ptTaskStack->hwDelayMS--;
if(!ptTaskStack->hwDelayMS){
ptTaskStack->hwDelayMS = DELAY_1MS;
ptTaskStack->hwDelayTimer--;
if(!ptTaskStack->hwDelayTimer){
ptTaskStack->state = TASK_DELAY_END;
}
}
break;
case TASK_DELAY_END:
if(USER_NEW_FSM(ptTaskStack->PCallBack,ptTaskStack,ADD_TASK_FIFO_TAIL)){
return false;
}
break;
}
return true;
}
/****************** TASK1 ******************/
static bool task1_start(void *pTemp)
{
static tLEDTaskStack s_tTask1Pram;
s_tTask1Pram.state=TASK_DELAY_START;
s_tTask1Pram.hwDelayTimer = 100;
s_tTask1Pram.PCallBack = NULL;
if(USER_NEW_FSM(task1_task,&s_tTask1Pram,ADD_TASK_FIFO_TAIL)){
return false;
}
return true;
}
static bool task1_task(void* pTemp)
{
tLEDTaskStack *ptTask1Pram = (tLEDTaskStack*)pTemp;
if(NULL == ptTask1Pram){
return false;
}
switch(ptTask1Pram->state){
case TASK_DELAY_START:
LED1 = ~LED1;
ptTask1Pram->state = TASK_DELAY_WAIT;
case TASK_DELAY_WAIT:
if(USER_NEW_FSM(task_delay,ptTask1Pram,ADD_TASK_FIFO_TAIL)){
ptTask1Pram->state=TASK_DELAY_START;
ptTask1Pram->PCallBack = task1_start;
return false;
}
break;
}
return true;
}
这版调度器目前不支持优先级,如果要支持优先级调度,那么出队是O(1),入队不管用链表、数组、队列,都是O(N),
只有用树,才是O(logN),目前正在研究。