OS_EVENT *OSMutexCreate (INT8U prio, INT8U *perr) { OS_EVENT *pevent; #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif #ifdef OS_SAFETY_CRITICAL if (perr == (INT8U *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return ((OS_EVENT *)0); } #endif #ifdef OS_SAFETY_CRITICAL_IEC61508 if (OSSafetyCriticalStartFlag == OS_TRUE) { OS_SAFETY_CRITICAL_EXCEPTION(); return ((OS_EVENT *)0); } #endif #if OS_ARG_CHK_EN > 0u if (prio != OS_PRIO_MUTEX_CEIL_DIS) { if (prio >= OS_LOWEST_PRIO) { /* Validate PCP */ *perr = OS_ERR_PRIO_INVALID; return ((OS_EVENT *)0); } } #endif if (OSIntNesting > 0u) { /* See if called from ISR ... */ *perr = OS_ERR_CREATE_ISR; /* ... can't CREATE mutex from an ISR */ return ((OS_EVENT *)0); } OS_ENTER_CRITICAL(); if (prio != OS_PRIO_MUTEX_CEIL_DIS) { if (OSTCBPrioTbl[prio] != (OS_TCB *)0) { /* Mutex priority must not already exist */ OS_EXIT_CRITICAL(); /* Task already exist at priority ... */ *perr = OS_ERR_PRIO_EXIST; /* ... ceiling priority */ return ((OS_EVENT *)0); } OSTCBPrioTbl[prio] = OS_TCB_RESERVED; /* Reserve the table entry */ } pevent = OSEventFreeList; /* Get next free event control block */ if (pevent == (OS_EVENT *)0) { /* See if an ECB was available */ if (prio != OS_PRIO_MUTEX_CEIL_DIS) { OSTCBPrioTbl[prio] = (OS_TCB *)0; /* No, Release the table entry */ } OS_EXIT_CRITICAL(); *perr = OS_ERR_PEVENT_NULL; /* No more event control blocks */ return (pevent); } OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; /* Adjust the free list */ OS_EXIT_CRITICAL(); pevent->OSEventType = OS_EVENT_TYPE_MUTEX; pevent->OSEventCnt = (INT16U)((INT16U)prio << 8u) | OS_MUTEX_AVAILABLE; /* Resource is avail. */ pevent->OSEventPtr = (void *)0; /* No task owning the mutex */ #if OS_EVENT_NAME_EN > 0u pevent->OSEventName = (INT8U *)(void *)"?"; #endif OS_EventWaitListInit(pevent); *perr = OS_ERR_NONE; return (pevent); }
/*$PAGE*/ void OSSemPend (OS_EVENT *pevent, INT32U timeout, INT8U *perr) { #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif #ifdef OS_SAFETY_CRITICAL if (perr == (INT8U *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return; } #endif #if OS_ARG_CHK_EN > 0u if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ *perr = OS_ERR_PEVENT_NULL; return; } #endif if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ *perr = OS_ERR_EVENT_TYPE; return; } if (OSIntNesting > 0u) { /* See if called from ISR ... */ *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ return; } if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ return; } OS_ENTER_CRITICAL(); /* 信号量大于0,则信号量减1,返回 */ if (pevent->OSEventCnt > 0u) { /* If sem. is positive, resource available ... */ pevent->OSEventCnt--; /* ... decrement semaphore only if positive. */ OS_EXIT_CRITICAL(); *perr = OS_ERR_NONE; return; } /* 信号量为0,则把TCB中的状态设置为等待信号量,并设置请求状态为请求OK */ /* Otherwise, must wait until event occurs */ OSTCBCur->OSTCBStat |= OS_STAT_SEM; /* Resource not available, pend on semaphore */ OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* 把等待时限写入TCB */ OSTCBCur->OSTCBDly = timeout; /* Store pend timeout in TCB */ /* 设置TCB中等待的事件 * 设置事件控制块中等待任务列表 * 取消当前任务的就绪状态 */ OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */ OS_EXIT_CRITICAL(); /* 查找最高优先级的就绪任务,并调度运行 */ OS_Sched(); /* Find next highest priority task ready */ /* 执行OS_Sched()后,已经切换到其他任务。执行这里时,已经是信号量有效或者是等待超时了 */ OS_ENTER_CRITICAL(); /* 根据状态设置函数返回值 */ switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */ case OS_STAT_PEND_OK: *perr = OS_ERR_NONE; break; case OS_STAT_PEND_ABORT: *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */ break; case OS_STAT_PEND_TO: default: /* 清除事件等待列表中的当前任务 * 因为OSSemPost()而退出等待状态的任务,会在OSSemPost()中清除事件等待列表中的该任务对应位 * 因为超时而退出等待状态的任务,对应的事件控制块的事件等待列表中该任务不会被清除,需要在这里清除 */ OS_EventTaskRemove(OSTCBCur, pevent); *perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */ break; } /* 设置当前任务控制块状态 */ OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */ OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */ #if (OS_EVENT_MULTI_EN > 0u) OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0; #endif OS_EXIT_CRITICAL(); }
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 OSFlagAccept(OS_FLAG_GRP * pgrp, OS_FLAGS flags, INT8U wait_type, INT8U * perr) { OS_FLAGS flags_rdy; INT8U result; 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 (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 &= ~OS_FLAG_CONSUME; consume = OS_TRUE; } else { consume = OS_FALSE; } /*$PAGE*/ *perr = OS_ERR_NONE; /* Assume NO error until proven otherwise. */ 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 */ } } else { *perr = OS_ERR_FLAG_NOT_RDY; } 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 */ } } else { *perr = OS_ERR_FLAG_NOT_RDY; } 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 */ } } else { *perr = OS_ERR_FLAG_NOT_RDY; } 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 */ } } else { *perr = OS_ERR_FLAG_NOT_RDY; } OS_EXIT_CRITICAL(); break; #endif default: OS_EXIT_CRITICAL(); flags_rdy = (OS_FLAGS) 0; *perr = OS_ERR_FLAG_WAIT_TYPE; break; } return (flags_rdy); }
/* The ambe_decode_wav() function decodes AMBE2+ bits to 80 samples (160 bytes) of 8kHz audio as signed shorts. This hook will optionally print that data to the dmesg buffer, where it can be extracted and recorded on the host. */ int ambe_decode_wav_hook(int *a1, signed int eighty, char *bitbuffer, int a4, short a5, short a6, int a7){ /* This prints the AMBE2+ structure that is to be decoded. The output is decodable with DSD, but it sounds horrible. */ #ifdef AMBEPRINT int ambestate=OS_ENTER_CRITICAL(); short *bits=(short*) bitbuffer; static int i; /* I don't know why, but this output can only be decoded by DSD if half the frames are dropped. The trick is to only decode those when the sixth paramter is zero, ignoring all the ones where that parameter is a one. Strangely enough, we do not skip half the frames of the WAV ouput below. */ if(!a6){ printf("AMBE2+ Corr: "); for(i=0;i<49;i++){ md380_putc(NULL,bits[i]?'1':'0'); } md380_putc(NULL,'\n'); } OS_EXIT_CRITICAL(ambestate); #endif //AMBEPRINT int toret=0xdeadbeef; #ifdef CONFIG_AMBE //First we call the original function. toret=ambe_decode_wav(a1, eighty, bitbuffer, a4, a5, a6, a7); #endif /* Print the parameters printf("ambe_decode_wav(0x%08x, %d, 0x%08x,\n" "%d, %d, %d, 0x%08x);\n", a1, eighty, bitbuffer, a4, a5, a6, a7); */ /* This is very noisy, so we don't enable it by default. It prints the WAV as hex pairs, which will quickly flood the buffer if it isn't cleared in time. */ #ifdef AMBEWAVPRINT //Does this really need to be in a critical section? int wavstate=OS_ENTER_CRITICAL(); //A1 holds audio as signed LE shorts. printf("WAV: "); printhex(a1,160); printf("\n"); OS_EXIT_CRITICAL(wavstate); #endif //AMBEWAVPRINT return toret; }
void *OSQPend (OS_EVENT *pevent, INT32U timeout, INT8U *perr) { void *pmsg; OS_Q *pq; #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif #ifdef OS_SAFETY_CRITICAL if (perr == (INT8U *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); } #endif #if OS_ARG_CHK_EN > 0u if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ *perr = OS_ERR_PEVENT_NULL; return ((void *)0); } #endif if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* Validate event block type */ *perr = OS_ERR_EVENT_TYPE; return ((void *)0); } if (OSIntNesting > 0u) { /* See if called from ISR ... */ *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ return ((void *)0); } if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ return ((void *)0); } OS_ENTER_CRITICAL(); pq = (OS_Q *)pevent->OSEventPtr; /* Point at queue control block */ if (pq->OSQEntries > 0u) { /* See if any messages in the queue */ pmsg = *pq->OSQOut++; /* Yes, extract oldest message from the queue */ pq->OSQEntries--; /* Update the number of entries in the queue */ if (pq->OSQOut == pq->OSQEnd) { /* Wrap OUT pointer if we are at the end of the queue */ pq->OSQOut = pq->OSQStart; } OS_EXIT_CRITICAL(); *perr = OS_ERR_NONE; return (pmsg); /* Return message received */ } OSTCBCur->OSTCBStat |= OS_STAT_Q; /* Task will have to pend for a message to be posted */ OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; OSTCBCur->OSTCBDly = timeout; /* Load timeout into TCB */ OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */ OS_EXIT_CRITICAL(); OS_Sched(); /* Find next highest priority task ready to run */ OS_ENTER_CRITICAL(); switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */ case OS_STAT_PEND_OK: /* Extract message from TCB (Put there by QPost) */ pmsg = OSTCBCur->OSTCBMsg; *perr = OS_ERR_NONE; break; case OS_STAT_PEND_ABORT: pmsg = (void *)0; *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */ break; case OS_STAT_PEND_TO: default: OS_EventTaskRemove(OSTCBCur, pevent); pmsg = (void *)0; *perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */ break; } OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */ OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */ #if (OS_EVENT_MULTI_EN > 0u) OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0; #endif OSTCBCur->OSTCBMsg = (void *)0; /* Clear received message */ OS_EXIT_CRITICAL(); return (pmsg); /* Return received message */ }
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); }
//等待事件标志组的事件标志位(事件组指针、需要检查的标志位、等待事件标志位的方式、允许等待 //的时钟节拍、出错代码的时钟节拍) 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); }
OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *perr) { OS_MEM *pmem; INT8U *pblk; void **plink; INT32U loops; INT32U i; #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif #ifdef OS_SAFETY_CRITICAL if (perr == (INT8U *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); } #endif #ifdef OS_SAFETY_CRITICAL_IEC61508 if (OSSafetyCriticalStartFlag == OS_TRUE) { OS_SAFETY_CRITICAL_EXCEPTION(); } #endif #if OS_ARG_CHK_EN > 0u if (addr == (void *)0) { /* Must pass a valid address for the memory part.*/ *perr = OS_ERR_MEM_INVALID_ADDR; return ((OS_MEM *)0); } if (((INT32U)addr & (sizeof(void *) - 1u)) != 0u){ /* Must be pointer size aligned */ *perr = OS_ERR_MEM_INVALID_ADDR; return ((OS_MEM *)0); } if (nblks < 2u) { /* Must have at least 2 blocks per partition */ *perr = OS_ERR_MEM_INVALID_BLKS; return ((OS_MEM *)0); } if (blksize < sizeof(void *)) { /* Must contain space for at least a pointer */ *perr = OS_ERR_MEM_INVALID_SIZE; return ((OS_MEM *)0); } #endif OS_ENTER_CRITICAL(); pmem = OSMemFreeList; /* Get next free memory partition */ if (OSMemFreeList != (OS_MEM *)0) { /* See if pool of free partitions was empty */ OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList; } OS_EXIT_CRITICAL(); if (pmem == (OS_MEM *)0) { /* See if we have a memory partition */ *perr = OS_ERR_MEM_INVALID_PART; return ((OS_MEM *)0); } plink = (void **)addr; /* Create linked list of free memory blocks */ pblk = (INT8U *)addr; loops = nblks - 1u; for (i = 0u; i < loops; i++) { pblk += blksize; /* Point to the FOLLOWING block */ *plink = (void *)pblk; /* Save pointer to NEXT block in CURRENT block */ plink = (void **)pblk; /* Position to NEXT block */ } *plink = (void *)0; /* Last memory block points to NULL */ pmem->OSMemAddr = addr; /* Store start address of memory partition */ pmem->OSMemFreeList = addr; /* Initialize pointer to pool of free blocks */ pmem->OSMemNFree = nblks; /* Store number of free blocks in MCB */ pmem->OSMemNBlks = nblks; pmem->OSMemBlkSize = blksize; /* Store block size of each memory blocks */ *perr = OS_ERR_NONE; return (pmem); }
void abx_mem_check_free( void *buf) { size_t old_size; INT8U* ptr = buf; int i; DECLARE_CPU_SR; if(ptr == NULL) { printf("abx_mem_free1\n"); while(1); } if ((u32_t)ptr % 4) { printf("abx_mem_free2\n"); while(1); } ptr -= 20; if((u32_t)ptr < ABX_MIN_MEM_PTR) { printf("abx_mem_free3\n"); while(1); } if((u32_t)ptr >= ABX_MAX_MEM_PTR) { printf("abx_mem_free4\n"); while(1); } if(memcmp(ptr, &mem_magic_head, 4)) { printf("abx_mem_free5\n"); while(1); } *(u32_t*)(ptr) = mem_free_magic_head; old_size = *(u32_t*)(ptr+4); if(memcmp(ptr + 20 + old_size, &mem_magic_tail, 4)) { printf("abx_mem_free6\n"); while(1); } memcpy(ptr + 20 + old_size, &mem_free_magic_tail, 4); if(g_abx_mem_used < old_size) { printf("abx_mem_free7\n"); while(1); } //his OS_ENTER_CRITICAL(); for(i=0; i< ABX_MEM_HIS_SIZE; i++) { if(g_abx_mem_his[i] == (abx_mem_struct_type*)ptr) { g_abx_mem_his[i] = NULL; g_abx_mem_his_used--; break; } } g_abx_mem_used -= old_size; OS_EXIT_CRITICAL(); if(i >= ABX_MEM_HIS_SIZE) { printf("abx_mem_free(his1)\n"); while(1); } AVMem_free(ptr); }
void *abx_mem_check_malloc( size_t size, const char* file, INT16U line) { INT8U *ret; size_t new_size; char *sp; int i; DECLARE_CPU_SR; new_size = size + 24; ret = AVMem_kmalloc(new_size); if(ret) { if ((u32_t)ret % 4) { printf("abx_mem_malloc1\n"); while(1); } if((u32_t)ret < ABX_MIN_MEM_PTR) { printf("abx_mem_malloc2\n"); while(1); } if((u32_t)ret >= ABX_MAX_MEM_PTR) { printf("abx_mem_malloc3\n"); while(1); } //his OS_ENTER_CRITICAL(); for(i=0; i< ABX_MEM_HIS_SIZE; i++) { if(g_abx_mem_his[i] == NULL) { g_abx_mem_his[i] = (abx_mem_struct_type*)ret; g_abx_mem_his_used++; break; } } g_abx_mem_used += size; OS_EXIT_CRITICAL(); if(i >= ABX_MEM_HIS_SIZE) { printf("abx_mem_malloc(his1)\n"); while(1); } memcpy(ret, &mem_magic_head, 4); ret += 4; *(u32_t*)ret = size; ret += 4; sp = strrchr((char*)file, '/'); if(!sp) sp = (char*)file; _rstrncpy((char*)ret, sp, 10); ret += 10; *(INT16U*)ret = line; ret += 2; memcpy(ret + size, &mem_magic_tail, 4); } return ret; }
void *abx_mem_check_realloc( void *buf, size_t size, const char* file, INT16U line) { size_t old_size; INT8U* ptr = buf; INT8U* ret; char *sp; int i; DECLARE_CPU_SR; if(ptr) { if ((u32_t)ptr % 4) { printf("abx_mem_realloc1\n"); while(1); } ptr -= 20; if((u32_t)ptr < ABX_MIN_MEM_PTR) { printf("abx_mem_realloc2\n"); while(1); } if((u32_t)ptr >= ABX_MAX_MEM_PTR) { printf("abx_mem_realloc3\n"); while(1); } if(memcmp(ptr, &mem_magic_head, 4)) { printf("abx_mem_realloc4\n"); while(1); } old_size = *(u32_t*)(ptr+4); if(memcmp(ptr + 20 + old_size, &mem_magic_tail, 4)) { printf("abx_mem_realloc5\n"); while(1); } if(g_abx_mem_used < old_size) { printf("abx_mem_realloc6\n"); while(1); } //his OS_ENTER_CRITICAL(); for(i=0; i< ABX_MEM_HIS_SIZE; i++) { if(g_abx_mem_his[i] == (abx_mem_struct_type*)ptr) { break; } } OS_EXIT_CRITICAL(); if(i >= ABX_MEM_HIS_SIZE) { printf("abx_mem_realloc(his1)\n"); while(1); } } ret = AVMem_krealloc(ptr, size); if(ret) { if ((u32_t)ret % 4) { printf("abx_mem_realloc7\n"); while(1); } if((u32_t)ret < ABX_MIN_MEM_PTR) { printf("abx_mem_realloc8\n"); while(1); } if((u32_t)ret >= ABX_MAX_MEM_PTR) { printf("abx_mem_realloc9\n"); while(1); } //his OS_ENTER_CRITICAL(); if(ptr) { if(i >= ABX_MEM_HIS_SIZE) { printf("abx_mem_realloc(his2)\n"); while(1); } g_abx_mem_his[i] = (abx_mem_struct_type*)ret; g_abx_mem_used += size - old_size; OS_EXIT_CRITICAL(); } else { for(i=0; i< ABX_MEM_HIS_SIZE; i++) { if(g_abx_mem_his[i] == NULL) { g_abx_mem_his[i] = (abx_mem_struct_type*)ret; g_abx_mem_his_used++; break; } } g_abx_mem_used += size; OS_EXIT_CRITICAL(); if(i >= ABX_MEM_HIS_SIZE) { printf("abx_mem_realloc(his3)\n"); while(1); } } // memcpy(ret, &mem_magic_head, 4); ret += 4; *(u32_t*)ret = size; ret += 4; sp = strrchr((char*)file, '/'); if(!sp) sp = (char*)file; _rstrncpy((char*)ret, sp, 10); ret += 10; *(INT16U*)ret = line; ret += 2; memcpy(ret + size, &mem_magic_tail, 4); } return ret; }
void Input_Task(void *parg) { u8 err; u8 OK=0; u8 buffer[4]={0}; u8 LEN=0; u8 flag=0; u16 e=0; OS_CPU_SR cpu_sr; (void)parg; for(;;) { OSSemPend(PENIRQ,0,&err); Exti_Set(0); OS_ENTER_CRITICAL(); touch.FLAG=Read_XY_2(&touch.AD_X,&touch.AD_Y); OS_EXIT_CRITICAL(); if(touch.FLAG) { Led_On(1); touch.FLAG=0; touch.LCD_X=CalcXY(touch.AD_X,0); touch.LCD_Y=CalcXY(touch.AD_Y,1); touch.KEY=Get_Key(touch.PID,touch.LCD_X,touch.LCD_Y); if(touch.KEY<=10) { OS_ENTER_CRITICAL(); Set_Color(WHITE,BLACK); if(touch.KEY==10) Show_Char('.',cursor.x,cursor.y); else { Show_Dec(touch.KEY,1,cursor.x,cursor.y); if(LEN<4) { buffer[LEN]=touch.KEY; LEN++; } } if(cursor.x<224) { cursor.x+=8; if(cursor.x>=224) cursor.x=224; } OS_EXIT_CRITICAL(); } else if(touch.KEY==11) { OK++; if(OK==1) { VALUE1=CalcDec(buffer,LEN); Set_Color(BLACK,GREEN); Show_String(">>VALUE1:",2,22); Show_Dec(VALUE1,LEN,82,22); OS_ENTER_CRITICAL(); LCD_Clear(4,121,232,38,WHITE); cursor.x=8; cursor.y=132; OS_EXIT_CRITICAL(); buffer[0]=0; buffer[1]=0; buffer[2]=0; buffer[3]=0; LEN=0; } else if(OK==2) { VALUE2=CalcDec(buffer,LEN); Set_Color(BLACK,GREEN); Show_String(">>VALUE2:",2,38); Show_Dec(VALUE2,LEN,82,38); OS_ENTER_CRITICAL(); LCD_Clear(4,121,232,38,WHITE); cursor.x=8; cursor.y=132; OS_EXIT_CRITICAL(); buffer[0]=0; buffer[1]=0; buffer[2]=0; buffer[3]=0; LEN=0; } else if(OK==3) { VALUE3=CalcDec(buffer,LEN); Set_Color(BLACK,GREEN); Show_String(">>VALUE3:",2,54); Show_Dec(VALUE3,LEN,82,54); OS_ENTER_CRITICAL(); LCD_Clear(4,121,232,38,WHITE); cursor.x=8; cursor.y=132; OS_EXIT_CRITICAL(); buffer[0]=0; buffer[1]=0; buffer[2]=0; buffer[3]=0; LEN=0; } else if(OK==4) { if(VALUE2>0&&VALUE2<=5000) { if(VALUE1<VALUE2&&VALUE1>0) { if(VALUE3>0&&VALUE3<10000) { e=0; Set_Color(BLACK,GREEN); Show_String(">>OK!",2,70); } else { e=1; } } else { e=1; } } else { e=1; } if(e) { Set_Color(BLACK,GREEN); Show_String(">>ERROR!",2,70); } } else if(OK==5) { if(!e) { OK=0; OSTaskSuspend(CURSOR_TASK_PRIO); Show_Main(VALUE1,VALUE2,VALUE3,1); } else { OK=0; e=0; LCD_Clear(2,20,236,100,BLACK); LCD_DrawEdit(input); Set_Cursor(8,132); } VALUE1=0; VALUE2=0; VALUE3=0; } else; } else if(touch.KEY==12) { OS_ENTER_CRITICAL(); if(LEN>0) { LEN--; } if(cursor.x>=8) { LCD_Clear(cursor.x,cursor.y,8,16,WHITE); cursor.x-=8; if(cursor.x<8) { cursor.x=8; } } OS_EXIT_CRITICAL(); } else if(touch.KEY==13) { if(flag==0) { flag=1; button1.str="stop"; button1.len=4; button1.line_color=GREEN; LCD_DrawButton(button1); OSTaskResume(TIMER_TASK_PRIO); } else { flag=0; button1.str="start"; button1.len=5; button1.line_color=BLACK; LCD_DrawButton(button1); OSTaskSuspend(TIMER_TASK_PRIO); } } else if(touch.KEY==14) { OSTaskSuspend(TIMER_TASK_PRIO); Show_KeyMap(); OSTaskResume(CURSOR_TASK_PRIO); } else if(touch.KEY==99)//無效輸入 {} else; OSTimeDlyHMSM(0,0,0,50); Led_Off(1); } Exti_Set(1); } }
int udpRead(u_int ud, void* buf, long len) { unsigned char* d; int rtn; NBuf* b; UDP_QUEUE* q; struct in_addr fromAddr; UBYTE err; // TRACE("udpRead(%d,%p,%ld)\n",ud,buf,len); if (!(udps[ud].flags & FUDP_OPEN)) return -1; d = (unsigned char*)buf; rtn = 0; OSSemPend(udps[ud].sem, 0, &err); if (udps[ud].head == NULL) { return -1; } fromAddr = udps[ud].theirAddr = udps[ud].head->srcAddr; udps[ud].theirPort = udps[ud].head->srcPort; UDPDEBUG(("fromAddr.s_addr = %08X, udps[ud].head->srcAddr.s_addr = %08X\n", fromAddr.s_addr, udps[ud].head->srcAddr.s_addr)); while ((udps[ud].head) && (len) && (fromAddr.s_addr == udps[ud].head->srcAddr.s_addr)) { // Get next nBuf b = udps[ud].head->nBuf; // While we have more buffer to copy out to AND // We have a queued nBuf while ((len) && (b)) { // While we have more buffer space to copy to AND // nBuf is not empty // while ((len) && (b->data != &b->body[b->len])) { while ( (len) && (b->len) ) { // Copy one byte *d++ = *b->data++; b->len--; len--; rtn++; } // If nBuf is empty // if (b->data == &b->body[b->len]) { if (!b->len) { OS_ENTER_CRITICAL(); b = udps[ud].head->nBuf = nFree(b); OS_EXIT_CRITICAL(); } } // If nBuf was freed (we need another one if any) if (b == NULL) { // Get next nBuf in queue q = udps[ud].head; OS_ENTER_CRITICAL(); udps[ud].head = q->next; OS_EXIT_CRITICAL(); free_udp_q(q); #if ONETASK_SUPPORT > 0 #else if (udps[ud].head) OSSemPend(udps[ud].sem, 0, &err); #endif } else { #if ONETASK_SUPPORT > 0 // nBuf was not freed but we have filled our buffer (buf) return rtn; #else OSSemPost(udps[ud].sem); #endif } } if (udps[ud].head == NULL) udps[ud].tail = NULL; return rtn; }
/*$PAGE*/ void *OSMboxPend (OS_EVENT *pevent, INT32U timeout, INT8U *perr) { void *pmsg; #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif #ifdef OS_SAFETY_CRITICAL if (perr == (INT8U *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); } #endif #if OS_ARG_CHK_EN > 0u if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ *perr = OS_ERR_PEVENT_NULL; return ((void *)0); } #endif if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */ *perr = OS_ERR_EVENT_TYPE; return ((void *)0); } if (OSIntNesting > 0u) { /* See if called from ISR ... */ *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ return ((void *)0); } if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ return ((void *)0); } OS_ENTER_CRITICAL(); pmsg = pevent->OSEventPtr; if (pmsg != (void *)0) { /* See if there is already a message */ pevent->OSEventPtr = (void *)0; /* Clear the mailbox */ OS_EXIT_CRITICAL(); *perr = OS_ERR_NONE; return (pmsg); /* Return the message received (or NULL) */ } OSTCBCur->OSTCBStat |= OS_STAT_MBOX; /* Message not available, task will pend */ OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; OSTCBCur->OSTCBDly = timeout; /* Load timeout in TCB */ OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */ OS_EXIT_CRITICAL(); OS_Sched(); /* Find next highest priority task ready to run */ OS_ENTER_CRITICAL(); switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */ case OS_STAT_PEND_OK: pmsg = OSTCBCur->OSTCBMsg; *perr = OS_ERR_NONE; break; case OS_STAT_PEND_ABORT: pmsg = (void *)0; *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */ break; case OS_STAT_PEND_TO: default: OS_EventTaskRemove(OSTCBCur, pevent); pmsg = (void *)0; *perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */ break; } OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */ OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */ #if (OS_EVENT_MULTI_EN > 0u) OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0; #endif OSTCBCur->OSTCBMsg = (void *)0; /* Clear received message */ OS_EXIT_CRITICAL(); return (pmsg); /* Return received message */ }
INT8U OSTaskChangePrio (INT8U oldprio, INT8U newprio) { #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 OS_TCB *ptcb; INT8U x; INT8U y; INT8U bitx; INT8U bity; #if OS_ARG_CHK_EN > 0 if ((oldprio >= OS_LOWEST_PRIO && oldprio != OS_PRIO_SELF) || newprio >= OS_LOWEST_PRIO) { return (OS_PRIO_INVALID); } #endif OS_ENTER_CRITICAL(); if (OSTCBPrioTbl[newprio] != (OS_TCB *)0) { /* New priority must not already exist */ OS_EXIT_CRITICAL(); return (OS_PRIO_EXIST); } else { OSTCBPrioTbl[newprio] = (OS_TCB *)1; /* Reserve the entry to prevent others */ OS_EXIT_CRITICAL(); y = newprio >> 3; /* Precompute to reduce INT. latency */ bity = OSMapTbl[y]; x = newprio & 0x07; bitx = OSMapTbl[x]; OS_ENTER_CRITICAL(); if (oldprio == OS_PRIO_SELF) { /* See if changing self */ oldprio = OSTCBCur->OSTCBPrio; /* Yes, get priority */ } ptcb = OSTCBPrioTbl[oldprio]; if (ptcb != (OS_TCB *)0) { /* Task to change must exist */ OSTCBPrioTbl[oldprio] = (OS_TCB *)0; /* Remove TCB from old priority */ if ((OSRdyTbl[ptcb->OSTCBY] & ptcb->OSTCBBitX) != 0x00) { /* If task is ready make it not */ if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00) { OSRdyGrp &= ~ptcb->OSTCBBitY; } OSRdyGrp |= bity; /* Make new priority ready to run */ OSRdyTbl[y] |= bitx; #if OS_EVENT_EN > 0 } else { pevent = ptcb->OSTCBEventPtr; if (pevent != (OS_EVENT *)0) { /* Remove from event wait list */ if ((pevent->OSEventTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) { pevent->OSEventGrp &= ~ptcb->OSTCBBitY; } pevent->OSEventGrp |= bity; /* Add new priority to wait list */ pevent->OSEventTbl[y] |= bitx; } #endif } OSTCBPrioTbl[newprio] = ptcb; /* Place pointer to TCB @ new priority */ ptcb->OSTCBPrio = newprio; /* Set new task priority */ ptcb->OSTCBY = y; ptcb->OSTCBX = x; ptcb->OSTCBBitY = bity; ptcb->OSTCBBitX = bitx; OS_EXIT_CRITICAL(); OS_Sched(); /* Run highest priority task ready */ return (OS_NO_ERR); } else { OSTCBPrioTbl[newprio] = (OS_TCB *)0; /* Release the reserved prio. */ OS_EXIT_CRITICAL(); return (OS_PRIO_ERR); /* Task to change didn't exist */ } } }
OS_EVENT *OSQDel (OS_EVENT *pevent, INT8U opt, INT8U *perr) { BOOLEAN tasks_waiting; OS_EVENT *pevent_return; OS_Q *pq; #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif #ifdef OS_SAFETY_CRITICAL if (perr == (INT8U *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); } #endif #if OS_ARG_CHK_EN > 0u if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ *perr = OS_ERR_PEVENT_NULL; return (pevent); } #endif if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */ *perr = OS_ERR_EVENT_TYPE; return (pevent); } if (OSIntNesting > 0u) { /* See if called from ISR ... */ *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ return (pevent); } OS_ENTER_CRITICAL(); if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on queue */ tasks_waiting = OS_TRUE; /* Yes */ } else { tasks_waiting = OS_FALSE; /* No */ } switch (opt) { case OS_DEL_NO_PEND: /* Delete queue only if no task waiting */ if (tasks_waiting == OS_FALSE) { #if OS_EVENT_NAME_EN > 0u pevent->OSEventName = (INT8U *)(void *)"?"; #endif pq = (OS_Q *)pevent->OSEventPtr; /* Return OS_Q to free list */ pq->OSQPtr = OSQFreeList; OSQFreeList = pq; pevent->OSEventType = OS_EVENT_TYPE_UNUSED; pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ pevent->OSEventCnt = 0u; OSEventFreeList = pevent; /* Get next free event control block */ OS_EXIT_CRITICAL(); *perr = OS_ERR_NONE; pevent_return = (OS_EVENT *)0; /* Queue has been deleted */ } else { OS_EXIT_CRITICAL(); *perr = OS_ERR_TASK_WAITING; pevent_return = pevent; } break; case OS_DEL_ALWAYS: /* Always delete the queue */ while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for queue */ (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_OK); } #if OS_EVENT_NAME_EN > 0u pevent->OSEventName = (INT8U *)(void *)"?"; #endif pq = (OS_Q *)pevent->OSEventPtr; /* Return OS_Q to free list */ pq->OSQPtr = OSQFreeList; OSQFreeList = pq; pevent->OSEventType = OS_EVENT_TYPE_UNUSED; pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ pevent->OSEventCnt = 0u; OSEventFreeList = pevent; /* Get next free event control block */ OS_EXIT_CRITICAL(); if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */ OS_Sched(); /* Find highest priority task ready to run */ } *perr = OS_ERR_NONE; pevent_return = (OS_EVENT *)0; /* Queue has been deleted */ break; default: OS_EXIT_CRITICAL(); *perr = OS_ERR_INVALID_OPT; pevent_return = pevent; break; } return (pevent_return); }
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; INT8U y; 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 */ y = ptcb->OSTCBY; OSRdyTbl[y] &= ~ptcb->OSTCBBitX; if (OSRdyTbl[y] == 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 */ pevent->OSEventTbl[y] &= ~ptcb->OSTCBBitX; if (pevent->OSEventTbl[y] == 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 < 255u) { 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; ptcb->OSTCBStkPtr = (OS_STK *)0; /* Show that TCB is 'unused' */ #if OS_TASK_NAME_SIZE > 0 (void)strcpy(ptcb->OSTCBTaskName, "?"); /* Unknown name */ #endif OS_EXIT_CRITICAL(); OS_Sched(); /* Find new highest priority task */ return (OS_NO_ERR); } OS_EXIT_CRITICAL(); return (OS_TASK_DEL_ERR); }
OS_FLAG_GRP *OSFlagDel(OS_FLAG_GRP * pgrp, INT8U opt, INT8U * perr) { BOOLEAN tasks_waiting; OS_FLAG_NODE *pnode; OS_FLAG_GRP *pgrp_return; #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 (pgrp); } if (pgrp == (OS_FLAG_GRP *) 0) { /* Validate 'pgrp' */ *perr = OS_ERR_FLAG_INVALID_PGRP; return (pgrp); } #endif if (OSIntNesting > 0) { /* See if called from ISR ... */ *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ return (pgrp); } if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Validate event group type */ *perr = OS_ERR_EVENT_TYPE; return (pgrp); } OS_ENTER_CRITICAL(); if (pgrp->OSFlagWaitList != (void *) 0) { /* See if any tasks waiting on event flags */ tasks_waiting = OS_TRUE; /* Yes */ } else { tasks_waiting = OS_FALSE; /* No */ } switch (opt) { case OS_DEL_NO_PEND: /* Delete group if no task waiting */ if (tasks_waiting == OS_FALSE) { #if OS_FLAG_NAME_SIZE > 1 pgrp->OSFlagName[0] = '?'; /* Unknown name */ pgrp->OSFlagName[1] = OS_ASCII_NUL; #endif pgrp->OSFlagType = OS_EVENT_TYPE_UNUSED; pgrp->OSFlagWaitList = (void *) OSFlagFreeList; /* Return group to free list */ pgrp->OSFlagFlags = (OS_FLAGS) 0; OSFlagFreeList = pgrp; OS_EXIT_CRITICAL(); *perr = OS_ERR_NONE; pgrp_return = (OS_FLAG_GRP *) 0; /* Event Flag Group has been deleted */ } else { OS_EXIT_CRITICAL(); *perr = OS_ERR_TASK_WAITING; pgrp_return = pgrp; } break; case OS_DEL_ALWAYS: /* Always delete the event flag group */ pnode = (OS_FLAG_NODE *) pgrp->OSFlagWaitList; while (pnode != (OS_FLAG_NODE *) 0) { /* Ready ALL tasks waiting for flags */ (void) OS_FlagTaskRdy(pnode, (OS_FLAGS) 0); pnode = (OS_FLAG_NODE *) pnode->OSFlagNodeNext; } #if OS_FLAG_NAME_SIZE > 1 pgrp->OSFlagName[0] = '?'; /* Unknown name */ pgrp->OSFlagName[1] = OS_ASCII_NUL; #endif pgrp->OSFlagType = OS_EVENT_TYPE_UNUSED; pgrp->OSFlagWaitList = (void *) OSFlagFreeList; /* Return group to free list */ pgrp->OSFlagFlags = (OS_FLAGS) 0; OSFlagFreeList = pgrp; OS_EXIT_CRITICAL(); if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */ OS_Sched(); /* Find highest priority task ready to run */ } *perr = OS_ERR_NONE; pgrp_return = (OS_FLAG_GRP *) 0; /* Event Flag Group has been deleted */ break; default: OS_EXIT_CRITICAL(); *perr = OS_ERR_INVALID_OPT; pgrp_return = pgrp; break; } return (pgrp_return); }
INT8U OSTaskChangePrio (INT8U oldprio, INT8U newprio) { #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 OS_TCB *ptcb; INT8U x; INT8U y; INT8U bitx; INT8U bity; INT8U y_old; #if OS_ARG_CHK_EN > 0 if (oldprio >= OS_LOWEST_PRIO) { if (oldprio != OS_PRIO_SELF) { return (OS_PRIO_INVALID); } } if (newprio >= OS_LOWEST_PRIO) { return (OS_PRIO_INVALID); } #endif OS_ENTER_CRITICAL(); if (OSTCBPrioTbl[newprio] != (OS_TCB *)0) { /* New priority must not already exist */ OS_EXIT_CRITICAL(); return (OS_PRIO_EXIST); } if (oldprio == OS_PRIO_SELF) { /* See if changing self */ oldprio = OSTCBCur->OSTCBPrio; /* Yes, get priority */ } ptcb = OSTCBPrioTbl[oldprio]; if (ptcb == (OS_TCB *)0) { /* Does task to change exist? */ OS_EXIT_CRITICAL(); /* No, can't change its priority! */ return (OS_PRIO_ERR); } y = newprio >> 3; /* Yes, compute new TCB fields */ bity = OSMapTbl[y]; x = newprio & 0x07; bitx = OSMapTbl[x]; OSTCBPrioTbl[oldprio] = (OS_TCB *)0; /* Remove TCB from old priority */ OSTCBPrioTbl[newprio] = ptcb; /* Place pointer to TCB @ new priority */ y_old = ptcb->OSTCBY; if ((OSRdyTbl[y_old] & ptcb->OSTCBBitX) != 0x00) { /* If task is ready make it not */ OSRdyTbl[y_old] &= ~ptcb->OSTCBBitX; if (OSRdyTbl[y_old] == 0x00) { OSRdyGrp &= ~ptcb->OSTCBBitY; } OSRdyGrp |= bity; /* Make new priority ready to run */ OSRdyTbl[y] |= bitx; #if OS_EVENT_EN > 0 } else { /* Task was not ready ... */ pevent = ptcb->OSTCBEventPtr; if (pevent != (OS_EVENT *)0) { /* ... remove from event wait list */ pevent->OSEventTbl[y_old] &= ~ptcb->OSTCBBitX; if (pevent->OSEventTbl[y_old] == 0) { pevent->OSEventGrp &= ~ptcb->OSTCBBitY; } pevent->OSEventGrp |= bity; /* Add new priority to wait list */ pevent->OSEventTbl[y] |= bitx; } #endif } ptcb->OSTCBPrio = newprio; /* Set new task priority */ ptcb->OSTCBY = y; ptcb->OSTCBX = x; ptcb->OSTCBBitY = bity; ptcb->OSTCBBitX = bitx; OS_EXIT_CRITICAL(); OS_Sched(); /* Run highest priority task ready */ return (OS_NO_ERR); }
/* ********************************************************************************************************* * POST EVENT FLAG BIT(S) * * Description: This function is called to set or clear some bits in an event flag group. The bits to * set or clear are specified by a 'bit mask'. * * Arguments : pgrp is a pointer to the desired event flag group. * * flags If 'opt' (see below) is OS_FLAG_SET, each bit that is set in 'flags' will * set the corresponding bit in the event flag group. e.g. to set bits 0, 4 * and 5 you would set 'flags' to: * * 0x31 (note, bit 0 is least significant bit) * * If 'opt' (see below) is OS_FLAG_CLR, each bit that is set in 'flags' will * CLEAR the corresponding bit in the event flag group. e.g. to clear bits 0, * 4 and 5 you would specify 'flags' as: * * 0x31 (note, bit 0 is least significant bit) * * opt indicates whether the flags will be: * set (OS_FLAG_SET) or * cleared (OS_FLAG_CLR) * * perr is a pointer to an error code and can be: * OS_ERR_NONE The call was successfull * OS_ERR_FLAG_INVALID_PGRP You passed a NULL pointer * OS_ERR_EVENT_TYPE You are not pointing to an event flag group * OS_ERR_FLAG_INVALID_OPT You specified an invalid option * * Returns : the new value of the event flags bits that are still set. * * Called From: Task or ISR * * WARNING(s) : 1) The execution time of this function depends on the number of tasks waiting on the event * flag group. * 2) The amount of time interrupts are DISABLED depends on the number of tasks waiting on * the event flag group. ********************************************************************************************************* */ OS_FLAGS OSFlagPost(OS_FLAG_GRP * pgrp, OS_FLAGS flags, INT8U opt, INT8U * perr) { OS_FLAG_NODE *pnode; BOOLEAN sched; OS_FLAGS flags_cur; OS_FLAGS flags_rdy; BOOLEAN rdy; #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 (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Make sure we are pointing to an event flag grp */ *perr = OS_ERR_EVENT_TYPE; return ((OS_FLAGS) 0); } /*$PAGE*/ OS_ENTER_CRITICAL(); switch (opt) { case OS_FLAG_CLR: pgrp->OSFlagFlags &= ~flags; /* Clear the flags specified in the group */ break; case OS_FLAG_SET: pgrp->OSFlagFlags |= flags; /* Set the flags specified in the group */ break; default: OS_EXIT_CRITICAL(); /* INVALID option */ *perr = OS_ERR_FLAG_INVALID_OPT; return ((OS_FLAGS) 0); } sched = OS_FALSE; /* Indicate that we don't need rescheduling */ pnode = (OS_FLAG_NODE *) pgrp->OSFlagWaitList; while (pnode != (OS_FLAG_NODE *) 0) { /* Go through all tasks waiting on event flag(s) */ switch (pnode->OSFlagNodeWaitType) { case OS_FLAG_WAIT_SET_ALL: /* See if all req. flags are set for current node */ flags_rdy = (OS_FLAGS) (pgrp->OSFlagFlags & pnode->OSFlagNodeFlags); if (flags_rdy == pnode->OSFlagNodeFlags) { rdy = OS_FlagTaskRdy(pnode, flags_rdy); /* Make task RTR, event(s) Rx'd */ if (rdy == OS_TRUE) { sched = OS_TRUE; /* When done we will reschedule */ } } break; case OS_FLAG_WAIT_SET_ANY: /* See if any flag set */ flags_rdy = (OS_FLAGS) (pgrp->OSFlagFlags & pnode->OSFlagNodeFlags); if (flags_rdy != (OS_FLAGS) 0) { rdy = OS_FlagTaskRdy(pnode, flags_rdy); /* Make task RTR, event(s) Rx'd */ if (rdy == OS_TRUE) { sched = OS_TRUE; /* When done we will reschedule */ } } break; #if OS_FLAG_WAIT_CLR_EN > 0 case OS_FLAG_WAIT_CLR_ALL: /* See if all req. flags are set for current node */ flags_rdy = (OS_FLAGS) (~pgrp->OSFlagFlags & pnode->OSFlagNodeFlags); if (flags_rdy == pnode->OSFlagNodeFlags) { rdy = OS_FlagTaskRdy(pnode, flags_rdy); /* Make task RTR, event(s) Rx'd */ if (rdy == OS_TRUE) { sched = OS_TRUE; /* When done we will reschedule */ } } break; case OS_FLAG_WAIT_CLR_ANY: /* See if any flag set */ flags_rdy = (OS_FLAGS) (~pgrp->OSFlagFlags & pnode->OSFlagNodeFlags); if (flags_rdy != (OS_FLAGS) 0) { rdy = OS_FlagTaskRdy(pnode, flags_rdy); /* Make task RTR, event(s) Rx'd */ if (rdy == OS_TRUE) { sched = OS_TRUE; /* When done we will reschedule */ } } break; #endif default: OS_EXIT_CRITICAL(); *perr = OS_ERR_FLAG_WAIT_TYPE; return ((OS_FLAGS) 0); } pnode = (OS_FLAG_NODE *) pnode->OSFlagNodeNext; /* Point to next task waiting for event flag(s) */ } OS_EXIT_CRITICAL(); if (sched == OS_TRUE) { OS_Sched(); } OS_ENTER_CRITICAL(); flags_cur = pgrp->OSFlagFlags; OS_EXIT_CRITICAL(); *perr = OS_ERR_NONE; return (flags_cur); }
OS_EVENT *OSSemDel (OS_EVENT *pevent, INT8U opt, INT8U *perr) { BOOLEAN tasks_waiting; OS_EVENT *pevent_return; #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 (pevent); } if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ *perr = OS_ERR_PEVENT_NULL; return (pevent); } #endif if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ *perr = OS_ERR_EVENT_TYPE; return (pevent); } if (OSIntNesting > 0) { /* See if called from ISR ... */ *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ return (pevent); } OS_ENTER_CRITICAL(); if (pevent->OSEventGrp != 0) { /* See if any tasks waiting on semaphore */ tasks_waiting = OS_TRUE; /* Yes */ } else { tasks_waiting = OS_FALSE; /* No */ } switch (opt) { case OS_DEL_NO_PEND: /* Delete semaphore only if no task waiting */ if (tasks_waiting == OS_FALSE) { #if OS_EVENT_NAME_SIZE > 1 pevent->OSEventName[0] = '?'; /* Unknown name */ pevent->OSEventName[1] = OS_ASCII_NUL; #endif pevent->OSEventType = OS_EVENT_TYPE_UNUSED; pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ pevent->OSEventCnt = 0; OSEventFreeList = pevent; /* Get next free event control block */ OS_EXIT_CRITICAL(); *perr = OS_ERR_NONE; pevent_return = (OS_EVENT *)0; /* Semaphore has been deleted */ } else { OS_EXIT_CRITICAL(); *perr = OS_ERR_TASK_WAITING; pevent_return = pevent; } break; case OS_DEL_ALWAYS: /* Always delete the semaphore */ while (pevent->OSEventGrp != 0) { /* Ready ALL tasks waiting for semaphore */ (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK); } #if OS_EVENT_NAME_SIZE > 1 pevent->OSEventName[0] = '?'; /* Unknown name */ pevent->OSEventName[1] = OS_ASCII_NUL; #endif pevent->OSEventType = OS_EVENT_TYPE_UNUSED; pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ pevent->OSEventCnt = 0; OSEventFreeList = pevent; /* Get next free event control block */ OS_EXIT_CRITICAL(); if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */ OS_Sched(); /* Find highest priority task ready to run */ } *perr = OS_ERR_NONE; pevent_return = (OS_EVENT *)0; /* Semaphore has been deleted */ break; default: OS_EXIT_CRITICAL(); *perr = OS_ERR_INVALID_OPT; pevent_return = pevent; break; } return (pevent_return); }
/*----------------------------------------------------------------------* rtp_irq_pop *----------------------------------------------------------------------*/ void rtp_irq_pop (RTP_HANDLE previousLevel) { OS_EXIT_CRITICAL(); }
//任务控制块初始化 INITIALIZE TCB //描述: 这个函数是uC/OS-II内部函数,在建立任务时调用的初始化任务控制块OS_TCB函数,含7个参数, // (查看 OSTaskCreate() 和 OSTaskCreateExt()). //参数: prio 任务的优先级 // ptos OSTaskInit()建立栈结构以后,ptos是指向栈顶的指针,且保存在OS_TCB的OSTCBStkPrt中 // pbos 指向栈底的指针,保存在OSTCBStkBottom变元中 // id 任务标志符(0..65535),保存在.OSTCBId中 // stk_size 堆栈的容量,保存在OS_TCB的OSTABStkSize中 // pext OS_TCB中的扩展指针,.OSTCBExtPtr的值 // opt OS_TCB的选择项,保存在.OSTCBOpt中 //返回: OS_NO_ERR 调用成功 // OS_NO_MORE_TCB 没有更多的任务控制块被分配,将无法创建新的任务 //注意: 这个函数是uC/OS-II内部函数,你不可以调用它。 INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt) { #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; #endif OS_TCB *ptcb; OS_ENTER_CRITICAL(); ptcb = OSTCBFreeList; /* Get a free TCB from the free TCB list */ if (ptcb != (OS_TCB *)0) { OSTCBFreeList = ptcb->OSTCBNext; /* Update pointer to free TCB list */ OS_EXIT_CRITICAL(); ptcb->OSTCBStkPtr = ptos; /* Load Stack pointer in TCB */ ptcb->OSTCBPrio = (INT8U)prio; /* Load task priority into TCB */ ptcb->OSTCBStat = OS_STAT_RDY; /* Task is ready to run */ ptcb->OSTCBDly = 0; /* Task is not delayed */ #if OS_TASK_CREATE_EXT_EN > 0 ptcb->OSTCBExtPtr = pext; /* Store pointer to TCB extension */ ptcb->OSTCBStkSize = stk_size; /* Store stack size */ ptcb->OSTCBStkBottom = pbos; /* Store pointer to bottom of stack */ ptcb->OSTCBOpt = opt; /* Store task options */ ptcb->OSTCBId = id; /* Store task ID */ #else pext = pext; /* Prevent compiler warning if not used */ stk_size = stk_size; pbos = pbos; opt = opt; id = id; #endif #if OS_TASK_DEL_EN > 0 ptcb->OSTCBDelReq = OS_NO_ERR; #endif ptcb->OSTCBY = prio >> 3; /* Pre-compute X, Y, BitX and BitY */ ptcb->OSTCBBitY = OSMapTbl[ptcb->OSTCBY]; ptcb->OSTCBX = prio & 0x07; ptcb->OSTCBBitX = OSMapTbl[ptcb->OSTCBX]; #if OS_EVENT_EN > 0 ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* Task is not pending on an event */ #endif #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0) ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; /* Task is not pending on an event flag */ #endif #if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) ptcb->OSTCBMsg = (void *)0; /* No message received */ #endif #if OS_VERSION >= 204 OSTCBInitHook(ptcb); #endif OSTaskCreateHook(ptcb); /* Call user defined hook */ OS_ENTER_CRITICAL(); OSTCBPrioTbl[prio] = ptcb; ptcb->OSTCBNext = OSTCBList; /* Link into TCB chain */ ptcb->OSTCBPrev = (OS_TCB *)0; if (OSTCBList != (OS_TCB *)0) { OSTCBList->OSTCBPrev = ptcb; } OSTCBList = ptcb; OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */ OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; OS_EXIT_CRITICAL(); return (OS_NO_ERR); }
OS_EVENT *OSSemDel (OS_EVENT *pevent, INT8U opt, INT8U *perr) { BOOLEAN tasks_waiting; OS_EVENT *pevent_return; #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif #ifdef OS_SAFETY_CRITICAL if (perr == (INT8U *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return ((OS_EVENT *)0); } #endif #if OS_ARG_CHK_EN > 0u if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ *perr = OS_ERR_PEVENT_NULL; return (pevent); } #endif if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ *perr = OS_ERR_EVENT_TYPE; return (pevent); } if (OSIntNesting > 0u) { /* See if called from ISR ... */ *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ return (pevent); } OS_ENTER_CRITICAL(); /* 检查是否有任务在等待该信号量 */ if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on semaphore */ tasks_waiting = OS_TRUE; /* Yes */ } else { tasks_waiting = OS_FALSE; /* No */ } switch (opt) { /* 没有任务等待该信号量时,才删除该信号量 */ case OS_DEL_NO_PEND: /* Delete semaphore only if no task waiting */ /* 没有任务等待,则直接删除该信号量 */ if (tasks_waiting == OS_FALSE) { #if OS_EVENT_NAME_EN > 0u pevent->OSEventName = (INT8U *)(void *)"?"; #endif pevent->OSEventType = OS_EVENT_TYPE_UNUSED; /* 把事件控制块放入空事件控制块链表 */ pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ pevent->OSEventCnt = 0u; OSEventFreeList = pevent; /* Get next free event control block */ OS_EXIT_CRITICAL(); *perr = OS_ERR_NONE; pevent_return = (OS_EVENT *)0; /* Semaphore has been deleted */ } else { OS_EXIT_CRITICAL(); *perr = OS_ERR_TASK_WAITING; pevent_return = pevent; } break; /* 强制删除信号量,并取消所有等待任务的等待状态 */ case OS_DEL_ALWAYS: /* Always delete the semaphore */ /* 取消所有等待任务的等待状态,如果任务没有被挂起,则使任务就绪 */ while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for semaphore */ (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT); } #if OS_EVENT_NAME_EN > 0u pevent->OSEventName = (INT8U *)(void *)"?"; #endif pevent->OSEventType = OS_EVENT_TYPE_UNUSED; /* 把事件控制块放入空事件控制块链表 */ pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ pevent->OSEventCnt = 0u; OSEventFreeList = pevent; /* Get next free event control block */ OS_EXIT_CRITICAL(); /* 如果有任务在等待该事件,说明已经将所有等待该事件的任务就绪了,进行调度 */ if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */ OS_Sched(); /* Find highest priority task ready to run */ } *perr = OS_ERR_NONE; pevent_return = (OS_EVENT *)0; /* Semaphore has been deleted */ break; default: OS_EXIT_CRITICAL(); *perr = OS_ERR_INVALID_OPT; pevent_return = pevent; break; } return (pevent_return); }
/*$PAGE*/ void OSSemPend (OS_EVENT *pevent, INT32U timeout, INT8U *perr) { #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif #ifdef OS_SAFETY_CRITICAL if (perr == (INT8U *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); } #endif #if OS_ARG_CHK_EN > 0u if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ *perr = OS_ERR_PEVENT_NULL; return; } #endif if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ *perr = OS_ERR_EVENT_TYPE; return; } if (OSIntNesting > 0u) { /* See if called from ISR ... */ *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ return; } if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ return; } OS_ENTER_CRITICAL(); if (pevent->OSEventCnt > 0u) { /* If sem. is positive, resource available ... */ pevent->OSEventCnt--; /* ... decrement semaphore only if positive. */ OS_EXIT_CRITICAL(); *perr = OS_ERR_NONE; return; } /* Otherwise, must wait until event occurs */ OSTCBCur->OSTCBStat |= OS_STAT_SEM; /* Resource not available, pend on semaphore */ OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; OSTCBCur->OSTCBDly = timeout; /* Store pend timeout in TCB */ OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */ OS_EXIT_CRITICAL(); OS_Sched(); /* Find next highest priority task ready */ OS_ENTER_CRITICAL(); switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */ case OS_STAT_PEND_OK: *perr = OS_ERR_NONE; break; case OS_STAT_PEND_ABORT: *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */ break; case OS_STAT_PEND_TO: default: OS_EventTaskRemove(OSTCBCur, pevent); *perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */ break; } OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */ OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */ #if (OS_EVENT_MULTI_EN > 0u) OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0; #endif OS_EXIT_CRITICAL(); }
OS_EVENT *OSSemDel (OS_EVENT *pevent, INT8U opt, INT8U *err) { #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; #endif BOOLEAN tasks_waiting; if (OSIntNesting > 0) { /* See if called from ISR ... */ *err = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ return (pevent); } #if OS_ARG_CHK_EN > 0 if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ *err = OS_ERR_PEVENT_NULL; return (pevent); } if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ *err = OS_ERR_EVENT_TYPE; return (pevent); } #endif OS_ENTER_CRITICAL(); if (pevent->OSEventGrp != 0x00) { /* See if any tasks waiting on semaphore */ tasks_waiting = TRUE; /* Yes */ } else { tasks_waiting = FALSE; /* No */ } switch (opt) { case OS_DEL_NO_PEND: /* Delete semaphore only if no task waiting */ if (tasks_waiting == FALSE) { pevent->OSEventType = OS_EVENT_TYPE_UNUSED; pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ OSEventFreeList = pevent; /* Get next free event control block */ OS_EXIT_CRITICAL(); *err = OS_NO_ERR; return ((OS_EVENT *)0); /* Semaphore has been deleted */ } else { OS_EXIT_CRITICAL(); *err = OS_ERR_TASK_WAITING; return (pevent); } case OS_DEL_ALWAYS: /* Always delete the semaphore */ while (pevent->OSEventGrp != 0x00) { /* Ready ALL tasks waiting for semaphore */ OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM); } pevent->OSEventType = OS_EVENT_TYPE_UNUSED; pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ OSEventFreeList = pevent; /* Get next free event control block */ OS_EXIT_CRITICAL(); if (tasks_waiting == TRUE) { /* Reschedule only if task(s) were waiting */ OS_Sched(); /* Find highest priority task ready to run */ } *err = OS_NO_ERR; return ((OS_EVENT *)0); /* Semaphore has been deleted */ default: OS_EXIT_CRITICAL(); *err = OS_ERR_INVALID_OPT; return (pevent); } }
OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err) { OS_MEM *pmem; INT8U *pblk; void **plink; INT32U i; #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 (err == (INT8U *)0) { /* Validate 'err' */ return ((OS_MEM *)0); } if (addr == (void *)0) { /* Must pass a valid address for the memory part.*/ *err = OS_MEM_INVALID_ADDR; return ((OS_MEM *)0); } if (((INT32U)addr & (sizeof(void *) - 1)) != 0){ /* Must be pointer size aligned */ *err = OS_MEM_INVALID_ADDR; return ((OS_MEM *)0); } if (nblks < 2) { /* Must have at least 2 blocks per partition */ *err = OS_MEM_INVALID_BLKS; return ((OS_MEM *)0); } if (blksize < sizeof(void *)) { /* Must contain space for at least a pointer */ *err = OS_MEM_INVALID_SIZE; return ((OS_MEM *)0); } if ((blksize % sizeof(void *)) != 0) { /* Must contain space for an integral number ... */ *err = OS_MEM_INVALID_SIZE; /* ... of pointer sized items */ return ((OS_MEM *)0); } #endif OS_ENTER_CRITICAL(); pmem = OSMemFreeList; /* Get next free memory partition */ if (OSMemFreeList != (OS_MEM *)0) { /* See if pool of free partitions was empty */ OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList; } OS_EXIT_CRITICAL(); if (pmem == (OS_MEM *)0) { /* See if we have a memory partition */ *err = OS_MEM_INVALID_PART; return ((OS_MEM *)0); } plink = (void **)addr; /* Create linked list of free memory blocks */ pblk = (INT8U *)((INT32U)addr + blksize); for (i = 0; i < (nblks - 1); i++) { *plink = (void *)pblk; /* Save pointer to NEXT block in CURRENT block */ plink = (void **)pblk; /* Position to NEXT block */ pblk = (INT8U *)((INT32U)pblk + blksize); /* Point to the FOLLOWING block */ } *plink = (void *)0; /* Last memory block points to NULL */ pmem->OSMemAddr = addr; /* Store start address of memory partition */ pmem->OSMemFreeList = addr; /* Initialize pointer to pool of free blocks */ pmem->OSMemNFree = nblks; /* Store number of free blocks in MCB */ pmem->OSMemNBlks = nblks; pmem->OSMemBlkSize = blksize; /* Store block size of each memory blocks */ *err = OS_NO_ERR; return (pmem); }
INT8U OSTaskChangePrio (INT8U oldprio, INT8U newprio) { #if (OS_EVENT_EN) OS_EVENT *pevent; #if (OS_EVENT_MULTI_EN > 0) OS_EVENT **pevents; #endif #endif OS_TCB *ptcb; INT8U y_new; INT8U x_new; INT8U y_old; #if OS_LOWEST_PRIO <= 63 INT8U bity_new; INT8U bitx_new; INT8U bity_old; INT8U bitx_old; #else INT16U bity_new; INT16U bitx_new; INT16U bity_old; INT16U bitx_old; #endif #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr = 0; /* Storage for CPU status register */ #endif /*$PAGE*/ #if OS_ARG_CHK_EN > 0 if (oldprio >= OS_LOWEST_PRIO) { if (oldprio != OS_PRIO_SELF) { return (OS_ERR_PRIO_INVALID); } } if (newprio >= OS_LOWEST_PRIO) { return (OS_ERR_PRIO_INVALID); } #endif OS_ENTER_CRITICAL(); if (OSTCBPrioTbl[newprio] != (OS_TCB *)0) { /* New priority must not already exist */ OS_EXIT_CRITICAL(); return (OS_ERR_PRIO_EXIST); } if (oldprio == OS_PRIO_SELF) { /* See if changing self */ oldprio = OSTCBCur->OSTCBPrio; /* Yes, get priority */ } ptcb = OSTCBPrioTbl[oldprio]; if (ptcb == (OS_TCB *)0) { /* Does task to change exist? */ OS_EXIT_CRITICAL(); /* No, can't change its priority! */ return (OS_ERR_PRIO); } if (ptcb == OS_TCB_RESERVED) { /* Is task assigned to Mutex */ OS_EXIT_CRITICAL(); /* No, can't change its priority! */ return (OS_ERR_TASK_NOT_EXIST); } #if OS_LOWEST_PRIO <= 63 y_new = (INT8U)(newprio >> 3); /* Yes, compute new TCB fields */ x_new = (INT8U)(newprio & 0x07); bity_new = (INT8U)(1 << y_new); bitx_new = (INT8U)(1 << x_new); #else y_new = (INT8U)((newprio >> 4) & 0x0F); x_new = (INT8U)( newprio & 0x0F); bity_new = (INT16U)(1 << y_new); bitx_new = (INT16U)(1 << x_new); #endif OSTCBPrioTbl[oldprio] = (OS_TCB *)0; /* Remove TCB from old priority */ OSTCBPrioTbl[newprio] = ptcb; /* Place pointer to TCB @ new priority */ y_old = ptcb->OSTCBY; bity_old = ptcb->OSTCBBitY; bitx_old = ptcb->OSTCBBitX; if ((OSRdyTbl[y_old] & bitx_old) != 0) { /* If task is ready make it not */ OSRdyTbl[y_old] &= ~bitx_old; if (OSRdyTbl[y_old] == 0) { OSRdyGrp &= ~bity_old; } OSRdyGrp |= bity_new; /* Make new priority ready to run */ OSRdyTbl[y_new] |= bitx_new; } #if (OS_EVENT_EN) pevent = ptcb->OSTCBEventPtr; if (pevent != (OS_EVENT *)0) { pevent->OSEventTbl[y_old] &= ~bitx_old; /* Remove old task prio from wait list */ if (pevent->OSEventTbl[y_old] == 0) { pevent->OSEventGrp &= ~bity_old; } pevent->OSEventGrp |= bity_new; /* Add new task prio to wait list */ pevent->OSEventTbl[y_new] |= bitx_new; } #if (OS_EVENT_MULTI_EN > 0) if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) { pevents = ptcb->OSTCBEventMultiPtr; pevent = *pevents; while (pevent != (OS_EVENT *)0) { pevent->OSEventTbl[y_old] &= ~bitx_old; /* Remove old task prio from wait lists */ if (pevent->OSEventTbl[y_old] == 0) { pevent->OSEventGrp &= ~bity_old; } pevent->OSEventGrp |= bity_new; /* Add new task prio to wait lists */ pevent->OSEventTbl[y_new] |= bitx_new; pevents++; pevent = *pevents; } } #endif #endif ptcb->OSTCBPrio = newprio; /* Set new task priority */ ptcb->OSTCBY = y_new; ptcb->OSTCBX = x_new; ptcb->OSTCBBitY = bity_new; ptcb->OSTCBBitX = bitx_new; OS_EXIT_CRITICAL(); if (OSRunning == OS_TRUE) { OS_Sched(); /* Find new highest priority task */ } return (OS_ERR_NONE); }
INT8U OS_FreeMem(VOID *memory) { R1 DM_PCB *pool; /* Pool pointer */ R1 DM_HEADER *header_ptr; /* Pointer to memory hdr */ R1 DM_HEADER *new_ptr; /* New memory block pointer */ INT8U status; /* Completion status */ #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0; #endif /* Initialize the status as successful. */ status = OS_ERR_NONE; /* Pickup the associated pool's pointer. It is inside the header of each memory. */ header_ptr = (DM_HEADER *) (((CHAR *) memory) - DM_OVERHEAD); pool = header_ptr->dm_memory_pool; /* Protect against simultaneous access to the memory pool. */ OS_ENTER_CRITICAL(); /* Mark the memory as available. */ header_ptr->dm_memory_free = TRUE; /* Adjust the available number of bytes. */ pool->dm_available = pool->dm_available + (((CHAR *) (header_ptr->dm_next_memory)) - ((CHAR *) header_ptr)) - DM_OVERHEAD; /* Determine if the block can be merged with the previous neighbor. */ if ((header_ptr->dm_previous_memory)->dm_memory_free) { /* Adjust the available number of bytes. */ pool->dm_available = pool->dm_available + DM_OVERHEAD; /* Yes, merge block with previous neighbor. */ (header_ptr->dm_previous_memory)->dm_next_memory = header_ptr->dm_next_memory; (header_ptr->dm_next_memory)->dm_previous_memory = header_ptr->dm_previous_memory; /* Move header pointer to previous. */ header_ptr = header_ptr->dm_previous_memory; /* Adjust the search pointer to the new merged block. */ pool->dm_search_ptr = header_ptr; } /* Determine if the block can be merged with the next neighbor. */ if ((header_ptr->dm_next_memory)->dm_memory_free) { /* Adjust the available number of bytes. */ pool->dm_available = pool->dm_available + DM_OVERHEAD; /* Yes, merge block with next neighbor. */ new_ptr = header_ptr->dm_next_memory; (new_ptr->dm_next_memory)->dm_previous_memory = header_ptr; header_ptr->dm_next_memory = new_ptr->dm_next_memory; /* Adjust the search pointer to the new merged block. */ pool->dm_search_ptr = header_ptr; } /* Release protection of the memory pool. */ OS_EXIT_CRITICAL(); /* Return the completion status. */ return(status); }