Upload
kt8815
View
214
Download
0
Embed Size (px)
Citation preview
Programming embedded systems
Seminar 5
Embedded Operating System
Dr. Tran Thanh Hung Department of Automation Technology,
College of Engineering, Can Tho UniversityEmail: [email protected]
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 taskvoid 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(); //Call the function (10 ms duration)
delay(40); //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(); //Call the function (10 ms duration)
delay(40); //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 TimerTF0 = 0; //make sure overflow flag off
TR0 = 1; //start Timer 0while(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 TimerET0 = 1; EA = 1; //Enable interruptTR0 = 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 againX(); //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{
TH0 = x/256;TL0 = x%256; //initialize timer 0 againX(); //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
Reload initial value
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 TimerEA = 1; ET2 = 1; //enable timer 2 interruptT2CON = 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}
EOS_ISR() interrupt INTERRUPT_Timer_2_Overflow{
TF2 = 0; Your_function(); //This function will be called every 50 ms
}
Problem ?
Embedded OS: Implementvoid 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.