- •Preface
- •Introduction
- •1.01 INCLUDES.H
- •1.02 Compiler Independent Data Types
- •1.03 Global Variables
- •1.04 OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL()
- •1.05 PC Based Services
- •1.05.01 PC Based Services, Character Based Display
- •1.05.02 PC Based Services, Elapsed Time Measurement
- •1.05.03 PC Based Services, Miscellaneous
- •1.07 Example #1
- •1.08 Example #2
- •1.09 Example #3
- •2.00 Foreground/Background Systems
- •2.01 Critical Section of Code
- •2.02 Resource
- •2.03 Shared Resource
- •2.04 Multitasking
- •2.05 Task
- •2.06 Context Switch (or Task Switch)
- •2.07 Kernel
- •2.08 Scheduler
- •2.09 Non-Preemptive Kernel
- •2.10 Preemptive Kernel
- •2.11 Reentrancy
- •2.12 Round Robin Scheduling
- •2.13 Task Priority
- •2.14 Static Priorities
- •2.15 Dynamic Priorities
- •2.16 Priority Inversions
- •2.17 Assigning Task Priorities
- •2.19 Mutual Exclusion
- •2.20 Deadlock (or Deadly Embrace)
- •2.21 Synchronization
- •2.22 Event Flags
- •2.23 Intertask Communication
- •2.24 Message Mailboxes
- •2.25 Message Queues
- •2.26 Interrupts
- •2.27 Interrupt Latency
- •2.28 Interrupt Response
- •2.29 Interrupt Recovery
- •2.30 Interrupt Latency, Response, and Recovery
- •2.31 ISR Processing Time
- •2.32 Non-Maskable Interrupts (NMIs)
- •2.33 Clock Tick
- •2.34 Memory Requirements
- •2.35 Advantages and Disadvantages of Real-Time Kernels
- •2.36 Real-Time Systems Summary
- •3.00 Critical Sections
- •3.01 Tasks
- •3.02 Task States
- •3.03 Task Control Blocks (OS_TCBs)
- •3.04 Ready List
- •3.05 Task Scheduling
- •3.06 Locking and Unlocking the Scheduler
- •3.07 Idle Task
- •3.08 Statistics Task
- •3.10 Clock Tick
- •3.14 OSEvent???() functions
- •4.00 Creating a Task, OSTaskCreate()
- •4.01 Creating a Task, OSTaskCreateExt()
- •4.02 Task Stacks
- •4.03 Stack Checking, OSTaskStkChk()
- •4.04 Deleting a Task, OSTaskDel()
- •4.05 Requesting to delete a task, OSTaskDelReq()
- •4.06 Changing a Task’s Priority, OSTaskChangePrio()
- •4.07 Suspending a Task, OSTaskSuspend()
- •4.08 Resuming a Task, OSTaskResume()
- •4.09 Getting Information about a Task, OSTaskQuery()
- •5.00 Delaying a task, OSTimeDly()
- •5.01 Delaying a task, OSTimeDlyHMSM()
- •5.02 Resuming a delayed task, OSTimeDlyResume()
- •5.03 System time, OSTimeGet() and OSTimeSet()
- •6.00 Event Control Blocks
- •6.01 Initializing an ECB, OSEventWaitListInit()
- •6.02 Making a task ready, OSEventTaskRdy()
- •6.03 Making a task wait for an event, OSEventTaskWait()
- •6.04 Making a task ready because of a timeout, OSEventTO()
- •6.05 Semaphores
- •6.06 Message Mailboxes
- •6.07 Message Queues
- •7.00 Memory Control Blocks
- •7.01 Creating a partition, OSMemCreate()
- •7.02 Obtaining a memory block, OSMemGet()
- •7.03 Returning a memory block, OSMemPut()
- •7.04 Obtaining status about memory partition, OSMemQuery()
- •7.05 Using memory partitions
- •7.06 Waiting for memory blocks from a partition
- •8.00 Development Tools
- •8.01 Directories and Files
- •8.02 INCLUDES.H
- •9.00 Development Tools
- •9.01 Directories and Files
- •9.02 INCLUDES.H
- •9.06 Memory requirements
- •9.07 Execution times
- •10.00 Directories and Files
- •10.01 INCLUDES.H
- •10.02.01 OS_CPU.H, Compiler specific data types
- •10.02.02 OS_CPU.H, OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL()
- •10.02.03 OS_CPU.H, OS_STK_GROWTH
- •10.02.04 OS_CPU.H, OS_TASK_SW()
- •10.03.01 OS_CPU_A.ASM, OSStartHighRdy()
- •10.03.02 OS_CPU_A.ASM, OSCtxSw()
- •10.03.03 OS_CPU_A.ASM, OSIntCtxSw()
- •10.03.04 OS_CPU_A.ASM, OSTickISR()
- •10.04.01 OS_CPU_C.C, OSTaskStkInit()
- •10.04.02 OS_CPU_C.C, OSTaskCreateHook()
- •10.04.03 OS_CPU_C.C, OSTaskDelHook()
- •10.04.04 OS_CPU_C.C, OSTaskSwHook()
- •10.04.05 OS_CPU_C.C, OSTaskStatHook()
- •10.04.06 OS_CPU_C.C, OSTimeTickHook()
- •10.05 Summary
- •OSInit()
- •OSIntEnter()
- •OSIntExit()
- •OSMboxAccept()
- •OSMboxCreate()
- •OSMboxPend()
- •OSMboxPost()
- •OSMboxQuery()
- •OSMemCreate()
- •OSMemGet()
- •OSMemPut()
- •OSMemQuery()
- •OSQAccept()
- •OSQCreate()
- •OSQFlush()
- •OSQPend()
- •OSQPost()
- •OSQPostFront()
- •OSQQuery()
- •OSSchedLock()
- •OSSchedUnlock()
- •OSSemAccept()
- •OSSemCreate()
- •OSSemPend()
- •OSSemPost()
- •OSSemQuery()
- •OSStart()
- •OSStatInit()
- •OSTaskChangePrio()
- •OSTaskCreate()
- •OSTaskCreateExt()
- •OSTaskDel()
- •OSTaskDelReq()
- •OSTaskResume()
- •OSTaskStkChk()
- •OSTaskSuspend()
- •OSTaskQuery()
- •OSTimeDly()
- •OSTimeDlyHMSM()
- •OSTimeDlyResume()
- •OSTimeGet()
- •OSTimeSet()
- •OSTimeTick()
- •OSVersion()
3.10 Clock Tick
µC/OS-II requires that you provide a periodic time source to keep track of time delays and timeouts. A tick should occur between 10 and 100 times per second, or Hertz. The faster the tick rate, the higher the overhead imposed on the system. The actual frequency of the clock tick depends on the desired tick resolution of your application. You can obtain a tick source by either dedicating a hardware timer, or generating an interrupt from an AC power line (50/60 Hz) signal.
You MUST enable ticker interrupts AFTER multitasking has started, i.e. after calling OSStart(). In other words, you should initialize and tick interrupts in the first task that executes following a call to OSStart(). A common mistake is to enable ticker interrupts between calling OSInit() and OSStart() as shown in listing 3.18.
void main(void) |
|
|
{ |
|
|
. |
|
|
. |
|
|
OSInit(); |
/* Initialize µC/OS-II |
*/ |
. |
|
|
. |
|
|
/* Application initialization code ... |
*/ |
|
/* ... Create at least on task by calling OSTaskCreate() |
*/ |
|
. |
|
|
. |
|
|
Enable TICKER interrupts; /* DO NOT DO THIS HERE!!! |
*/ |
|
. |
|
|
. |
|
|
OSStart(); |
/* Start multitasking |
*/ |
} |
|
|
Listing 3.18, Incorrect way to start the ticker.
What could happen (and it has happened) is that the tick interrupt could be serviced before µC/OS -II starts the first task. At this point, µC/OS-II is in an unknown state and will cause your application to crash.
µC/OS-II’s clock tick is serviced by calling OSTimeTick() from a tick ISR. The tick ISR follows all the rules described in the previous section. The pseudo code for the tick ISR is shown in listing 3.19. This code must be written in assembly language because you cannot access CPU registers directly from C.
void OSTickISR(void)
{
Save processor registers;
Call OSIntEnter() or increment OSIntNesting; Call OSTimeTick();
Call OSIntExit();
Restore processor registers;
Execute a return from interrupt instruction;
}
Listing 3.19, Pseudo code for Tick ISR.
The code for OSTimeTick() is shown in listing 3.20. OSTimeTick() starts by calling a user definable function (OSTimeTickHook()) which can be used to extend the functionality of OSTimeTick() L3.20(1). I decided to call OSTimeTickHook() first to give your application a chance to do something as soon as the tick is serviced because you may have some time critical work to do. Most of the work done byOSTimeTick() basically consist of decrementing the OSTCBDly field for each OS_TCB (if it’s nonzero). OSTimeTick() follows the chain of OS_TCB starting at OSTCBList L3.20(2) until it reaches the idle task L3.20(3). When the OSTCBDly field of a task's OS_TCB is decremented to zero, the task is made ready to run L3.20(4). The task is not readied, however, if it was explicitly suspended by OSTaskSuspend() L3.20(5). The execution time of OSTimeTick() is directly proportional to the number of tasks created in an application.
void OSTimeTick (void)
{
OS_TCB *ptcb; |
|
|
OSTimeTickHook(); |
|
(1) |
ptcb = OSTCBList; |
|
(2) |
while (ptcb->OSTCBPrio != OS_IDLE_PRIO) { |
(3) |
|
OS_ENTER_CRITICAL(); |
|
|
if (ptcb->OSTCBDly != 0) { |
|
|
if (--ptcb->OSTCBDly == 0) { |
|
|
if (!(ptcb->OSTCBStat & OS_STAT_SUSPEND)) { |
(5) |
|
OSRdyGrp |
|= ptcb->OSTCBBitY; |
(4) |
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; |
|
|
} else { |
|
|
ptcb->OSTCBDly = 1; |
|
|
} |
|
|
} |
|
|
} |
|
|
ptcb = ptcb->OSTCBNext; |
|
|
OS_EXIT_CRITICAL(); |
|
|
} |
|
|
OS_ENTER_CRITICAL(); |
|
(7) |
OSTime++; |
|
(6) |
OS_EXIT_CRITICAL(); |
|
|
}
Listing 3.20, Code to service a tick.
OSTimeTick() also accumulates the number of clock ticks since power up in an unsigned 32-bit variable called OSTime L3.20(6). Note that I disable interrupts L3.20(7) before incrementing OSTime because on some processors, a 32-bit increment will most likely be done using multiple instructions.
If you don't like to make ISRs any longer than they must be, OSTimeTick() can be called at the task level as shown
in listing 3.21. To do this, you would create a task which has a higher priority than all your application tasks. The tick ISR would need to signal this high priority task by using either a semaphore or a message mailbox.
void TickTask (void *pdata) |
|
{ |
|
pdata = pdata; |
|
for (;;) { |
|
OSMboxPend(...); |
/* Wait for signal from Tick ISR */ |
OSTimeTick(); |
|
} |
|
} |
|
Listing 3.21, Code to service a tick.
You would obviously need to create a mailbo x (initialized to NULL) which would signal the task that a tick interrupt occurred. The tick ISR would now look as shown in listing 3.22.
void OSTickISR(void)
{
Save processor registers;
Call OSIntEnter() or increment OSIntNesting;
Post a ‘dummy’ message (e.g. (void *)1) to the tick mailbox;
Call OSIntExit();
Restore processor registers;
Execute a return from interrupt instruction;
}
Listing 3.22, Code to service a tick.
3.11 µC/OS-II Initialization
A requirement of µC/OS-II is that you call OSInit() before you call any of its other services. OSInit() initializes all of µC/OS-II’s variables and data structures (see OS_CORE.C).
OSInit() creates the idle task (OSTaskIdle()) which is always ready -to-run. The priority of OSTaskIdle() is always set to OS_LOWEST_PRIO. If OS_TASK_STAT_EN and OS_TASK_CREATE_EXT_EN (see OS_CFG.H) are both set to 1, OSInit() also creates the statistic task, OSTaskStat() and makes it ready-to-run. The priority of OSTaskStat() is always set to OS_LOWEST_PRIO – 1.
Figure 3-7 shows the relationship between some of µC/OS-II’s variables and data structures after calling OSInit(). The illustration assumes that:
1.OS_TASK_STAT_EN is set to 1 in OS_CFG.H
2.OS_LOWEST_PRIO is set to 63 in OS_CFG.H
3.OS_MAX_TASKS is set to a value higher that 2 in OS_CFG.H
The Task Control Blocks (OS_TCBs) of these two tasks are chained together in a doubly -linked list. OSTCBList points to the beginning of this chain. When a task is created, it is always placed at the beginning of the list. In other words, OSTCBList always points to the OS_TCB of last task created. The ends of the chain point to NULL (i.e. 0).
Because both tasks are ready-to-run, their corresponding bit in OSRdyTbl[] are set to 1. Also, because the bit of both tasks are on the same row in OSRdyTbl[], only one bit in OSRdyGrp is set to 1.
|
|
OSRdyGrp |
|
Ready List |
|
|
|
|
|
|
|
|
|
|
||||||
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
|
|
OSRdyTbl[] |
|
|
OSTCBPrioTbl[] |
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
0 |
|
[0] |
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0 |
|
[1] |
|
|
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
|
0 |
|
[2] |
||
|
|
|
|
|
|
|
|
0 |
|
[3] |
||||||||||
|
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
|
0 |
|
[4] |
||
|
|
|
|
|
|
|
|
0 |
|
[5] |
||||||||||
|
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
|
0 |
|
[6] |
||
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||
|
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
|
0 |
|
|
||
|
|
|
|
|
|
|
|
0 |
|
|
||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0 |
|
[OS_LOWEST_PRIO - 1] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[OS_LOWEST_PRIO] |
|
|
|
|
|
|
|
|
|
|
OSTaskStat() |
OSTaskIdle() |
|||||||||
|
|
|
|
|
|
|
|
|
|
|
|
OS_TCB |
|
|
|
|
OS_TCB |
|
|
|
OSTCBList
OSPrioCur |
= 0 |
0 |
OSPrioHighRdy = 0 |
||
OSTCBCur |
= NULL |
|
OSTCBHighRdy |
= NULL |
|
OSTime |
= 0L |
|
OSIntNesting |
= 0 |
|
OSLockNesting = 0 |
|
|
OSCtxSwCtr |
= 0 |
|
OSTaskCtr |
= 2 |
|
OSRunning |
= FALSE |
|
OSCPUUsage |
= 0 |
|
OSIdleCtrMax |
= 0L |
|
OSIdleCtrRun |
= 0L |
|
OSIdleCtr |
= 0L |
|
OSStatRdy |
= FALSE |
|
OSTCBStkPtr |
OSTCBExtPtr = NULL |
OSTCBStkBottom |
OSTCBStkSize = stack size |
OSTCBId = OS_LOWEST_PRIO |
OSTCBNext |
OSTCBPrev |
OSTCBEventPtr = NULL |
OSTCBMsg = NULL |
OSTCBDly = 0 |
OSTCBStat = OS_STAT_RDY |
OSTCBPrio = OS_LOWEST_PRIO-1 |
OSTCBX = 6 |
OSTCBY = 7 |
OSTCBBitX = 0x40 |
OSTCBBitY = 0x80 |
OSTCBDelReq = FALSE |
OSTCBStkPtr |
|
|
|
|
|
|
|
OSTCBExtPtr = NULL |
|
|
|
|
|||
OSTCBStkBottom |
|
|
|
|
|
||
OSTCBStkSize = stack size |
|
|
|
|
|||
OSTCBId = OS_LOWEST_PRIO |
|
|
|
|
|||
OSTCBNext |
|
|
|
|
|||
OSTCBPrev |
|
|
|
|
|||
OSTCBEventPtr = NULL |
|
|
|
|
|||
OSTCBMsg = NULL |
|
|
|
0 |
|||
OSTCBDly = 0 |
|
|
|
||||
OSTCBStat = OS_STAT_RDY |
|
|
|||||
OSTCBPrio = OS_LOWEST_PRIO |
|
|
|
|
|||
OSTCBX = 7 |
|
|
|
|
|||
OSTCBY = 7 |
|
|
|
|
|||
OSTCBBitX = 0x80 |
|
|
|
|
|||
OSTCBBitY = 0x80 |
|
|
|
|
|||
OSTCBDelReq = FALSE |
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Task Stack
Task Stack
Figure 3-7, Data structures after calling OSInit()
µC/OS-II also initializes four pools of free data structures as shown in figure 3-8. Each of these pools are singly linked lists and allows µC/OS-II to quickly obtain and return an element from and to a pool. Note that the number of free OS_TCBs in the free pool is determined by OS_MAX_TASKS specified in OS_CFG.H. µC/OS -II automatically allocates OS_N_SYS_TASKS (see uCOS_II.H) OS_TCB entries automatically. This of course allows for sufficient task control blocks for the statistic task and the idle task. The lists pointed to by OSEventFreeList and OSQFreeList will be discussed in Chapter 6, Intertask Communication & Synchronization . The list pointed to by OSMemFreeList will be discussed in Chapter 7, Memory Management.
OSTCBFreeList
OS_MAX_TASKS
OS_TCB |
OS_TCB |
|
OS_TCB |
|
OS_TCB |
|
||
OSTCBStkPtr |
OSTCBStkPtr |
|
OSTCBStkPtr |
|
OSTCBStkPtr |
|
||
OSTCBExtPtr |
OSTCBExtPtr |
|
OSTCBExtPtr |
|
OSTCBExtPtr |
|
||
OSTCBStkBottom |
OSTCBStkBottom |
|
OSTCBStkBottom |
|
OSTCBStkBottom |
|
||
OSTCBStkSize |
OSTCBStkSize |
|
OSTCBStkSize |
|
OSTCBStkSize |
|
||
OSTCBId |
OSTCBId |
|
OSTCBId |
|
OSTCBId |
|
||
OSTCBNext |
|
OSTCBNext |
|
OSTCBNext |
|
OSTCBNext |
|
0 |
OSTCBPrev |
OSTCBPrev |
|
OSTCBPrev |
|
OSTCBPrev |
|||
OSTCBEventPtr |
OSTCBEventPtr |
|
OSTCBEventPtr |
|
OSTCBEventPtr |
|
||
OSTCBMsg |
OSTCBMsg |
|
OSTCBMsg |
|
OSTCBMsg |
|
||
OSTCBDly |
OSTCBDly |
|
OSTCBDly |
|
OSTCBDly |
|
||
OSTCBStat |
OSTCBStat |
|
OSTCBStat |
|
OSTCBStat |
|
||
OSTCBPrio |
OSTCBPrio |
|
OSTCBPrio |
|
OSTCBPrio |
|
||
OSTCBX |
OSTCBX |
|
OSTCBX |
|
OSTCBX |
|
||
OSTCBY |
OSTCBY |
|
OSTCBY |
|
OSTCBY |
|
||
OSTCBBitX |
OSTCBBitX |
|
OSTCBBitX |
|
OSTCBBitX |
|
||
OSTCBBitY |
OSTCBBitY |
|
OSTCBBitY |
|
OSTCBBitY |
|
||
OSTCBDelReq |
OSTCBDelReq |
|
OSTCBDelReq |
|
OSTCBDelReq |
|
||
OSEventFreeList 
OSQFreeList
OS_MAX_EVENTS 
OS_EVENT |
OS_EVENT |
OS_EVENT |
OS_EVENT |
|
OSEventPtr |
OSEventPtr |
OSEventPtr |
OSEventPtr |
0 |
OSEventTbl[] |
OSEventTbl[] |
OSEventTbl[] |
OSEventTbl[] |
|
OSEventCnt |
OSEventCnt |
OSEventCnt |
OSEventCnt |
|
OSEventType |
OSEventType |
OSEventType |
OSEventType |
|
OSEventGrp |
OSEventGrp |
OSEventGrp |
OSEventGrp |
|
|
|
OS_MAX_QS |
|
|
OS_Q |
OS_Q |
OS_Q |
OS_Q |
|
OSQPtr |
OSQPtr |
OSQPtr |
OSQPtr |
0 |
OSQStart |
OSQStart |
OSQStart |
OSQStart |
|
OSQEnd |
OSQEnd |
OSQEnd |
OSQEnd |
|
OSQIn |
OSQIn |
OSQIn |
OSQIn |
|
OSQOut |
OSQOut |
OSQOut |
OSQOut |
|
OSQSize |
OSQSize |
OSQSize |
OSQSize |
|
OSQEntries |
OSQEntries |
OSQEntries |
OSQEntries |
|
OS_MAX_MEM_PART
OSMemFreeList
OS_MEM |
OS_MEM |
OS_MEM |
OS_MEM |
|
OSMemAddr |
OSMemAddr |
OSMemAddr |
OSMemAddr |
|
OSMemFreeList |
OSMemFreeList |
OSMemFreeList |
OSMemFreeList |
0 |
OSMemBlkSize |
OSMemBlkSize |
OSMemBlkSize |
OSMemBlkSize |
|
OSMemNBlks |
OSMemNBlks |
OSMemNBlks |
OSMemNBlks |
|
OSNFree |
OSNFree |
OSNFree |
OSNFree |
|
Figure 3-8, Free Pools
3.12 Starting µC/OS-II
You start multitasking by calling OSStart() . Before you start µC/OS-II, however, you MUST create at least one of your application tasks as shown in listing 3.23.
void main (void) |
|
|
{ |
|
|
OSInit(); |
/* Initialize uC/OS-II |
*/ |
. |
|
|
.
Create at least 1 task using either OSTaskCreate() or OSTaskCreateExt();
. |
|
. |
|
OSStart(); |
/* Start multitasking! OSStart() will not return */ |
} |
|
|
Listing 3.23, Initializing and Starting µC/OS-II. |
The code for OSStart() is shown in listing 3.24. When called, OSStart() finds the OS_TCB of the highest priority task that you have created (done through the ready list) L3.24(1). Then, OSStart() calls OSStartHighRdy() L3.24(2) (see OS_CPU_A.ASM) for the processor being used. Basically, OSStartHighRdy() restores the CPU registers by popping them off the task’s stack and then, executes a return from interrupt instruction which forces the CPU to execute your task’s code (see Section 9.04.01, OS_CPU_A.ASM, OSStartHighRdy() for details on how this is done for the 80x86). You should note that OSStartHighRdy() will never return to OSStart().
void OSStart (void)
{
INT8U y; INT8U x;
if (OSRunning == FALSE) { |
|
|
y |
= OSUnMapTbl[OSRdyGrp]; |
|
x |
= OSUnMapTbl[OSRdyTbl[y]]; |
|
OSPrioHighRdy = (INT8U)((y << 3) + x); |
|
|
OSPrioCur |
= OSPrioHighRdy; |
|
OSTCBHighRdy |
= OSTCBPrioTbl[OSPrioHighRdy]; |
(1) |
OSTCBCur |
= OSTCBHighRdy; |
|
OSStartHighRdy(); |
(2) |
|
} |
|
|
}
Listing 3.24, Starting multitasking.
Figure 3-9 shows the contents of the variables and data structures after multitasking has started. Here I assumed that the task you created has a priority of 6. You will notice that OSTaskCtr indicates that three tasks have been created, OSRunning is set toTRUE indicating that multitasking has started,OSPrioCur andOSPrioHighRdy contain the priority of your application task and, OSTCBCur and OSTCBHighRdy both point to the OS_TCB of your task.
|
|
|
|
OSRdyGrp |
|
Ready List |
|
|
|
|
|
|
|
|||||
OSTime |
= 0L |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
|
OSRdyTbl[] |
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
OSIntNesting |
= 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OSLockNesting |
= 0 |
|
|
|
|
|
|
|
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
|
|
OSCtxSwCtr |
= 0 |
|
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
|
|
OSTaskCtr |
= 3 |
|
|
|
|
|
|
|
|
|
||||||||
OSRunning |
= TRUE |
|
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
|
|
OSCPUUsage |
= 0 |
|
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
|
|
OSIdleCtrMax |
= 0L |
|
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
|
|
OSIdleCtrRun |
= 0L |
|
|
|
|
|
|
|
OSTCBPrioTbl[] |
|||||||||
OSIdleCtr |
= 0L |
|
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
||
OSStatRdy |
= FALSE |
|
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
[0] |
|
|
|
|
|
|
|
|
|
0 |
[1] |
||||||||
OSPrioCur |
= 6 |
|
|
|
|
|
|
|
1 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
[2] |
|
|
|
|
|
|
|
0 |
[3] |
||||||||||
OSPrioHighRdy = 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0 |
[4] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0 |
[5] |
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[6] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0 |
[OS_LOWEST_PRIO - 1] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[OS_LOWEST_PRIO] |
|
YouAppTask() |
|
|
|
OSTaskStat() |
|
|
|
OSTaskIdle() |
|||||||||
|
|
OS_TCB |
|
|
|
|
|
|
|
OS_TCB |
|
|
|
|
|
|
OS_TCB |
|
OSTCBCur
OSTCBHighRdy
OSTCBList
0
OSTCBStkPtr OSTCBExtPtr = NULL
OSTCBStkBottom OSTCBStkSize = stack size
OSTCBId = 6
OSTCBNext
OSTCBPrev
OSTCBEventPtr = NULL OSTCBMsg = NULL
OSTCBDly = 0
OSTCBStat = OS_STAT_RDY
OSTCBPrio = 6
OSTCBX = 6
OSTCBY = 0 OSTCBBitX = 0x40
OSTCBBitY = 0x01 OSTCBDelReq = FALSE
OSTCBStkPtr |
OSTCBExtPtr = NULL |
OSTCBStkBottom |
OSTCBStkSize = stack size |
OSTCBId = OS_LOWEST_PRIO |
OSTCBNext |
OSTCBPrev |
OSTCBEventPtr = NULL |
OSTCBMsg = NULL |
OSTCBDly = 0 |
OSTCBStat = OS_STAT_RDY |
OSTCBPrio = OS_LOWEST_PRIO-1 |
OSTCBX = 6 |
OSTCBY = 7 |
OSTCBBitX = 0x40 |
OSTCBBitY = 0x80 |
OSTCBDelReq = FALSE |
OSTCBStkPtr |
|
|
|
|
|
|
|
OSTCBExtPtr = NULL |
|
|
|
|
|||
OSTCBStkBottom |
|
|
|
|
|
||
OSTCBStkSize = stack size |
|
|
|
|
|||
OSTCBId = OS_LOWEST_PRIO |
|
|
|
|
|||
OSTCBNext |
|
|
|
|
|||
OSTCBPrev |
|
|
|
|
|||
OSTCBEventPtr = NULL |
|
|
|
|
|||
OSTCBMsg = NULL |
|
|
|
0 |
|||
OSTCBDly = 0 |
|
|
|
||||
OSTCBStat = OS_STAT_RDY |
|
|
|||||
OSTCBPrio = OS_LOWEST_PRIO |
|
|
|
|
|||
OSTCBX = 7 |
|
|
|
|
|||
OSTCBY = 7 |
|
|
|
|
|||
OSTCBBitX = 0x80 |
|
|
|
|
|||
OSTCBBitY = 0x80 |
|
|
|
|
|||
OSTCBDelReq = FALSE |
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Task Stack
Task Stack
Task Stack
Figure 3-9, Variables and Data Structures after calling OSStart()
3.13 Obtaining µC/OS-II’s version
You can obtain the current version of µC/OS-II from your application by calling OSVersion(). OSVersion() returns the version number multiplied by 100. In other words, version 1.00 would be returned as 100.
INT16U OSVersion (void)
{
return (OS_VERSION);
}
Listing 3.25, Getting µC/OS-II’s version.
