- •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()
\SOFTWARE\uCOS\M68HC11 |
\SOFTWARE\uCOS-II\M68HC11 |
M68HC11.H |
OS_CPU.H |
M68HC11.C |
OS_CPU_C.C |
|
|
\SOFTWARE\uCOS\Z80 |
\SOFTWARE\uCOS-II\Z80 |
Z80.H |
OS_CPU.H |
Z80_A.ASM |
OS_CPU_A.ASM |
Z80_C.C |
OS_CPU_C.C |
Table 10.2, Renaming files from µC/OS to µC/OS-II
10.01INCLUDES.H
You will need to modify the INCLUDES.H file of your application. For example, the µC/OS INCLUDES.H file for the Intel 80x86 real mode, large model looks as shown in listing 10.1. You will need to edit this file and change:
a)the directory name UCOS to uCOS-II
b)the file name IX86L.H to OS_CPU.H
c)the file name UCOS.H to uCOS_II.H
The new file should thus look as shown in listing 10.2.
/*
***************************************************************
* INCLUDES.H
***************************************************************
*/
#include <STDIO.H> #include <STRING.H> #include <CTYPE.H> #include <STDLIB.H> #include <CONIO.H> #include <DOS.H>
#include "\SOFTWARE\UCOS\IX86L\IX86L.H" #include "OS_CFG.H"
#include "\SOFTWARE\UCOS\SOURCE\UCOS.H"
Listing 10.1, µC/OS INCLUDES.H
/*
***************************************************************
* INCLUDES.H
***************************************************************
*/
#include <STDIO.H>
#include <STRING.H> #include <CTYPE.H>
#include <STDLIB.H> #include <CONIO.H> #include <DOS.H>
#include "\SOFTWARE\uCOS-II\IX86L\OS_CPU.H" #include "OS_CFG.H"
#include "\SOFTWARE\uCOS-II\SOURCE\uCOS_II.H"
Listing 10.2, µC/OS-II INCLUDES.H
10.02OS_CPU.H
OS_CPU.Hcontains processor and implementation specific #defines constants, macros, and typedefs.
10.02.01 OS_CPU.H, Compiler specific data types
To satisfy µC/OS-II, you will need to create six new data types: INT8U, INT8S, INT16U, INT16S, INT32U and INT32S. These corresponds to unsigned and signed 8, 16 and 32 bit integers, respectively. In µC/OS, I had declared the equivalent data types: UBYTE, BYTE, UWORD, WORD, ULONG and LONG. All you have to do is copy the µC/OS data types and change UBYTE to INT8U, BYTE to INT8S, UWORD to INT16U … as shown in listing 10.3.
/* uC/OS data types: |
|
|
|
|
*/ |
|
typedef unsigned |
char |
UBYTE; |
/* Unsigned |
8 |
bit quantity |
*/ |
typedef signed |
char |
BYTE; |
/* Signed |
8 |
bit quantity |
*/ |
typedef unsigned |
int |
UWORD; |
/* Unsigned 16 bit quantity |
*/ |
||
typedef signed |
int |
WORD; |
/* Signed |
16 bit quantity |
*/ |
|
typedef unsigned |
long |
ULONG; |
/* Unsigned 32 bit quantity |
*/ |
||
typedef signed |
long |
LONG; |
/* Signed |
32 |
bit quantity |
*/ |
/* uC/OS-II data |
types |
|
|
|
|
*/ |
typedef unsigned |
char |
INT8U; |
/* Unsigned |
8 |
bit quantity |
*/ |
typedef signed |
char |
INT8S; |
/* Signed |
8 |
bit quantity |
*/ |
typedef unsigned |
int |
INT16U; |
/* Unsigned 16 bit quantity |
*/ |
||
typedef signed |
int |
INT16S; |
/* Signed |
16 |
bit quantity |
*/ |
typedef unsigned |
long |
INT32U; |
/* Unsigned 32 bit quantity |
*/ |
||
typedef signed |
long |
INT32S; |
/* Signed |
32 |
bit quantity |
*/ |
Listing 10.3, µC/OS to µC/OS-II data types
In µC/OS, a task stack was declared as being of type OS_STK_TYPE. A stack, in µC/OS-II, must be declared as being of type OS_STK. To prevent you from editing all your application files, you could simply create the two data types in OS_CPU.H as shown in listing 10.4 (Intel 80x86 given as an example).
#define |
OS_STK_TYPE |
UBYTE |
/* Satisfy uC/OS |
*/ |
#define |
OS_STK |
INT8U |
/* Satisfy uC/OS-II |
*/ |
Listing 10.4, µC/OS and µC/OS-II task stack data types
10.02.02 OS_CPU.H, OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL()
µC/OS-II (as did µC/OS) defines two macros to disable and enable interrupts: OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL(), respectively. You shouldn’t have to change these macros when migrating from
µC/OS to µC/OS-II.
10.02.03 OS_CPU.H, OS_STK_GROWTH
The stack on most microprocessors and microcontrollers grows from high-memory to low-memory. There are, however, some processors that work the other way around. µC/OS-II has been designed to be able to handle either flavor. This
is accomplished by specifying to µC/OS-II which way the stack grows through the configuration constant
OS_STK_GROWTH as shown below:
Set OS_STK_GROWTH to 0 for Low to High memory stack growth.
Set OS_STK_GROWTH to 1 for High to Low memory stack growth.
These are new #define constants from µC/OS so you will need to include them in OS_CPU.H.
10.02.04 OS_CPU.H, OS_TASK_SW()
OS_TASK_SW() is a macro that is invoked when µC/OS-II switches from a low-priority task to the highes t-priority task. OS_TASK_SW() is always called from task level code. This macro doesn’t need to be changed from µC/OS to µC/OS-II.
10.02.05 OS_CPU.H, OS_FAR
OS_FAR was used in µC/OS because of the Intel 80x86 architecture. This#definehas been removed in µC/OS-II because it made the code less portable. It turns out that if you specify the large model (for the Intel 80x86) then all memory references assumed the ‘far’attribute anyway.
All tasks in µC/OS were declared as shown in listing OS_FAR or simply create a macro in OS_CPU.H
10.5. You can either edit all the files that made references to to equate OS_FAR to nothing in order to satisfy µC/OS-II.
void OS_FAR task (void *pdata)
{
pdata = pdata; while (1) {
.
.
}
}
Listing 10.5, Declaration of a task in µC/OS
10.03OS_CPU_A.ASM
A µC/OS and µC/OS-II port requires that you write four fairly simple assembly language functions:
OSStartHighRdy()
OSCtxSw()
OSIntCtxSw()
OSTickISR()
10.03.01 OS_CPU_A.ASM, OSStartHighRdy()
In µC/OS-II, OSStartHighRdy() MUST call OSTaskSwHook(). OSTaskSwHook() did not
exist. OSStartHighRdy() need to call OSTaskSwHook() before you load the stack pointer of the highest priority task. Also, OSStartHighRdy() needs to set OSRunning to 1 immediately after calling OSTaskSwHook(). Listing 10.6 shows the pseudo-code of OSStartHighRdy(). µC/OS only had the last three steps.
OSStartHighRdy:
Call OSTaskSwHook(); Set OSRunning to 1;
Load the processor stack pointer with OSTCBHighRdy->OSTCBStkPtr; POP all the processor registers from the stack;
Execute a Return from Interrupt instruction;
Listing 10.6, Pseudo -code for OSStartHighRdy()
10.03.02 OS_CPU_A.ASM, OSCtxSw()
Two things have been added in µC/OS-II during a context switch. First, you MUST call OSTaskSwHook()
immediately after saving the current task’s stack pointer into the current task’s TCB. Second, you MUST set OSPrioCur to OSPrioHighRdy BEFORE you load the new task’s stack pointer.
Listing 10.7 shows the pseudo-code of OSCtxSw(). µC/OS-II adds steps L10.7(1) and L10.7(2).
OSCtxSw: |
|
PUSH processor registers onto the current task’s stack; |
|
Save the stack pointer at OSTCBCur->OSTCBStkPtr; |
|
Call OSTaskSwHook(); |
(1) |
OSTCBCur = OSTCBHighRdy; |
|
OSPrioCur = OSPrioHighRdy; |
(2) |
Load the processor stack pointer with OSTCBHighRdy->OSTCBStkPtr; |
|
POP all the processor registers from the stack;
Execute a Return from Interrupt instruction;
Listing 10.7, Pseudo -code for OSCtxSw()
10.03.03 OS_CPU_A.ASM, OSIntCtxSw()
Like OSCtxSw(), two things have been added in OSIntCtxSw() for µC/OS-II. First, you MUST call OSTaskSwHook()immediately after saving the current task’s stack pointer into the current task’s TCB. Second, you MUST set OSPrioCur to OSPrioHighRdy BEFORE you load the new task’s stack pointer.
Listing 10.8 shows the pseudo-code of OSIntCtxSw(). µC/OS-II adds steps L10.8(1) and L10.8(2).