1 / 39

Embedded Software

dr. Stefan Dulman Embedded Software Group. Embedded Software. TI2720-C. 4 . RTOS- es and services. Test.

sibley
Download Presentation

Embedded Software

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. dr. Stefan Dulman Embedded Software Group Embedded Software TI2720-C 4. RTOS-es and services

  2. Test Consider the following (pseudo) code, which reads the current values of 3 different buttons and acts accordingly. The 3 buttons are all mapped to bits 0..2 of the register buttons. The buttons are already debounced; execution time of ISR is negligible. void task1(void) { delay(1000); } void task2(void) { delay(2000); } void task3(void) { delay(3000); } isr_button1() {b1=1}; // arrive here if button 1 is pressed isr_button2() {b2=1}; // arrive here if button 2 is pressed isr_button3() {b3=1}; // arrive here if button 3 is pressed void main (void) { while (1) { if (b1) { task1(); b1=0; } if (b2) { task2(); b2=0; } if (b3) { task3(); b3=0; }}}

  3. Question 1: • Which of the following statements is correct? This source code is an example of a … a) RR architecture b) RRI architecture c) FQS architecture d) RTOS architecture

  4. Question 2: • None of the buttons has been pressed. Button 3 is pressed and released three times during an interval of 2 seconds. None of the buttons is pressed afterwards. Which of the following is true? a) task3() is not executed at all. b) task3() might not be executed at all. c) task3() executes only once. d) task3() executes three times.

  5. Question 3: • None of the buttons has been pressed. Button 3 is pressed and immediately released. After 2 seconds, button 2 is pressed and immediately released. After 2 more seconds, button 2 is pressed and immediately released. Which of the following is true? a) task2() preempts the execution of task3() b) task2() executes once c) task2() executes twice d) none of the above

  6. Lecture overview • RTOSes • Task/context switching • Reentrancy • Usage of semaphores

  7. Why choose an RTOS? • Task switching with priority preemption • Additional services: semaphores, timers, queues, … • Better code! • Interrupts can do the job in various situations • However, in vast majority of the cases the code becomes • Cleaner, much more readable • Less buggy, more efficient • The price: negligible run-time overhead and small footprint • Terminology! (kernel, RTOS kernel, RTK, etc…)

  8. Embedded RTOS • Characteristics • It is quite different from Linux & co. • Application usually has control and starts the OS • Little protection on RTOS side • Pointers – if application fails, all fails! • Restarting application = restarting the whole software • Specific configuration selected at runtime

  9. Task switching • Task switching = switching from current context (PC, stack, registers) to another context • Context • thread identity, hence multithreading • needs two constructs: initialize context, switch to context • X32 (see previous lecture!) void *stack[1024]; init_stack(stack, (void *) task, (void *) 0) context_switch (new_context, &old_context)

  10. 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”); } voidtask_a(void) { print(“now in thread_a\n“); context_switch(thread_main,&thread_a); }

  11. ready blocked event occurred running highest prio ready preempted by higher prio waiting for event Task Switching in RTOS • Task switching is performed by RTOS (simple scheduler) • RTOS scheduler decides which task to run (continue) • Scheduling based on the state of all tasksterminology!!! suspended, pended, waiting, dormant, delayed

  12. Questions • How does the scheduler know when a task has become blocked/unblocked? • What happens if all tasks are blocked? • What if two tasks with the same priority are ready? • What happens with the running task when a higher priority task becomes unblocked?

  13. UTMS Example void vButtonTask(void) // high priority { while (TRUE) { !! block until button push event !! quickly respond to user } } void vLevelsTask(void) // low priority { while (TRUE) { !! read float levels in tank !! do a looooong calculation } }

  14. RTOS interference • block construct in vButtonTask is a call to the RTOS to de-schedule the task until event has occurred • Another thread must eventually post this event • Notify the RTOS that the event has occurred • Otherwise we have “starvation” (common source of error) • Once the RTOS is notified it will unblock vButtonTask • Change its 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)

  15. RTOS Implementation Example (1) void OS_Pend(int event) /* BLOCK */ { !! 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 }

  16. RTOS Implementation Example (2) void OS_Post(int event) /* RESUME */ { !! old_id = event_task[event]; !! task_state[old_id] = READY !! figure out which task to run -> new_id !! (old_id may have higher priority) !! if not other task then return !! else context switch: !! current_id= current task_id !! context_switch(task[new_id], &(task[current_id])) !! return // to task[current_id] once rescheduled to run }

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

  18. UTMS Context Switching highest priority task starts first context switch button ISR RTOS vButtonTask vLevelsTask button IRQ OS_Pend OS_Post OS_Pend

  19. Advantages RTOS • Efficiency: no polling for button state • This could not be done by vButtonTask because of priorities • Clean code • Alternative = polling by vLevelsTask => awful code • Interrupt solution would be efficient • But the slow processing (e.g., printing) within vButtonTask should NOT be done by an ISR! • Destroys interrupt latency, see earlier lecture

  20. Our RTOS: uC/OS • Comes with book (CDROM) • Extremely simple • CDROM includes DOS port, and demo exes • Non-preemptive threading model - no time slicing, so no task preempts another task unless that task blocks (semaphore, delay, ..) • All tasks must have different priority • Needs 1 (timer) interrupt to implement time delays • X32 port • Context switching with X32 context_switch() • Uses TIMER1 IRQ for time delays • See in2305 Lab Manual and X32 site for documentation

  21. X32: Demo Demo .. ucos_hello.c, buttonsSem.c

  22. Lecture overview • RTOSes • Task/context switching • Reentrancy • Usage of semaphores

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

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

  25. Example Reentrancy Problem void task1(void) void task2(void) { { ..; vAdd(9); ..; ..; vAdd(11); ..; } } void vAdd(int cInc) // NOT reentrant! { cErrors = cErrors + cInc; } context switch task1 task2 cErrors + cInc cErrors = .. NOT atomic

  26. Reentrancy • Each task (thread) has its own context: • PC, stack, registers, … • local C variables as they are stored on the stack • Function using local vars can be called by multiple threads • no risk of messing up other threads’ copies of the local vars (cf. function recursion) • If using non local vars, a shared data problem may occur • The function is not reentrant

  27. Variable storage static intstatic_int; intpublic_int; intinitialized = 4; char *string = "Where does this string go?"; void *vPointer; void function(intparm, int * parm_int) { static intstatic_local; intlocal; ... } Where are these variables being stored?

  28. Solution • Use local variables • No shared data problem • Reentrancy guaranteed • No need for atomicity • Local vars don’t get you very far - you will need to share data • Make critical sections atomic • For interrupts we used: disable(), enable() • For tasks we use OS_Pend() and OS_Post() • Classic OS service: semaphores • P()/V(), pend()/post(), take()/release(), .. • cf. OS_Pend()/OS_Post() we saw earlier

  29. Example Reentrancy Solution void task1(void) void task2(void) { { ..; vAdd(9); ..; ..; vAdd(11); ..; } } void vAdd(intcInc) // Reentrant! { pend(s);cErrors = cErrors + cInc; post(s); } new context switch task1 task2 cErrors + cInc cErrors = .. pend pend post post

  30. Reentrancy rules • A reentrant function… • May not use variables in a non-atomic way unless they are on the stack of the task that called the function (or private variables of the task) • May not call any other function that is non-reentrant • May not use hardware in a non-atomic way • Reentrancy depends on the processor architecture and compiler! (just as atomic “instructions”)

  31. Is this function reentrant? Why? BOOL fError; void processError(int j) { if (!fError) { printf("Value: %d\n", j); j = 0; fError = TRUE; } else { printf("Could not display value\n"); fError = FALSE; } }

  32. Lecture overview • RTOSes • Task/context switching • Reentrancy • Usage of semaphores

  33. Semaphores “Take” semaphore Semaphore is “taken” “Take” semaphore “Release” semaphore

  34. Semaphore implementation • Semaphore: • Value – integer (usually initialized to 1)ProcessList – a list of processes • Process P “takes” semaphore (terminology: pend) Value ← Value – 1If Value<0, Add P to ProcessList BlockEnd • Process P “releases” semaphore (terminology: post) Value ← Value + 1If Value<=0, Pick a process P from ProcessList Wake up PEnd

  35. Semaphores: Versatile & Efficient • Useful for protecting critical sections (e.g., in vAdd()) • Also useful for signaling between code (cf. UTMS!) s = Init(1); s = Init(0); ME CS pend(s); pend(s); pend(s); post(s); c r i t i c a l s e c t i o n post(s); post(s); ME = Mutual Exclusion CS = Condition Synchronization

  36. Semaphores: Pitfalls … • Classical: Deadlock • Less trivial: Priority Inversion s = Init(0); pend(A) pend(B) pend(B) deadlock pend(A) task A task B task C if B weren’t there pend(R) pend(R) post

  37. Semaphores = perfect solution? • Maybe – but there is at least one human in the loop • Forget to take the semaphore • Forget to release the semaphore • Take the wrong semaphore • Hold a semaphore for too long • Priority inversion • Deadly embrace

  38. Protecting Shared Data • Disabling/Enabling Interrupts: • Fast (single instruction) • Only method when data shared between task and ISR * • Drastic: affects response time + affects context switching! • Taking/Releasing Semaphores: • Less fast (OS function) • Doesn’t work for ISRs * • More transparent to IRQ and task response times • Disable task switching • In between the previous two methods * Taking semaphores in ISR is NOT allowed (discussed later)

  39. Conclusions • We addressed aspects of RTOSes: • Task/context switching • OS_Post(event), OS_Pend(event) • Reentrancy • Three rules for reentrant functions • Usage of semaphores • Advantages and pitfalls

More Related