创建信号量,挂起信号量和发布信号量
创建信号量
void OSSemCreate (OS_SEM *p_sem,CPU_CHAR *p_name,OS_SEM_CTR cnt,OS_ERR *p_err)
{
CPU_SR_ALLOC();//分配CPU状态寄存器,字节为单位;cpu.h中#define CPU_SR cpu_sr = (CPU_SR)0
CPU_CRITICAL_ENTER();//CPU_INT_DIS(); cpu_sr = CPU_SR_Save(); //CPU_SR_Save 是汇编语言,见note1
//CPU_IntDisMeasStart(); //见Note2
p_sem->Type = OS_OBJ_TYPE_SEM;
p_sem->Ctr = cnt; /* Set semaphore value */ //信号量被发起的次数
p_sem->TS = (CPU_TS)0;
p_sem->NamePtr = p_name;
OS_PendListInit(&p_sem->PendList); //初始化任务挂起表
OSSemQty++; //信号量个数
OS_CRITICAL_EXIT_NO_SCHED(); //CPU_IntDisMeasStop(); //见Note3
// CPU_INT_EN(); //CPU_SR_Restore(cpu_sr); //汇编语言,见Note4
}
挂起信号量
OS_SEM_CTR OSSemPend (OS_SEM *p_sem,OS_TICK timeout,OS_OPT opt,CPU_TS *p_ts,OS_ERR *p_err)
{
CPU_SR_ALLOC();
CPU_CRITICAL_ENTER();
if (p_sem->Ctr > (OS_SEM_CTR)0) { /* Resource available? */ //信号量post过?
p_sem->Ctr--; /* Yes, caller may proceed */
*p_ts = p_sem->TS; /* get timestamp of last post */
ctr = p_sem->Ctr;
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_NONE;
return (ctr);
}
//信号量没有post过,执行以下
OS_Pend(&pend_data,(OS_PEND_OBJ *)((void *)p_sem),OS_TASK_PEND_ON_SEM,timeout); /* Block task pending on Semaphore */ //pend类型是信号量,去掉就绪状态,可以设定timeout(插入定时列表),见NOTE5
OS_CRITICAL_EXIT_NO_SCHED();
OSSched(); //任务调度,包括切换
CPU_CRITICAL_ENTER(); //重新进入任务的该函数?
switch (OSTCBCurPtr->PendStatus) {
case OS_STATUS_PEND_OK:
break;
case OS_STATUS_PEND_ABORT:
break;
}
ctr = p_sem->Ctr;
CPU_CRITICAL_EXIT(); return (ctr);}
发布信号量
OS_SEM_CTR OSSemPost (OS_SEM *p_sem,OS_OPT opt,OS_ERR *p_err)
{
OS_Post((OS_PEND_OBJ *)((void *)p_sem),p_tcb,(void *)0,(OS_MSG_SIZE)0,ts);
}
NOTE1
CPU_SR_Save
MRS R0, PRIMASK ; Set prio int mask to mask all (except faults)
CPSID I BX LRNOTE2
void CPU_IntDisMeasStart (void)
{ CPU_IntDisMeasCtr++; if (CPU_IntDisNestCtr == 0u) { /* If ints NOT yet dis'd, ... */ CPU_IntDisMeasStart_cnts = CPU_TS_TmrRd(); /* ... get ints dis'd start time. */ 0xE0001004 } CPU_IntDisNestCtr++;}NOTE3
void CPU_IntDisMeasStop (void)
{ CPU_TS_TMR time_ints_disd_cnts; CPU_IntDisNestCtr--; if (CPU_IntDisNestCtr == 0u) { /* If ints NO longer dis'd, ... */ CPU_IntDisMeasStop_cnts = CPU_TS_TmrRd(); /* ... get ints dis'd stop time & ... */ /* ... calc ints dis'd tot time (see Note #1b2A). */ time_ints_disd_cnts = CPU_IntDisMeasStop_cnts - CPU_IntDisMeasStart_cnts; /* Calc max ints dis'd times. */ if (CPU_IntDisMeasMaxCur_cnts < time_ints_disd_cnts) { CPU_IntDisMeasMaxCur_cnts = time_ints_disd_cnts; } if (CPU_IntDisMeasMax_cnts < time_ints_disd_cnts) { CPU_IntDisMeasMax_cnts = time_ints_disd_cnts; } }}NOTE4
CPU_SR_Restore ; See Note #2.
MSR PRIMASK, R0 BX LRNOTE5
void OS_Pend (OS_PEND_DATA *p_pend_data,OS_PEND_OBJ *p_obj,OS_STATE pending_on,OS_TICK timeout)
{ OSTCBCurPtr->PendOn = pending_on; //正在等待的事件OSTCBCurPtr->PendStatus = OS_STATUS_PEND_OK;
OS_TaskBlock(OSTCBCurPtr, timeout);/* Block the task and add it to the tick list if needed */ //见NOTE6
if (p_obj != (OS_PEND_OBJ *)0) { /* Add the current task to the pend list ... */
p_pend_list = &p_obj->PendList; /* ... if there is an object to pend on */ p_pend_data->PendObjPtr = p_obj; /* Save the pointer to the object pending on */ OS_PendDataInit((OS_TCB *)OSTCBCurPtr, /* Initialize the remaining field */ (OS_PEND_DATA *)p_pend_data, (OS_OBJ_QTY )1); OS_PendListInsertPrio(p_pend_list, /* Insert in the pend list in priority order */ p_pend_data); } else { OSTCBCurPtr->PendDataTblEntries = (OS_OBJ_QTY )0; /* If no object being pended on the clear these fields */ OSTCBCurPtr->PendDataTblPtr = (OS_PEND_DATA *)0; /* ... in the TCB */ }#if OS_CFG_DBG_EN > 0u OS_PendDbgNameAdd(p_obj, OSTCBCurPtr);#endif}
NOTE6
void OS_TaskBlock (OS_TCB *p_tcb,
OS_TICK timeout){ if (timeout > (OS_TICK)0) { /* Add task to tick list if timeout non zero */ OS_TickListInsert(&OSTickListTimeout, p_tcb, timeout); p_tcb->TaskState = OS_TASK_STATE_PEND_TIMEOUT; } else { p_tcb->TaskState = OS_TASK_STATE_PEND; } OS_RdyListRemove(p_tcb); //任务就绪表中去除当前任务}
/* 以下条件都没满足:没有定义,或#define 0;
#ifdef OS_SAFETY_CRITICAL#ifdef OS_SAFETY_CRITICAL_IEC61508 //没有定义
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
#if OS_CFG_ARG_CHK_EN > 0u
*/
}