You are on page 1of 71

Chapter 1:

Getting Started with μC/OS-II

1
(Kernel mode) 0G~
2

Task (thread)
μC/OS-II

Device driver

Task (thread)
kernel

Task (thread)
Introduction

Task (thread)
Task (process)

Device driver
Task (process)

kernel
Linux Task (process)
Task (process)
User mode (0-3G) (Kernel mode) 3G-4G
Introduction
• μC/OS-II
– Micro-Controller 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.
• It’s source is open but not free for commercial
usages.

3
Introduction
• μC/OS-II
– Preemptible priority-driven real-time scheduling.
• 64 priority levels (max 64 tasks)
• 8 (/1/2) reserved for μC/OS-II
• Each task is an infinite loop.
– Deterministic execution times for most μC/OS-II
functions and services.
– Nested interrupts could go up to 256 levels.

4
Introduction
• μC/OS-II
– Supports of various 8-bit to 64-bit platforms: x86,
68x, MIPS, 8051, etc
– Easy for development: Borland C++ compiler and
DOS (optional).
• However, μC/OS-II still lacks of the following
features:
– Resource synchronization protocols.
– Sporadic task support.
– Soft-real-time support.

5
Introduction
• Getting started with μC/OS-II!
– See how a μC/OS-II program looks like.
– Learn how to write a skeleton program for
μC/OS-II.
• How to initialize μC/OS-II?
• How to create tasks?
• How to use inter-task communication
mechanisms?
• How to catch system events?
6
7
牡羊座本日運勢

心情指數

牡羊座
心  情 寫程式錢應該先好好沈澱一下,但不
: 容易如願。
愛  情 幫同學解釋一些 OS 上的盲點可能會
: 有意想不到的收穫。
財  運 有一筆錢入帳,讓手頭鬆了不少 ( 先
: 拿去買教科書 ?) 。
工  作 為人辛苦為人忙,看什麼都不順眼。
: 寫共筆前試著先到 sandbox 寫一些文
章出出氣。

8
Getting started with μC/OS-II
• Example 1: Multitasking
• Example 2: Stack Checking
• Example 3: Extension of μC/OS-II
• Example 4: Portability

9
Example 1: Multitasking

10
main
OSInit

Install context switch handler

OSSemCreate

OSTaskCreate DOS

OSStart
TaskStart
Multiprogramming
install tick ISR

Create other tasks


Task1 Task10

longmp

Exit? OSSemPend OSSemPend


OSTimeDlyHMSM random ... random
OSSemPost OSSemPost
OSTimeDly OSTimeDly

11
Example 1: Multitasking
• 13 tasks run concurrently.
– 2 internal tasks:
The idle task and the statistic task.
– 11 user tasks:
Randomly print numbers onto the screen.

• Focus: System initialization and task creation.

12
Example 1: Multitasking
• Files
– The main program (test.c)
– The big include file (includes.h)
– The configuration of μC/OS-II (os_cfg.h) for each
application

• Tools needed:
– Borland C++ compiler (V3.1+)

13
The μC/OS-II File Structure

Application Code (test.c)

Processor independent Application Specific


implementations Configurations
•Scheduling policy
•Event flags OS_CFG.H
•Semaphores
•Mailboxes
•Event queues •Max # of tasks
•Task management •Max Queue length
•Time management
•Memory management •…

μC/OS-II port for processor specific codes


Software
Hardware

CPU Timer
14
includes.h

15
OS_CFG.H

.
.
.
.

16
test.c

A semaphore Stacks
(explain later) (explain later)
17
test.c: main()

18
main
OSInit

Install context switch handler

OSSemCreate

OSTaskCreate DOS

OSStart
TaskStart
Multiprogramming
install tick ISR

Create other tasks


Task1 Task10

longmp

Exit? OSSemPend OSSemPend


OSTimeDlyHMSM random ... random
OSSemPost OSSemPost
OSTimeDly OSTimeDly

19
OSInit()
• Internal structures of μC/OS-II.
– Task ready list.
– Priority table.
• a mapping table.
• give a priority/pid; return @TCB)
– Task control blocks (TCB).
– Free pools.
• Create housekeeping tasks.
– The idle task.
– The statistic task.

20
OSinit()
OSRdyGrp Ready List
1 0 0 0 0 0 0 0 OSTCBPrioTbl[]
OSRdyTbl[] 0 [0]
0 [1]
0 [2]
0 0 0 0 0 0 0 0 0 [3]
0 [4]
0 0 0 0 0 0 0 0 0 [5]
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
0 0 0 0 0 0 0 0
0
1 1 0 0 0 0 0 0 0
0
[OS_LOWEST_PRIO - 1]
[OS_LOWEST_PRIO]

OSTaskStat() OSTaskIdle()
OS_TCB OS_TCB
OSTCBStkPtr OSTCBStkPtr
OSTCBExtPtr = NULL OSTCBExtPtr = NULL
OSTCBStkBottom OSTCBStkBottom
OSTCBStkSiz e = stack size OSTCBStkSize = stack size
OSTCBId = OS_LOWEST_PRIO OSTCBId = OS_LOWEST_PRIO
OSTCBList OSTCBNext
OSTCBPrev
OSTCBNext
OSTCBPrev
OSTCBEventPtr = NULL OSTCBEventPtr = NULL
OSPrioCur     = 0 OSTCBMsg = NULL OSTCBMsg = NULL
OSPrioHighRdy = 0 0 OSTCBDly = 0
OSTCBStat = OS_STAT_RDY
OSTCBDly = 0
OSTCBStat = OS_STAT_RDY 0
OSTCBCur      = NULL OSTCBPrio = OS_LOWEST_PRIO-1
OSTCBX = 6
OSTCBPrio = OS_LOWEST_PRIO
OSTCBX = 7
OSTCBHighRdy  = NULL OSTCBY = 7 OSTCBY = 7
OSTime        = 0L OSTCBBitX = 0x40
OSTCBBitY = 0x80
OSTCBBitX = 0x80
OSTCBBitY = 0x80
OSIntNesting  = 0 OSTCBDelReq = FALSE OSTCBDelReq = FALSE
OSLockNesting = 0
OSCtxSwCtr    = 0
OSTaskCtr     = 2
OSRunning     = FALSE
OSCPUUsage    = 0
OSIdleCtrMax  = 0L
OSIdleCtrRun  = 0L
OSIdleCtr     = 0L Task Stack 21
OSStatRdy     = FALSE Task Stack
OSinit()
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
OSTCBFreeList OSTCBPrev OSTCBPrev OSTCBPrev OSTCBPrev 0
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

OS_MAX_EVENTS
OS_EVENT OS_EVENT OS_EVENT OS_EVENT

OSEventFreeList OSEventPtr
OSEventTbl[]
OSEventPtr
OSEventTbl[]
OSEventPtr
OSEventTbl[]
OSEventPtr
OSEventTbl[]
0
OSEventCnt OSEventCnt OSEventCnt OSEventCnt
OSEventType OSEventType OSEventType OSEventType
OSEventGrp OSEventGrp OSEventGrp OSEventGrp

OS_MAX_QS
OS_Q OS_Q OS_Q OS_Q

OSQPtr
OSQFreeList OSQStart
OSQPtr
OSQStart
OSQPtr
OSQStart
OSQPtr
OSQStart
0
OSQEnd OSQEnd OSQEnd OSQEnd
OSQIn OSQIn OSQIn OSQIn
OSQOut OSQOut OSQOut OSQOut
OSQSize OSQSize OSQSize OSQSize
OSQEntries OSQEntries OSQEntries OSQEntries

OS_MAX_MEM_PART
OS_MEM OS_MEM OS_MEM OS_MEM

OSMemAddr OSMemAddr OSMemAddr OSMemAddr


OSMemFreeList OSMemFreeList OSMemFreeList OSMemFreeList
OSMemFreeList OSMemBlkSize OSMemBlkSize OSMemBlkSize OSMemBlkSize 0
OSMemNBlks OSMemNBlks OSMemNBlks OSMemNBlks
OSNFree OSNFree OSNFree OSNFree

22
The PC IVT
• Interrupt vector table (IVT)
Before (DOS only) After (μC/OS-II installed)

23
PC_DOSSaveReturn()
• Save the current status of DOS for the future
restoration.
– Interrupt vectors and the RTC tick rate.
• Set a global returning point by calling setjmp().
– μC/OS-II can come back here when it
terminates.
– PC_DOSReturn()

24
PC_DOSSaveReturn()

25
setjmp

setjmp +longjmp ≒ goto


26
longjmp

27
PC_VectSet()
• PC_VectSet(uCOS, OSCtxSw)
– Install the context switch handler (OSCtxSw).
– Interrupt 0x80 (uCOS) under 80x86 family.
• Invoked by INT instruction.

Disable interrupt

Enable interrupt

28
OSSemCreate()
• Create a semaphore for resource synchronization.
– To protect non-reentrant codes.

• The created semaphore becomes a mutual


exclusive mechanism if “1” is given as the initial
value.

• In this example, a semaphore is created to


protect the standard C library “random()”.

29
OSTaskCreate()
• Functionality
– Create tasks with the given arguments.
– Tasks become “ready” after they are created.
• Task
– An active entity which could do some computations.
– Priority, CPU registers, stack, text, housekeeping status.
• The μC/OS-II picks up the highest-priority task to run
on context-switching.
– Tightly coupled with ISR.

30
OSTaskCreate()
Entry point of the task (a
pointer to function)
• OSTaskCreate(
User-specified
TaskStart, data
(void *)0,
&TaskStartStk[TASK_STK_SIZE - 1],
0 Top of Stack
Priority
); (0=hightest)

31
OSStart()
• OSStart()
– Start multitasking of μC/OS-II .
– It never returns to main().
– μC/OS-II is terminated if PC_DOSReturn() is
called.

32
main
OSInit

Install context switch handler

OSSemCreate

OSTaskCreate DOS

OSStart
TaskStart
Multiprogramming
install tick ISR

Create other tasks


Task1 Task10

longmp

Exit? OSSemPend OSSemPend


OSTimeDlyHMSM random ... random
OSSemPost OSSemPost
OSTimeDly OSTimeDly

33
OSTaskCreate(
TaskStart,
(void *)0,

TaskStart() &TaskStartStk[TASK_STK_SIZE - 1],


0);

void TaskStart (void *pdata)

for (i=0 to 9) {
OSTaskCeate
}

Wait one second


34
TaskStart()
• OS_ENTER_CRITICAL()/OS_EXIT_CRITICAL()
– Enable/disable most interrupts.
– An alternative way to accomplish mutual
exclusion.
• No rescheduling is possible during the disabling of
interrupts. (different from semaphores)
– Processor specific.
• CLI/STI (x86 real mode)
• Interrupt descriptors (x86 protected mode)

35
TaskStartCreateTasks()

Entry point of the Argument: Stack Priority


created task character to print

36
Task()

Semaphore
operations.

37
main
OSInit

Install context switch handler

OSSemCreate

OSTaskCreate DOS

OSStart
TaskStart
Multiprogramming
install tick ISR

Create other tasks


Task1 Task10

longmp

Exit? OSSemPend OSSemPend


OSTimeDlyHMSM random ... random
OSSemPost OSSemPost
OSTimeDly OSTimeDly

38
Semaphores
• A semaphore consists of a wait list and an integer
counter.
– OSSemPend():
• Counter--
• If the value of the semaphore < 0, then the task is blocked and
moved to the wait list immediately.
• A time-out value can be specified.
– OSSemPost():
• Counter++
• If the value of the semaphore ≧ 0, then a task in the wait list is
removed from the wait list.
• Reschedule if needed.

39
Example 1: Multitasking
• Summary:
– μC/OS-II is initialized and started by calling OSInit()
and OSStart(), respectively.
– Before μC/OS-II is started,
• The DOS status is saved by calling PC_DOSSaveReturn().
• A context switch handler is installed by calling PC_VectSet().
• One user task must be created first!
– Shared resources can be protected by semaphores.
• OSSemPend(), OSSemPost().

40
Example 2

41
main

OSInit

Install context switch handler

OSTaskStkInit_FPE_X86 DOS
& OSTaskCreateExt

OSStart
TaskStart
Multiprogramming
install tick ISR

Create other tasks


Task1 Task4 Task5

OSMboxPost
Update the display OSTaskStkChk &OSMobxPend OSMboxPost

42
Example 2: Stack Checking

• Five tasks do jobs on message


sending/receiving.
– More task creation options
• Better judgment on stack sizes
– Stack usage of each task
• Different stack sizes for tasks
– Emulation of floating point operations
• 80386 or lower-end CPU’s
– Communication through mailbox
• Only the pointer is passed.
43
2 Mailboxes
44
Main()

OSTaskStkInit_FPE_x86(&ptos, &pbos, &size)

45
OSTaskStkInit_FPE_x86()

• OSTaskStkInit_FPE_x86(&ptos, &pbos, &size)


– Passing the original top address, bottom address,
and size of the stack.
– On the return, arguments are modified, and some
stack space are reserved for the floating point
library.
ptos
• For context switches.

同學:加油, size
快下課了!

pbos
46
OSCreateTaskExt()
• OSTaskCreatExt(
TaskStart,
(void *)0,
ptos,
TASK_START_PRIO,
TASK_START_ID,
pbos,
size, User supplied data which can be used to extend TCB
(void *)0,
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR
); options

47
TaskStart()

Create 2
mailboxes

The dummy loop


wait for ‘ESC’

48
Task1()

49
Task2 and Task3

for (i=0; i<499; i++) {


dymmy[i] = ‘?’;
}

50
Task4 and Task5

???

OSTimeDlyHMSM(0, 0, 1, 0);
51
MailBox
• A mailbox is for data exchanging between tasks.
– A mailbox consists of a data pointer and a wait-list.
• 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.

52
OSTaskStkCheck()
• Check for stack overflow.
– bos < (tos – stack length)
– Local variables, arguments for procedure calls, temporary
storage for ISR’s.
– μC/OS-II can check for stack overflow on the creation of
tasks and when OSTaskStkCheck() is called.
– μC/OS-II does not automatically check stacks.

53
(Linux 2.6)
stack
User mode

Kernel mode
(kernel service routines)
stack stack

Kernel mode stack


(interrupt service routines)

54
(Linux 2.4)
stack
User mode

Kernel mode
(kernel service routines)
stack stack

Kernel mode
(interrupt service routines)

55
μC/OS-II

Kernel mode

Kernel mode
(kernel service routines)
stack

Kernel mode
(interrupt service routines)

56
Example2: Stack Checking

• Summary:
– Local variable, function calls, and ISR’s will utilize
the stack space of user tasks.
– ISR will use the stack of the interrupted task.
– If floating-point operations are needed, then some
stack space should be reserved.
– Mailboxes can be used to synchronize the work of
tasks.

57
Example 3: Extension of μC/OS-II

• A Pointer to from the TCB of each task to a


user-provided data structure
– Passing user-specified data structures on task
creations or have application-specific usage.
• Message queues
– More than one pointers
• Demonstration on how to use OS hooks to
receive/process desired event from the
μC/OS-II

58
Example 3

59
User-defined
data structure
to pass to tasks

Message queue and


an array of event

60
61
.
.
.

62
63
Task 2, 3, 4 are
functionally
identical.

64
Message Queues
• A message queue consists of an array of elements and a wait-
list.
• Different from a mailbox, a message queue can hold many
data elements (in a FIFO basis).
• As same as mailboxes, there can be multiple tasks pend/post
to a message queue.
• OSQPost(): a message is appended to the queue. The highest-
priority task (in the wait-list) receives the message and is
scheduled to run, if any.
• OSQPend(): a message is removed from the array of elements.
If no message can be retrieved, the task is moved to the wait-
list and becomes blocked.

65
Hooks
• A hook function will be called by μC/OS-II when the
corresponding event occurs.
– Event handlers could be in user programs.
– For example, OSTaskSwHook () is called every time when
context switch occurs.
• The hooks are specified in the compiling time in μC/OS-
II :
– μC/OS-II is an embedded OS.
• OS_CFG.H (OS_CPU_HOOKS_EN = 0)
– Many OS’s can register and un-register hooks.

66
User Customizable Hooks for μC/OS-II

• void OSInitHookBegin (void)


• void OSInitHookEnd (void)
• void OSTaskCreateHook (OS_TCB *ptcb)
• void OSTaskDelHook (OS_TCB *ptcb)
• void OSTaskIdleHook (void)
• void OSTaskStatHook (void)
• void OSTaskSwHook (void)
• void OSTCBInitHook (OS_TCB *ptcb)
• void OSTimeTickHook (void)

67
OSTaskStatHook()

68
OSTaskSwHook()

Elapsed time for OSTCBCur TCB of the


the current task current task
OSTCBHighRdyTCB of
the new task

69
Example 3: Extension of μC/OS-II

• Summary:
– Message queues can be used to synchronize among tasks.
• Multiple messages can be held in a queue.
• Multiple tasks can “pend”/“post” to message queues
simultaneously.
– Hooks can be used to do some user-specific computations
on certain OS events occurs.
• They are specified in the compiling time.
• A Pointer to from the TCB of each task to a user-provided data
structure

70
Getting Started with μC/OS-II?
Getting Started with μC/OS-II :
– How the control flows among procedures?
– How tasks are created?
– How tasks are synchronized by semaphore,
mailbox, and message queues?
– How the space of a stack is utilized?
– How to capture system events?
– How to write a dummy μC/OS-II program?

71

You might also like