前面写了switch case做任务调度的应用,这边写一下如何实现.像一般的RTOS一样都有一个任务控制块(TCB)列表来管理所有的任务,所以这里也需要一个结构体来管理动作任务,这里叫做ACB吧.
动作任务管理结构体
这个结构体用来记录当前动作任务的当前步骤,函数地址,事件处理函数的函数地址,动作名称,运行时间等.
typedef struct _ACB
{
uint8_t nStep; // 分支动作步骤
uint8_t nChildID; //子动作ID
uint32_t nDelay; // 延时
uint32_t nStartTime;
uint32_t nUsedTime;
uint32_t nStatus; //当前状态
ActionEvent EventQueue[4]; //动作事件队列
uint8_t nEventCnt; //事件数量和个数
void (*AppCallBack)(); //业务动作函数指针
void (*EventCallback)(); //事件处理函数指针
void (*ActionCallback)(); //当前运行的函数指针
char ActionParam[10]; //动作参数
//17
char* pActionName; //动作名称
char* pErrorInfo; //错误信息
//8
struct _ACB* next; //上一个控制块 便于删除添加到就绪队列
struct _ACB* prev; //下一个控制块 便于添加删除到就绪队列
} ACB;
动作任务创建
//将OpApp业务函数指针和ACB结构体绑定
void AddAction(int nID,void (*OpApp)(),const char* pActionName)
{
if(nID<90)
{
mOS.ActionPool[nID].AppCallBack = OpApp;
mOS.ActionPool[nID].EventCallback = EventAction;
mOS.ActionPool[nID].ActionCallback = OpApp;
mOS.ActionPool[nID].nStatus = 0xff;
mOS.ActionPool[nID].nEventCnt = 0;
mOS.ActionPool[nID].nUsedTime = 0;
mOS.ActionPool[nID].nStartTime = 0;
mOS.ActionPool[nID].pActionName = (char*)pActionName;
}
}
动作任务执行
1.动作结构体初始化,添加到就绪队列
//根据ID启动动作任务
int8_t StartAction(uint8_t ActionId)
{
if(ActionId>90)
{
return false;
}
ACB* pAction = &mOS.ActionPool[ActionId];
pAction->ActionStartTime = mOS.SystemTime;
pAction->nStep = STEP1;
pAction->nEventCnt = 0;
pAction->nUsedTime = 0;
pAction->nChildID = 0;
pAction->EventCallback = EventAction;
pAction->ActionCallback = pAction->AppCallBack;//先指向业务函数指针
AddReadyActionToTail(pAction); //把当前的控制块添加到就绪队列
return true;
}
//将要运行的动作添加到就绪运行队列
void AddReadyActionToTail(ACB * pAction)
{
pAction->nStaus = 0;
pAction->next = NULL;
pAction->prev = mOS.tail; //
if(mOS.head==NULL)
{
mOS.head = pAction;
}
if(mOS.tail!=NULL) //当就绪链表没有动作时 tail为空
{
mOS.tail->next = pAction;
}
mOS.tail = pAction; //移动尾部指针
}
2.就绪队列遍历
inline void AppLoop()
{
mOS.current = mOS.head;
while(mOS.current!=NULL)
{
mOS.current->ActionCallback();
DelFinishAction(); //需要把完成的任务从就绪队列删除
mOS.current = mOS.current->next;
}
}
//动作完成后,并计算动作使用时间,从链表删除
inline void DelFinishAction()
{
if(mOS.current->nStatus==0) //动作任务正在运行
{
return ;
}
//统计任务耗时
mOS.current->nUsedTime = mOS.SystemTime - mOS.CurrentAction->nStartTime; //当前时间减去开始时间
if(mOS.head==mOS.tail) //只有一个元素
{
mOS.head= NULL;
mOS.tail = NULL;
return ;
}
if(mOS.current==mOS.head) //头部删除,需要将头部指针往后移动
{
mOS.head = mOS.current->next;
return ;
}
if(mOS.current==mOS.tail) //尾部删除,需要将尾部指针往前移动
{
mOS.tail = mOS.current->prev;
mOS.tail->next = NULL;
return ;
}
//中间删除
mOS.current->prev->next = mOS.current->next;
mOS.current->next->prev = mOS.current->prev;
}
全部0条评论
快来发表一下你的评论吧 !