1、重讲任务
(3)任务可以在多任务调度之前开始建立,也可以在其他的任务中创建需要的任务。但是有一点需要注意的是,在启动UCOS之前必须至少得建立一个任务。
2、分析创建任务函数
如果创建的时候检测到任务的优先级比最大的优先级(数值上,实际上是最小)还大的话,那么就直接退出,输出一个错误码。
我们不允许创建任务是在中断中进行的,所以我们也会在中断时创建任务返回一个错误码。
最后就是把刚刚的四个参数赋值到任务当中去,实现任务的创建。
#if OS_TASK_CREATE_EN > 0u INT8U OSTaskCreate (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT8U prio) {
OS_STK *psp; INT8U err; #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif #ifdef OS_SAFETY_CRITICAL_IEC61508 if (OSSafetyCriticalStartFlag == OS_TRUE) {
OS_SAFETY_CRITICAL_EXCEPTION(); } #endif #if OS_ARG_CHK_EN > 0u if (prio > OS_LOWEST_PRIO) {
/* 确认优先级在一个合法的范围内 */ return (OS_ERR_PRIO_INVALID); } #endif OS_ENTER_CRITICAL(); if (OSIntNesting > 0u) {
/* 确保我们不在中断中创建任务 */ OS_EXIT_CRITICAL(); return (OS_ERR_TASK_CREATE_ISR); } if (OSTCBPrioTbl[prio] == (OS_TCB *)0) {
/* 初始化任务的优先级 */ OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ... */ /* ... the same thing until task is created. */ OS_EXIT_CRITICAL(); psp = OSTaskStkInit(task, p_arg, ptos, 0u); /* 初始化任务堆栈 */ err = OS_TCBInit(prio, psp, (OS_STK *)0, 0u, 0u, (void *)0, 0u); if (err == OS_ERR_NONE) {
if (OSRunning == OS_TRUE) {
/* Find highest priority task if multitasking has started */ OS_Sched(); } } else {
OS_ENTER_CRITICAL(); OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others */ OS_EXIT_CRITICAL(); } return (err); } OS_EXIT_CRITICAL(); return (OS_ERR_PRIO_EXIST); } #endif
3、再谈任务堆栈
任务的堆栈可以使用静态的堆栈生成,也可以使用动态的堆栈生成。
(1)静态堆栈:
static OS_STK MyTaskStack[stack_size];
(2)动态堆栈:
OS_STK *pstk; pstk = (OS_STK *)malloc(stack_size); if(pstk != (OS_STK *)0) {
//确保malloc能够得到足够的内存空间 }
OS_STK TaskStack[TASK_STACK_SIZE]; OSTaskCreate(task, pdata, &TaskStack[0], prio);
这个是堆栈从上往下增长的:
OS_STK TaskStack[TASK_STACK_SIZE]; OSTaskCreate(task, pdata, &TaskStack[TASK_STACK_SIZE-1], prio);
#if OS_TASK_DEL_EN > 0u INT8U OSTaskDel (INT8U prio) {
#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) OS_FLAG_NODE *pnode; #endif OS_TCB *ptcb; #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif if (OSIntNesting > 0u) {
/* See if trying to delete from ISR */ return (OS_ERR_TASK_DEL_ISR); } if (prio == OS_TASK_IDLE_PRIO) {
/* Not allowed to delete idle task */ return (OS_ERR_TASK_DEL_IDLE); } #if OS_ARG_CHK_EN > 0u if (prio >= OS_LOWEST_PRIO) {
/* Task priority valid ? */ if (prio != OS_PRIO_SELF) {
return (OS_ERR_PRIO_INVALID); } } #endif /*$PAGE*/ OS_ENTER_CRITICAL(); if (prio == OS_PRIO_SELF) {
/* See if requesting to delete self */ prio = OSTCBCur->OSTCBPrio; /* Set priority to delete to current */ } ptcb = OSTCBPrioTbl[prio]; if (ptcb == (OS_TCB *)0) {
/* Task to delete must exist */ OS_EXIT_CRITICAL(); return (OS_ERR_TASK_NOT_EXIST); } if (ptcb == OS_TCB_RESERVED) {
/* Must not be assigned to Mutex */ OS_EXIT_CRITICAL(); return (OS_ERR_TASK_DEL); } OSRdyTbl[ptcb->OSTCBY] &= (OS_PRIO)~ptcb->OSTCBBitX; if (OSRdyTbl[ptcb->OSTCBY] == 0u) {
/* 把该任务从就绪表中删除,也就是置0处理 */ OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY; } #if (OS_EVENT_EN) if (ptcb->OSTCBEventPtr != (OS_EVENT *)0) {
OS_EventTaskRemove(ptcb, ptcb->OSTCBEventPtr); /* 把该任务从事件控制块的列表中移除 */ } #if (OS_EVENT_MULTI_EN > 0u) if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) {
/* Remove this task from any events' wait lists*/ OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr); } #endif #endif #if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) pnode = ptcb->OSTCBFlagNode; if (pnode != (OS_FLAG_NODE *)0) {
/* If task is waiting on event flag */ OS_FlagUnlink(pnode); /* 从事件标志组中移除 */ } #endif ptcb->OSTCBDly = 0u; /* 禁止时间等待 */ ptcb->OSTCBStat = OS_STAT_RDY; /* Prevent task from being resumed */ ptcb->OSTCBStatPend = OS_STAT_PEND_OK; if (OSLockNesting < 255u) {
/* Make sure we don't context switch */ OSLockNesting++; } OS_EXIT_CRITICAL(); /* Enabling INT. ignores next instruc. */ OS_Dummy(); /* ... Dummy ensures that INTs will be */ OS_ENTER_CRITICAL(); /* ... disabled HERE! */ if (OSLockNesting > 0u) {
/* Remove context switch lock */ OSLockNesting--; } OSTaskDelHook(ptcb); /* Call user defined hook */ OSTaskCtr--; /* One less task being managed */ OSTCBPrioTbl[prio] = (OS_TCB *)0; /* Clear old priority entry */ if (ptcb->OSTCBPrev == (OS_TCB *)0) {
/* Remove from TCB chain */ ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0; OSTCBList = ptcb->OSTCBNext; } else {
ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext; ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev; } ptcb->OSTCBNext = OSTCBFreeList; /* Return TCB to free TCB list */ OSTCBFreeList = ptcb; #if OS_TASK_NAME_EN > 0u ptcb->OSTCBTaskName = (INT8U *)(void *)"?"; #endif OS_EXIT_CRITICAL(); if (OSRunning == OS_TRUE) {
OS_Sched(); /* Find new highest priority task */ } return (OS_ERR_NONE); } #endif 5、挂起任务,OS_TaskSuspend()和恢复挂起任务OSTaskResume() (1)这个函数是必须进行说明的一个函数,因为他涉及到任务的状态机。 (2)这个实现挂起的函数主要是删除就绪表中的位图的相应优先级的那个位进行置0的操作。 (3)然后将任务的相应的状态进行赋值为挂起的状态。 (4)最后在最后要进行任务的调度的操作,如果当前是这个任务在进行的话,要切换到别的任务中继续去运行。 INT8U OSTaskSuspend (INT8U prio) {
BOOLEAN self; OS_TCB *ptcb; if (prio == OS_IDLE_PRIO) {
(1) return (OS_TASK_SUSPEND_IDLE); } if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) {
(2) return (OS_PRIO_INVALID); } OS_ENTER_CRITICAL(); if (prio == OS_PRIO_SELF) {
(3) prio = OSTCBCur->OSTCBPrio; self = TRUE; } else if (prio == OSTCBCur->OSTCBPrio) {
(4) self = TRUE; } else {
self = FALSE; } if ((ptcb = OSTCBPrioTbl[prio]) == (OS_TCB *)0) {
(5) OS_EXIT_CRITICAL(); return (OS_TASK_SUSPEND_PRIO); } else {
if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) {
(6)//就绪表中的相应的位置0操作 OSRdyGrp &= ~ptcb->OSTCBBitY; } ptcb->OSTCBStat |= OS_STAT_SUSPEND; (7) 把TCB的状态也设置为挂起的状态标志位 OS_EXIT_CRITICAL(); if (self == TRUE) {
(8) OSSched(); } return (OS_NO_ERR); } }
OSTaskResume()恢复任务的源码也是差不多的,就是一个是对就绪表上面的内容进行置0的操作,一个是对就绪表的内容进行置1的操作。
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/227024.html原文链接:https://javaforall.net
