μC/OS-II System Basics Embedded Development Programming Tutorial

μC/OS-II maintains all the information of an event control block through the OS_EVENT data structure defined in uCOS_II.H [List of procedures L6.1], which is the event control block ECB mentioned in the beginning of this chapter. In addition to the definition of the event itself, such as counters for semaphores, pointers to mailboxes, and arrays of pointers to message queues, the structure also defines a list of all tasks waiting for the event.

μC/OS-II System Basics Embedded Development Programming Tutorial

Typedef struct {

Void *OSEventPtr; /* Pointer to message or message queue */

INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* Wait for task list */

INT16U OSEventCnt; /* Counter (when the event is a semaphore) */

INT8U OSEventType; /* time type*/

INT8U OSEventGrp; /* group where the task is waiting */

} OS_EVENT;

.OSEventPtr Pointer, used only if the defined event is a mailbox or message queue. When the defined event is

When it is a mailbox, it points to a message. When the defined event is a message queue, it points to a data structure. See 6.06 for details.

Section message mailboxes and 6.07 message queues.

.OSEventTbl[] and .OSEventGrp are similar to the OSRdyTbl[] and OSRdyGrp mentioned earlier, but the former two

Contains tasks that wait for an event, while the latter two contain tasks that are in a ready state on the system. (See section 3.04

Thread table

.OSEventCnt When the event is a semaphore, .OSEventCnt is a counter for the semaphore (see Section 6.05).

signal).

e.OSEventType defines the specific type of event. It can be semaphore (OS_EVENT_SEM), mailbox

One of (OS_EVENT_TYPE_MBOX) or message queue (OS_EVENT_TYPE_Q). The user should be based on the specific value of the domain

To call the corresponding system function to ensure the correctness of its operation.

The following code places a task in the waiting task list for the event.

Listing L6.2 - Inserting a Task into the Waiting Task List of Events

Pevent->OSEventGrp |= OSMapTbl[prio >> 3];

Pevent->OSEventTbl[prio >> 3] |= OSMapTbl[prio & 0x07];

List of Procedures L6.3 Remove a Task from the Waiting Task List

If ((pevent->OSEventTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0) {

Pevent->OSEventGrp &= ~OSMapTbl[prio >> 3];

}

Checklist L6.4 Finding the Highest Priority Task in the Waiting Task List

y = OSUnMapTbl[pevent->OSEventGrp];

x = OSUnMapTbl[pevent->OSEventTbl[y]];

Prio = (y << 3) + x;

Void OSEventWaitListInit (OS_EVENT *pevent)

{

INT8U i;

Pevent->OSEventGrp = 0x00;

For (i = 0; i < OS_EVENT_TBL_SIZE; i++) {

Pevent->OSEventTbl[i] = 0x00;

}

}

List of Procedures L6.6 Makes a Task Ready

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)(( << << 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;

#endif

Ptcb->OSTCBStat &= ~msk; (11)

If (ptcb->OSTCBStat == OS_STAT_RDY) { (12)

OSRdyGrp |= bity; (13)

OSRdyTbl[y] |= bitx;

}

}

List of Procedures L6.7 Putting a Task Into a Wait State

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;

}

List of Programs L6.8 Make the Task Ready Because of a Wait Timeout

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)

}

signal

The semaphore in μC/OS-II consists of two parts: one is the semaphore count value, which is a 16-bit unsigned integer

Number (between 0 and 65,535); The other is a waiting task list consisting of tasks waiting for this semaphore. User wants to be in OS_CFG.H

Set the OS_SEM_EN binary constant to 1 so that μC/OS-II can support semaphores. signal

The semaphore in μC/OS-II consists of two parts: one is the semaphore count value, which is a 16-bit unsigned integer

Number (between 0 and 65,535); The other is a waiting task list consisting of tasks waiting for this semaphore. User wants to be in OS_CFG.H

Set the OS_SEM_EN binary constant to 1 so that μC/OS-II can support semaphores.

List of procedures to create a semaphore L6.9

OS_EVENT *OSSemCreate (INT16U cnt)

{

OS_EVENT *pevent;

OS_ENTER_CRITICAL();

Pevent = OSEventFreeList; (1)

If (OSEventFreeList != (OS_EVENT *)0) { (2)

OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;

}

OS_EXIT_CRITICAL();

If (pevent != (OS_EVENT *)0) { (3)

Pevent->OSEventType = OS_EVENT_TYPE_SEM; (4)

Pevent->OSEventCnt = cnt; (5)

OSEventWaitListInit(pevent); (6)

}

Return (pevent); (7)

}

Program Listing L6.10 Waits for a Semaphore

Void OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)

{

OS_ENTER_CRITICAL();

If (pevent->OSEventType != OS_EVENT_TYPE_SEM) { (1)

OS_EXIT_CRITICAL();

*err = OS_ERR_EVENT_TYPE;

}

If (pevent->OSEventCnt > 0) { (2)

Pevent->OSEventCnt--; (3)

OS_EXIT_CRITICAL();

*err = OS_NO_ERR;

6-15

} Else if (OSIntNesting > 0) { (4)

OS_EXIT_CRITICAL();

*err = OS_ERR_PEND_ISR;

} Else {

OSTCBCur->OSTCBStat |= OS_STAT_SEM; (5)

OSTCBCur->OSTCBDly = timeout; (6)

OSEventTaskWait(pevent); (7)

OS_EXIT_CRITICAL();

OSSched(); (8)

OS_ENTER_CRITICAL();

If (OSTCBCur->OSTCBStat & OS_STAT_SEM) { (9)

OSEventTO(pevent); (10)

OS_EXIT_CRITICAL();

*err = OS_TIMEOUT;

} Else {

OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; (11)

OS_EXIT_CRITICAL();

*err = OS_NO_ERR;

}

}

}

List L6.11 sends a semaphore

INT8U OSSemPost (OS_EVENT *pevent)

{

OS_ENTER_CRITICAL();

If (pevent->OSEventType != OS_EVENT_TYPE_SEM) { (1)

OS_EXIT_CRITICAL();

Return (OS_ERR_EVENT_TYPE);

}

If (pevent->OSEventGrp) { (2)

OSEventTaskRdy(pevent, (void *)0, OS_STAT_SEM); (3)

OS_EXIT_CRITICAL();

OSSched(); (4)

Return (OS_NO_ERR);

} Else {

If (pevent->OSEventCnt < 65535) {

Pevent->OSEventCnt++; (5)

OS_EXIT_CRITICAL();

Return (OS_NO_ERR);

} Else {

OS_EXIT_CRITICAL();

Return (OS_SEM_OVF);

}

}

}

List L6.12 Requests a Semaphore without Waiting

INT16U OSSemAccept (OS_EVENT *pevent)

{

INT16U cnt;

OS_ENTER_CRITICAL();

If (pevent->OSEventType != OS_EVENT_TYPE_SEM) { (1)

OS_EXIT_CRITICAL();

Return (0);

}

Cnt = pevent->OSEventCnt; (2)

If (cnt > 0) { (3)

Pevent->OSEventCnt--; (4)

}

OS_EXIT_CRITICAL();

Return (cnt); (5)

}

List of Procedures L6.13 Querying the Status of a Semaphore

INT8U OSSemQuery (OS_EVENT *pevent, OS_SEM_DATA *pdata)

{

INT8U i;

INT8U *psrc;

INT8U *pdest;

OS_ENTER_CRITICAL();

If (pevent->OSEventType != OS_EVENT_TYPE_SEM) { (1)

OS_EXIT_CRITICAL();

Return (OS_ERR_EVENT_TYPE);

}

Pdata->OSEventGrp = pevent->OSEventGrp; (2)

Psrc = &pevent->OSEventTbl[0];

Pdest = &pdata->OSEventTbl[0];

For (i = 0; i < OS_EVENT_TBL_SIZE; i++) {

*pdest++ = *psrc++;

}

Pdata->OSCnt = pevent->OSEventCnt; (3)

OS_EXIT_CRITICAL();

Return (OS_NO_ERR);

}

List of procedures L6.14 to create a mailbox

OS_EVENT *OSMboxCreate (void *msg)

6-20

{

OS_EVENT *pevent;

OS_ENTER_CRITICAL();

Pevent = OSEventFreeList;

If (OSEventFreeList != (OS_EVENT *)0) {

OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;

}

OS_EXIT_CRITICAL();

If (pevent != (OS_EVENT *)0) {

Pevent->OSEventType = OS_EVENT_TYPE_MBOX; (1)

Pevent->OSEventPtr = msg; (2)

OSEventWaitListInit(pevent);

}

Return (pevent); (3)

}

List L6.15 waiting for a message in a mailbox

Void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)

{

Void *msg;

OS_ENTER_CRITICAL();

If (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (1)

OS_EXIT_CRITICAL();

*err = OS_ERR_EVENT_TYPE;

Return ((void *)0);

}

Msg = pevent->OSEventPtr;

If (msg != (void *)0) { (2)

Pevent->OSEventPtr = (void *)0; (3)

OS_EXIT_CRITICAL();

*err = OS_NO_ERR;

} Else if (OSIntNesting > 0) { (4)

OS_EXIT_CRITICAL();

*err = OS_ERR_PEND_ISR;

} Else {

OSTCBCur->OSTCBStat |= OS_STAT_MBOX; (5)

OSTCBCur->OSTCBDly = timeout;

OSEventTaskWait(pevent);

OS_EXIT_CRITICAL();

OSSched();

OS_ENTER_CRITICAL();

If ((msg = OSTCBCur->OSTCBMsg) != (void *)0) { (6)

OSTCBCur->OSTCBMsg = (void *)0;

OSTCBCur->OSTCBStat = OS_STAT_RDY;

OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;

OS_EXIT_CRITICAL();

*err = OS_NO_ERR;

} Else if (OSTCBCur->OSTCBStat & OS_STAT_MBOX) { (7)

OSEventTO(pevent); (8)

OS_EXIT_CRITICAL();

Msg = (void *)0; (9)

*err = OS_TIMEOUT;

} Else {

6-22

Msg = pevent->OSEventPtr; (10)

Pevent->OSEventPtr = (void *)0;

(11)

OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; (12)

OS_EXIT_CRITICAL();

*err = OS_NO_ERR;

}

}

Return (msg);

}

List of Procedures L6.16 Sends a Message to the Mailbox

INT8U OSMboxPost (OS_EVENT *pevent, void *msg)

{

OS_ENTER_CRITICAL();

If (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (1)

OS_EXIT_CRITICAL();

Return (OS_ERR_EVENT_TYPE);

}

If (pevent->OSEventGrp) { (2)

OSEventTaskRdy(pevent, msg, OS_STAT_MBOX); (3)

OS_EXIT_CRITICAL();

OSSched(); (4)

Return (OS_NO_ERR);

} Else {

If (pevent->OSEventPtr != (void *)0) { (5)

OS_EXIT_CRITICAL();

Return (OS_MBOX_FULL);

} Else {

Pevent->OSEventPtr = msg; (6)

OS_EXIT_CRITICAL();

Return (OS_NO_ERR);

}

}

}

List of Procedures L6.16 Sends a Message to the Mailbox

INT8U OSMboxPost (OS_EVENT *pevent, void *msg)

{

OS_ENTER_CRITICAL();

If (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (1)

OS_EXIT_CRITICAL();

Return (OS_ERR_EVENT_TYPE);

}

If (pevent->OSEventGrp) { (2)

OSEventTaskRdy(pevent, msg, OS_STAT_MBOX); (3)

OS_EXIT_CRITICAL();

OSSched(); (4)

Return (OS_NO_ERR);

} Else {

If (pevent->OSEventPtr != (void *)0) { (5)

OS_EXIT_CRITICAL();

Return (OS_MBOX_FULL);

} Else {

Pevent->OSEventPtr = msg; (6)

OS_EXIT_CRITICAL();

Return (OS_NO_ERR);

}

}

}

List of procedures L6.17 get messages from the mailbox without waiting

Void *OSMboxAccept (OS_EVENT *pevent)

{

Void *msg;

OS_ENTER_CRITICAL();

If (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (1)

OS_EXIT_CRITICAL();

Return ((void *)0);

}

Msg = pevent->OSEventPtr; (2)

If (msg != (void *)0) { (3)

Pevent->OSEventPtr = (void *)0; (4)

}

OS_EXIT_CRITICAL();

Return (msg); (5)

}

List of procedures L6.18 query the status of the mailbox

INT8U OSMboxQuery (OS_EVENT *pevent, OS_MBOX_DATA *pdata)

{

INT8U i;

6-25

INT8U *psrc;

INT8U *pdest;

OS_ENTER_CRITICAL();

If (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (1)

OS_EXIT_CRITICAL();

Return (OS_ERR_EVENT_TYPE);

}

Pdata->OSEventGrp = pevent->OSEventGrp; (2)

Psrc = &pevent->OSEventTbl[0];

Pdest = &pdata->OSEventTbl[0];

For (i = 0; i < OS_EVENT_TBL_SIZE; i++) {

*pdest++ = *psrc++;

}

Pdata->OSMsg = pevent->OSEventPtr; (3)

OS_EXIT_CRITICAL();

Return (OS_NO_ERR);

}

List of procedures L6.19 uses mailboxes as binary semaphores

OS_EVENT *MboxSem;

Void Task1 (void *pdata)

{

INT8U err;

For (;;) {

OSMboxPend(MboxSem, 0, &err); /* Get access to resources */

6-26

.

. /* task gets semaphores and accesses resources */

.

OSMboxPost(MboxSem, (void*)1); /* Release access to resources*/

}

}

List of procedures L6.21 establish a message queue

OS_EVENT *OSQCreate (void **start, INT16U size)

{

OS_EVENT *pevent;

OS_Q *pq;

OS_ENTER_CRITICAL();

Pevent = OSEventFreeList; (1)

If (OSEventFreeList != (OS_EVENT *)0) {

OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; (2)

}

OS_EXIT_CRITICAL();

If (pevent != (OS_EVENT *)0) {

OS_ENTER_CRITICAL();

Pq = OSQFreeList; (3)

If (OSQFreeList != (OS_Q *)0) {

OSQFreeList = OSQFreeList->OSQPtr;

}

OS_EXIT_CRITICAL();

If (pq != (OS_Q *)0) {

Pq->OSQStart = start; (4)

Pq->OSQEnd = &start[size];

Pq->OSQIn = start;

Pq->OSQOut = start;

Pq->OSQSize = size;

Pq->OSQEntries = 0;

Pevent->OSEventType = OS_EVENT_TYPE_Q; (5)

Pevent->OSEventPtr = pq; (6)

OSEventWaitListInit(pevent); (7)

} Else {

OS_ENTER_CRITICAL();

Pevent->OSEventPtr = (void *)OSEventFreeList; (8)

6-33

OSEventFreeList = pevent;

OS_EXIT_CRITICAL();

Pevent = (OS_EVENT *)0;

}

}

Return (pevent); (9)

}

9.03 OS_CPU.H File

The OS_CPU.H file contains definitions of processor-related constants, macros, and structures. List of procedures L9.2 is 80x86 series

Write the contents of the OS_CPU.H file.

9.04 OS_CPU_A.ASM

Migration of μC/OS-II requires the user to override the four functions in OS_CPU_A.ASM:

OSStartHighRdy()

OSCtxSw()

OSIntCtxSw()

OSTickISR()

9.04.01 OSStartHighRdy()

This function is called by the SStart() function. The function is to run the highest priority ready task before calling OSStart().

The user must first call OSInit() and have created at least one task (see OSTaskCreate() and

OSTaskCreateExt() function). OSStartHighRdy() default pointer OSTCBHighRdy points to the highest priority ready task

The task control block (OS_TCB) (previously OSTCBHighRdy was set by OSStart()). Figure F9.3 gives

The stack structure of the task created by the function OSTaskCreate() or OSTaskCreateExt(). It is clear,

OSTCBHighRdy->OSTCBStkPtr points to the top of the task stack.

List of procedures L 9.3 OSStartHighRdy().

_OSStartHighRdy PROC FAR

MOV AX, SEG _OSTCBHighRdy ; Load DS

MOV DS, AX ;

LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr

(1)

MOV SS, ES: [BX+2] ;

MOV SP, ES:[BX+0];

;

POP DS ; Recovery Task Environment (2)

POP ES; (3)

POPA; (4)

;

IRET ; Running Tasks (5)

_OSStartHighRdy ENDP

9.05 OS_CPU_C.C

Migration of μC/OS-II requires the user to overwrite six functions in OS_CPU_C.C:

OSTaskStkInit()

OSTaskCreateHook()

OSTaskDelHook()

OSTaskSwHook()

OSTaskStatHook()

OSTimeTickHook()

The return value of OSTaskResume () is one of the following:

OS_NO_ERR: The function call succeeded.

OS_TASK_RESUME_PRIO: The task to wake up does not exist.

OS_TASK_NOT_SUSPENDED: The task to wake up is not pending.

• The OS_PRIO_INVALID: parameter specifies a priority greater than or equal to OS_LOWEST_PRIO.

OS_MAX_EVENTS defines the maximum number of event control blocks in the system. Every message mailbox in the system, the news team

Columns, semaphores all require an event control block. For example, there are 10 message mailboxes, 5 message queues, and 3 signals in the system

Quantity, the minimum OS_MAX_EVENTS should be 18. As long as the program uses message mailboxes, message queues or semaphores,

The minimum OS_MAX_EVENTS should be set to 2.

Protectors

Temperature Controlling Thermostat,Thermal Cutout Water Heater,Thermal Cut Out,Limit Thermostat Cutout

Foshan City Jiulong Machine Co., Ltd , https://www.jlthermostat.com