RTOS Slides UCOS II
-
Upload
grhvgmct8224 -
Category
Documents
-
view
152 -
download
8
description
Transcript of RTOS Slides UCOS II
1
Real Time Operating Systems
2
Course flow
3
Session 1
• Startup code
• Runtime memory map
• Is OS needed?
• “Process” a living entity?
4© Copyright 2004, All Rights Reserved. OASIS Technologies
Motherboard block Diagram
5
Runtime Memory MapHigh Memory End of RAM
Low Memory start of ROM
End of ROM
Start of RAM
text and RO
uninitialized data
initialized data
stack
heap
6
Application startup
Startup code: Low level hardware initialization
PLL clock
Serial port
Video controller
BSS & Data Segment initialization
7
CPU Vs Memory Technology
8© Copyright 2004, All Rights Reserved. OASIS Technologies
OS : What is it Anyway?
• A program that acts as an intermediary between a user of a computer and the computer hardware.
• Operating system goals:– Execute user programs and make
solving user problems easier.– Make the computer system convenient
to use.– Use the computer hardware in an
efficient manner.
9© Copyright 2004, All Rights Reserved. OASIS Technologies
OS : Components
• Process Management• Memory Management• Secondary Storage Management• I/O System• File Management• Protection System• Networking• Command Interpreter System
10
OS Architecture
11
What OS provides?
• Hardware Abstraction– Application developers
need not know about the underlying hardware
• Proper Scheduling ensures an efficient usage of resources
• User Programs can be protected from each other
• Application can communicate with each other with ease
• Faster Storage and Retrieval of Data
• Portability
• Kernel with Hardware Abstraction Layer + I/O Management
• Scheduling
• Process Management
• Inter Process Communication
• File Management
• POSIX and other compliance Subsystem
12© Copyright 2004, All Rights Reserved. OASIS Technologies
What is a Process• Also called a Task
• Set of Instructions and Data
• “Execution” part of an individual program
For a program to be executed, a process or a task is created…
13© Copyright 2004, All Rights Reserved. OASIS Technologies
Process Address Space (Process Image)
0x00000000
0xFFFFFFFF
Virtual
address space
Code(text)
static data
Heap(dynamically allocated)
Stack(dynamically allocated)
PC
SP
14© Copyright 2004, All Rights Reserved. OASIS Technologies
Process Context• A process consists of :
– an address space – usually protected and virtual – mapped into memory
– the code for the running program– the data for the running program– an execution stack and stack pointer (SP)– the program counter (PC)– a set of processor registers – general
purpose and status– a set of system resources
15© Copyright 2004, All Rights Reserved. OASIS Technologies
Process State Diagram
16
Process State Diagram
17
END OF SESSION 1(Thank God!!!)
18
Session 2
• What are embedded systems?
• What are Real time systems?
• Analyzing Cyclic programming in embedded systems
• Constraints on an OS in embedded systems
19
Embedded Systems
• An embedded system is a special-purpose system in which the computer is completely encapsulated by the device it controls.
• Some characteristics include :– Customized hardware– Customized software– Predefined Tasks with specific requirements– Small footprint
20
Embedded system examples• Virtually all systems that have a digital interface
-- watches, microwaves, VCRs, cars -- utilize embedded systems.
• Artificial Satellites, Space Vehicles( Voyager, Mars Polar Lander etc.)
• Automobiles, Telecommunication
21
Real Time System
“ A real-time system is one in which the correctness
of the computations not only depends on their logical correctness, but also on the time at which the result is produced ”
● In other words, a late answer is a wrong answer.
Characteristics of a Embedded Real Time system:● Deadline driven● Process the events in a deterministic time.● Have limited resources.
22
Hard or Soft?
• Hard real time systems have hard deadlines, which must be met at each and every time– The result of a missed deadline is “Fatal” it
would cause great loss in some manner, especially physically damaging the surroundings or threatening human lives.
23
• Car engine control, ABS, car airbags, heart pacemakers, Industrial control, nuclear power stations.
• Soft real time systems can miss a deadline, once in a while.
• Mobile, music player, video player
24
How to process the events in embedded real time system?
– Simplest approach: cyclic program• loop• do part of task 1• do part of task 2• do part of task 3• end loop
25
Cyclic Programming of Real Time systems
Open Fuel Valve
Wait for ½ Rev
Ignition
Wait for ½ Rev
Open exhaust valve
Close Fuel Valve
Wait for ½ Rev
Wait for ½ Rev
26
Cyclic Programming of Real Time systems
System initialization
Get Temperature()
Check if exceeds Threshold
If Yes turn ON Valve 1
Update Display
Check if need to relocate robotic arm
If yes move the robotic arm
Check the if position ok
Update Display
27
A Look at Cyclic Program
• Advantages– Simple implementation– Low overhead– Very predictable
• Disadvantages– Can’t handle sporadic events– Everything must operate in lockstep– Code must be scheduled manually
28
How to overcome limitations of cyclic loops ?● Using a mechanism through which critical
events can be processed by pre-empting the less critical currently executing task.
● Achieved by implementing in software/firmware an algorithm which will behave in the same way a hardware interrupts and IRS
● By wisely and judiciously utilising the CPU utilization
● By implementing a software/firmware that controls the CPU allocation to various tasks in the system
● Both the above implementation will lead us to the implementation of a software/firmware layer which we can call as OS
29
OS in Embedded System:
• Embedded System often has a specialized operating system, often a real time operating system.
• Has a very small foot print
• Is a customized OS to perform a specific task
• Has efficient Task Management and InterTask Communication Mechanism
30
What is an RTOS ? Helps us in processing Real Time events
HOW● Providing Deterministic execution time of
the code...● Provides worst case guarantee for interrupts,
context switch & system call.● Performing Efficient Multitasking…
● Ensures that events are timely processed.● Efficient use of resources.
● Real Time applications can be designed and scaled easily...
● Simplifies the design process by splitting application code in to separate tasks.
● Functionality can be easily added without significant changes to the application.
31
Multi-Tasking
• The ability to execute more than one task at the same time is Multi Tasking.
• A fundamental feature of an OS.
• Efficient utilization of CPU resources.
• Enables modular construction of applications.
• DO WE NEED THIS SLIDE????????????
32
Design constraints for an Embedded RTOS
● Time Constraint● Small Footprint● Low Interrupt Latency● Robust● Efficient usage of Resource
33
Embedded RT System requirements
• Deadline driven:– Hard real time systems:
• Failure to meet the deadline is considered to be a fatal fault.
– Soft real time systems:• Failure to meet the deadline undesirable.
• Deterministic execution time– Provide worst case guarantee for interrupts, context
switch time and system call.
34
END OF SESSION 2
35
SESSION 3
• RTOS architecture
• Building blocks of RTOS
• RTOS terminologies
• Introduction to ucosII OS
36
Real Time OS Architecture
Hardware
HAL Scheduler
Context Switch handler
IPC ISR
APPLICATION
Kernel
37
Building Blocks of a Real Time OS
• Kernel– Task Management– Scheduling– Context switching– IPC mechanism– Timer Handling
• Memory Management• Device driver• Protocol stack
38
Kernel Structure
Types of Kernel– monolithic kernel that contains all services– micro-kernel -- contain the minimal services to support
optional and cooperating processes• small (10K bytes) and modular• configurable
Services provided by kernel– task management– inter-task communication -- message queue, mailbox,
and shared memory– synchronization & mutual exclusion -- semaphore and
signal– interrupt support and error handling– memory management– time management and timer services– multiprocessor support
39
Micro-kernel
Kernel
File System
Device Driver
Net Application
HWHAL
Memory Mgmt.
MINIX 3, L4, QNX
40
Monolithic Kernel
Proc
File System
Device Driver
Net
ApplicationHW
HAL
Memory Mgmt.
Linux, Windows
41
Scheduler
Role?• It is the part of the kernel responsible for determining
which task runs next.
What? An Algorithm• The basis for the selection of the new task which will run is
based on the scheduling policy/algorithm.
When?• Scheduling decisions are made at the task level and at
the interrupt level.
• Task level scheduling is done when a system call (an API provided by the OS) is executed.
• Interrupt level when an ISR is processed.
42
Round Robin Scheduling
• Equal Priority tasks given control of CPU in Round Robin Fashion : One after the other
• Equal Time Slices for each task.
43
Priority Base Preemptive Scheduling
• Preempt (Suspend) the currently running task and Schedule the higher Priority task.
• Processor never idle if tasks are waiting (max. CPU utilization)
44
Context switch
• Role: switch out one task and make the newly selected task by the scheduler to run on the CPU
• What: hardware dependant* function that performs save & restore of context
• When: when invoked by the scheduler
(* varies from processor to processor. )
45
What are Threads?
• In a single address space– For the Application, Thread = Code + data
• Functions/Subroutines
– For RTOS, Thread = Code + data + context• Context is maintained in Task Control block.
46
What are Tasks?
• The executing entity consuming CPU cycles is nothing but a task
– Code + data• Functions/Subroutines
– Form a RTOS perspective• Task = Threads (in a single process address space)
47
Important aspects of Threads
• Functional entity in operation
• Has its own context
• Follows task state transitions.
48
IPC mechanisms
• Pipes
• Shared memory
• semaphores
• Mailbox
• Message queues
49
RTOS Terminologies
• Re-entrant
• Critical section
• Atomicity
• Deadlock
50
Review RTOS
• Advantages:• Better CPU utilization• Better handling of time-critical code.• Easier functionality expansion & hence shorter time-to-
market.
• Disadvantage:• Purchase Cost – huge, license fees, royalty• Size – ROM & RAM requirements, both• Maintenance cost
51
Introduction to uC/OSII OS• Features:
1. Supports multitasking for up to 64 tasks2. 0 implies maximum priority3. Pre-emptive kernel4. Portable & scalable5. Several IPC mechanisms for task
communication
52
Sample Application codeint main(){
}
void t1(void){
while(1){
waitfordata();getData();…..
}}void print(char *data_t){
}
void t2(void){
while(1){
print();wait();…….
}}
int getData(void){
}
53
A Simple Task Model
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]void init_timer();int main(void){
OSInit(); init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart();
}
void task1(void *data){
while(1){
block…………
}}
void task2(void *data)
{
while(1)
{
block……
……
}
}
54
A Simple Task Model
void task1(void *data){
while(1){
block…………
}}
void task2(void *data)
{
while(1)
{
block……
……
}
}
Task Priorities
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]void init_timer();int main(void){
OSInit(); init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart();
}
55
A Simple Task Model
void task1(void *data)
{
while(1)
{
block……
……
}
}
void task2(void *data)
{
while(1)
{
block……
……
}
}
After OSStart you will not come here but will go to highest priority task code in this case task1
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]void init_timer();int main(void){
OSInit(); init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart();
}
56
A Simple Task Model
void task1(void *data){
while(1){
block…………
}}
void task2(void *data){
while(1){
block…………
}}
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]void init_timer();int main(void){
OSInit(); init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart();
}
57
A Simple Task Model
void task1(void *data)
{
while(1)
{
block……
……
}
}
void task2(void *data)
{
while(1)
{
block……
……
}
}
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]void init_timer();int main(void){
OSInit(); init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart();
}
58
A Simple Task Model
void task1(void *data)
{
while(1)
{
block……
……
}
}
void task2(void *data)
{
while(1)
{
block……
……
}
}
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]void init_timer();int main(void){
OSInit(); init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart();
}
59
A Simple Task Model
void task1(void *data)
{
while(1)
{
block……
……
}
}
void task2(void *data)
{
while(1)
{
block……
……
}
}
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]void init_timer();int main(void){
OSInit(); init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart();
}
60
A Simple Task Model
void task1(void *data)
{
while(1)
{
block……
……
}
}
void task2(void *data)
{
while(1)
{
block……
……
}
}
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]void init_timer();int main(void){
OSInit(); init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart();
}
61
Understanding ‘task create’ system call 1/4
void task1(void *data)
{
while(1)
{
block……
……
}
}
void task2(void *data)
{
while(1)
{
block……
……
}
}
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]void init_timer();int main(void){
OSInit(); init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart();
}
62
Understanding ‘task create’ system call 2/4
void task1(void *data)
{
while(1)
{
block……
……
}
}
void task2(void *data)
{
while(1)
{
block……
……
}
}
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]void init_timer();int main(void){
OSInit(); init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart();
}
63
Understanding ‘task create’ system call 3/4
void task1(void *data)
{
while(1)
{
block……
……
}
}
void task2(void *data)
{
while(1)
{
block……
……
}
}
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]void init_timer();int main(void){
OSInit(); init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart();
}
64
Understanding ‘task create’ system call 4/4
void task1(void *data)
{
while(1)
{
block……
……
}
}
void task2(void *data)
{
while(1)
{
block……
……
}
}
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]void init_timer();int main(void){
OSInit(); init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart();
}
65
Stacks allocated on TaskStk
void task1(void *data)
{
while(1)
{
block……
……
}
}
void task2(void *data)
{
while(1)
{
block……
……
}
}
Stack for Task1
Stack for Task2
Tasks stack—USER HAS TO INCLUDE it
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]void init_timer();int main(void){
OSInit(); init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart();
}
66
Kernel data structure
typedef struct _TCB{
unsigned int *stkptr;unsigned int taskprio;STATE *tskstate;MSGEVENT *tskevent;char *tskname;TCB *next;
} TCB;
typedef struct _STATE
{
char *readyQ;
char *waitQ;
} STATE;
typedef struct _EVENT
{
unsigned int type;
void *data;
} MSGEVENT;
char waitQ[NO_TASK];
char readyQ[NO_TASK]
unsigned int TaskStk[NO_TASK][TASK_STK_SIZE];
TCB TaskTCB[NO_TASK];
TCB *current, *next;
0 0 1 0 0 1 0 0 1 0 0
1 0 0 1 1 0 1 1 0 1 1
readyQ
waitQ
67
Kernel data structure
typedef struct _TCB{
unsigned int *stkptr;unsigned int taskprio;STATE *tskstate;MSGEVENT *tskevent;char *tskname;TCB *next;
} TCB;
typedef struct _STATE
{
char *readyQ;
char *waitQ;
} STATE;
typedef struct _EVENT
{
unsigned int type;
void *data;
} MSGEVENT;
char waitQ[NO_TASK];
char readyQ[NO_TASK]
unsigned int TaskStk[NO_TASK][TASK_STK_SIZE];
TCB TaskTCB[NO_TASK];
TCB *current, *next;
0 0 1 0 0 1 0 0 1 0 0
1 0 0 1 1 0 1 1 0 1 1
readyQ
waitQ
68
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1
R0
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1
R0
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1
R0
stkptr
taskprio
tskstate
tskevent
taskname
NEXT
stkptr
taskprio
tskstate
tskevent
taskname
NEXT
stkptr
taskprio
tskstate
tskevent
taskname
NEXT NULL
0 0 1 0 0 1 0 0 1 0 0
1 0 0 1 1 0 1 1 0 1 1
readyQ
waitQ
readyQ
waitQ
RUN
readyQ
waitQ
RUN
readyQ
waitQ
RUN
TskStk[0] TskStk[1] TskStk[N]
TaskTCB[0] TaskTCB[1] TaskTCB[N]
TaskCreate():• Fill the TaskStk[taskprio]
with the stack frame• Initializes the
TaskTCB[taskprio].stkptr• Initializes the
tskstate.waitQ to waitQ[taskprio]
• Initializes the tskstate.readyQ to readyQ[taskprio]
OSInit():• Initialize kernel data
structures• Create an Ideal task
69
A Simple Task Model
void task1(void *data){
while(1){
block…………
}}
void task2(void *data){
while(1){
block…………
}}
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]void init_timer();int main(void){
OSInit(); init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart();
}
70
OSStart 1/11
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
SP
OSStart():
current = taskTCB[hiprio]
//SP = taskTCB[hiprio]->stkptr
ldr lr, = taskTCB[hiprio]
ldr lr, [lr]
ldr sp, [lr]
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
ldmia sp!, {lr}
msr spsr, lr
ldmia sp!, {lr}
movs pc, lr
High Priority Task’s Stack
stkptr
taskprio
tskstate
tskevent
taskname
NEXT
High Priority Task’sTCB
OSStart:
• Find the Highest priority task
• Load SP with TaskTCB[hiprio].stkptr
• Load the context
71
OSStart 2/11
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
SP
OSStart():
current = taskTCB[hiprio]
//SP = taskTCB[hiprio]->stkptr
ldr lr, = taskTCB[hiprio]
ldr lr, [lr]
ldr sp, [lr]
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
ldmia sp!, {lr}
msr spsr, lr
ldmia sp!, {lr}
movs pc, lr
High Priority Task’s Stack
stkptr
taskprio
tskstate
tskevent
taskname
NEXT
High Priority Task’sTCB
OSStart:
• Find the Highest priority task
• Load SP with TaskTCB[hiprio].stkptr
• Load the context
72
TCB stack pointer?
typedef struct _TCB{
unsigned int *stkptrunsigned int taskprioSTATE *tskstateMSGEVENT *tskeventchar *tsknameTCB *next;
} TCB;
typedef struct _STATE
{
char *readyQ
char *waitQ
} STATE;
typedef struct _EVENT
{
unsigned int type
void *data
} MSGEVENT;
char waitQ[NO_TASK];
char readyQ[NO_TASK]
unsigned int TaskStk[NO_TASK][TASK_STK_SIZE];
TCB TaskTCB[NO_TASK];
TCB *current, *next;
0 0 1 0 0 1 0 0 1 0 0
1 0 0 1 1 0 1 1 0 1 1
readyQ
waitQ
73
OSStart 3/11
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
SP
OSStart():
current = taskTCB[hiprio]
//SP = taskTCB[hiprio]->stkptr
ldr lr, = taskTCB[hiprio]
ldr lr, [lr]
ldr sp, [lr]
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
ldmia sp!, {lr}
msr spsr, lr
ldmia sp!, {lr}
movs pc, lr
High Priority Task’s Stack
stkptr
taskprio
tskstate
tskevent
taskname
NEXT
High Priority Task’sTCB
OSStart:
• Find the Highest priority task
• Load SP with TaskTCB[hiprio].stkptr
• Load the context
74
OSStart 4/11
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
SP
OSStart():
current = taskTCB[hiprio]
//SP = taskTCB[hiprio]->stkptr
ldr lr, = taskTCB[hiprio]
ldr lr, [lr]
ldr sp, [lr]
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
ldmia sp!, {lr}
msr spsr, lr
ldmia sp!, {lr}
movs pc, lr
High Priority Task’s Stack
stkptr
taskprio
tskstate
tskevent
taskname
NEXT
High Priority Task’sTCB
OSStart:
• Find the Highest priority task
• Load SP with TaskTCB[hiprio].stkptr
• Load the context
75
OSStart 5/11
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
SP
OSStart():
current = taskTCB[hiprio]
//SP = taskTCB[hiprio]->stkptr
ldr lr, = taskTCB[hiprio]
ldr lr, [lr]
ldr sp, [lr]
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
ldmia sp!, {lr}
msr spsr, lr
ldmia sp!, {lr}
movs pc, lr
High Priority Task’s Stack
stkptr
taskprio
tskstate
tskevent
taskname
NEXT
High Priority Task’sTCB
OSStart:
• Find the Highest priority task
• Load SP with TaskTCB[hiprio].stkptr
• Load the context
76
OSStart 6/11
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
SP
OSStart():
current = taskTCB[hiprio]
//SP = taskTCB[hiprio]->stkptr
ldr lr, = taskTCB[hiprio]
ldr lr, [lr]
ldr sp, [lr]
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
ldmia sp!, {lr}
msr spsr, lr
ldmia sp!, {lr}
movs pc, lr
High Priority Task’s Stack
stkptr
taskprio
tskstate
tskevent
taskname
NEXT
High Priority Task’sTCB
OSStart:
• Find the Highest priority task
• Load SP with TaskTCB[hiprio].stkptr
• Load the context
77
OSStart 7/11
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
SP
OSStart():
current = taskTCB[hiprio]
//SP = taskTCB[hiprio]->stkptr
ldr lr, = taskTCB[hiprio]
ldr lr, [lr]
ldr sp, [lr]
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
ldmia sp!, {lr}
msr spsr, lr
ldmia sp!, {lr}
movs pc, lr
High Priority Task’s Stack
stkptr
taskprio
tskstate
tskevent
taskname
NEXT
High Priority Task’sTCB
OSStart:
• Find the Highest priority task
• Load SP with TaskTCB[hiprio].stkptr
• Load the context
78
OSStart 8/11
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
SP
OSStart():
current = taskTCB[hiprio]
//SP = taskTCB[hiprio]->stkptr
ldr lr, = taskTCB[hiprio]
ldr lr, [lr]
ldr sp, [lr]
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
ldmia sp!, {lr}
msr spsr, lr
ldmia sp!, {lr}
movs pc, lr
High Priority Task’s Stack
stkptr
taskprio
tskstate
tskevent
taskname
NEXT
High Priority Task’sTCB
OSStart:
• Find the Highest priority task
• Load SP with TaskTCB[hiprio].stkptr
• Load the context
79
OSStart 9/11
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
SP
OSStart():
current = taskTCB[hiprio]
//SP = taskTCB[hiprio]->stkptr
ldr lr, = taskTCB[hiprio]
ldr lr, [lr]
ldr sp, [lr]
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
ldmia sp!, {lr}
msr spsr, lr
ldmia sp!, {lr}
movs pc, lr
High Priority Task’s Stack
stkptr
taskprio
tskstate
tskevent
taskname
NEXT
High Priority Task’sTCB
OSStart:
• Find the Highest priority task
• Load SP with TaskTCB[hiprio].stkptr
• Load the context
80
OSStart 10/11
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
SP
OSStart():
current = taskTCB[hiprio]
//SP = taskTCB[hiprio]->stkptr
ldr lr, = taskTCB[hiprio]
ldr lr, [lr]
ldr sp, [lr]
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
ldmia sp!, {lr}
msr spsr, lr
ldmia sp!, {lr}
movs pc, lr
High Priority Task’s Stack
stkptr
taskprio
tskstate
tskevent
taskname
NEXT
High Priority Task’sTCB
OSStart:
• Find the Highest priority task
• Load SP with TaskTCB[hiprio].stkptr
• Load the context
81
OSStart 11/11
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
SP
OSStart():
current = taskTCB[hiprio]
//SP = taskTCB[hiprio]->stkptr
ldr lr, = taskTCB[hiprio]
ldr lr, [lr]
ldr sp, [lr]
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
ldmia sp!, {lr}
msr spsr, lr
ldmia sp!, {lr}
movs pc, lr
High Priority Task’s Stack
stkptr
taskprio
tskstate
tskevent
taskname
NEXT
High Priority Task’sTCB
OSStart:
• Find the Highest priority task
• Load SP with TaskTCB[hiprio].stkptr
• Load the context
82
Entry from OSStart
void task1(void *data)
{
while(1)
{
block……
……
}
}
void task2(void *data)
{
while(1)
{
block……
……
}
}
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]void init_timer();int main(void){
OSInit(); init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart();
}
83
Condition on tasks- should be infinite
void task1(void *data)
{
while(1)
{
block……
……
}
}
void task2(void *data)
{
while(1)
{
block……
……
}
}
Tasks should never return
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]void init_timer();int main(void){
OSInit(); init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart();
}
84
Blocking/ unblocking calls mechanisms 1/11
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]
int main(void){
OSInit();TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart
}
void task1(void *data)
{
while(1)
{
block……
……
}
}
void task2(void *data)
{
while(1)
{
block……
……
}
}
85
Pseudo for Blocking / Unblocking call 2/11
Blockingcall(void)
{
//Check if called from ISR
current->taskstate->waitQ=1;
//Update current->tskevent
Sched();
}
UnBlockingcall(void)
{
//Check Task TCB to find the // task blocked on this event
taskTCB.taskstate->waitQ=0;
taskTCB.taskstate->readtQ=1;
//Update current->tskevent
Sched();
}
86
Blocking / Unblocking call 3/11
Blockingcall(void)
{
//Check if called from ISR
current->taskstate->waitQ=1;
//Update current->tskevent
Sched();
}
UnBlockingcall(void)
{
//Check Task TCB to find the // task blocked on this event
taskTCB.taskstate->waitQ=0;
taskTCB.taskstate->readtQ=1;
//Update current->tskevent
Sched();
}
87
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1
R0
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1
R0
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1
R0
stkptr
taskprio
tskstate
tskevent
taskname
NEXT
stkptr
taskprio
tskstate
tskevent
taskname
NEXT
stkptr
taskprio
tskstate
tskevent
taskname
NEXT NULL
0 0 1 0 0 1 0 0 1 0 0
1 0 0 1 1 0 1 1 0 1 1
readyQ
waitQ
readyQ
waitQ
RUN
readyQ
waitQ
RUN
readyQ
waitQ
RUN
TskStk[0] TskStk[1] TskStk[N]
TaskTCB[0] TaskTCB[1] TaskTCB[N]
TaskCreate():• Fill the TaskStk[taskprio]
with the stack frame• Initializes the
TaskTCB[taskprio].stkptr• Initializes the
tskstate.waitQ to waitQ[taskprio]
• Initializes the tskstate.readyQ to readyQ[taskprio]
OSInit():• Initialize kernel data
structures• Create an Idle task
Entry into the wait queue 4/11
88
Update task event 5/11
Blockingcall(void)
{
//Check if called from ISR
current->taskstate->waitQ=1;
//Update current->tskevent
Sched();
}
UnBlockingcall(void)
{
//Check Task TCB to find the // task blocked on this event
taskTCB.taskstate->waitQ=0;
taskTCB.taskstate->readtQ=1;
//Update current->tskevent
Sched();
}
89
Invoke scheduler 6/11
Blockingcall(void)
{
//Check if called from ISR
current->taskstate->waitQ=1;
//Update current->tskevent
Sched();
}
UnBlockingcall(void)
{
//Check Task TCB to find the // task blocked on this event
taskTCB.taskstate->waitQ=0;
taskTCB.taskstate->readtQ=1;
//Update current->tskevent
Sched();
}
90
Scheduler-code eg 7/11
• Schedule: to determine which job assigned to processor at any time.
Sched(void){
while(taskTCB.next != NULL){
if(taskTCB.tskstate.readyQ == 1) { if (currentTCB.Taskprio < taskTCB[prio] .taskprio
{next = taskTCB[prio]ContextSW();
} }}
}
91
Scheduler-check for H.P. ready 8/11
• Schedule: to determine which job assigned to processor at any time.
Sched(void){
while(taskTCB.next != NULL){
if(taskTCB.tskstate.readyQ == 1) { if (currentTCB.Taskprio < taskTCB[prio] .taskprio
{next = taskTCB[prio]ContextSW();
} }}
}
92
Scheduler-check for priority 9/11
• Schedule: to determine which job assigned to processor at any time.
Sched(void){
while(taskTCB.next != NULL){
if(taskTCB.tskstate.readyQ == 1) { if (currentTCB.Taskprio < taskTCB[prio] .taskprio
{next = taskTCB[prio]ContextSW();
} }}
}
93
Scheduler-load next task to run 10/11
• Schedule: to determine which job assigned to processor at any time.
Sched(void){
while(taskTCB.next != NULL){
if(taskTCB.tskstate.readyQ == 1) { if (currentTCB.Taskprio < taskTCB[prio] .taskprio
{next = taskTCB[prio]ContextSW();
} }}
}
94
Scheduler- calls context switch 11/11
• Schedule: to determine which job assigned to processor at any time.
Sched(void){
while(taskTCB.next != NULL){
if(taskTCB.tskstate.readyQ == 1) { if (currentTCB.Taskprio < taskTCB[prio] .taskprio
{next = taskTCB[prio]ContextSW();
} }}
}
95
Context SW Handler
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
SP
Context Load
Load Context:
current = next
SP = next.stkptr
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
ldmia sp!, {lr}
msr spsr, lr
ldmia sp!, {lr}
movs pc, lr
Save Context:
stmdb sp!, {lr}
mrs lr, cpsr
stmdb sp!, {lr}
stmdb sp!, {r0-r12}
current.stkptr=SP
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
current->stkptr
Context Save
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
next
96
Context SW Handler
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
SP
Context Load
Load Context:
current = next
SP = next.stkptr
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
ldmia sp!, {lr}
msr spsr, lr
ldmia sp!, {lr}
movs pc, lr
Save Context:
stmdb sp!, {lr}
mrs lr, cpsr
stmdb sp!, {lr}
stmdb sp!, {r0-r12}
current.stkptr=SP
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
current->stkptr
Context Save
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
next
SP
97
Context SW Handler
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
SP
Context Load
Load Context:
current = next
SP = next.stkptr
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
ldmia sp!, {lr}
msr spsr, lr
ldmia sp!, {lr}
movs pc, lr
Save Context:
stmdb sp!, {lr}
mrs lr, cpsr
stmdb sp!, {lr}
stmdb sp!, {r0-r12}
current.stkptr=SP
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
current->stkptr
Context Save
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
next
98
Context SW Handler
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
SP
Context Load
Load Context:
current = next
SP = next.stkptr
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
ldmia sp!, {lr}
msr spsr, lr
ldmia sp!, {lr}
movs pc, lr
Save Context:
stmdb sp!, {lr}
mrs lr, cpsr
stmdb sp!, {lr}
stmdb sp!, {r0-r12}
current.stkptr=SP
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
current->stkptr
Context Save
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
next
99
Context SW Handler
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
SP
Context Load
Load Context:
current = next
SP = next.stkptr
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
ldmia sp!, {lr}
msr spsr, lr
ldmia sp!, {lr}
movs pc, lr
Save Context:
stmdb sp!, {lr}
mrs lr, cpsr
stmdb sp!, {lr}
stmdb sp!, {r0-r12}
current.stkptr=SP
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
current->stkptr
Context Save
PCCPSR
LRR12R11R10R9R8R7R6R5R4R3R2R1R0
next
100
Task 2 now gets to run
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]
int main(void){
OSInit();TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart
}
void task1(void *data)
{
while(1)
{
block……
……
}
}
void task2(void *data)
{
while(1)
{
block……
……
}
}
101
Task States
• Executing: running on the CPU
• Ready: could run but another one is using the CPU
• Blocked: waits for something (I/O, signal, resource, etc.)
• Dormant: created but not executing yet
• Terminated: no longer activate
102
Task State Transition
TaskBlocked
TaskReady
TaskRunning
Sched/ContextSW
Preemption
TaskTerminated
TaskDormant
ContextSW
Un Blocking call Blocking call
TaskCreate
TaskDel
103
A Simple Task Model
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]
int main(void){
OSInit();TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart
}
void task1(void *data)
{
while(1)
{
block……
……
}
}
void task2(void *data)
{
while(1)
{
block……
……
}
}
104
A Simple Task Model
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]
int main(void){
OSInit();TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart
}
void task1(void *data)
{
//while(1)
{
block……
……
}
}
void task2(void *data)
{
//while(1)
{
block……
……
}
}
Return from subroutine instructions are available here (eg: MOV PC, LR)
105
Task State Transition
TaskBlocked
TaskReady
TaskRunning
Sched/ContextSW
Preemption
TaskTerminated
TaskDormant
ContextSW
Un Blocking call Blocking call
TaskCreate
TaskDel
106
Deleting a Task
#define NO_TASKS 3#define TASK_STK_SIZE 100unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]
int main(void){
OSInit();TaskCreate(task1, (void *) 0, “Task1”, 0);TaskCreate(task2, (void *) 0, “Task2”, 1);OSStart
}
void task1(void *data)
{
{
block……
……
}
TaskDel();
}
void task2(void *data)
{
{
block……
……
}
TaskDel();
}
107
Understanding Response & Execution time
void task1 (void *data){
while(1){
blockonEvent1();……..……..……..
}}
Execution Time
Event HW latency
ISR
Scheduler
Context SWDispatch Time/Response Time
Dispatch Time + Execution Time = Release Time < Dead Line
Release Time (t1) + Release Time (tn) < 100%
108
Task1 blocks
void task1 (void *data){
while(1){
blockonEvent1();……..……..……..
}}
Execution Time
Event HW latency
ISR
Scheduler
Context SWDispatch Time/Response Time
Dispatch Time + Execution Time = Release Time < Dead Line
Release Time (t1) + Release Time (tn) < 100%
109
An external event occurs
void task1 (void *data){
while(1){
blockonEvent1();……..……..……..
}}
Execution Time
Event HW latency
ISR
Scheduler
Context SWDispatch Time/Response Time
Dispatch Time + Execution Time = Release Time < Dead Line
Release Time (t1) + Release Time (tn) < 100%
110
Hardware latency for event to get detected
void task1 (void *data){
while(1){
blockonEvent1();……..……..……..
}}
Execution Time
Event HW latency
ISR
Scheduler
Context SWDispatch Time/Response Time
Dispatch Time + Execution Time = Release Time < Dead Line
Release Time (t1) + Release Time (tn) < 100%
111
void task1 (void *data){
while(1){
blockonEvent1();……..……..……..
}}
Execution Time
Event HW latency
ISR
Scheduler
Context SWDispatch Time/Response Time
Dispatch Time + Execution Time = Release Time < Dead Line
Release Time (t1) + Release Time (tn) < 100%
ISR gets executed
112
Scheduler is invoked
void task1 (void *data){
while(1){
blockonEvent1();……..……..……..
}}
Execution Time
Event HW latency
ISR
Scheduler
Context SWDispatch Time/Response Time
Dispatch Time + Execution Time = Release Time < Dead Line
Release Time (t1) + Release Time (tn) < 100%
113
void task1 (void *data){
while(1){
blockonEvent1();……..……..……..
}}
Execution Time
Event HW latency
ISR
Scheduler
Context SWDispatch Time/Response Time
Dispatch Time + Execution Time = Release Time < Dead Line
Release Time (t1) + Release Time (tn) < 100%
Dispatcher is invoked
114
void task1 (void *data){
while(1){
blockonEvent1();……..……..……..
}}
Execution Time
Event HW latency
ISR
Scheduler
Context SWDispatch Time/Response Time
Dispatch Time + Execution Time = Release Time < Dead Line
Release Time (t1) + Release Time (tn) < 100%
Task 1 is entered again Response time
115
void task1 (void *data){
while(1){
blockonEvent1();……..……..……..
}}
Execution Time
Event HW latency
ISR
Scheduler
Context SWDispatch Time/Response Time
Dispatch Time + Execution Time = Release Time < Dead Line
Release Time (t1) + Release Time (tn) < 100%
Execution time of task
116
void task1 (void *data){
while(1){
blockonEvent1();……..……..……..
}}
Execution Time
Event HW latency
ISR
Scheduler
Context SWDispatch Time/Response Time
Dispatch Time + Execution Time = Release Time < Dead Line
Release Time (t1) + Release Time (tn) < 100%
Deadline condition
117
void task1 (void *data){
while(1){
blockonEvent1();……..……..……..
}}
Execution Time
Event HW latency
ISR
Scheduler
Context SWDispatch Time/Response Time
Dispatch Time + Execution Time = Release Time < Dead Line
Release Time (t1) + Release Time (tn) < 100%
Release time condition
118
Interrupt Latency
Interrupt Response
Interrupt Recovery
119
For a Foreground/background system
TIME
120
For a non-preemptive scheduler
TIME
121
For a Preemptive scheduler
TIME
122
RTOS Tasks: Code Sharing Issues
• Reentrancy: A function is called reentrant if it can be entered simultaneously, by multiple tasks.
• Rules: A reentrant function– May not use variables in a non-atomic way (unless
local variables or private variables of the calling task)– May not call other, non-reentrant functions– May not use the HW in a non-atomic way
123
Achieving atomicity
• Test & Set
• Disable interrupts
• Use flags to prevent entry in to the critical sections
• Use of semaphores
124
Use Flags for atomicity
void taskl() {
while(flag !=1);
flag = 0;countErr(9);flag = 1;…..
}
void task2()
{
while(flag !=1);
flag = 0;
countErr(9);
flag = 1;
…..
}
125
Use Semaphore for atomicity
void taskl() {
OSSemPend();countErr(9);OSSemPost();…..
}
void task2()
{
OSSemPend();
countErr(9);
OSSemPost();
…..
}
int main() {
sem = OSSemCreate();}
126
How by Semaphores?
OSSemPend(sem)
{
if(flag == 1)
{
flag = 0;
}
else
{
// Add the task in waitQ
sched();
}
}
OSSemPost(sem)
{
if(flag == 0)
{
flag = 1;
// check the waitQ for
// the task blocked on
// sem
// If found then
// Remove it from waitQ
// and add in to ReadyQ
sched()
}
}
127
uCOS-II Semaphores usage
OS_EVENT *sem;void task(void *data){
char err;while(1){
OSSemPend(sem, 0, &err);
q_printf(“task”);OSSemPost(sem);
}}
int main(){
OSInit();init_timer();
sem=OSSemCreate(1);TaskCreate(…..);OSStart();
}
128
Shared Resource problems
129
Practical Problem 1
• Semaphore/mutex 1 used by Task1 to lock resource 1• Semaphore/mutex 2 used by Task2 to lock resource 2
• Task1 requires resource 2 to proceed • Task2 requires resource 1 to proceed
• Scenario: Neither of the tasks can proceed to completion
• Result: Deadlocks
130
131
Problem 2
• Priority Inversion : Higher priority task executed at the mercy of lower priority task
• Resource desired by higher priority task locked (say using semaphore ) by lower priority task
132
133
Solution for priority inversion
• Priority Inheritance: – Priority of Low level task raised to that of the
high priority task . – Avoids preemption of low priority task by
medium priority task.• Priority Ceiling
– Mutex or Semaphore initialized to a level known as the ceiling
– Priority of task that acquires the semaphore raised to the ceiling
– Priority raised above all other tasks desiring the semaphore.
134
Mutex System Calls
OS_EVENT *OSMutexCreate(INT8U prio,INT8U *err);
void OSMutexPend(OS_EVENT *pevent, INT16U timeout, INT8U *err);
INT8U OSMutexPost(OS_EVENT *pevent);
135
Mailbox
Task n blocksTask m unblocks by posting
Pointer sized data
136
Mailbox Systems Calls
OS_EVENT *OSMboxCreate(void *msg);
void *OSMboxPend(OS_EVENT *pevent, INT16U timeout, INT8U *err);
INT8U OSMboxPost(OS_EVENT *pevent, void *msg);
137
Message queue
138
M.Q. System Calls
OS_EVENT *OSQCreate(void **start, INT16U size);
void *OSQPend(OS_EVENT *pevent, INT16U timeout, INT8U *err);
INT8U OSQPost(OS_EVENT *pevent, void *msg);
139
We are Done
Questions??