180 likes | 312 Views
Chapter 6 Event Control Blocks. Figure 6.1 use of event control blocks (ECB) how tasks and ISRs can interact with each other. Event Control Blocks. typedef struct { INT8U OSEventType; /* Event type */
E N D
Figure 6.1 use of event control blocks (ECB)how tasks and ISRs can interact with each other
Event Control Blocks typedef struct { INT8U OSEventType; /* Event type */ INT8U OSEventGrp; /* Group for wait list */ INT16U OSEventCnt; /* Count (when event is a semaphore) */ void *OSEventPtr; /* Ptr to message or queue structure */ INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* Wait list for event to occur */ } OS_EVENT; • Each semaphore, mailbox, and queue is assigned an ECB • OSEventType: contains the type associated with the ECB • OS_EVENT_SEM, OS_EVENT_TYPE_MUTEX, OS_EVENT_TYPE_MBOX, OS_EVENT_TYPE_Q • OSEventPtr: only used when the ECB is assigned to a mailbox or a queue • OSEventTbl[] and OSEventGrp • similar to OSRdyTbl[ and OSRdyGrp • Contain a list of tasks waiting on the event instead of a list of tasks ready to run • OSEventCnt: used to hold the semaphore count
Event Control Block (ECB) • Each task that needs to wait for the event to occur is placed in the wait list • Consist of the two variables: OSEventGrp and OSEventTbl[ ] OS_EVENT pevent OSEvnetType OSEvnetCnt OSEvnetPtr OSEvnetGrp 7 6 5 4 3 2 1 0 OSEventTbl[ ] 63 62 61 60 59 58 57 56
pevent->OSEventGrp |= OSMapTbl[prio >> 3]; pevent->OSEventTbl[prio >> 3] |= OSMapTbl[prio & 0x07]; Making a task wait for an event Removing a task from a wait list if ((pevent->OSEventTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0) { pevent->OSEventGrp &= ~OSMapTbl[prio >> 3]; } Finding the highest priority task waiting for the event y = OSUnMapTbl[pevent->OSEventGrp]; x = OSUnMapTbl[pevent->OSEventTbl[y]]; prio = (y << 3) + x;
OSUnMapTbl[ ] INT8U const OSUnMapTbl[] = { 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
Example of ECB wait list • OSEventGrp = 11001000 => OSUnMapTbl[OSEventGrp] = 3 • OSEventTbl[3] = 00010000 OSUnMapTbl[OSEventTbl[3] ] = 4 • The priority of the task waiting is 3*8+4 = 28
OS_EVENT pevent OSEvnetType OSEvnetCnt OSEvnetPtr OSEvnetGrp 7 6 5 4 3 2 1 0 63 62 61 60 59 58 57 56 Figure 6.3 List of free ECBs • The number of ECBs to allocate depends on the number of semaphores, mailboxes, and queues needed for your application • When OSInit() is called, all ECBs are linked in a singly linked list • The list of free ECBs
Four common operations can be performed on ECBs • Initialize an ECB • Make a task ready • Make a task wait for an event • Make a task ready because a timeout occurred while waiting for an event • Four functions have been created to performs these operations • OSEventWaitListInit(): called when a semaphore, mutex, message mailbos, or message queue is created • OSEventTaskRdy() • OSEventWait() • OSEventTO()
Initializing an ECBOSEventWaitListInit() • Is called by OSSemCreate(), OSMutexCreate() OSMboxCreate (), OSQCreate () • No task is waiting on the ECB new version void OSEventWaitListInit (OS_EVENT *pevent) { INT8U *ptbl; pevent->OSEventGrp = 0x00; ptlb = & pevent->OSEventTbl[0]; #if OS_EVENT_TBL_SIZE > 0 *ptbl++ = 0x00; #endif #if OS_EVENT_TBL_SIZE > 1 *ptbl++ = 0x00; #endif . . . } Old version void OSEventWaitListInit (OS_EVENT *pevent) { INT8U i; pevent->OSEventGrp = 0x00; for (i = 0; i < OS_EVENT_TBL_SIZE; i++) { pevent->OSEventTbl[i] = 0x00; } } The code is implemented inline to avoid the overhead of a for loop
Making a task readyOSEventTaskRdy() • This function is called by • OSSemPost(), OSMutexPost(), OSMbosPost(), OSQPost(), and OSQPostFront() • Removes the highest priority task (HPT) from the wait list of the ECB and makes this task ready to run void OSEventTaskRdy (OS_EVENT *pevent, void *msg, INT8U msk) { OS_TCB *ptcb; INT8U x; INT8U y; INT8U bitx; INT8U bity; INT8U prio;
y = OSUnMapTbl[pevent->OSEventGrp]; (1) bity = OSMapTbl[y]; (2) x = OSUnMapTbl[pevent->OSEventTbl[y]]; (3) bitx = OSMapTbl[x]; (4) prio = (INT8U)((y << 3) + x); (5) if ((pevent->OSEventTbl[y] &= ~bitx) == 0) { (6) pevent->OSEventGrp &= ~bity; } ptcb = OSTCBPrioTbl[prio]; (7) ptcb->OSTCBDly = 0; (8) ptcb->OSTCBEventPtr = (OS_EVENT *)0; (9) #if (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_MBOX_EN ptcb->OSTCBMsg = msg; (10) #else msg = msg; //avoid a warning message in compiler #endif ptcb->OSTCBStat &= ~msk; //OS_STAT_SEM, OS_STAT_MUTEX, OS_STAT_MBOX, OS_STAT_Q (11) if (ptcb->OSTCBStat == OS_STAT_RDY) { (12) OSRdyGrp |= bity; (13) OSRdyTbl[y] |= bitx; } } OSEventTaskRdy (cont’d)
Making a task wait for an eventOSEventTaskWait() • Called by OSSemPend(), OSMutexPend(), OSMboxPend, and OSQPend() when a task must wait on an ECB • OSEventTaskWait() removes the current task from the ready list and places it in the wait list of the ECB void OSEventTaskWait (OS_EVENT *pevent) { OSTCBCur->OSTCBEventPtr = pevent; (1) if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) { (2) OSRdyGrp &= ~OSTCBCur->OSTCBBitY; } pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX; (3) pevent->OSEventGrp |= OSTCBCur->OSTCBBitY; }
Making a task ready because of a timeoutOSEventTO() • Called by OSSemPend(), OSMboxPend(), OSQPend() when a task has been made ready to run by OSTimeTick() • OSEventTO() must remove the task from the wait list of the ECB and mark the task as being ready void OSEventTO (OS_EVENT *pevent) { if ((pevent->OSEventTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) { (1) pevent->OSEventGrp &= ~OSTCBCur->OSTCBBitY; } OSTCBCur->OSTCBStat = OS_STAT_RDY; (2) OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; (3) }