Vous êtes sur la page 1sur 22

Programming embedded systems

Seminar 5

Embedded Operating System


Dr. Tran Thanh Hung Department of Automation Technology, College of Engineering, Can Tho University Email: tthung@ctu.edu.vn

Review
In the previous seminars, we use a super loop to run a task. In this seminar, we will use a different way to run a task.

Outline
How to create an Embedded OS for embedded applications?
Periodic functions Implement periodic functions Creating Embedded OS Using Embedded OS

Seminar objectives

At the end of this seminar, by referring the lecture notes, students will be able to: understand issue of periodic function use timer to create a simple Embedded OS (EOS) implement periodic functions running in EOS

How to run a task?


We has used a super loop architecture to run a task
void main (void) { X_Init() ; //Prepare for Task X() while(1) //super loop { X(); //Perform task X() } }

With this architecture, it is very difficult to run the task at a precise interval of time.

Periodic function
There are many applications require to run tasks repeatedly, at precise intervals
Keypad need to be scanned every 200ms The display (PC monitor, LCD) must be refreshed 60 times every second Music must be sampled at 44.100 times per second Temperature sensors must be sampled once per second

In practice, many embedded systems must be able to support this type of periodic function

Periodic function
If you need to run the function X() every 50 ms, how do you implement? If you know the function takes 10 ms to complete
while(1) //super loop { X(); delay(40); }

//Call the function (10 ms duration) //Delay for 40 ms

This approach will be fine, if: 1. We know the precise duration of X() 2. This duration never varies

Periodic function
while(1) //super loop { X(); delay(40); }

//Call the function (10 ms duration) //Delay for 40 ms

However, 1. It is very difficult to know the duration of X() 2. This duration often vary 3. This approach is in inefficient: waste in a delay loop
Is there any way to implement periodic function, running at precise 50 ms interval ?

Timer delay: review


void delay_t0(tWord x) { TMOD &= 0xF0; TMOD |= 0x01; //set Timer 0 mode 1 x = 65536 - x + 26; TH0 = x/256;TL0 = x%256; //set initial value of Timer TF0 = 0; //make sure overflow flag off TR0 = 1; //start Timer 0 while(TF0==0); //wait Timer 0 overflow (TF = 1) TR0 = 0; //stop Timer 0 } Note: 1 increment of timer takes (OSC_PER_INTS/OSC_FRE)*103 ms

Instead of waiting for timer overflow, you can setup an interrupt from timer

Timer interrupt setup


Run Example 4.1 in simulator, toggle Disassembler window Chose PeripheralTimerTimer 0 Chose PeripheralInterrupt Click Run and then Halt In Interrupt System, click Timer 0 Check EA and ET0 Now set TH0 TL0 = FF F1 Click until TH0 TL0 = FF FF Look at the program while clicking one more time. What happen to the program?

Timer interrupt setup


void Timer0_interrupt_init(tWord x) { TMOD &= 0xF0; TMOD |= 0x01; //set Timer 0 mode 1 x = 65536 - x; TH0 = x/256;TL0 = x%256; //set initial value of Timer ET0 = 1; EA = 1; //Enable interrupt TR0 = 1; //start Timer 0 }

Implement periodic function


Instead of writing a program like this:
void main (void) { X_Init() ; //Prepare for Task X() while(1) //super loop { X(); //Call the function (10 ms duration) delay(40); //Delay for 40 ms }

We use a better way to do:

Implement periodic function


#include <main.h> static unsigned int x; void main (void) { X_Init() ; //Prepare for Task X() Timer0_interrupt_init(50000);//initialize timer1 to interrupt every 50 ms while(1); //empty loop } Timer0_ISR() interrupt INTERRUPT_Timer_0_Overflow { TH0 = x/256;TL0 = x%256; //initialize timer1 again X(); //Call the function } What is the value of timer after overflow ?

Exercise 1
Put Timer0_interrupt_init() and Timer0_ISR() into file Interrupt.c and Interrupt.h Modify the program in Exercise 4.3, using Timer0_interrupt_init and Timer0_ISR()

Implement periodic function: Problem


void main (void) { X_Init() ; //Prepare for Task X() Timer0_interrupt_init(50000);//initialize timer1 to interrupt every 50 ms while(1); //empty loop } Timer0_ISR() interrupt INTERRUPT_Timer_0_Overflow Reload { initial value TH0 = x/256;TL0 = x%256; //initialize timer 0 again X(); //Call the function }

It takes time to reload the initial value for the timer. Sometime you forget to reload the value. This approach is not adequate if the system requires very precise timing

Embedded OS: Timer 2


Run Example 4.1 in simulator Chose PeripheralTimerTimer 2 Chose PeripheralInterrupt Click Run and then Halt Do you see any change on Timer 2? Now check TR2, note value of T2CON Now set T2 = FFF0 and RCAP2 = FFF0 Click until T2 = FFFF Look at T2 while clicking one more time. What happen to T2 ? (Repeat again with other value of RCAP2) In Interrupt System, click Timer 2 Check EA and ET2, repeat again What happen to the program when timer overflows?

Embedded OS: Initialize


/******************************************************************************* * @fn EOS_init (unsigned int x) * @brief Initialize for Embedded Operating System: * - timer 2 interrupt in next x microsecond * - no reload required * @param x : number of microsecond * @return void */

void EOS_init(unsigned int x) { unsigned int _count = 65536 - x; RCAP2H = _count/256; RCAP2L = _count%256;//set reload value TH2 = RCAP2H; TL2 = RCAP2L;//set initial value of Timer EA = 1; ET2 = 1; //enable timer 2 interrupt T2CON = 0x04; //set Timer 2 as 16 bit timer, start timer }

Embedded OS: Implement


void main (void) { Your_function _Init() ; //Initialize for Your_function EOS_init(50000); //initialize timer 2 to interrupt every 50 ms while(1); //empty loop }
Problem ?

EOS_ISR() interrupt INTERRUPT_Timer_2_Overflow { TF2 = 0; Your_function(); //This function will be called every 50 ms }

Embedded OS: Implement


void main (void) { Your_function _Init() ; //Initialize for Your_function EOS_init (50000);//initialize timer1 to interrupt every 50 ms while(1); //empty loop { go_to_sleep(); } } EOS_ISR() interrupt INTERRUPT_Timer_2_Overflow { TF2 = 0; Your_function(); //This function will be called every 50 ms } void go_to_sleep(void) { PCON |= 0x01; // Enter idle mode }

Example 5.1
#include <main.h> #include <delay.h> void main (void) { while(1) { P0=~P0; // delay_t0(50000); } }

Run Example 4.1 in simulator Use Performance Analyzer (PA) to see the percentage of time that delay_t0 taken How many percent?

Example 5.2
#include "Main.h" #include "EOS.h" void main (void) { EOS_init(50000); while(1) // Super Loop { go_to_sleep(); // Enter idle mode to save power } }

EOS_ISR() interrupt INTERRUPT_Timer_2_Overflow //in file EOS.c { TF2 = 0; // Put your code here P0 = ~P0; }

Run Example 5.2 in simulator Use Performance Analyzer (PA) to see the percentage of time that go_to_sleep() taken How many percent?

Exercise 2
Put EOS_init() and EOS_ISR() into file Interrupt.c and Interrupt.h Modify the program in Exercise 5.1, using EOS Only run the time if the switch connected to P1.0 is pressed. Reset the time if the switch connected to P1.3 is pressed.

Vous aimerez peut-être aussi