📄 os_mutex.lst
字号:
181 * opt == OS_DEL_NO_PEND Delete mutex ONLY if no task pending
182 * opt == OS_DEL_ALWAYS Deletes the mutex even if tasks are waiting.
183 * In this case, all the tasks pending will be readied.
184 *
185 * err is a pointer to an error code that can contain one of the following values:
186 * OS_NO_ERR The call was successful and the mutex was deleted
187 * OS_ERR_DEL_ISR If you attempted to delete the MUTEX from an ISR
188 * OS_ERR_INVALID_OPT An invalid option was specified
189 * OS_ERR_TASK_WAITING One or more tasks were waiting on the mutex
190 * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mutex
191 * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
192 *
193 * Returns : pevent upon error
194 * (OS_EVENT *)0 if the mutex was successfully deleted.
195 *
196 * Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of
197 * the mutex MUST check the return code of OSMutexPend().
198 * 2) This call can potentially disable interrupts for a long time. The interrupt disable
199 * time is directly proportional to the number of tasks waiting on the mutex.
200 * 3) Because ALL tasks pending on the mutex will be readied, you MUST be careful because the
201 * resource(s) will no longer be guarded by the mutex.
202 *********************************************************************************************************
203 */
204
205 #if OS_MUTEX_DEL_EN
206 OS_EVENT *OSMutexDel (OS_EVENT *pevent, INT8U opt, INT8U *err) KCREENTRANT
207 {
208 1 #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
211 1 BOOLEAN tasks_waiting;
212 1 INT8U pip;
213 1
214 1
215 1 if (OSIntNesting > 0) { /* See if called from ISR ... */
216 2 *err = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
217 2 return (pevent);
218 2 }
219 1 #if OS_ARG_CHK_EN > 0
220 1 if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
221 2 *err = OS_ERR_PEVENT_NULL;
222 2 return ((OS_EVENT *)0);
223 2 }
224 1 if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */
225 2 *err = OS_ERR_EVENT_TYPE;
226 2 return (pevent);
227 2 }
228 1 #endif
229 1 OS_ENTER_CRITICAL();
230 1 if (pevent->OSEventGrp != 0x00) { /* See if any tasks waiting on mutex */
231 2 tasks_waiting = TRUE; /* Yes */
232 2 } else {
233 2 tasks_waiting = FALSE; /* No */
234 2 }
235 1 switch (opt) {
236 2 case OS_DEL_NO_PEND: /* Delete mutex only if no task waiting */
237 2 if (tasks_waiting == FALSE) {
238 3 pip = (INT8U)(pevent->OSEventCnt >> 8);
239 3 OSTCBPrioTbl[pip] = (OS_TCB *)0; /* Free up the PIP */
240 3 pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
241 3 pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
C51 COMPILER V6.23a OS_MUTEX 12/09/2004 16:50:26 PAGE 5
242 3 OSEventFreeList = pevent;
243 3 OS_EXIT_CRITICAL();
244 3 *err = OS_NO_ERR;
245 3 return ((OS_EVENT *)0); /* Mutex has been deleted */
246 3 } else {
247 3 OS_EXIT_CRITICAL();
248 3 *err = OS_ERR_TASK_WAITING;
249 3 return (pevent);
250 3 }
251 2
252 2 case OS_DEL_ALWAYS: /* Always delete the mutex */
253 2 while (pevent->OSEventGrp != 0x00) { /* Ready ALL tasks waiting for mutex */
254 3 OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX);
255 3 }
256 2 pip = (INT8U)(pevent->OSEventCnt >> 8);
257 2 OSTCBPrioTbl[pip] = (OS_TCB *)0; /* Free up the PIP */
258 2 pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
259 2 pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
260 2 OSEventFreeList = pevent; /* Get next free event control block */
261 2 OS_EXIT_CRITICAL();
262 2 if (tasks_waiting == TRUE) { /* Reschedule only if task(s) were waiting */
263 3 OS_Sched(); /* Find highest priority task ready to run */
264 3 }
265 2 *err = OS_NO_ERR;
266 2 return ((OS_EVENT *)0); /* Mutex has been deleted */
267 2
268 2 default:
269 2 OS_EXIT_CRITICAL();
270 2 *err = OS_ERR_INVALID_OPT;
271 2 return (pevent);
272 2 }
273 1 }
274 #endif
275
276 /*$PAGE*/
277 /*
278 *********************************************************************************************************
279 * PEND ON MUTUAL EXCLUSION SEMAPHORE
280 *
281 * Description: This function waits for a mutual exclusion semaphore.
282 *
283 * Arguments : pevent is a pointer to the event control block associated with the desired
284 * mutex.
285 *
286 * timeout is an optional timeout period (in clock ticks). If non-zero, your task will
287 * wait for the resource up to the amount of time specified by this argument.
288 * If you specify 0, however, your task will wait forever at the specified
289 * mutex or, until the resource becomes available.
290 *
291 * err is a pointer to where an error message will be deposited. Possible error
292 * messages are:
293 * OS_NO_ERR The call was successful and your task owns the mutex
294 * OS_TIMEOUT The mutex was not available within the specified time.
295 * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mutex
296 * OS_ERR_PEVENT_NULL 'pevent' is a NULL pointer
297 * OS_ERR_PEND_ISR If you called this function from an ISR and the result
298 * would lead to a suspension.
299 *
300 * Returns : none
301 *
302 * Note(s) : 1) The task that owns the Mutex MUST NOT pend on any other event while it owns the mutex.
303 * 2) You MUST NOT change the priority of the task that owns the mutex
C51 COMPILER V6.23a OS_MUTEX 12/09/2004 16:50:26 PAGE 6
304 *********************************************************************************************************
305 */
306 void OSMutexPend (OS_EVENT *pevent, INT16U timeout, INT8U *err) KCREENTRANT
307 {
308 1 #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
311 1 INT8U pip; /* Priority Inheritance Priority (PIP) */
312 1 INT8U mprio; /* Mutex owner priority */
313 1 BOOLEAN rdy; /* Flag indicating task was ready */
314 1 OS_TCB *ptcb;
315 1
316 1
317 1 if (OSIntNesting > 0) { /* See if called from ISR ... */
318 2 *err = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
319 2 return;
320 2 }
321 1 #if OS_ARG_CHK_EN > 0
322 1 if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
323 2 *err = OS_ERR_PEVENT_NULL;
324 2 return;
325 2 }
326 1 if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */
327 2 *err = OS_ERR_EVENT_TYPE;
328 2 return;
329 2 }
330 1 #endif
331 1 OS_ENTER_CRITICAL(); /* Is Mutex available? */
332 1 if ((INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) {
333 2 pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8; /* Yes, Acquire the resource */
334 2 pevent->OSEventCnt |= OSTCBCur->OSTCBPrio; /* Save priority of owning task */
335 2 pevent->OSEventPtr = (void *)OSTCBCur; /* Point to owning task's OS_TCB */
336 2 OS_EXIT_CRITICAL();
337 2 *err = OS_NO_ERR;
338 2 return;
339 2 }
340 1 pip = (INT8U)(pevent->OSEventCnt >> 8); /* No, Get PIP from mutex */
341 1 mprio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* Get priority of mutex owner */
342 1 ptcb = (OS_TCB *)(pevent->OSEventPtr); /* Point to TCB of mutex owner */
343 1 if (ptcb->OSTCBPrio != pip && mprio > OSTCBCur->OSTCBPrio) { /* Need to promote prio of owner?*/
344 2 if ((OSRdyTbl[ptcb->OSTCBY] & ptcb->OSTCBBitX) != 0x00) { /* See if mutex owner is ready */
345 3 /* Yes, Remove owner from Rdy ...*/
346 3 /* ... list at current prio */
347 3 if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00) {
348 4 OSRdyGrp &= ~ptcb->OSTCBBitY;
349 4 }
350 3 rdy = TRUE;
351 3 } else {
352 3 rdy = FALSE; /* No */
353 3 }
354 2 ptcb->OSTCBPrio = pip; /* Change owner task prio to PIP */
355 2 ptcb->OSTCBY = ptcb->OSTCBPrio >> 3;
356 2 ptcb->OSTCBBitY = OSMapTbl[ptcb->OSTCBY];
357 2 ptcb->OSTCBX = ptcb->OSTCBPrio & 0x07;
358 2 ptcb->OSTCBBitX = OSMapTbl[ptcb->OSTCBX];
359 2 if (rdy == TRUE) { /* If task was ready at owner's priority ...*/
360 3 OSRdyGrp |= ptcb->OSTCBBitY; /* ... make it ready at new priority. */
361 3 OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
362 3 }
363 2 OSTCBPrioTbl[pip] = (OS_TCB *)ptcb;
364 2 }
365 1 OSTCBCur->OSTCBStat |= OS_STAT_MUTEX; /* Mutex not available, pend current task */
C51 COMPILER V6.23a OS_MUTEX 12/09/2004 16:50:26 PAGE 7
366 1 OSTCBCur->OSTCBDly = timeout; /* Store timeout in current task's TCB */
367 1 OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */
368 1 OS_EXIT_CRITICAL();
369 1 OS_Sched(); /* Find next highest priority task ready */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -