//使等待事件标志的任务进入就绪态 MAKE TASK READY-TO-RUN, EVENT(s) OCCURRED //描述: 这个函数是 uC/OS-II内部函数. // 该处理在uC/OS-II中是一个标准过程,这个惟一的不同在于,事件标志组中当一个任务等待的 // 事件标志发生后,为该任务建立的OS_FLAG_NODE数据结构就没有用处了;所以这里把这个任务 // 的OS_FLAG_NODE数据结构从等待任务链表中删除掉,同时还会把这个OS_FLAG_NODE数据结构指 // 针,从该任务的事件控制块中删除掉。 //参数: pnode 标志节点is a pointer to a structure which contains data about the task // waiting forevent flag bit(s) to be set. // flags_rdy contains the bit pattern of the event flags that cause the task to become // ready-to-run. //返回: 无 //访问: 本函数在OS_FLAG.C的OSFlagsPost() 中 //注意: 1) 即使任务等待的事件标志都发生了,任务已经从事件标志组的等待任务链表中被删除了,但 // 是这个任务可能由于其它的原因而不能进入就绪态; // 2) 这个函数是uC/OS-II内部函数,你应用的时候不要调用它. static BOOLEAN OS_FlagTaskRdy (OS_FLAG_NODE *pnode, OS_FLAGS flags_rdy) { OS_TCB *ptcb; BOOLEAN sched; ptcb = (OS_TCB *)pnode->OSFlagNodeTCB; /* Point to TCB of waiting task */ ptcb->OSTCBDly = 0; ptcb->OSTCBFlagsRdy = flags_rdy; ptcb->OSTCBStat &= ~OS_STAT_FLAG; if (ptcb->OSTCBStat == OS_STAT_RDY) { /* Put task into ready list */ OSRdyGrp |= ptcb->OSTCBBitY; OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; sched = TRUE; } else { sched = FALSE; } OS_FlagUnlink(pnode); return (sched); }
//等待事件标志组的事件标志位(事件组指针、需要检查的标志位、等待事件标志位的方式、允许等待 //的时钟节拍、出错代码的时钟节拍) OS_FLAGS OSFlagPend (OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U wait_type, INT16U timeout, INT8U *err) { #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; #endif OS_FLAG_NODE node; OS_FLAGS flags_cur; OS_FLAGS flags_rdy; BOOLEAN consume; if (OSIntNesting > 0) { /* See if called from ISR ... */ *err = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ return ((OS_FLAGS)0); } #if OS_ARG_CHK_EN > 0 if (pgrp == (OS_FLAG_GRP *)0) { /* Validate 'pgrp' */ *err = OS_FLAG_INVALID_PGRP; return ((OS_FLAGS)0); } if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Validate event block type */ *err = OS_ERR_EVENT_TYPE; return ((OS_FLAGS)0); } #endif if (wait_type & OS_FLAG_CONSUME) { /* See if we need to consume the flags */ wait_type &= ~OS_FLAG_CONSUME; consume = TRUE; } else { consume = FALSE; } /*$PAGE*/ OS_ENTER_CRITICAL(); switch (wait_type) { case OS_FLAG_WAIT_SET_ALL: /* See if all required flags are set */ flags_rdy = pgrp->OSFlagFlags & flags; /* Extract only the bits we want */ if (flags_rdy == flags) { /* Must match ALL the bits that we want */ if (consume == TRUE) { /* See if we need to consume the flags */ pgrp->OSFlagFlags &= ~flags_rdy; /* Clear ONLY the flags that we wanted */ } flags_cur = pgrp->OSFlagFlags; /* Will return the state of the group */ OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */ *err = OS_NO_ERR; return (flags_cur); } else { /* Block task until events occur or timeout */ OS_FlagBlock(pgrp, &node, flags, wait_type, timeout); OS_EXIT_CRITICAL(); } break; case OS_FLAG_WAIT_SET_ANY: flags_rdy = pgrp->OSFlagFlags & flags; /* Extract only the bits we want */ if (flags_rdy != (OS_FLAGS)0) { /* See if any flag set */ if (consume == TRUE) { /* See if we need to consume the flags */ pgrp->OSFlagFlags &= ~flags_rdy; /* Clear ONLY the flags that we got */ } flags_cur = pgrp->OSFlagFlags; /* Will return the state of the group */ OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */ *err = OS_NO_ERR; return (flags_cur); } else { /* Block task until events occur or timeout */ OS_FlagBlock(pgrp, &node, flags, wait_type, timeout); OS_EXIT_CRITICAL(); } break; #if OS_FLAG_WAIT_CLR_EN > 0 case OS_FLAG_WAIT_CLR_ALL: /* See if all required flags are cleared */ flags_rdy = ~pgrp->OSFlagFlags & flags; /* Extract only the bits we want */ if (flags_rdy == flags) { /* Must match ALL the bits that we want */ if (consume == TRUE) { /* See if we need to consume the flags */ pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we wanted */ } flags_cur = pgrp->OSFlagFlags; /* Will return the state of the group */ OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */ *err = OS_NO_ERR; return (flags_cur); } else { /* Block task until events occur or timeout */ OS_FlagBlock(pgrp, &node, flags, wait_type, timeout); OS_EXIT_CRITICAL(); } break; case OS_FLAG_WAIT_CLR_ANY: flags_rdy = ~pgrp->OSFlagFlags & flags; /* Extract only the bits we want */ if (flags_rdy != (OS_FLAGS)0) { /* See if any flag cleared */ if (consume == TRUE) { /* See if we need to consume the flags */ pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we got */ } flags_cur = pgrp->OSFlagFlags; /* Will return the state of the group */ OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */ *err = OS_NO_ERR; return (flags_cur); } else { /* Block task until events occur or timeout */ OS_FlagBlock(pgrp, &node, flags, wait_type, timeout); OS_EXIT_CRITICAL(); } break; #endif default: OS_EXIT_CRITICAL(); flags_cur = (OS_FLAGS)0; *err = OS_FLAG_ERR_WAIT_TYPE; return (flags_cur); } OS_Sched(); /* Find next HPT ready to run */ OS_ENTER_CRITICAL(); if (OSTCBCur->OSTCBStat & OS_STAT_FLAG) { /* Have we timed-out? */ OS_FlagUnlink(&node); OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Yes, make task ready-to-run */ OS_EXIT_CRITICAL(); flags_cur = (OS_FLAGS)0; *err = OS_TIMEOUT; /* Indicate that we timed-out waiting */ } else { if (consume == TRUE) { /* See if we need to consume the flags */ switch (wait_type) { case OS_FLAG_WAIT_SET_ALL: case OS_FLAG_WAIT_SET_ANY: /* Clear ONLY the flags we got */ pgrp->OSFlagFlags &= ~OSTCBCur->OSTCBFlagsRdy; break; #if OS_FLAG_WAIT_CLR_EN > 0 case OS_FLAG_WAIT_CLR_ALL: case OS_FLAG_WAIT_CLR_ANY: /* Set ONLY the flags we got */ pgrp->OSFlagFlags |= OSTCBCur->OSTCBFlagsRdy; break; #endif } } flags_cur = pgrp->OSFlagFlags; OS_EXIT_CRITICAL(); *err = OS_NO_ERR; /* Event(s) must have occurred */ } return (flags_cur); }
INT8U OSTaskDel (INT8U prio) { #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; #endif #if OS_EVENT_EN > 0 OS_EVENT *pevent; #endif #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) OS_FLAG_NODE *pnode; #endif OS_TCB *ptcb; BOOLEAN self; if (OSIntNesting > 0) { /* See if trying to delete from ISR */ return (OS_TASK_DEL_ISR); } #if OS_ARG_CHK_EN > 0 if (prio == OS_IDLE_PRIO) { /* Not allowed to delete idle task */ return (OS_TASK_DEL_IDLE); } if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) { /* Task priority valid ? */ return (OS_PRIO_INVALID); } #endif 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 */ if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00) { /* Make task not ready */ OSRdyGrp &= ~ptcb->OSTCBBitY; } #if OS_EVENT_EN > 0 pevent = ptcb->OSTCBEventPtr; if (pevent != (OS_EVENT *)0) { /* If task is waiting on event */ if ((pevent->OSEventTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) { /* ... remove task from */ pevent->OSEventGrp &= ~ptcb->OSTCBBitY; /* ... event ctrl block */ } } #endif #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) pnode = ptcb->OSTCBFlagNode; if (pnode != (OS_FLAG_NODE *)0) { /* If task is waiting on event flag */ OS_FlagUnlink(pnode); /* Remove from wait list */ } #endif ptcb->OSTCBDly = 0; /* Prevent OSTimeTick() from updating */ ptcb->OSTCBStat = OS_STAT_RDY; /* Prevent task from being resumed */ if (OSLockNesting < 255) { OSLockNesting++; } OS_EXIT_CRITICAL(); /* Enabling INT. ignores next instruc. */ OS_Dummy(); /* ... Dummy ensures that INTs will be */ OS_ENTER_CRITICAL(); /* ... disabled HERE! */ if (OSLockNesting > 0) { 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; OS_EXIT_CRITICAL(); OS_Sched(); /* Find new highest priority task */ return (OS_NO_ERR); } OS_EXIT_CRITICAL(); return (OS_TASK_DEL_ERR); }
// CODE_SECTION(OSTaskDel,".UserProgramCode") INT8U OSTaskDel( INT8U prio ) { #if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) OS_FLAG_NODE *pnode; #endif OS_TCB *ptcb; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0; #endif if ( OSIntNesting > 0 ) /* 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 > 0 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] &= ~ptcb->OSTCBBitX; if ( OSRdyTbl[ptcb->OSTCBY] == 0 ) /* Make task not ready */ { OSRdyGrp &= ~ptcb->OSTCBBitY; } #if (OS_EVENT_EN) if ( ptcb->OSTCBEventPtr != ( OS_EVENT * )0 ) { OS_EventTaskRemove( ptcb, ptcb->OSTCBEventPtr ); /* Remove this task from any event wait list */ } #if (OS_EVENT_MULTI_EN > 0) 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 > 0) && (OS_MAX_FLAGS > 0) pnode = ptcb->OSTCBFlagNode; if ( pnode != ( OS_FLAG_NODE * )0 ) /* If task is waiting on event flag */ { OS_FlagUnlink( pnode ); /* Remove from wait list */ } #endif ptcb->OSTCBDly = 0; /* Prevent OSTimeTick() from updating */ 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 > 0 ) /* 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_SIZE > 1 ptcb->OSTCBTaskName[0] = '?'; /* Unknown name */ ptcb->OSTCBTaskName[1] = OS_ASCII_NUL; #endif OS_EXIT_CRITICAL(); if ( OSRunning == OS_TRUE ) { OS_Sched(); /* Find new highest priority task */ } return ( OS_ERR_NONE ); }
OS_FLAGS OSFlagPend(OS_FLAG_GRP * pgrp, OS_FLAGS flags, INT8U wait_type, INT16U timeout, INT8U * perr) { OS_FLAG_NODE node; OS_FLAGS flags_rdy; INT8U result; INT8U pend_stat; BOOLEAN consume; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0; #endif #if OS_ARG_CHK_EN > 0 if (perr == (INT8U *) 0) { /* Validate 'perr' */ return ((OS_FLAGS) 0); } if (pgrp == (OS_FLAG_GRP *) 0) { /* Validate 'pgrp' */ *perr = OS_ERR_FLAG_INVALID_PGRP; return ((OS_FLAGS) 0); } #endif if (OSIntNesting > 0) { /* See if called from ISR ... */ *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ return ((OS_FLAGS) 0); } if (OSLockNesting > 0) { /* See if called with scheduler locked ... */ *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ return ((OS_FLAGS) 0); } if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Validate event block type */ *perr = OS_ERR_EVENT_TYPE; return ((OS_FLAGS) 0); } result = (INT8U) (wait_type & OS_FLAG_CONSUME); if (result != (INT8U) 0) { /* See if we need to consume the flags */ wait_type &= ~(INT8U) OS_FLAG_CONSUME; consume = OS_TRUE; } else { consume = OS_FALSE; } /*$PAGE*/ OS_ENTER_CRITICAL(); switch (wait_type) { case OS_FLAG_WAIT_SET_ALL: /* See if all required flags are set */ flags_rdy = (OS_FLAGS) (pgrp->OSFlagFlags & flags); /* Extract only the bits we want */ if (flags_rdy == flags) { /* Must match ALL the bits that we want */ if (consume == OS_TRUE) { /* See if we need to consume the flags */ pgrp->OSFlagFlags &= ~flags_rdy; /* Clear ONLY the flags that we wanted */ } OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */ OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */ *perr = OS_ERR_NONE; return (flags_rdy); } else { /* Block task until events occur or timeout */ OS_FlagBlock(pgrp, &node, flags, wait_type, timeout); OS_EXIT_CRITICAL(); } break; case OS_FLAG_WAIT_SET_ANY: flags_rdy = (OS_FLAGS) (pgrp->OSFlagFlags & flags); /* Extract only the bits we want */ if (flags_rdy != (OS_FLAGS) 0) { /* See if any flag set */ if (consume == OS_TRUE) { /* See if we need to consume the flags */ pgrp->OSFlagFlags &= ~flags_rdy; /* Clear ONLY the flags that we got */ } OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */ OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */ *perr = OS_ERR_NONE; return (flags_rdy); } else { /* Block task until events occur or timeout */ OS_FlagBlock(pgrp, &node, flags, wait_type, timeout); OS_EXIT_CRITICAL(); } break; #if OS_FLAG_WAIT_CLR_EN > 0 case OS_FLAG_WAIT_CLR_ALL: /* See if all required flags are cleared */ flags_rdy = (OS_FLAGS) (~pgrp->OSFlagFlags & flags); /* Extract only the bits we want */ if (flags_rdy == flags) { /* Must match ALL the bits that we want */ if (consume == OS_TRUE) { /* See if we need to consume the flags */ pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we wanted */ } OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */ OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */ *perr = OS_ERR_NONE; return (flags_rdy); } else { /* Block task until events occur or timeout */ OS_FlagBlock(pgrp, &node, flags, wait_type, timeout); OS_EXIT_CRITICAL(); } break; case OS_FLAG_WAIT_CLR_ANY: flags_rdy = (OS_FLAGS) (~pgrp->OSFlagFlags & flags); /* Extract only the bits we want */ if (flags_rdy != (OS_FLAGS) 0) { /* See if any flag cleared */ if (consume == OS_TRUE) { /* See if we need to consume the flags */ pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we got */ } OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */ OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */ *perr = OS_ERR_NONE; return (flags_rdy); } else { /* Block task until events occur or timeout */ OS_FlagBlock(pgrp, &node, flags, wait_type, timeout); OS_EXIT_CRITICAL(); } break; #endif default: OS_EXIT_CRITICAL(); flags_rdy = (OS_FLAGS) 0; *perr = OS_ERR_FLAG_WAIT_TYPE; return (flags_rdy); } /*$PAGE*/ OS_Sched(); /* Find next HPT ready to run */ OS_ENTER_CRITICAL(); if (OSTCBCur->OSTCBStatPend != OS_STAT_PEND_OK) { /* Have we timed-out or aborted? */ pend_stat = OSTCBCur->OSTCBStatPend; OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; OS_FlagUnlink(&node); OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Yes, make task ready-to-run */ OS_EXIT_CRITICAL(); flags_rdy = (OS_FLAGS) 0; switch (pend_stat) { case OS_STAT_PEND_ABORT: *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted waiting */ break; case OS_STAT_PEND_TO: default: *perr = OS_ERR_TIMEOUT; /* Indicate that we timed-out waiting */ break; } return (flags_rdy); } flags_rdy = OSTCBCur->OSTCBFlagsRdy; if (consume == OS_TRUE) { /* See if we need to consume the flags */ switch (wait_type) { case OS_FLAG_WAIT_SET_ALL: case OS_FLAG_WAIT_SET_ANY: /* Clear ONLY the flags we got */ pgrp->OSFlagFlags &= ~flags_rdy; break; #if OS_FLAG_WAIT_CLR_EN > 0 case OS_FLAG_WAIT_CLR_ALL: case OS_FLAG_WAIT_CLR_ANY: /* Set ONLY the flags we got */ pgrp->OSFlagFlags |= flags_rdy; break; #endif default: OS_EXIT_CRITICAL(); *perr = OS_ERR_FLAG_WAIT_TYPE; return ((OS_FLAGS) 0); } } OS_EXIT_CRITICAL(); *perr = OS_ERR_NONE; /* Event(s) must have occurred */ return (flags_rdy); }