OS_MSG_QTY OSQFlush (OS_Q *p_q, OS_ERR *p_err) { OS_MSG_QTY entries; CPU_SR_ALLOC(); #ifdef OS_SAFETY_CRITICAL if (p_err == (OS_ERR *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return ((OS_MSG_QTY)0); } #endif #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Can't flush a message queue from an ISR */ *p_err = OS_ERR_FLUSH_ISR; return ((OS_MSG_QTY)0); } #endif #if OS_CFG_ARG_CHK_EN > 0u if (p_q == (OS_Q *)0) { /* Validate arguments */ *p_err = OS_ERR_OBJ_PTR_NULL; return ((OS_MSG_QTY)0); } #endif #if OS_CFG_OBJ_TYPE_CHK_EN > 0u if (p_q->Type != OS_OBJ_TYPE_Q) { /* Make sure message queue was created */ *p_err = OS_ERR_OBJ_TYPE; return ((OS_MSG_QTY)0); } #endif OS_CRITICAL_ENTER(); entries = OS_MsgQFreeAll(&p_q->MsgQ); /* Return all OS_MSGs to the OS_MSG pool */ OS_CRITICAL_EXIT(); *p_err = OS_ERR_NONE; return ((OS_MSG_QTY)entries); }
/*FUNCTION********************************************************************** * * Function Name : OSA_MsgQDestroy * Description : This function is used to destroy the message queue. * Return kStatus_OSA_Success if the message queue is destroyed successfully, * otherwise return kStatus_OSA_Error. * *END**************************************************************************/ osa_status_t OSA_MsgQDestroy(msg_queue_handler_t handler) { OS_ERR err; #if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL) CPU_SR cpu_sr = (CPU_SR)0; #endif OSQDel(&(handler->queue), OS_OPT_DEL_ALWAYS, &err); if (OS_ERR_NONE == err) { OS_CRITICAL_ENTER(); OSMemQty--; OS_CRITICAL_EXIT_NO_SCHED(); return kStatus_OSA_Success; } else { return kStatus_OSA_Error; } }
void OS_TickTask (void *p_arg) { OS_ERR err; CPU_TS ts; CPU_TS ts_delta; CPU_TS ts_delta_dly; CPU_TS ts_delta_timeout; CPU_SR_ALLOC(); (void)&p_arg; /* Prevent compiler warning */ while (DEF_ON) { (void)OSTaskSemPend((OS_TICK )0, (OS_OPT )OS_OPT_PEND_BLOCKING, (CPU_TS *)&ts, (OS_ERR *)&err); /* Wait for signal from tick interrupt */ if (err == OS_ERR_NONE) { if (OSRunning == OS_STATE_OS_RUNNING) { OS_CRITICAL_ENTER(); OSTickCtr++; /* Keep track of the number of ticks */ #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u)) TRACE_OS_TICK_INCREMENT(OSTickCtr); /* Record the event. */ #endif OS_CRITICAL_EXIT(); ts_delta_dly = OS_TickListUpdateDly(); ts_delta_timeout = OS_TickListUpdateTimeout(); ts_delta = ts_delta_dly + ts_delta_timeout; /* Compute total execution time of list updates */ if (OSTickTaskTimeMax < ts_delta) { OSTickTaskTimeMax = ts_delta; } } } } }
/*-------------------- S e r _ I S R ( ) ------------------------------------- Purpose: Call ServiceRx() to handle Rx interrupts and then call ServiceTx() to handle Tx interrupts. [Added the prologue and epilogue to make this ISR compatible with uC/OS-III.] */ CPU_VOID Ser_ISR(CPU_VOID){ //OS_ERR osErr; /* O/S Error code */ /*---------------------- Prologue ----------------*/ /*Disable Interrupts*/ CPU_SR_ALLOC(); OS_CRITICAL_ENTER(); /*Tell the kernel we are in an ISR*/ OSIntEnter(); /* Enable Interrupts */ OS_CRITICAL_EXIT(); /*---------------------- ISR -------------------*/ ServiceRx(); ServiceTx(); /*---------------------- Epilogue ----------------*/ /*Give the O/S a chance to swap tasks. */ OSIntExit(); }
//开始任务函数 void start_task(void *p_arg) { OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; CPU_Init(); #if OS_CFG_STAT_TASK_EN > 0u OSStatTaskCPUUsageInit(&err); //统计任务 #endif #ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间 CPU_IntDisMeasMaxCurReset(); #endif #if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候 //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms OSSchedRoundRobinCfg(DEF_ENABLED,1,&err); #endif OS_CRITICAL_ENTER(); //进入临界区 OSTaskCreate((OS_TCB * )&Led0TaskTCB, (CPU_CHAR * )"led0 task", (OS_TASK_PTR )led0_task, (void * )0, (OS_PRIO )LED0_TASK_PRIO, (CPU_STK * )&LED0_TASK_STK[0], (CPU_STK_SIZE)LED0_STK_SIZE/10, (CPU_STK_SIZE)LED0_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); OS_TaskSuspend((OS_TCB*)&StartTaskTCB,&err); //挂起开始任务 OS_CRITICAL_EXIT(); //进入临界区 }
static CPU_TS OS_TickListUpdateTimeout (void) { OS_TCB *p_tcb; OS_TICK_LIST *p_list; CPU_TS ts_start; CPU_TS ts_delta_timeout; #if OS_CFG_DBG_EN > 0u OS_OBJ_QTY nbr_updated; #endif CPU_SR_ALLOC(); OS_CRITICAL_ENTER(); /* ======= UPDATE TASKS WAITING WITH TIMEOUT ======= */ ts_start = OS_TS_GET(); #if OS_CFG_DBG_EN > 0u nbr_updated = (OS_OBJ_QTY)0u; #endif p_list = &OSTickListTimeout; p_tcb = p_list->TCB_Ptr; if (p_tcb != (OS_TCB *)0) { p_tcb->TickRemain--; while (p_tcb->TickRemain == 0u) { #if OS_CFG_DBG_EN > 0u nbr_updated++; #endif if (p_tcb->TaskState == OS_TASK_STATE_PEND_TIMEOUT) { #if (OS_MSG_EN > 0u) p_tcb->MsgPtr = (void *)0; p_tcb->MsgSize = (OS_MSG_SIZE)0u; #endif p_tcb->TS = OS_TS_GET(); OS_PendListRemove(p_tcb); /* Remove from wait list */ OS_RdyListInsert(p_tcb); /* Insert the task in the ready list */ p_tcb->TaskState = OS_TASK_STATE_RDY; p_tcb->PendStatus = OS_STATUS_PEND_TIMEOUT; /* Indicate pend timed out */ p_tcb->PendOn = OS_TASK_PEND_ON_NOTHING; /* Indicate no longer pending */ } else if (p_tcb->TaskState == OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED) { #if (OS_MSG_EN > 0u) p_tcb->MsgPtr = (void *)0; p_tcb->MsgSize = (OS_MSG_SIZE)0u; #endif p_tcb->TS = OS_TS_GET(); OS_PendListRemove(p_tcb); /* Remove from wait list */ p_tcb->TaskState = OS_TASK_STATE_SUSPENDED; p_tcb->PendStatus = OS_STATUS_PEND_TIMEOUT; /* Indicate pend timed out */ p_tcb->PendOn = OS_TASK_PEND_ON_NOTHING; /* Indicate no longer pending */ } p_list->TCB_Ptr = p_tcb->TickNextPtr; p_tcb = p_list->TCB_Ptr; /* Get 'p_tcb' again for loop */ if (p_tcb == (OS_TCB *)0) { #if OS_CFG_DBG_EN > 0u p_list->NbrEntries = (OS_OBJ_QTY)0u; #endif break; } else { #if OS_CFG_DBG_EN > 0u p_list->NbrEntries--; #endif p_tcb->TickPrevPtr = (OS_TCB *)0; } } } #if OS_CFG_DBG_EN > 0u p_list->NbrUpdated = nbr_updated; #endif ts_delta_timeout = OS_TS_GET() - ts_start; /* Measure execution time of the update */ OS_CRITICAL_EXIT(); /* ------------------------------------------------- */ return (ts_delta_timeout); }
void OSTimeDlyHMSM (CPU_INT16U hours, CPU_INT16U minutes, CPU_INT16U seconds, CPU_INT32U milli, OS_OPT opt, OS_ERR *p_err) { #if OS_CFG_ARG_CHK_EN > 0u CPU_BOOLEAN opt_invalid; CPU_BOOLEAN opt_non_strict; #endif OS_OPT opt_time; OS_RATE_HZ tick_rate; OS_TICK ticks; CPU_SR_ALLOC(); #ifdef OS_SAFETY_CRITICAL if (p_err == (OS_ERR *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return; } #endif #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u if (OSIntNestingCtr > (OS_NESTING_CTR)0u) { /* Not allowed to call from an ISR */ *p_err = OS_ERR_TIME_DLY_ISR; return; } #endif if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0u) { /* Can't delay when the scheduler is locked */ *p_err = OS_ERR_SCHED_LOCKED; return; } opt_time = opt & OS_OPT_TIME_MASK; /* Retrieve time options only. */ switch (opt_time) { case OS_OPT_TIME_DLY: case OS_OPT_TIME_TIMEOUT: case OS_OPT_TIME_PERIODIC: if (milli == (CPU_INT32U)0u) { /* Make sure we didn't specify a 0 delay */ if (seconds == (CPU_INT16U)0u) { if (minutes == (CPU_INT16U)0u) { if (hours == (CPU_INT16U)0u) { *p_err = OS_ERR_TIME_ZERO_DLY; return; } } } } break; case OS_OPT_TIME_MATCH: break; default: *p_err = OS_ERR_OPT_INVALID; return; } #if OS_CFG_ARG_CHK_EN > 0u /* Validate arguments to be within range */ opt_invalid = DEF_BIT_IS_SET_ANY(opt, ~OS_OPT_TIME_OPTS_MASK); if (opt_invalid == DEF_YES) { *p_err = OS_ERR_OPT_INVALID; return; } opt_non_strict = DEF_BIT_IS_SET(opt, OS_OPT_TIME_HMSM_NON_STRICT); if (opt_non_strict != DEF_YES) { if (milli > (CPU_INT32U)999u) { *p_err = OS_ERR_TIME_INVALID_MILLISECONDS; return; } if (seconds > (CPU_INT16U)59u) { *p_err = OS_ERR_TIME_INVALID_SECONDS; return; } if (minutes > (CPU_INT16U)59u) { *p_err = OS_ERR_TIME_INVALID_MINUTES; return; } if (hours > (CPU_INT16U)99u) { *p_err = OS_ERR_TIME_INVALID_HOURS; return; } } else { if (minutes > (CPU_INT16U)9999u) { *p_err = OS_ERR_TIME_INVALID_MINUTES; return; } if (hours > (CPU_INT16U)999u) { *p_err = OS_ERR_TIME_INVALID_HOURS; return; } } #endif /* Compute the total number of clock ticks required.. */ /* .. (rounded to the nearest tick) */ tick_rate = OSCfg_TickRate_Hz; ticks = ((OS_TICK)hours * (OS_TICK)3600u + (OS_TICK)minutes * (OS_TICK)60u + (OS_TICK)seconds) * tick_rate + (tick_rate * ((OS_TICK)milli + (OS_TICK)500u / tick_rate)) / (OS_TICK)1000u; if (ticks > (OS_TICK)0u) { OS_CRITICAL_ENTER(); OSTCBCurPtr->TaskState = OS_TASK_STATE_DLY; OS_TickListInsert(OSTCBCurPtr, ticks, opt_time, p_err); if (*p_err != OS_ERR_NONE) { OS_CRITICAL_EXIT_NO_SCHED(); return; } OS_RdyListRemove(OSTCBCurPtr); /* Remove current task from ready list */ OS_CRITICAL_EXIT_NO_SCHED(); OSSched(); /* Find next task to run! */ *p_err = OS_ERR_NONE; } else { *p_err = OS_ERR_TIME_ZERO_DLY; } }
void OS_TickListUpdate (void) { CPU_BOOLEAN done; OS_TICK_SPOKE *p_spoke; OS_TCB *p_tcb; OS_TCB *p_tcb_next; OS_TICK_SPOKE_IX spoke; CPU_TS ts_start; CPU_TS ts_end; CPU_SR_ALLOC(); OS_CRITICAL_ENTER(); ts_start = OS_TS_GET(); OSTickCtr++; /* Keep track of the number of ticks */ spoke = (OS_TICK_SPOKE_IX)(OSTickCtr % OSCfg_TickWheelSize); p_spoke = &OSCfg_TickWheel[spoke]; p_tcb = p_spoke->FirstPtr; done = DEF_FALSE; while (done == DEF_FALSE) { if (p_tcb != (OS_TCB *)0) { p_tcb_next = p_tcb->TickNextPtr; /* Point to next TCB to update */ switch (p_tcb->TaskState) { case OS_TASK_STATE_RDY: case OS_TASK_STATE_PEND: case OS_TASK_STATE_SUSPENDED: case OS_TASK_STATE_PEND_SUSPENDED: break; case OS_TASK_STATE_DLY: p_tcb->TickRemain = p_tcb->TickCtrMatch /* Compute time remaining of current TCB */ - OSTickCtr; if (OSTickCtr == p_tcb->TickCtrMatch) { /* Process each TCB that expires */ p_tcb->TaskState = OS_TASK_STATE_RDY; OS_TaskRdy(p_tcb); /* Make task ready to run */ } else { done = DEF_TRUE; /* Don't find a match, we're done! */ } break; case OS_TASK_STATE_PEND_TIMEOUT: p_tcb->TickRemain = p_tcb->TickCtrMatch /* Compute time remaining of current TCB */ - OSTickCtr; if (OSTickCtr == p_tcb->TickCtrMatch) { /* Process each TCB that expires */ #if (OS_MSG_EN > 0u) p_tcb->MsgPtr = (void *)0; p_tcb->MsgSize = (OS_MSG_SIZE)0u; #endif p_tcb->TS = OS_TS_GET(); OS_PendListRemove(p_tcb); /* Remove from wait list */ OS_TaskRdy(p_tcb); p_tcb->TaskState = OS_TASK_STATE_RDY; p_tcb->PendStatus = OS_STATUS_PEND_TIMEOUT; /* Indicate pend timed out */ p_tcb->PendOn = OS_TASK_PEND_ON_NOTHING; /* Indicate no longer pending */ } else { done = DEF_TRUE; /* Don't find a match, we're done! */ } break; case OS_TASK_STATE_DLY_SUSPENDED: p_tcb->TickRemain = p_tcb->TickCtrMatch /* Compute time remaining of current TCB */ - OSTickCtr; if (OSTickCtr == p_tcb->TickCtrMatch) { /* Process each TCB that expires */ p_tcb->TaskState = OS_TASK_STATE_SUSPENDED; OS_TickListRemove(p_tcb); /* Remove from current wheel spoke */ } else { done = DEF_TRUE; /* Don't find a match, we're done! */ } break; case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED: p_tcb->TickRemain = p_tcb->TickCtrMatch /* Compute time remaining of current TCB */ - OSTickCtr; if (OSTickCtr == p_tcb->TickCtrMatch) { /* Process each TCB that expires */ #if (OS_MSG_EN > 0u) p_tcb->MsgPtr = (void *)0; p_tcb->MsgSize = (OS_MSG_SIZE)0u; #endif p_tcb->TS = OS_TS_GET(); OS_PendListRemove(p_tcb); /* Remove from wait list */ OS_TickListRemove(p_tcb); /* Remove from current wheel spoke */ p_tcb->TaskState = OS_TASK_STATE_SUSPENDED; p_tcb->PendStatus = OS_STATUS_PEND_TIMEOUT; /* Indicate pend timed out */ p_tcb->PendOn = OS_TASK_PEND_ON_NOTHING; /* Indicate no longer pending */ } else { done = DEF_TRUE; /* Don't find a match, we're done! */ } break; default: break; } p_tcb = p_tcb_next; } else { done = DEF_TRUE; } } ts_end = OS_TS_GET() - ts_start; /* Measure execution time of tick task */ if (ts_end > OSTickTaskTimeMax) { OSTickTaskTimeMax = ts_end; } OS_CRITICAL_EXIT(); }
//开始任务函数 void start_task(void *p_arg) { OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; CPU_Init(); #if OS_CFG_STAT_TASK_EN > 0u OSStatTaskCPUUsageInit(&err); //统计任务 #endif #ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间 CPU_IntDisMeasMaxCurReset(); #endif #if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候 //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms OSSchedRoundRobinCfg(DEF_ENABLED,1,&err); #endif OS_CRITICAL_ENTER(); //进入临界区 //创建定时器1 OSTmrCreate((OS_TMR *)&tmr1, //定时器1 (CPU_CHAR *)"tmr1", //定时器名字 (OS_TICK )0, //0ms (OS_TICK )50, //50*10=500ms (OS_OPT )OS_OPT_TMR_PERIODIC, //周期模式 (OS_TMR_CALLBACK_PTR)tmr1_callback,//定时器1回调函数 (void *)0, //参数为0 (OS_ERR *)&err); //返回的错误码 //创建主任务 OSTaskCreate((OS_TCB * )&Main_TaskTCB, (CPU_CHAR * )"Main task", (OS_TASK_PTR )main_task, (void * )0, (OS_PRIO )MAIN_TASK_PRIO, (CPU_STK * )&MAIN_TASK_STK[0], (CPU_STK_SIZE)MAIN_STK_SIZE/10, (CPU_STK_SIZE)MAIN_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); //创建MSGDIS任务 OSTaskCreate((OS_TCB * )&Msgdis_TaskTCB, (CPU_CHAR * )"Msgdis task", (OS_TASK_PTR )msgdis_task, (void * )0, (OS_PRIO )MSGDIS_TASK_PRIO, (CPU_STK * )&MSGDIS_TASK_STK[0], (CPU_STK_SIZE)MSGDIS_STK_SIZE/10, (CPU_STK_SIZE)MSGDIS_STK_SIZE, (OS_MSG_QTY )TASK_Q_NUM, //任务Msgdis_task需要使用内建消息队列,消息队列长度为4 (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); OS_CRITICAL_EXIT(); //退出临界区 OSTaskDel((OS_TCB*)0,&err); //删除start_task任务自身 }
void OSMutexCreate (OS_MUTEX *p_mutex, CPU_CHAR *p_name, OS_ERR *p_err) { CPU_SR_ALLOC(); #ifdef OS_SAFETY_CRITICAL if (p_err == (OS_ERR *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return; } #endif #ifdef OS_SAFETY_CRITICAL_IEC61508 if (OSSafetyCriticalStartFlag == DEF_TRUE) { *p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME; return; } #endif #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to be called from an ISR */ *p_err = OS_ERR_CREATE_ISR; return; } #endif #if OS_CFG_ARG_CHK_EN > 0u if (p_mutex == (OS_MUTEX *)0) { /* Validate 'p_mutex' */ *p_err = OS_ERR_OBJ_PTR_NULL; return; } #endif OS_CRITICAL_ENTER(); #if OS_OBJ_TYPE_REQ > 0u p_mutex->Type = OS_OBJ_TYPE_MUTEX; /* Mark the data structure as a mutex */ #endif #if OS_CFG_DBG_EN > 0u p_mutex->NamePtr = p_name; #else (void)&p_name; #endif p_mutex->OwnerTCBPtr = (OS_TCB *)0; p_mutex->OwnerNestingCtr = (OS_NESTING_CTR)0; /* Mutex is available */ p_mutex->TS = (CPU_TS )0; p_mutex->OwnerOriginalPrio = OS_CFG_PRIO_MAX; OS_PendListInit(&p_mutex->PendList); /* Initialize the waiting list */ #if OS_CFG_DBG_EN > 0u OS_MutexDbgListAdd(p_mutex); #endif OSMutexQty++; #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u)) TRACE_OS_MUTEX_CREATE(p_mutex, p_name); /* Record the event. */ #endif OS_CRITICAL_EXIT_NO_SCHED(); *p_err = OS_ERR_NONE; }
void OSSemCreate (OS_SEM *p_sem, CPU_CHAR *p_name, OS_SEM_CTR cnt, OS_ERR *p_err) { CPU_SR_ALLOC(); #ifdef OS_SAFETY_CRITICAL if (p_err == (OS_ERR *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return; } #endif #ifdef OS_SAFETY_CRITICAL_IEC61508 if (OSSafetyCriticalStartFlag == DEF_TRUE) { *p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME; return; } #endif #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to be called from an ISR */ *p_err = OS_ERR_CREATE_ISR; return; } #endif #if OS_CFG_ARG_CHK_EN > 0u if (p_sem == (OS_SEM *)0) { /* Validate 'p_sem' */ *p_err = OS_ERR_OBJ_PTR_NULL; return; } #endif OS_CRITICAL_ENTER(); #if OS_OBJ_TYPE_REQ > 0u p_sem->Type = OS_OBJ_TYPE_SEM; /* Mark the data structure as a semaphore */ #endif p_sem->Ctr = cnt; /* Set semaphore value */ p_sem->TS = (CPU_TS)0; #if OS_CFG_DBG_EN > 0u p_sem->NamePtr = p_name; /* Save the name of the semaphore */ #else (void)&p_name; #endif OS_PendListInit(&p_sem->PendList); /* Initialize the waiting list */ #if OS_CFG_DBG_EN > 0u OS_SemDbgListAdd(p_sem); #endif OSSemQty++; #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u)) TRACE_OS_SEM_CREATE(p_sem, p_name); /* Record the event. */ #endif OS_CRITICAL_EXIT_NO_SCHED(); *p_err = OS_ERR_NONE; }
void OS_StatTask (void *p_arg) { #if OS_CFG_DBG_EN > 0u #if OS_CFG_TASK_PROFILE_EN > 0u OS_CPU_USAGE usage; OS_CYCLES cycles_total; #endif OS_TCB *p_tcb; #endif OS_ERR err; OS_TICK dly; CPU_TS ts_start; CPU_TS ts_end; CPU_SR_ALLOC(); p_arg = p_arg; /* Prevent compiler warning for not using 'p_arg' */ while (OSStatTaskRdy != DEF_TRUE) { OSTimeDly(2u * OSCfg_StatTaskRate_Hz, /* Wait until statistic task is ready */ OS_OPT_TIME_DLY, &err); } OSStatReset(&err); /* Reset statistics */ dly = (OS_TICK)0; /* Compute statistic task sleep delay */ if (OSCfg_TickRate_Hz > OSCfg_StatTaskRate_Hz) { dly = (OS_TICK)(OSCfg_TickRate_Hz / OSCfg_StatTaskRate_Hz); } if (dly == (OS_TICK)0) { dly = (OS_TICK)(OSCfg_TickRate_Hz / (OS_RATE_HZ)10); } while (DEF_ON) { ts_start = OS_TS_GET(); #ifdef CPU_CFG_INT_DIS_MEAS_EN OSIntDisTimeMax = CPU_IntDisMeasMaxGet(); #endif CPU_CRITICAL_ENTER(); /* ----------------- OVERALL CPU USAGE ------------------ */ OSStatTaskCtrRun = OSStatTaskCtr; /* Obtain the of the stat counter for the past .1 second */ OSStatTaskCtr = (OS_TICK)0; /* Reset the stat counter for the next .1 second */ CPU_CRITICAL_EXIT(); if (OSStatTaskCtrMax > OSStatTaskCtrRun) { if (OSStatTaskCtrMax > (OS_TICK)0) { OSStatTaskCPUUsage = (OS_CPU_USAGE)((OS_TICK)100u - 100u * OSStatTaskCtrRun / OSStatTaskCtrMax); } else { OSStatTaskCPUUsage = (OS_CPU_USAGE)100; } } else { OSStatTaskCPUUsage = (OS_CPU_USAGE)100; } OSStatTaskHook(); /* Invoke user definable hook */ #if OS_CFG_DBG_EN > 0u #if OS_CFG_TASK_PROFILE_EN > 0u cycles_total = (OS_CYCLES)0; p_tcb = OSTaskDbgListPtr; while (p_tcb != (OS_TCB *)0) { /* ----------------- TOTAL CYCLES COUNT ----------------- */ OS_CRITICAL_ENTER(); p_tcb->CyclesTotalPrev = p_tcb->CyclesTotal; /* Save accumulated # cycles into a temp variable */ p_tcb->CyclesTotal = (OS_CYCLES)0; /* Reset total cycles for task for next run */ OS_CRITICAL_EXIT(); cycles_total += p_tcb->CyclesTotalPrev;/* Perform sum of all task # cycles */ p_tcb = p_tcb->DbgNextPtr; } #endif #if OS_CFG_TASK_PROFILE_EN > 0u cycles_total /= 100; /* ------------- INDIVIDUAL TASK CPU USAGE -------------- */ #endif p_tcb = OSTaskDbgListPtr; while (p_tcb != (OS_TCB *)0) { #if OS_CFG_TASK_PROFILE_EN > 0u /* Compute execution time of each task */ if (cycles_total > (OS_CYCLES)0) { usage = (OS_CPU_USAGE)(p_tcb->CyclesTotalPrev / cycles_total); if (usage > 100u) { usage = 100u; } } else { usage = 0u; } p_tcb->CPUUsage = usage; #endif #if OS_CFG_STAT_TASK_STK_CHK_EN > 0u OSTaskStkChk( p_tcb, /* Compute stack usage of active tasks only */ &p_tcb->StkFree, &p_tcb->StkUsed, &err); #endif p_tcb = p_tcb->DbgNextPtr; } #endif if (OSStatResetFlag == DEF_TRUE) { /* Check if need to reset statistics */ OSStatResetFlag = DEF_FALSE; OSStatReset(&err); } ts_end = OS_TS_GET() - ts_start; /* Measure execution time of statistic task */ if (ts_end > OSStatTaskTimeMax) { OSStatTaskTimeMax = ts_end; } OSTimeDly(dly, OS_OPT_TIME_DLY, &err); } }
void OSTimeDly (OS_TICK dly, OS_OPT opt, OS_ERR *p_err) { CPU_SR_ALLOC(); #ifdef OS_SAFETY_CRITICAL if (p_err == (OS_ERR *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return; } #endif #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u if (OSIntNestingCtr > (OS_NESTING_CTR)0u) { /* Not allowed to call from an ISR */ *p_err = OS_ERR_TIME_DLY_ISR; return; } #endif if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0u) { /* Can't delay when the scheduler is locked */ *p_err = OS_ERR_SCHED_LOCKED; return; } switch (opt) { case OS_OPT_TIME_DLY: case OS_OPT_TIME_TIMEOUT: case OS_OPT_TIME_PERIODIC: if (dly == (OS_TICK)0u) { /* 0 means no delay! */ *p_err = OS_ERR_TIME_ZERO_DLY; return; } break; case OS_OPT_TIME_MATCH: break; default: *p_err = OS_ERR_OPT_INVALID; return; } OS_CRITICAL_ENTER(); OS_TickListInsertDly(OSTCBCurPtr, dly, opt, p_err); if (*p_err != OS_ERR_NONE) { OS_CRITICAL_EXIT_NO_SCHED(); return; } #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u)) TRACE_OS_TASK_DLY(dly); /* Record the event. */ #endif OS_RdyListRemove(OSTCBCurPtr); /* Remove current task from ready list */ OS_CRITICAL_EXIT_NO_SCHED(); OSSched(); /* Find next task to run! */ *p_err = OS_ERR_NONE; }
//开始任务函数 void start_task(void *p_arg) { OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; CPU_Init(); #if OS_CFG_STAT_TASK_EN > 0u OSStatTaskCPUUsageInit(&err); //统计任务 #endif #ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间 CPU_IntDisMeasMaxCurReset(); #endif #if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候 //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms OSSchedRoundRobinCfg(DEF_ENABLED,1,&err); #endif OS_CRITICAL_ENTER(); //进入临界区 //创建信号量Test_Sem1 OSSemCreate ((OS_SEM* )&Test_Sem1, (CPU_CHAR* )"Test_Sem1", (OS_SEM_CTR)0, (OS_ERR* )&err); //创建信号量Test_Sem2 OSSemCreate ((OS_SEM* )&Test_Sem2, (CPU_CHAR* )"Test_Sem2", (OS_SEM_CTR)0, (OS_ERR* )&err); //创建消息队列 OSQCreate ((OS_Q* )&Test_Q, //消息队列 (CPU_CHAR* )"KEY Msg", //消息队列名称 (OS_MSG_QTY )QUEUE_NUM, //消息队列长度 (OS_ERR* )&err); //错误码 //创建TASK1任务 OSTaskCreate((OS_TCB * )&Task1_TaskTCB, (CPU_CHAR * )"Task1 task", (OS_TASK_PTR )task1_task, (void * )0, (OS_PRIO )TASK1_TASK_PRIO, (CPU_STK * )&TASK1_TASK_STK[0], (CPU_STK_SIZE)TASK1_STK_SIZE/10, (CPU_STK_SIZE)TASK1_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); //创建MULTI测试任务 OSTaskCreate((OS_TCB * )&Multi_TaskTCB, (CPU_CHAR * )"Multi task", (OS_TASK_PTR )multi_task, (void * )0, (OS_PRIO )MULTI_TASK_PRIO, (CPU_STK * )&MULTI_TASK_STK[0], (CPU_STK_SIZE)MULTI_STK_SIZE/10, (CPU_STK_SIZE)MULTI_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); OS_CRITICAL_EXIT(); //退出临界区 OSTaskDel((OS_TCB*)0,&err); //删除start_task任务自身 }
//开始任务函数 void start_task(void *p_arg) { OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; CPU_Init(); #if OS_CFG_STAT_TASK_EN > 0u OSStatTaskCPUUsageInit(&err); //统计任务 #endif #ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间 CPU_IntDisMeasMaxCurReset(); #endif #if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候 //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms OSSchedRoundRobinCfg(DEF_ENABLED,1,&err); #endif OS_CRITICAL_ENTER(); //进入临界区 OSFlagCreate((OS_FLAG_GRP *)&event_flag, (CPU_CHAR *)"event flag", (OS_FLAGS)0x00, (OS_ERR *)&err ); OSTaskCreate((OS_TCB * )&Led0TaskTCB, (CPU_CHAR * )"led0 task", (OS_TASK_PTR )led0_task, (void * )0, (OS_PRIO )LED0_TASK_PRIO, (CPU_STK * )&LED0_TASK_STK[0], (CPU_STK_SIZE)LED0_STK_SIZE/10, (CPU_STK_SIZE)LED0_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); //创建浮点测试任务 OSTaskCreate((OS_TCB * )&FloatTaskTCB, (CPU_CHAR * )"float test task", (OS_TASK_PTR )float_task, (void * )0, (OS_PRIO )FLOAT_TASK_PRIO, (CPU_STK * )&FLOAT_TASK_STK[0], (CPU_STK_SIZE)FLOAT_STK_SIZE/10, (CPU_STK_SIZE)FLOAT_STK_SIZE, (OS_MSG_QTY )5, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); //创建协议处理任务 OSTaskCreate((OS_TCB * )&ProtocolTaskTCB, (CPU_CHAR * )"protocol task", (OS_TASK_PTR )protocol_task, (void * )0, (OS_PRIO )Protocol_TASK_PRIO, (CPU_STK * )&Protocol_TASK_STK[0], (CPU_STK_SIZE)Protocol_STK_SIZE/10, (CPU_STK_SIZE)Protocol_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); OS_CRITICAL_EXIT(); //进入临界区 OSTaskDel(NULL,&err); }
void OSMemCreate (OS_MEM *p_mem, CPU_CHAR *p_name, void *p_addr, OS_MEM_QTY n_blks, OS_MEM_SIZE blk_size, OS_ERR *p_err) { #if OS_CFG_ARG_CHK_EN > 0u CPU_DATA align_msk; #endif OS_MEM_QTY i; OS_MEM_QTY loops; CPU_INT08U *p_blk; void **p_link; CPU_SR_ALLOC(); #ifdef OS_SAFETY_CRITICAL if (p_err == (OS_ERR *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return; } #endif #ifdef OS_SAFETY_CRITICAL_IEC61508 if (OSSafetyCriticalStartFlag == DEF_TRUE) { *p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME; return; } #endif #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to call from an ISR */ *p_err = OS_ERR_MEM_CREATE_ISR; return; } #endif #if OS_CFG_ARG_CHK_EN > 0u if (p_addr == (void *)0) { /* Must pass a valid address for the memory part. */ *p_err = OS_ERR_MEM_INVALID_P_ADDR; return; } if (n_blks < (OS_MEM_QTY)2) { /* Must have at least 2 blocks per partition */ *p_err = OS_ERR_MEM_INVALID_BLKS; return; } if (blk_size < sizeof(void *)) { /* Must contain space for at least a pointer */ *p_err = OS_ERR_MEM_INVALID_SIZE; return; } align_msk = sizeof(void *) - 1u; if (align_msk > 0u) { if (((CPU_ADDR)p_addr & align_msk) != 0u){ /* Must be pointer size aligned */ *p_err = OS_ERR_MEM_INVALID_P_ADDR; return; } if ((blk_size & align_msk) != 0u) { /* Block size must be a multiple address size */ *p_err = OS_ERR_MEM_INVALID_SIZE; return; } } #endif p_link = (void **)p_addr; /* Create linked list of free memory blocks */ p_blk = (CPU_INT08U *)p_addr; loops = n_blks - 1u; for (i = 0u; i < loops; i++) { p_blk += blk_size; *p_link = (void *)p_blk; /* Save pointer to NEXT block in CURRENT block */ p_link = (void **)(void *)p_blk; /* Position to NEXT block */ } *p_link = (void *)0; /* Last memory block points to NULL */ OS_CRITICAL_ENTER(); #if OS_OBJ_TYPE_REQ > 0u p_mem->Type = OS_OBJ_TYPE_MEM; /* Set the type of object */ #endif #if OS_CFG_DBG_EN > 0u p_mem->NamePtr = p_name; /* Save name of memory partition */ #else (void)&p_name; #endif p_mem->AddrPtr = p_addr; /* Store start address of memory partition */ p_mem->FreeListPtr = p_addr; /* Initialize pointer to pool of free blocks */ p_mem->NbrFree = n_blks; /* Store number of free blocks in MCB */ p_mem->NbrMax = n_blks; p_mem->BlkSize = blk_size; /* Store block size of each memory blocks */ #if OS_CFG_DBG_EN > 0u OS_MemDbgListAdd(p_mem); #endif OSMemQty++; #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u)) TRACE_OS_MEM_CREATE(p_mem, p_name); /* Record the event. */ #endif OS_CRITICAL_EXIT_NO_SCHED(); *p_err = OS_ERR_NONE; }
void OSTmrCreate (OS_TMR *p_tmr, CPU_CHAR *p_name, OS_TICK dly, OS_TICK period, OS_OPT opt, OS_TMR_CALLBACK_PTR p_callback, void *p_callback_arg, OS_ERR *p_err) { CPU_SR_ALLOC(); #ifdef OS_SAFETY_CRITICAL if (p_err == (OS_ERR *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return; } #endif #ifdef OS_SAFETY_CRITICAL_IEC61508 if (OSSafetyCriticalStartFlag == DEF_TRUE) { *p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME; return; } #endif #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to call from an ISR */ *p_err = OS_ERR_TMR_ISR; return; } #endif #if OS_CFG_ARG_CHK_EN > 0u if (p_tmr == (OS_TMR *)0) { /* Validate 'p_tmr' */ *p_err = OS_ERR_OBJ_PTR_NULL; return; } switch (opt) { case OS_OPT_TMR_PERIODIC: if (period == (OS_TICK)0) { *p_err = OS_ERR_TMR_INVALID_PERIOD; return; } break; case OS_OPT_TMR_ONE_SHOT: if (dly == (OS_TICK)0) { *p_err = OS_ERR_TMR_INVALID_DLY; return; } break; default: *p_err = OS_ERR_OPT_INVALID; return; } #endif OS_CRITICAL_ENTER(); p_tmr->State = (OS_STATE )OS_TMR_STATE_STOPPED; /* Initialize the timer fields */ p_tmr->Type = (OS_OBJ_TYPE )OS_OBJ_TYPE_TMR; p_tmr->NamePtr = (CPU_CHAR *)p_name; p_tmr->Dly = (OS_TICK )dly; p_tmr->Match = (OS_TICK )0; p_tmr->Remain = (OS_TICK )0; p_tmr->Period = (OS_TICK )period; p_tmr->Opt = (OS_OPT )opt; p_tmr->CallbackPtr = (OS_TMR_CALLBACK_PTR)p_callback; p_tmr->CallbackPtrArg = (void *)p_callback_arg; p_tmr->NextPtr = (OS_TMR *)0; p_tmr->PrevPtr = (OS_TMR *)0; #if OS_CFG_DBG_EN > 0u OS_TmrDbgListAdd(p_tmr); #endif OSTmrQty++; /* Keep track of the number of timers created */ OS_CRITICAL_EXIT_NO_SCHED(); *p_err = OS_ERR_NONE; }
static CPU_TS OS_TickListUpdateTimeout (void) { OS_TCB *p_tcb; OS_TICK_LIST *p_list; CPU_TS ts_start; CPU_TS ts_delta_timeout; #if OS_CFG_DBG_EN > 0u OS_OBJ_QTY nbr_updated; #endif #if OS_CFG_MUTEX_EN > 0u OS_TCB *p_tcb_owner; OS_PRIO prio_new; #endif CPU_SR_ALLOC(); OS_CRITICAL_ENTER(); /* ======= UPDATE TASKS WAITING WITH TIMEOUT ======= */ ts_start = OS_TS_GET(); #if OS_CFG_DBG_EN > 0u nbr_updated = (OS_OBJ_QTY)0u; #endif p_list = &OSTickListTimeout; p_tcb = p_list->TCB_Ptr; if (p_tcb != (OS_TCB *)0) { p_tcb->TickRemain--; while (p_tcb->TickRemain == 0u) { #if OS_CFG_DBG_EN > 0u nbr_updated++; #endif #if OS_CFG_MUTEX_EN > 0u p_tcb_owner = (OS_TCB *)0; if (p_tcb->PendOn == OS_TASK_PEND_ON_MUTEX) { p_tcb_owner = ((OS_MUTEX *)p_tcb->PendDataTblPtr->PendObjPtr)->OwnerTCBPtr; } #endif #if (OS_MSG_EN > 0u) p_tcb->MsgPtr = (void *)0; p_tcb->MsgSize = (OS_MSG_SIZE)0u; #endif p_tcb->TS = OS_TS_GET(); OS_PendListRemove(p_tcb); /* Remove from wait list */ if (p_tcb->TaskState == OS_TASK_STATE_PEND_TIMEOUT) { OS_RdyListInsert(p_tcb); /* Insert the task in the ready list */ p_tcb->TaskState = OS_TASK_STATE_RDY; } else if (p_tcb->TaskState == OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED) { p_tcb->TaskState = OS_TASK_STATE_SUSPENDED; } p_tcb->PendStatus = OS_STATUS_PEND_TIMEOUT; /* Indicate pend timed out */ p_tcb->PendOn = OS_TASK_PEND_ON_NOTHING; /* Indicate no longer pending */ #if OS_CFG_MUTEX_EN > 0u if(p_tcb_owner != (OS_TCB *)0) { if ((p_tcb_owner->Prio != p_tcb_owner->BasePrio) && (p_tcb_owner->Prio == p_tcb->Prio)) { /* Has the owner inherited a priority? */ prio_new = OS_MutexGrpPrioFindHighest(p_tcb_owner); prio_new = prio_new > p_tcb_owner->BasePrio ? p_tcb_owner->BasePrio : prio_new; if(prio_new != p_tcb_owner->Prio) { OS_TaskChangePrio(p_tcb_owner, prio_new); #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u)) TRACE_OS_MUTEX_TASK_PRIO_DISINHERIT(p_tcb_owner, p_tcb_owner->Prio) #endif } } }
void OSQCreate (OS_Q *p_q, CPU_CHAR *p_name, OS_MSG_QTY max_qty, OS_ERR *p_err) { CPU_SR_ALLOC(); #ifdef OS_SAFETY_CRITICAL if (p_err == (OS_ERR *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return; } #endif #ifdef OS_SAFETY_CRITICAL_IEC61508 if (OSSafetyCriticalStartFlag == DEF_TRUE) { *p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME; return; } #endif #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to be called from an ISR */ *p_err = OS_ERR_CREATE_ISR; return; } #endif #if OS_CFG_ARG_CHK_EN > 0u if (p_q == (OS_Q *)0) { /* Validate arguments */ *p_err = OS_ERR_OBJ_PTR_NULL; return; } if (max_qty == (OS_MSG_QTY)0) { /* Cannot specify a zero size queue */ *p_err = OS_ERR_Q_SIZE; return; } #endif OS_CRITICAL_ENTER(); #if OS_OBJ_TYPE_REQ > 0u p_q->Type = OS_OBJ_TYPE_Q; /* Mark the data structure as a message queue */ #endif #if OS_CFG_DBG_EN > 0u p_q->NamePtr = p_name; #else (void)&p_name; #endif OS_MsgQInit(&p_q->MsgQ, /* Initialize the queue */ max_qty); OS_PendListInit(&p_q->PendList); /* Initialize the waiting list */ #if OS_CFG_DBG_EN > 0u OS_QDbgListAdd(p_q); #endif OSQQty++; /* One more queue created */ #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u)) TRACE_OS_Q_CREATE(p_q, p_name); /* Record the event. */ #endif OS_CRITICAL_EXIT_NO_SCHED(); *p_err = OS_ERR_NONE; }
OS_OBJ_QTY OSMutexDel (OS_MUTEX *p_mutex, OS_OPT opt, OS_ERR *p_err) { OS_OBJ_QTY cnt; OS_OBJ_QTY nbr_tasks; OS_PEND_DATA *p_pend_data; OS_PEND_LIST *p_pend_list; OS_TCB *p_tcb; OS_TCB *p_tcb_owner; CPU_TS ts; CPU_SR_ALLOC(); #ifdef OS_SAFETY_CRITICAL if (p_err == (OS_ERR *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return ((OS_OBJ_QTY)0); } #endif #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to delete a mutex from an ISR */ *p_err = OS_ERR_DEL_ISR; return ((OS_OBJ_QTY)0); } #endif #if OS_CFG_ARG_CHK_EN > 0u if (p_mutex == (OS_MUTEX *)0) { /* Validate 'p_mutex' */ *p_err = OS_ERR_OBJ_PTR_NULL; return ((OS_OBJ_QTY)0); } switch (opt) { /* Validate 'opt' */ case OS_OPT_DEL_NO_PEND: case OS_OPT_DEL_ALWAYS: break; default: *p_err = OS_ERR_OPT_INVALID; return ((OS_OBJ_QTY)0); } #endif #if OS_CFG_OBJ_TYPE_CHK_EN > 0u if (p_mutex->Type != OS_OBJ_TYPE_MUTEX) { /* Make sure mutex was created */ *p_err = OS_ERR_OBJ_TYPE; return ((OS_OBJ_QTY)0); } #endif OS_CRITICAL_ENTER(); p_pend_list = &p_mutex->PendList; cnt = p_pend_list->NbrEntries; nbr_tasks = cnt; switch (opt) { case OS_OPT_DEL_NO_PEND: /* Delete mutex only if no task waiting */ if (nbr_tasks == (OS_OBJ_QTY)0) { #if OS_CFG_DBG_EN > 0u OS_MutexDbgListRemove(p_mutex); #endif OSMutexQty--; #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u)) TRACE_OS_MUTEX_DEL(p_mutex); /* Record the event. */ #endif OS_MutexClr(p_mutex); OS_CRITICAL_EXIT(); *p_err = OS_ERR_NONE; } else { OS_CRITICAL_EXIT(); *p_err = OS_ERR_TASK_WAITING; } break; case OS_OPT_DEL_ALWAYS: /* Always delete the mutex */ p_tcb_owner = p_mutex->OwnerTCBPtr; /* Did we had to change the prio of owner? */ if ((p_tcb_owner != (OS_TCB *)0) && (p_tcb_owner->Prio != p_mutex->OwnerOriginalPrio)) { switch (p_tcb_owner->TaskState) { /* yes */ case OS_TASK_STATE_RDY: OS_RdyListRemove(p_tcb_owner); p_tcb_owner->Prio = p_mutex->OwnerOriginalPrio; /* Lower owner's prio back */ #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u)) TRACE_OS_MUTEX_TASK_PRIO_DISINHERIT(p_tcb_owner, p_tcb_owner->Prio) #endif OS_PrioInsert(p_tcb_owner->Prio); OS_RdyListInsertTail(p_tcb_owner); /* Insert owner in ready list at new prio */ break; case OS_TASK_STATE_DLY: case OS_TASK_STATE_SUSPENDED: case OS_TASK_STATE_DLY_SUSPENDED: p_tcb_owner->Prio = p_mutex->OwnerOriginalPrio; /* Not in any pend list, change the prio */ #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u)) TRACE_OS_MUTEX_TASK_PRIO_DISINHERIT(p_tcb_owner, p_tcb_owner->Prio) #endif break; case OS_TASK_STATE_PEND: case OS_TASK_STATE_PEND_TIMEOUT: case OS_TASK_STATE_PEND_SUSPENDED: case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED: OS_PendListChangePrio(p_tcb_owner, /* Owner is pending on another object */ p_mutex->OwnerOriginalPrio); #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u)) TRACE_OS_MUTEX_TASK_PRIO_DISINHERIT(p_tcb_owner, p_tcb_owner->Prio) #endif break; default: OS_CRITICAL_EXIT(); *p_err = OS_ERR_STATE_INVALID; return ((OS_OBJ_QTY)0); } } ts = OS_TS_GET(); /* Get timestamp */ while (cnt > 0u) { /* Remove all tasks from the pend list */ p_pend_data = p_pend_list->HeadPtr; p_tcb = p_pend_data->TCBPtr; OS_PendObjDel((OS_PEND_OBJ *)((void *)p_mutex), p_tcb, ts); cnt--; } #if OS_CFG_DBG_EN > 0u OS_MutexDbgListRemove(p_mutex); #endif OSMutexQty--; #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u)) TRACE_OS_MUTEX_DEL(p_mutex); /* Record the event. */ #endif OS_MutexClr(p_mutex); OS_CRITICAL_EXIT_NO_SCHED(); OSSched(); /* Find highest priority task ready to run */ *p_err = OS_ERR_NONE; break; default: OS_CRITICAL_EXIT(); *p_err = OS_ERR_OPT_INVALID; break; } return (nbr_tasks); }