180 likes | 327 Vues
This chapter delves into Event Control Blocks (ECBs) that manage task interactions and Interrupt Service Routines (ISRs) in real-time operating systems. It explains the structure of an ECB, detailing its components such as OSEventType, OSEventGrp, and OSEventCnt. Each task waiting for an event is placed in a wait list, enabling efficient task management. The chapter also covers operations like initializing an ECB, making tasks ready or waiting for events, and handling timeouts, illustrating how these operations can be implemented in code for effective multitasking.
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) }