Embedded Systems Programming RTOS introduction 14, Study notes of Embedded Systems Programming

Slides on: priority preemption, task switching,

Typology: Study notes

2010/2011

Uploaded on 08/28/2011

nihira
nihira 🇮🇳

4.3

(63)

90 documents

1 / 26

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
IN2305-II
Embedded Programming
Lecture 6:
RTOS Introduction
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a

Partial preview of the text

Download Embedded Systems Programming RTOS introduction 14 and more Study notes Embedded Systems Programming in PDF only on Docsity!

IN2305-II

Embedded Programming

Lecture 6:

RTOS Introduction

RTOS: Primary Motivation

Task switching with priority preemption

Additional services (semaphores, timers,

queues, ..)

Better code!

 Having interrupt facilities, one doesn’t always need to

throw a full-fledged RTOS at a problem

 However, in vast majority of the cases the code

becomes (1) cleaner, (2) much more readable by

another programmer, (3) less buggy, (4) more efficient

The price: negligible run-time overhead and

small footprint

Simple Example (X32)

void **thread_main; **thread_a; void *stack_a[1024];

int main(void) { thread_a = init_stack(stack_a, task_a); printf(“now in thread_main\n”); context_switch(thread_a,&thread_main); printf(“back in main_thread\n”); }

void task_a(void) { print(“now in thread_a\n“); context_switch(thread_main,&thread_a); }

Time Slicing Example (1)

void **thread_main; **thread_a; void *stack_a[1024]; int thread_id;

void isr_timer(void) { if (thread_id == 0) { thread_id = 1; context_switch(thread_a,&thread_main); } else { thread_id = 0; context_switch(thread_main,&thread_a); } }

X32: Demo

Demo ..

(x32_projects.tgz: slicing.c)

Task Switching in RTOS

In an RTOS task switching is performed by the RTOS

RTOS scheduler decides which task to run (continue)

Scheduling based on the state of all tasks:

blocked

running

ready

event occurred

waiting for event

highest prio ready

preempted by higher prio

RTOS interference

The block construct in vButtonTask is a call to the RTOS to deschedule the task until event has occurred This implies that another thread must eventually post this event, i.e., notifies the RTOS that the event has occurred, again by calling the RTOS Once the RTOS is notified it will unblock vButtonTask (i.e., move it’s state from blocked to ready) Thus, two RTOS functions are needed:  (^) OS_Pend(event) // block, go execute some other task  (^) OS_Post(event) // unblock the blocked task (eventually)

RTOS Implementation Example (1)

void OS_Pend(int event) { !! old_id = current task_id !! task_state[old_id] = BLOCKED !! event_task[event] = old_id; !! figure out which task to run -> new_id !! context_switch(task[new_id],&(task[old_id])) !! return // to task[old_id], once !! rescheduled to run }

UTMS Example Revisited

void isr_buttons(void) // ISR: be quick! only post { if (peripherals[BUTTONS] & 0x01) // button 0 OS_Post(event); // signal event }

void vButtonTask(void) // task: do the slow printing { while (TRUE) { OS_Pend(event); // wait for event printf(“current float levels: \n”); !! list them } }

UTMS Context Switching

vLevelsTask

button IRQ

button ISR

vButtonTask

OS_Pend OS_Post

RTOS

OS_Pend

highest priority task starts first

context switch

Shared Data Problem

Each task (thread) has its own context: PC, stack, regs (SP, other ..)

The rest is shared between all tasks

Shared data allows inter-task communication

Tasks can be preempted by another task (just like preemption by an ISR): shared data problem!

UTMS Example

void vButtonTask(void) // high priority { while (TRUE) { !! block until button push event !! print tankdata[i].lTimeUpdated !! print tankdata[i].lTankLevel } }

void vLevelsTask(void) // low priority { while (TRUE) { !! read + calculate tankdata[i].lTimeUpdated = !! time tankdata[i].lTankLevel = !! calc result } }

OS_Post

Example Reentrancy Problem

void task1(void) void task2(void) { { ..; vAdd(9); ..; ..; vAdd(11); ..; } }

void vAdd(int cInc) // NOT reentrant! { cErrors = cErrors + cInc; }

task task cErrors + cInc cErrors = ..

14 16 14

16 14

atomic

context switch

NOT atomic

Solutions

Just use local vars: no shared data problem, reentrancy guaranteed, no need for atomicity

But local vars don’t get you very far, at some point need to share data: make critical sections atomic In the case of interrupts we used {EN|DIS}ABLE_INT

Now we need to stop RTOS to preempt: OS_XXX() Classic OS service: semaphores P()/V(), pend()/post(), take()/release(), ..

cf. OS_Pend()/OS_Post() we saw earlier