Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
RTOS
Reference Book
Build Toolchain
Build GDB
Binutils
cd binutils-2.13.90.0.16
./configure --target=powerpc-linux --prefix=/opt/linuxppc
make
make install
/opt/linuxppc/bin
--prefix
/usr/local/usr
GCC
st
(1
Compile)
cd gcc-2.95.3
./configure --target=powerpc-linux prefix=/opt/linuxppc \
--enable-shared --enable-languages=c --with-newlib
make
make install
Extract Kernel
tar
xvfz
GLIBC
Un-compress
GLIBC
&
glibc-linuxthreads
ln s include/asm-ppc /opt/powerpc-linux/include/asm
ln s include/linux /opt/powerpc-linux/include/linux
CC = powerpc-linux-gcc
AR=powerpc-linux-ar
RANLIB=powerpc-linux-ranlib
./configure --host=powerpc-linux enable-add-ons \
--with-headers=/opt/powerpc-linux/include\
--prefix=/opt/linuxppc
make
make install_root=/opt/powerpc-linux install
GCC
nd
(2
Compile)
make distclean
./configure --prefix=/opt/linuxppc target=powerpc-linux \
--enable-shared enable-threads
make && make install
Why RTOS?
Learn
RTOS:
RTOS:
)
C/C++ JAVA
Advantage/Disadvantage of
Using RTOS
Advantage
Split application to multi tasks, simplify the
design, easy to be understand, expend and
maintenance
Time latency is guaranteed
Higher system reliability
Disadvantage
More RAM/ROM usage
2~5% CPU overhead
Adding additional cost, if commercial TROS is
used
About 80 RTOS vendors, cost from $70 to $30,000 some
are royalty free, some need $5 to $250 /MCU, MCU
dependent
Operating Systems,
Version 2
A very small real-time kernel.
Memory footprint is about 20KB for a
fully functional kernel.
Source code is about 5,500 lines,
mostly in ANSI C.
Its source is open but not free for
commercial usages.
Feature of uC/OSII
instruments
Engine control
musical instruments
network adapter
highway telephone call
box
ATM machine
industrial robots
AMD
Analog Device
ARM
Atmel
Fujitsu
Hitachi
Infineon
Intel
Motorola
M68HC16,
Philips
ST
TI
Automation
Zilog
80x86
SHARC (AD21065L)
ARM7
AVR, AT103
SPARC
64180, H8-300H, H8S,SH2,SH3
Tri.Core, 80C166/167
Strong ARM110,80C251,XC52, 80x86,
196K
M68HC08, M68HC11, M68HC12,
M68000, CPU32, DSP568xx, Cold.Fire,
M.Core, PowerPC8xx,MPC555
XA
80C166/167
TMS320-C40, TMS320-C6201
V8
Z-80, Z-180
Roadmap of Learning
uCOS II Architecture
Applications (Tasks)
CPU Independent Code
uCOS-II.h (Global Var)
uCOS_II.c Groups:
OS_Core.c OS_Task.c
OS_Time.c OS_Sem.c
OS_Mbox.c OS_Q.c
OS_Mem.c
Application
Configuration
Code
OS_CFG.h
Includes.h
Feature of uCOSII
Portable :
Interrupt Management
Int. can be nested up to 255 levels deep
Robust and Reliable
OS Functions Provided by
uCOSII
Term (1)
Multitasking
The process of scheduling and switching the CPU
between several tasks
Task
A simple program which thinks it has the CPU all
to itself.
Kernel
The part of the multitasking system responsible for
the management of tasks and communication
between tasks
Task Switch
Kernel saves the current task's context (CPU
registers) onto the current task's stack.
Kernel load new task's context from the tasks
stack of new task
Term (2)
TCB
Task Control Block
Scheduler
Also called the dispatcher, is the part of the kernel
which is responsible for determining which task
will run next
Non-preemptive scheduling
Each task is required to explicitly give up control of
the CPU. (ex. System API Call)
cooperative multitasking; tasks cooperate with
each other to gain control of the CPU.
Term (3)
Preemptive
Kernel
uC/OS II Overview
External
IRQ
TaskA() TaskB() TaskC()
Task Scheduler
Timer
MultiTasking
Overview
Task1
MBox0
MBox1
Task1()
{
#include "includes.h"
Sample
Code (2)
Sample
Code (3)
while (1)
{
// Do something
for (i = 0; i < 10000; i++) n++;
while (1)
{
// Do something
for (i = 0; i < 1234; i++) m++;
}
}
}
}
Task1
Calculate n
Calculate m
Send mail to 1
Waiting reply from 1
Reply 0
Calculate n
Send mail to 1
Calculate m
Wait mail from 0
OSInit (1)
OSTaskCreate();
The idle task.
OSTaskCreate();
The statistics task.
OSStart();
return 0; // Never return
}
OSInit
(2)
Ready List
OSRdyGrp
OSTCBPrioTbl[]
1 0 0 0 0 0 0 0
OSRdyTbl[]
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
1
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
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]
[2]
[3]
[4]
[5]
[6]
0
0
0
[OS_LOWEST_PRIO - 1]
[OS_LOWEST_PRIO]
OSTaskStat()
OS_TCB
OSTCBList
OSPrioCur
OSPrioHighRdy
OSTCBCur
OSTCBHighRdy
OSTime
OSIntNesting
OSLockNesting
OSCtxSwCtr
OSTaskCtr
OSRunning
OSCPUUsage
OSIdleCtrMax
OSIdleCtrRun
OSIdleCtr
OSStatRdy
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
0
0
NULL
NULL
0L
0
0
0
2
FALSE
0
0L
0L
0L
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
Task Stack
OSTaskIdle()
OS_TCB
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
OSTCBX = 7
OSTCBY = 7
OSTCBBitX = 0x80
OSTCBBitY = 0x80
OSTCBDelReq = FALSE
Task Stack
OS_MAX_TASKS
OS_TCB
OSTCBFr
List
OSInit
(4)
OS_TCB
OS_TCB
OS_TCB
OSTCBStkPtr
OSTCBExtPtr
OSTCBStkBottom
OSTCBStkSize
OSTCBId
OSTCBNext
OSTCBPrev
OSTCBEventPtr
OSTCBMsg
OSTCBDly
OSTCBStat
OSTCBPrio
OSTCBX
OSTCBY
OSTCBBitX
OSTCBBitY
OSTCBDelReq
OSTCBStkPtr
OSTCBExtPtr
OSTCBStkBottom
OSTCBStkSize
OSTCBId
OSTCBNext
OSTCBPrev
OSTCBEventPtr
OSTCBMsg
OSTCBDly
OSTCBStat
OSTCBPrio
OSTCBX
OSTCBY
OSTCBBitX
OSTCBBitY
OSTCBDelReq
OSTCBStkPtr
OSTCBExtPtr
OSTCBStkBottom
OSTCBStkSize
OSTCBId
OSTCBNext
OSTCBPrev
OSTCBEventPtr
OSTCBMsg
OSTCBDly
OSTCBStat
OSTCBPrio
OSTCBX
OSTCBY
OSTCBBitX
OSTCBBitY
OSTCBDelReq
OSTCBStkPtr
OSTCBExtPtr
OSTCBStkBottom
OSTCBStkSize
OSTCBId
OSTCBNext
OSTCBPrev
OSTCBEventPtr
OSTCBMsg
OSTCBDly
OSTCBStat
OSTCBPrio
OSTCBX
OSTCBY
OSTCBBitX
OSTCBBitY
OSTCBDelReq
OS_MAX_EVENTS
OS_EVENT
OSEventFreeList
OSEventPtr
OSEventTbl[]
OSEventCnt
OSEventType
OSEventGrp
OS_EVENT
OS_EVENT
OSEventPtr
OSEventTbl[]
OSEventCnt
OSEventType
OSEventGrp
OSEventPtr
OSEventTbl[]
OSEventCnt
OSEventType
OSEventGrp
OS_EVENT
OSEventPtr
OSEventTbl[]
OSEventCnt
OSEventType
OSEventGrp
OS_MAX_QS
OS_Q
OSQFreeList
OSQPtr
OSQStart
OSQEnd
OSQIn
OSQOut
OSQSize
OSQEntries
OS_Q
OS_Q
OSQPtr
OSQStart
OSQEnd
OSQIn
OSQOut
OSQSize
OSQEntries
OSQPtr
OSQStart
OSQEnd
OSQIn
OSQOut
OSQSize
OSQEntries
OS_Q
OSQPtr
OSQStart
OSQEnd
OSQIn
OSQOut
OSQSize
OSQEntries
OS_MAX_MEM_PART
OS_MEM
OSMemFreeList
OSMemAddr
OSMemFreeList
OSMemBlkSize
OSMemNBlks
OSNFree
OS_MEM
OSMemAddr
OSMemFreeList
OSMemBlkSize
OSMemNBlks
OSNFree
OS_MEM
OSMemAddr
OSMemFreeList
OSMemBlkSize
OSMemNBlks
OSNFree
OS_MEM
OSMemAddr
OSMemFreeList
OSMemBlkSize
OSMemNBlks
OSNFree
OSInit (3)
OSRdyGr
7
OSRdyTbl[OS_LOWEST_PRIO / 8
i
st ri rit Task
X
[0]
[1]
15 14 13 12 11 10
[2]
23 22 21 20 19 18 17 16
[3]
31 30 29 28 27 26 25 24
[4]
39 38 37 36 35 34 33 32
[5]
47 46 45 44 43 42 41 40
[6]
55 54 53 52 51 50 49 48
[7]
63 62 61 60 59 58 57 56
Task ri rit #
Bit
siti
st ri rit Task
(I l Task)
i OSRdyTbl[OS_LOWEST_PRIO / 8
1]
1]
1]
OSTaskCreate (1)
OSInit();
stack, text, housekeeping
OSTaskCreate();
status.
OSTaskCreate();
Task never return;
OSStart();
return 0; // Never return
OSTaskCreate (2)
Task Function
*/
*/
/* ... the same thing until task is created.
OS_EXIT_CRITICAL();
psp = (void *)OSTaskStkInit(task, pdata, ptos, 0);
err = OSTCBInit(prio, psp, (void *)0, 0, 0, (void *)0, 0);
if (err == OS_NO_ERR) {
OS_ENTER_CRITICAL();
OSTaskCtr++;
OSTaskCreateHook(OSTCBPrioTbl[prio]);
OS_EXIT_CRITICAL();
if (OSRunning) {
*/
*/
*/
*/
*/
OSSched();
}
} else {
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = (OS_TCB *)0;
OS_EXIT_CRITICAL();
}
return (err);
} else {
OS_EXIT_CRITICAL();
return (OS_PRIO_EXIST);
}
}
*/
OSStart
Start
multitasking of uC/OS-2.
It never returns to main()
The uC/OS-II picks up the highestpriority task to run on context-switching.
Tightly coupled with RTC ISR.
int main (void)
{
OSInit();
OSTaskCreate();
OSTaskCreate();
OSStart();
return 0; // Never return
}
WAITING
OSTaskDel()
OSMBoxPost()
OSQPost()
OSQPostFront()
OSSemPost()
OSTaskResume()
OSTimeDlyResume()
OSTimeTick()
OSTaskCreate()
OSTaskCreateExt()
DORMANT
READY
Task
Management
OSMBoxPend()
OSQPend()
OSSemPend()
OSTaskSuspend()
OSTimeDly()
OSTimeDlyHMSM()
OSStart()
OSIntExit()
OS_TASK_SW()
Interrupt
RUNNING
ISR
OSIntExit()
OSTaskDel()
Task is Preempted
OSTaskDel()
TCB
Structure
OSTCBFreeList
OSTCBTbl[1]
OSTCBTbl[2]
OSTCBNext
OSTCBNext
OSTCBNext
OSTCBNext
Task Scheduling
Task-level scheduling is performed by OSSched().
ISR-level scheduling is handled by OSIntExit().
void OSSched (void)
{
INT8U y;
OS_ENTER_CRITICAL();
if ((OSLockNesting | OSIntNesting) == 0) {/* Task scheduling must be enabled and not ISR level */
y = OSUnMapTbl[OSRdyGrp];
/* Get pointer to highest priority task ready to run */
OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
if (OSPrioHighRdy != OSPrioCur) {
/* No context switch if current task is highest ready */
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
OSCtxSwCtr++;
/* Increment context switch counter
*/
OS_TASK_SW();
/* Perform a context switch
*/
}
}
OS_EXIT_CRITICAL();
}
pmem
OSMemAddr
= addr
OSMemFreeList= addr
OSMemBlkSize = blksize
OSMemNBlks
= nblks
OSMemNFree
= nblks
Contiguous memory
OSMemCreate() arguments
Only empty
data structs
after init
OSMemAddr
OSMemAddr
OSMemFreeList
OSMemFreeList
OSMemFreeList
OSMemBlkSize
OSMemFreeList
OSMemAddr
OSMemBlkSize
OSMemBlkSize
OSMemNBlks
OSMemNBlks
OSMemNBlks
OSMemNFree
OSMemNFree
OSMemNFree
OS_MAX_MEM_PART
Memory
Management in
uCOS (contd.)
typedef struct {
void *OSMemAddr;
void *OSMemFreeList;
INT32U OSMemBlkSize;
INT32U OSMemNBlks;
INT32U OSMemBNFree;
} OS_MEM;
OS_MEM *CommTxBuf;
INT8U CommTxPart[100][32];
void main(void)
{
INT8U err;
...
OSInit();
...
CommTxBuf = OSMemCreate(CommTxPart, 100, 32, &err);
...
OSStart();
}
OSMemPut (OS_MEM
OSMemQuery()
Obtaining status of a Memory partition
(3)
ErrMsgQ
Analog
Inputs
AI
Task
OSQPost()
OSQPend()
(5)
(6)
Error
Handler
(1)
(4)
OSMemGet()
(2)
ErrMsgPart
(7)
OSMemPut()
(8)
Time Management
10m s
(2)
(1)
(5)
(4)
5m s
OSTimeDly()
Delay for a user-specified
OSTimeDlyHMSM()
hours(H), minutes(M), seconds(S),
milliseconds(m), Maximum Delay 256hours (11days)
OSTimeDlyHMSM( 0, 0, 1, 500);
OSTimeDlyResume()
Resuming a Delayed Task
Task A
Task A call
OSTimeDly(100)
2
3
Task B
Find the highest
priority ready task
B, and activate it
Task A
Hooks
Mail Box
OSMboxPend():
The message in the mailbox is retrieved.
If the mailbox is empty, the task is immediately
blocked and moved to the wait-list.
A time-out value can be specified.
OSMboxPost():
A message is posted in the mailbox.
If there is already a message in the mailbox, then
an error is returned (not overwritten).
If tasks are waiting for a message from the mailbox,
then the task with the highest priority is removed
from the wait-list and scheduled to run.
MBox0 = OSMboxCreate((void*)0);
MBox1 = OSMboxCreate((void*)0);
OSMboxCreate
Step 1
Get a OS_EVENT node from OSEventFreeList
Step 2
Assign type OS_EVENT_TYPE_MBOX to the OS_EVENT
node
Step 3
Attach the message (given from caller) to the OS_EVENT
node
Step 4
Return the point of the OS_EVENT node to the caller
Note
Mail box is an event in the view of uCOS
Mail box is not attach to specific task when created
The mail box has a table to record the tasks that are waiting
on the mail box.
OSMboxPost
Step 1
If there has some Task waiting on the mail box,
wake up it and give the message to it directly
Step 1
OSMboxPend
Message Qeue
IS R
IS R
W ait
EC B
EC B
Ta s k
Ta s k
Ta s k
EC B
W ait
Ta s k
T im e
ou t
Sign al
Ta s k
Sign al
W ait
T im e
ou t
Sign al
W ait/
Sign al
Ta s k
W ait
T im e
ou t
EC B
Ta s k
W ait/
Sign al
T im e
ou t
Ta s k
typedef struct {
void *OSEventPtr;
INT8U OSEventTbl[OS_EVENT_TBL_SIZE];
INT16U OSEventCnt;
INT8U OSEventType;
INT8U OSEventGrp;
} OS_EVENT;
Event Control
ECB is assigned to a mailbox or a queue
Blocks
OSEventPtr
.OSEventGrp
7 6
4 3
1 0
.OSEventTbl[OS_LOWEST_PRIO/8+1]
[0]
15 14 13 12 11 10 9
[2]
23 22 21 20 19 18 17 16
[3]
31 30 29 28 27 26 25 24
[4]
39 38 37 36 35 34 33 32
[5]
47 46 45 44 43 42 41 40
[6]
[1]
Tasks Priority
55 54 53 52 51 50 49 48
[7]
63 62 61 60 59 58 57 56
0 Y Y Y X X X
Bit position in .OSEventTbl[]
it M ask(B inary)
0 0 0 0 0 0 01
0 0 0 0 0 0 10
0 0 0 0 0 1 00
0 0 0 0 1 0 00
0 0 0 1 0 0 00
0 0 1 0 0 0 00
0 1 0 0 0 0 00
1 0 0 0 0 0 00
OSEventWaitListInit()
: a function called when a semaphore, message mailbox, message queue is created
initializing an ECB
OSEventTaskRdy()
: Removes the highest priority task(HPT) from the wait list of the ECB and make
this task ready to run
called by OSSemPost(), OSMboxPosr(), OSQPost(), OSQPostFront()
OSEventTaskWait()
: called by OSSemPend(), OSMboxPend(), OSQPend() when a task must wait on
an ECB
Removes the current task from the ready list and places it in the wait list of the
ECB
Semaphores
16-bit unsigned integer used to hod the semaphore count (0 to 65535)
a list of tasks waiting for the semaphore count to be greater than 0
uC/OS-II provides five services to semaphores
OS S e m Cre a te ()
- OSSemCreate()
- OSSemPend()
OS S e m Po s t()
- OSSemPost()
- OSSemAccept()
OS S e m Pe n d ()
OS S e m Ac c e p t()
OS S e m Que ry()
Ta s k
N
- OSSemQuery()
OR
SR
OS S e m Po s t()
OS S e m Ac c e p t()
Ta s k
OSSemCreate()
: Creates and initializes a semaphore
OS_EVENT *DispSem;
void main(void)
{
...
OSInit();
...
DispSem = OSSemCreate(1);
...
OSStart();
OSSemPend()
: When a task wants exclusive access to
a resource, needs to synchronize its
activities with an ISR or a task, or is
waiting until an event occurs
...
}
}
OSSemPost()
: A semaphore is signaled by calling
OSSemPost().
OSSemQuery()
: Obtain information about a semaphore
{
OS_SEM_DAT sem_data:
INT8U err, highest, x, y;
pdata = pdata;
for (;;) {
...
err = OSSemQuery(DispSem,&sem_data);
if (err==OS_NO_ERR) {
y=OSUnMapTbl[sem_data.OSEventGrp];
x=OSunMapTbl[sem_data.OSEventTbl[y]];
highest = (y<<3)+x;
...
Message Mailboxes
A message mailbox is a uC/OS-II object that allows a task or an ISR to send a
pointer sized variable to another task
uC/OS-II provides five services to mailboxes
OS Mb o xC e a te ()
- OSMboxCreate()
OS Mb o xPo s t()
- OSMboxPend()
- OSMboxPost()
Ta s k
OS Mb o xPe n d ()
OS Mb o xAc c e p t()
OS Mb o xQue y()
- OSMboxAccept()
- OSMboxQuery()
Ta s k
IS R
Ma ilb o x
Me s s a g e
OS Mb o xPo s t()
OS Mb o xAc c e p t()
OSMboxCreate()
: Creates and initializes a mailbox
OSMboxPend()
: When a task task expects to receive a
message.
OS_EVENT *CommMbox;
void main(void)
{
...
OSInit();
...
CommMbox = OSMboxCreate((void *)0);
...
OSStart();
}
OSMboxPost()
: Send a message to a task through
a mailbox
OS_EVENT *CommMBox
INT8U CommRxBuf[100];
OSMboxQuery()
: Obtain information about a message
mailbox
Message Queues
A message queue is a uC/OS-II object that allows a task or an ISR to send pointer
sized variables to another task.
- OSQCreate()
- OSQPostFront()
- OSQAccept()
Ta s k
u u
IS R
OS
s t()
OS
s tFr t()
OS Flus h()
OS A
t()
M s s ag
- OSQQuery()
- OSQFlush()
()
OS
OS A
t()
OS
u r ()
Ta s k
s t()
OS
OS
s tFr t()
OS Flus h()
- OSQPost()
- OSQPend()
r a t ()
OS
OSQCreate()
: Creates a message queue
OSQPend()
: When a task task expects to receive a
message from a queue
OS_EVENT *CommQ;
void *CommMsg[10];
void main(void)
{
INT8U err;
void *msg;
pdata = pdata;
...
for (;;) {
OSInit();
...
...
CommQ=OSQCreate(&CommMsg[0],10); msg=OSQPend(CommQ, 100, &err);
...
if (err==OS_NO_ERR) {
OSStart();
/* Message received wihin 100 ticks! */ }
}
else {
/* Message not received, must have
timed out */
...
OSQPost()
: Send a message to a task through
a queue
OSQPostFront()
: Send a message to a task through a
queue
OS_EVENT *CommQ;
OS_EVENT *CommQ;
INT8U CommRxBuf[100];
INT8U CommRxBuf[100];
{
INT8U err;
...
pdata = pdata;
for (;;) {
...
err = OSQPost(CommQ, (void *)
&CommRxBuf[0]);
...
INT8U err;
...
pdata = pdata;
for (;;) {
...
err = OSQPostFront(CommQ, (void *)
&CommRxBuf[0]);
...
Semaphore
MMU?
Not implemented
Startup.s
Basic init before main is run
OS_CPU_a.s
System code for task swapping & IRQ (FIQ)
OS_CPU.c, OS_CPU.h
Hooks and the C extention of IRQ (FIQ)
handler
OS_CFG.h
Which modules are compiled into code?
Interrupt
Startup.s
OS_CPU_a.s
uCOS core
TaskA(){}
TaskB(){}
TaskC(){}
TaskD(){}
All of them
are
compiled
into a large
binary file