RTOS Slides UCOS II

Preview:

DESCRIPTION

Notes on RTOS UCOS II

Citation preview

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

Recommended