0% found this document useful (0 votes)
1K views

RTOS Slides UCOS II

Notes on RTOS UCOS II

Uploaded by

grhvg_mct8224
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1K views

RTOS Slides UCOS II

Notes on RTOS UCOS II

Uploaded by

grhvg_mct8224
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 139

Real Time Operating Systems

1
Course flow

2
Session 1

• Startup code

• Runtime memory map

• Is OS needed?

• “Process” a living entity?

3
Motherboard block Diagram

4
© Copyright 2004, All Rights Reserved. OASIS Technologies
Runtime Memory Map
High Memory
stack End of RAM

heap

initialized data
Start of RAM
uninitialized data
End of ROM
text and RO
Low Memory
start of ROM
5
Application startup

Startup code: Low level hardware initialization


PLL clock
Serial port
Video controller
BSS & Data Segment initialization

6
CPU Vs Memory
Technology

7
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.

8
© 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

9
© Copyright 2004, All Rights Reserved. OASIS Technologies
OS Architecture

10
What OS provides?
• Kernel with Hardware • Hardware Abstraction
Abstraction Layer + I/O
Management – Application developers
need not know about
the underlying
hardware

• Scheduling • Proper Scheduling ensures


an efficient usage of
resources

• Process Management • User Programs can be


protected from each other

• Application can
• Inter Process Communication communicate with each
other with ease

• File Management • Faster Storage and


Retrieval of Data
• POSIX and other compliance
Subsystem • Portability

11
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…

12
© Copyright 2004, All Rights Reserved. OASIS Technologies
Process Address Space
(Process Image)
0xFFFFFFFF
Stack
(dynamically allocated)
SP

Virtual Heap
address space (dynamically allocated)
static data

Code PC
0x00000000 (text)

13
© 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
14
© Copyright 2004, All Rights Reserved. OASIS Technologies
Process State Diagram

15
© Copyright 2004, All Rights Reserved. OASIS Technologies
Process State Diagram

16
END OF SESSION 1
(Thank God!!!)

17
Session 2

• What are embedded systems?

• What are Real time systems?

• Analyzing Cyclic programming in embedded


systems

• Constraints on an OS in embedded systems

18
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

19
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

20
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.

21
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.

22
• 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

23
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

24
Cyclic Programming of Real Time systems

Open Fuel Valve


Wait for ½ Rev
Close Fuel Valve
Wait for ½ Rev
Ignition
Wait for ½ Rev

Open exhaust valve


Wait for ½ Rev

25
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

26
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

27
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
28
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

29
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.

30
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????????????

31
Design constraints for an Embedded RTOS


Time Constraint

Small Footprint

Low Interrupt Latency

Robust

Efficient usage of Resource

32
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.

33
END OF SESSION 2

34
SESSION 3

• RTOS architecture

• Building blocks of RTOS

• RTOS terminologies

• Introduction to ucosII OS

35
Real Time OS Architecture

APPLICATION

Kernel
IPC ISR

HAL Scheduler

Context Switch handler

Hardware

36
Building Blocks of a Real Time OS

• Kernel
– Task Management
– Scheduling
– Context switching
– IPC mechanism
– Timer Handling
• Memory Management
• Device driver
• Protocol stack

37
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

38
Micro-kernel
MINIX 3, L4, QNX

Net Application

H
HW Kernel
A
L

File Device Memory


System Driver Mgmt.

39
Monolithic Kernel
Linux, Windows

Net

H
HW Proc
A Device Application
L Driver

Memory
Mgmt. File
System

40
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.

41
Round Robin Scheduling

• Equal Priority tasks given control of CPU in Round Robin


Fashion : One after the other
• Equal Time Slices for each task.

42
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)

43
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. )

44
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.

45
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)

46
Important aspects of Threads

• Functional entity in operation

• Has its own context

• Follows task state transitions.

47
IPC mechanisms
• Pipes
• Shared memory
• semaphores
• Mailbox
• Message queues

48
RTOS Terminologies
• Re-entrant
• Critical section
• Atomicity
• Deadlock

49
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

50
Introduction to uC/OSII OS
• Features:

1. Supports multitasking for up to 64 tasks


2. 0 implies maximum priority
3. Pre-emptive kernel
4. Portable & scalable
5. Several IPC mechanisms for task communication

51
Sample Application code
int main() void t2(void)
{ {
while(1)
} {
print();
void t1(void)
{ wait();
while(1) …….
{ }
waitfordata(); }
getData();
….. int getData(void)
} {
}
void print(char *data_t)
{
}

}
52
A Simple Task Model
#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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) void task2(void *data)
{ {
while(1) while(1)
{ {
block…… block……
…… ……
} }
} } 53
A Simple Task Model
#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]
void init_timer();
int main(void)
{
OSInit(); Task Priorities
init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);
TaskCreate(task2, (void *) 0, “Task2”, 1);
OSStart();
}
void task2(void *data)
void task1(void *data)
{
{
while(1) while(1)
{ {
block…… block……
…… ……
} }
}
} 54
A Simple Task Model
#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]
void init_timer();
int main(void)
{
OSInit();
init_timer(); After OSStart you
TaskCreate(task1, (void *) 0, “Task1”, 0); will not come here
TaskCreate(task2, (void *) 0, “Task2”, 1); but will go to highest
OSStart(); priority task code in
} this case task1

void task1(void *data)


void task2(void *data)
{
{
while(1)
while(1)
{
{
block……
block……
……
……
}
}
}
} 55
A Simple Task Model
#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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 task2(void *data)
void task1(void *data) {
{ while(1)
while(1) {
{ block……
block…… ……
…… }
} }
}
56
A Simple Task Model
#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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) void task2(void *data)


{ {
while(1) while(1)
{ {
block…… block……
…… ……
} }
} }
57
A Simple Task Model
#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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 task2(void *data)
void task1(void *data)
{
{
while(1)
while(1)
{
{
block……
block……
……
……
}
}
}
}
58
A Simple Task Model
#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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) void task2(void *data)


{
{
while(1)
while(1)
{
{
block…… block……
……
……
} }
} }
59
A Simple Task Model

#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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) void task2(void *data)
{ {
while(1) while(1)
{ {
block…… block……
…… ……
} }
} } 60
Understanding ‘task create’ system call 1/4
#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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)


void task2(void *data)
{
{
while(1)
while(1)
{
{
block……
block……
……
……
}
} 61
}
Understanding ‘task create’ system call 2/4
#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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)


void task2(void *data)
{
{
while(1)
while(1)
{
{
block……
block……
……
……
}
} 62
}
Understanding ‘task create’ system call 3/4
#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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)


void task2(void *data)
{
{
while(1)
while(1)
{
{
block……
block……
……
……
}
} 63
}
Understanding ‘task create’ system call 4/4
#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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) void task2(void *data)
{ {
while(1) while(1)
{ {
block…… block……
…… ……
} }
} }
64
Stacks allocated on TaskStk
#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned int TaskStk[NO_TASK][TASK_STK_SIZE]
void init_timer(); Tasks stack—USER
int main(void) HAS TO INCLUDE it
{
OSInit();
init_timer();
TaskCreate(task1, (void *) 0, “Task1”, 0);
TaskCreate(task2, (void *) 0, “Task2”, 1); Stack
OSStart(); for
} Task2

void task1(void *data) Stack void task2(void *data)


for
{ Task1 {
while(1) while(1)
{ {
block…… block……
…… ……
} }
} }
65
Kernel data structure

typedef struct _TCB typedef struct _STATE typedef struct _EVENT


{ { {
unsigned int *stkptr; char *readyQ; unsigned int type;
unsigned int taskprio; void *data;
char *waitQ;
STATE *tskstate; } MSGEVENT;
} STATE;
MSGEVENT *tskevent;
char *tskname;
TCB *next;
} TCB;
unsigned int TaskStk[NO_TASK][TASK_STK_SIZE];
TCB TaskTCB[NO_TASK];
char waitQ[NO_TASK];
TCB *current, *next;
char readyQ[NO_TASK]

readyQ 0 0 1 0 0 1 0 0 1 0 0

waitQ 1 0 0 1 1 0 1 1 0 1 1
66
Kernel data structure

typedef struct _TCB typedef struct _STATE typedef struct _EVENT


{ { {
unsigned int *stkptr; char *readyQ; unsigned int type;
unsigned int taskprio; void *data;
char *waitQ;
STATE *tskstate; } MSGEVENT;
} STATE;
MSGEVENT *tskevent;
char *tskname;
TCB *next;
} TCB;
unsigned int TaskStk[NO_TASK][TASK_STK_SIZE];
TCB TaskTCB[NO_TASK];
char waitQ[NO_TASK];
TCB *current, *next;
char readyQ[NO_TASK]

readyQ 0 0 1 0 0 1 0 0 1 0 0

waitQ 1 0 0 1 1 0 1 1 0 1 1
67
PC PC
PC TaskCreate(): CPSR
CPSR CPSR
LR OSInit(): LR • Fill the TaskStk[taskprio] LR
R12 R12
R12 • Initialize kernel data R11
with the stack frame R11
R11 R10
R10 structures R10 • Initializes the R9
R9 R9
R8 • Create an Ideal task R8 TaskTCB[taskprio].stkptr R8
R7 R7
R7
R6 • Initializes the R6
R6 R5
R5 R5 tskstate.waitQ to
R4 R4
R4
R3 R3 waitQ[taskprio] R3
R2 R2
R2
R1
• Initializes the R1
R1
R0 R0 tskstate.readyQ to R0
readyQ[taskprio]

TskStk[0] TskStk[1] TskStk[N]


TaskTCB[N]
TaskTCB[0] TaskTCB[1]
stkptr stkptr stkptr
taskprio readyQ taskprio taskprio
readyQ readyQ
tskstate
tskstate waitQ tskstate
waitQ waitQ tskevent
tskevent RUN tskevent
RUN RUN taskname
taskname taskname
NEXT NEXT
NEXT NULL

readyQ 0 0 1 0 0 1 0 0 1 0 0
waitQ 1 0 0 1 1 0 1 1 0 1 1
68
A Simple Task Model

#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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) void task2(void *data)


{ {
while(1) while(1)
{ {
block…… block……
…… ……
} }
} }
69
OSStart 1/11

OSStart:
• Find the Highest priority task High Priority Task’s Stack
• Load SP with TaskTCB[hiprio].stkptr
PC
• Load the context CPSR
LR
OSStart(): R12
current = taskTCB[hiprio] R11
R10
//SP = taskTCB[hiprio]->stkptr R9
ldr lr, = taskTCB[hiprio] R8
R7
ldr lr, [lr] R6
R5
ldr sp, [lr] R4
High Priority Task’sTCB
ldmia sp!, {r0-r12} R3
SP stkptr R2
ldmia sp!, {lr} taskprio R1
ldmia sp!, {lr} tskstate R0
tskevent
msr spsr, lr taskname
ldmia sp!, {lr} NEXT
movs pc, lr 70
OSStart 2/11

OSStart:
• Find the Highest priority task High Priority Task’s Stack
• Load SP with TaskTCB[hiprio].stkptr
PC
• Load the context CPSR
LR
OSStart(): R12
current = taskTCB[hiprio] R11
R10
//SP = taskTCB[hiprio]->stkptr R9
ldr lr, = taskTCB[hiprio] R8
R7
ldr lr, [lr] R6
R5
ldr sp, [lr] R4
High Priority Task’sTCB
ldmia sp!, {r0-r12} R3
SP stkptr R2
ldmia sp!, {lr} taskprio R1
ldmia sp!, {lr} tskstate R0
tskevent
msr spsr, lr taskname
ldmia sp!, {lr} NEXT
movs pc, lr 71
TCB stack pointer?

typedef struct _TCB typedef struct _STATE typedef struct _EVENT


{ { {
unsigned int *stkptr char *readyQ unsigned int type
unsigned int taskprio void *data
char *waitQ
STATE *tskstate } MSGEVENT;
} STATE;
MSGEVENT *tskevent
char *tskname
TCB *next;
} TCB;
unsigned int TaskStk[NO_TASK][TASK_STK_SIZE];
TCB TaskTCB[NO_TASK];
char waitQ[NO_TASK];
TCB *current, *next;
char readyQ[NO_TASK]

readyQ 0 0 1 0 0 1 0 0 1 0 0

waitQ 1 0 0 1 1 0 1 1 0 1 1
72
OSStart 3/11

OSStart:
• Find the Highest priority task High Priority Task’s Stack
• Load SP with TaskTCB[hiprio].stkptr
PC
• Load the context CPSR
LR
OSStart(): R12
current = taskTCB[hiprio] R11
R10
//SP = taskTCB[hiprio]->stkptr R9
ldr lr, = taskTCB[hiprio] R8
R7
ldr lr, [lr] R6
R5
ldr sp, [lr] R4
High Priority Task’sTCB
ldmia sp!, {r0-r12} R3
SP stkptr R2
ldmia sp!, {lr} taskprio R1
ldmia sp!, {lr} tskstate R0
tskevent
msr spsr, lr taskname
ldmia sp!, {lr} NEXT
movs pc, lr 73
OSStart 4/11

OSStart:
• Find the Highest priority task High Priority Task’s Stack
• Load SP with TaskTCB[hiprio].stkptr
PC
• Load the context CPSR
LR
OSStart(): R12
current = taskTCB[hiprio] R11
R10
//SP = taskTCB[hiprio]->stkptr R9
ldr lr, = taskTCB[hiprio] R8
R7
ldr lr, [lr] R6
R5
ldr sp, [lr] R4
High Priority Task’sTCB
ldmia sp!, {r0-r12} R3
SP stkptr R2
ldmia sp!, {lr} taskprio R1
ldmia sp!, {lr} tskstate R0
tskevent
msr spsr, lr taskname
ldmia sp!, {lr} NEXT
movs pc, lr 74
OSStart 5/11

OSStart:
• Find the Highest priority task High Priority Task’s Stack
• Load SP with TaskTCB[hiprio].stkptr
PC
• Load the context CPSR
LR
OSStart(): R12
current = taskTCB[hiprio] R11
R10
//SP = taskTCB[hiprio]->stkptr R9
ldr lr, = taskTCB[hiprio] R8
R7
ldr lr, [lr] R6
R5
ldr sp, [lr] R4
High Priority Task’sTCB
ldmia sp!, {r0-r12} R3
SP stkptr R2
ldmia sp!, {lr} taskprio R1
ldmia sp!, {lr} tskstate R0
tskevent
msr spsr, lr taskname
ldmia sp!, {lr} NEXT
movs pc, lr 75
OSStart 6/11

OSStart:
• Find the Highest priority task High Priority Task’s Stack
• Load SP with TaskTCB[hiprio].stkptr
PC
• Load the context CPSR
LR
OSStart(): R12
current = taskTCB[hiprio] R11
R10
//SP = taskTCB[hiprio]->stkptr R9
ldr lr, = taskTCB[hiprio] R8
R7
ldr lr, [lr] R6
R5
ldr sp, [lr] R4
High Priority Task’sTCB
ldmia sp!, {r0-r12} R3
SP stkptr R2
ldmia sp!, {lr} taskprio R1
ldmia sp!, {lr} tskstate R0
tskevent
msr spsr, lr taskname
ldmia sp!, {lr} NEXT
movs pc, lr 76
OSStart 7/11

OSStart:
• Find the Highest priority task High Priority Task’s Stack
• Load SP with TaskTCB[hiprio].stkptr
PC
• Load the context CPSR
LR
OSStart(): R12
current = taskTCB[hiprio] R11
R10
//SP = taskTCB[hiprio]->stkptr R9
ldr lr, = taskTCB[hiprio] R8
R7
ldr lr, [lr] R6
R5
ldr sp, [lr] R4
High Priority Task’sTCB
ldmia sp!, {r0-r12} R3
SP stkptr R2
ldmia sp!, {lr} taskprio R1
ldmia sp!, {lr} tskstate R0
tskevent
msr spsr, lr taskname
ldmia sp!, {lr} NEXT
movs pc, lr 77
OSStart 8/11

OSStart:
• Find the Highest priority task High Priority Task’s Stack
• Load SP with TaskTCB[hiprio].stkptr
PC
• Load the context CPSR
LR
OSStart(): R12
current = taskTCB[hiprio] R11
R10
//SP = taskTCB[hiprio]->stkptr R9
ldr lr, = taskTCB[hiprio] R8
R7
ldr lr, [lr] R6
R5
ldr sp, [lr] R4
High Priority Task’sTCB
ldmia sp!, {r0-r12} R3
SP stkptr R2
ldmia sp!, {lr} taskprio R1
ldmia sp!, {lr} tskstate R0
tskevent
msr spsr, lr taskname
ldmia sp!, {lr} NEXT
movs pc, lr 78
OSStart 9/11

OSStart:
• Find the Highest priority task High Priority Task’s Stack
• Load SP with TaskTCB[hiprio].stkptr
PC
• Load the context CPSR
LR
OSStart(): R12
current = taskTCB[hiprio] R11
R10
//SP = taskTCB[hiprio]->stkptr R9
ldr lr, = taskTCB[hiprio] R8
R7
ldr lr, [lr] R6
R5
ldr sp, [lr] R4
High Priority Task’sTCB
ldmia sp!, {r0-r12} R3
SP stkptr R2
ldmia sp!, {lr} taskprio R1
ldmia sp!, {lr} tskstate R0
tskevent
msr spsr, lr taskname
ldmia sp!, {lr} NEXT
movs pc, lr 79
OSStart 10/11

OSStart:
• Find the Highest priority task High Priority Task’s Stack
• Load SP with TaskTCB[hiprio].stkptr
PC
• Load the context CPSR
LR
OSStart(): R12
current = taskTCB[hiprio] R11
R10
//SP = taskTCB[hiprio]->stkptr R9
ldr lr, = taskTCB[hiprio] R8
R7
ldr lr, [lr] R6
R5
ldr sp, [lr] R4
High Priority Task’sTCB
ldmia sp!, {r0-r12} R3
SP stkptr R2
ldmia sp!, {lr} taskprio R1
ldmia sp!, {lr} tskstate R0
tskevent
msr spsr, lr taskname
ldmia sp!, {lr} NEXT
movs pc, lr 80
OSStart 11/11

OSStart:
• Find the Highest priority task High Priority Task’s Stack
• Load SP with TaskTCB[hiprio].stkptr
PC
• Load the context CPSR
LR
OSStart(): R12
current = taskTCB[hiprio] R11
R10
//SP = taskTCB[hiprio]->stkptr R9
ldr lr, = taskTCB[hiprio] R8
R7
ldr lr, [lr] R6
R5
ldr sp, [lr] R4
High Priority Task’sTCB
ldmia sp!, {r0-r12} R3
SP stkptr R2
ldmia sp!, {lr} taskprio R1
ldmia sp!, {lr} tskstate R0
tskevent
msr spsr, lr taskname
ldmia sp!, {lr} NEXT
movs pc, lr 81
Entry from OSStart
#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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)


void task2(void *data)
{
{
while(1)
while(1)
{
{
block……
block……
……
……
}
} 82
}
Condition on tasks- should be infinite
#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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();
}
Tasks should never return
void task1(void *data)
void task2(void *data)
{
{
while(1)
while(1)
{
{
block……
block……
……
……
}
} 83
}
Blocking/ unblocking calls mechanisms 1/11

#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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)


void task2(void *data)
{
{
while(1)
while(1)
{
{
block……
block……
……
……
}
} 84
}
Pseudo for Blocking / Unblocking call 2/11

Blockingcall(void) UnBlockingcall(void)
{ {
//Check if called from ISR //Check Task TCB to find
the // task blocked on this
current->taskstate->waitQ=1;
event
//Update current->tskevent
taskTCB.taskstate->waitQ=0;
Sched();
taskTCB.taskstate->readtQ=1;
}
//Update current->tskevent
Sched();
}

85
Blocking / Unblocking call 3/11

Blockingcall(void) UnBlockingcall(void)
{ {
//Check if called from ISR //Check Task TCB to find
the // task blocked on this
current->taskstate->waitQ=1;
event
//Update current->tskevent
taskTCB.taskstate->waitQ=0;
Sched();
taskTCB.taskstate->readtQ=1;
}
//Update current->tskevent
Sched();
}

86
Entry into the wait queue 4/11
PC PC
PC TaskCreate(): CPSR
CPSR CPSR
LR OSInit(): LR • Fill the TaskStk[taskprio] LR
R12 R12
R12 • Initialize kernel data R11
with the stack frame R11
R11 R10
R10 structures R10 • Initializes the R9
R9 R9
R8 • Create an Idle task R8 TaskTCB[taskprio].stkptr R8
R7 R7
R7
R6 • Initializes the R6
R6 R5
R5 R5 tskstate.waitQ to
R4 R4
R4
R3 R3 waitQ[taskprio] R3
R2 R2
R2
R1
• Initializes the R1
R1
R0 R0 tskstate.readyQ to R0
readyQ[taskprio]

TskStk[0] TskStk[1] TskStk[N]


TaskTCB[N]
TaskTCB[0] TaskTCB[1]
stkptr stkptr stkptr
taskprio readyQ taskprio taskprio
readyQ readyQ
tskstate
tskstate waitQ tskstate
waitQ waitQ tskevent
tskevent RUN tskevent
RUN RUN taskname
taskname taskname
NEXT NEXT
NEXT NULL

readyQ 0 0 1 0 0 1 0 0 1 0 0
waitQ 1 0 0 1 1 0 1 1 0 1 1
87
Update task event 5/11

Blockingcall(void) UnBlockingcall(void)
{ {
//Check if called from ISR //Check Task TCB to find
the // task blocked on this
current->taskstate->waitQ=1;
event
//Update current->tskevent
taskTCB.taskstate->waitQ=0;
Sched();
taskTCB.taskstate->readtQ=1;
}
//Update current->tskevent
Sched();
}

88
Invoke scheduler 6/11

Blockingcall(void) UnBlockingcall(void)
{ {
//Check if called from ISR //Check Task TCB to find
the // task blocked on this
current->taskstate->waitQ=1;
event
//Update current->tskevent
taskTCB.taskstate->waitQ=0;
Sched();
taskTCB.taskstate->readtQ=1;
}
//Update current->tskevent
Sched();
}

89
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();
}
}
}
}

90
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();
}
}
}
}

91
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();
}
}
}
}

92
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();
}
}
}
}

93
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();
}
}
}
}

94
Context SW Handler
Context Save Context Load
Save Context:
stmdb sp!, {lr}
mrs lr, cpsr
stmdb sp!, {lr} PC PC
stmdb sp!, {r0-r12} CPSR CPSR
LR LR
current.stkptr=SP R12 R12
R11 R11
R10 R10
Load Context: R9 R9
current = next R8 R8
R7 R7
SP = next.stkptr R6 R6
R5 R5
ldmia sp!, {r0-r12} R4 R4
ldmia sp!, {lr} R3 R3
R2 R2
ldmia sp!, {lr} R1 R1
msr spsr, lr R0 R0
current->stkptr
ldmia sp!, {lr} SP
movs pc, lr next 95
Context SW Handler

Save Context: Context Save Context Load


stmdb sp!, {lr}
mrs lr, cpsr
stmdb sp!, {lr}
stmdb sp!, {r0-r12} SP PC PC
CPSR CPSR
current.stkptr=SP LR LR
R12 R12
R11 R11
Load Context: R10
R10
current = next R9 R9
R8 R8
SP = next.stkptr R7 R7
ldmia sp!, {r0-r12} R6 R6
R5 R5
ldmia sp!, {lr} R4 R4
R3 R3
ldmia sp!, {lr} R2
R2
msr spsr, lr R1 R1
R0 R0
ldmia sp!, {lr} current->stkptr SP
movs pc, lr
next 96
Context SW Handler

Save Context: Context Save Context Load


stmdb sp!, {lr}
mrs lr, cpsr
stmdb sp!, {lr}
stmdb sp!, {r0-r12} PC PC
CPSR CPSR
current.stkptr=SP LR LR
R12 R12
R11 R11
Load Context: R10
R10
current = next R9 R9
R8 R8
SP = next.stkptr R7 R7
ldmia sp!, {r0-r12} R6 R6
R5 R5
ldmia sp!, {lr} R4 R4
R3 R3
ldmia sp!, {lr} R2
R2
msr spsr, lr R1 R1
R0 R0
ldmia sp!, {lr} current->stkptr SP
movs pc, lr
next 97
Context SW Handler
Save Context: Context Save Context Load
stmdb sp!, {lr}
mrs lr, cpsr
stmdb sp!, {lr}
stmdb sp!, {r0-r12} PC PC
CPSR CPSR
current.stkptr=SP LR LR
R12 R12
R11 R11
Load Context: R10
R10
current = next R9 R9
R8 R8
SP = next.stkptr R7 R7
ldmia sp!, {r0-r12} R6 R6
R5 R5
ldmia sp!, {lr} R4 R4
R3 R3
ldmia sp!, {lr} R2
R2
msr spsr, lr R1 R1
R0 R0
ldmia sp!, {lr} current->stkptr SP
movs pc, lr
next 98
Context SW Handler

Save Context: Context Save Context Load


stmdb sp!, {lr}
mrs lr, cpsr
stmdb sp!, {lr}
stmdb sp!, {r0-r12} PC PC
CPSR CPSR
current.stkptr=SP LR LR
R12 R12
R11 R11
Load Context: R10
R10
current = next R9 R9
R8 R8
SP = next.stkptr R7 R7
ldmia sp!, {r0-r12} R6 R6
R5 R5
ldmia sp!, {lr} R4 R4
R3 R3
ldmia sp!, {lr} R2
R2
msr spsr, lr R1 R1
R0 R0
ldmia sp!, {lr} current->stkptr SP
movs pc, lr
next 99
Task 2 now gets to run

#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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)


void task2(void *data)
{
{
while(1)
while(1)
{
{
block……
block……
……
……
}
} 100
}
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

101
Task State Transition

Task
Task Blocked
Dormant
Un Blocking call
Blocking call
TaskCreate

Sched/ContextSW Task Task


Task
Ready Running Terminated
TaskDel
ContextSW
Preemption

102
A Simple Task Model

#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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)


void task2(void *data)
{
{
while(1)
while(1)
{
{
block……
block……
……
……
}
} 103
}
A Simple Task Model

#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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) void task2(void *data)


{ {
//while(1) //while(1)
{ {
block…… Return from subroutine block……
instructions are available
…… here (eg: MOV PC, LR) ……
} }
104
} }
Task State Transition

Task
Task Blocked
Dormant
Un Blocking call
Blocking call
TaskCreate

Sched/ContextSW Task Task


Task
Ready Running Terminated
TaskDel
ContextSW
Preemption

105
Deleting a Task

#define NO_TASKS 3
#define TASK_STK_SIZE 100
unsigned 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) void task2(void *data)


{ {
{ {
block…… block……
…… ……
} }
TaskDel(); TaskDel();
106
} }
Understanding Response & Execution time

Event HW ISR
latency
void task1 (void *data) Scheduler
{
while(1) Context SW
{ Dispatch Time/Response Time
blockonEvent1();
……..
…….. Execution Time
……..
}
} Dispatch Time + Execution Time = Release Time < Dead Line

Release Time (t1) + Release Time (tn) < 100%


107
Task1 blocks

Event HW ISR
latency
void task1 (void *data) Scheduler
{
while(1) Context SW
{ Dispatch Time/Response Time
blockonEvent1();
……..
…….. Execution Time
……..
}
} Dispatch Time + Execution Time = Release Time < Dead Line

Release Time (t1) + Release Time (tn) < 100%


108
An external event occurs

Event HW ISR
latency
void task1 (void *data) Scheduler
{
while(1) Context SW
{ Dispatch Time/Response Time
blockonEvent1();
……..
…….. Execution Time
……..
}
} Dispatch Time + Execution Time = Release Time < Dead Line

Release Time (t1) + Release Time (tn) < 100%


109
Hardware latency for event to get detected

Event HW ISR
latency
void task1 (void *data) Scheduler
{
while(1) Context SW
{ Dispatch Time/Response Time
blockonEvent1();
……..
…….. Execution Time
……..
}
} Dispatch Time + Execution Time = Release Time < Dead Line

Release Time (t1) + Release Time (tn) < 100%


110
ISR gets executed

Event HW ISR
latency
void task1 (void *data) Scheduler
{
while(1) Context SW
{ Dispatch Time/Response Time
blockonEvent1();
……..
…….. Execution Time
……..
}
} Dispatch Time + Execution Time = Release Time < Dead Line

Release Time (t1) + Release Time (tn) < 100%


111
Scheduler is invoked

Event HW ISR
latency
void task1 (void *data) Scheduler
{
while(1) Context SW
{ Dispatch Time/Response Time
blockonEvent1();
……..
…….. Execution Time
……..
}
} Dispatch Time + Execution Time = Release Time < Dead Line

Release Time (t1) + Release Time (tn) < 100%


112
Dispatcher is invoked

Event HW ISR
latency
void task1 (void *data) Scheduler
{
while(1) Context SW
{ Dispatch Time/Response Time
blockonEvent1();
……..
…….. Execution Time
……..
}
} Dispatch Time + Execution Time = Release Time < Dead Line

Release Time (t1) + Release Time (tn) < 100%


113
Task 1 is entered again  Response time

Event HW ISR
latency
void task1 (void *data) Scheduler
{
while(1) Dispatch Time/Response Time
Context SW
{
blockonEvent1();
……..
…….. Execution Time
……..
}
} Dispatch Time + Execution Time = Release Time < Dead Line

Release Time (t1) + Release Time (tn) < 100%


114
Execution time of task

Event HW ISR
latency
void task1 (void *data) Scheduler
{
while(1) Context SW
{ Dispatch Time/Response Time
blockonEvent1();
……..
…….. Execution Time
……..
}
} Dispatch Time + Execution Time = Release Time < Dead Line

Release Time (t1) + Release Time (tn) < 100%


115
Deadline condition

Event HW ISR
latency
void task1 (void *data) Scheduler
{
while(1) Context SW
{ Dispatch Time/Response Time
blockonEvent1();
……..
…….. Execution Time
……..
}
} Dispatch Time + Execution Time = Release Time < Dead Line

Release Time (t1) + Release Time (tn) < 100%


116
Release time condition

Event HW ISR
latency
void task1 (void *data) Scheduler
{
while(1) Context SW
{ Dispatch Time/Response Time
blockonEvent1();
……..
…….. Execution Time
……..
}
} Dispatch Time + Execution Time = Release Time < Dead Line

Release Time (t1) + Release Time (tn) < 100%


117
Interrupt Latency

Interrupt Response

Interrupt Recovery

118
For a Foreground/background system

TIME

119
For a non-preemptive scheduler

TIME

120
For a Preemptive scheduler

TIME

121
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

122
Achieving atomicity

• Test & Set

• Disable interrupts

• Use flags to prevent entry in to the critical sections

• Use of semaphores

123
Use Flags for atomicity

void taskl() void task2()


{ {
while(flag !=1); while(flag !=1);
flag = 0;
flag = 0;
countErr(9); countErr(9);
flag = 1; flag = 1;
….. …..
} }

124
Use Semaphore for atomicity

int main()
{
sem = OSSemCreate();
} void task2()
{
void taskl()
OSSemPend();
{
OSSemPend(); countErr(9);
countErr(9); OSSemPost();
OSSemPost(); …..
….. }
}

125
How by Semaphores?

OSSemPend(sem) OSSemPost(sem)
{ {
if(flag == 1) if(flag == 0)
{ {
flag = 0; flag = 1;
} // check the waitQ for
else // the task blocked on
{ // sem
// Add the task in waitQ // If found then
sched(); // Remove it from waitQ
} // and add in to ReadyQ
} sched()
}
} 126
uCOS-II Semaphores usage

OS_EVENT *sem; int main()


void task(void *data) {
{ OSInit();
char err; init_timer();
while(1)
{ sem=OSSemCreate(
OSSemPend(sem, 0, 1);
&err); TaskCreate(…..);
q_printf(“task”); OSStart();
OSSemPost(sem); }
}
}

127
Shared Resource problems

128
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

129
130
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

131
132
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.
133
Mutex System Calls
OS_EVENT *OSMutexCreate(INT8U prio,INT8U *err);
void OSMutexPend(OS_EVENT *pevent, INT16U timeout, INT8U *err);
INT8U OSMutexPost(OS_EVENT *pevent);

134
Mailbox

Task m unblocks by
Task n blocks posting

Pointer sized data

135
Mailbox Systems Calls

OS_EVENT *OSMboxCreate(void *msg);


void *OSMboxPend(OS_EVENT *pevent, INT16U timeout, INT8U *err);
INT8U OSMboxPost(OS_EVENT *pevent, void *msg);

136
Message queue

137
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);

138
We are Done

Questions??

139

You might also like