Title: ECE 532 Embedded Systems Winter 2004
1ECE 532 Embedded SystemsWinter 2004
2Time Driven Schedules
- Previous discussions have dealt with round robin
schedules. - The class examples and the first two projects
were free running - Systems would work if processor was fast enough
to sample at the required rates - Sample rate is determined by the processor speed
- As additional complexity was introduced, sampling
rate was reduced - Better approach for most systems is to use a
clock to define minor frame boundaries - Makes system deterministic
- Allows designer to specify consistent sampling
rates - Sampling dependent upon time not processor speed
- Paves way for mixing periodic and a periodic
operations
3Real-Time Clock
- What is a real-time clock?
- Hardware counter and connection to the computer
interrupt system - How does it work?
- Preset counter to number corresponding to the
desired time period - Count x clock period time period
- Enable the interrupt for the Real-Time Clock
- When clock interrupts, the processor will vector
to the interrupt service routine (user provided)
4How do we use it?
- Set up a variable to maintain minor frame counts
e.g. mc - Set up variable to initialize clock count to
proper amount for minor frame time - Start clock
- When interrupt occurs, do the following
- Reset clock
- Increment mc
- If mc gt mcmax, set mc to 1
- Acquire signals for MinorFrame mc
- When finished, return to main
- If clock interrupts before minor frame is
finished, generate an error condition.
5Clock Driven System
6Project 3
- Using the functions developed for project 2,
develop a time driven scheduler to handle the
system described in project 2. - Reference the nios timer documentation
- Reference the nios example files (e.g.
lcd_demo1.c)
7Proposed Projects and Project Due Dates
- Project 1 Simple Round Robin Scheduling Jan 22
- Project 2 Expanded Round Robin Scheduling Jan
29 - Project 3 Time Driven Scheduling Feb 19
- Project 4 Forground/BackGround, Table Driven Mar
11 - Project 5 Real-Time OS Sample Mar 25
- Project 6 Term Project April 22
- Term project with presentation, report, and code
files - For each project other than project 6
- Brief description of project and results paper
report - Working (commented ) Code (all modules required
to compile and run) - Prefer a zip file including all modules
8The Nios Timer
- Set to 1 when timer counter reaches 0
- Explicitly Cleared by software write to status
register
- Run bit is set to 1 when timer is running.
- Not effected by write to status register
- Start and Stop Timer by setting bits in Control
Register
9Timer Variables (nios.h)
// ----------------------------------------------
// Timer Peripheral // Timer Registers typedef
volatile struct int np_timerstatus // read
only, 2 bits (any write to clear TO) int
np_timercontrol // write/readable, 4 bits int
np_timerperiodl // write/readable, 16 bits int
np_timerperiodh // write/readable, 16 bits int
np_timersnapl // read only, 16 bits int
np_timersnaph // read only, 16 bits
np_timer // Timer Register Bits enum np_timer
status_run_bit 1, // timer is
running np_timerstatus_to_bit 0, // timer
has timed out np_timercontrol_stop_bit 3, //
stop the timer np_timercontrol_start_bit 2, //
start the timer np_timercontrol_cont_bit 1,
// continous mode np_timercontrol_ito_bit 0,
// enable time out interrupt np_timerstatus_run_
mask (1ltlt1), // timer is running np_timersta
tus_to_mask (1ltlt0), // timer has timed
out np_timercontrol_stop_mask (1ltlt3), //
stop the timer np_timercontrol_start_mask
(1ltlt2), // start the timer np_timercontrol_cont_m
ask (1ltlt1), // continous mode np_timercontrol_
ito_mask (1ltlt0) // enable time out
interrupt // Timer Routines int
nr_timer_milliseconds(void) // Starts on first
call, hogs timer1.
10LCD_demo1.c Code
// file lcd_demo1.c include
ltstdio.hgt include "pio_lcd16207.h" include
"nios.h" // Prototype for Interrupt Service
Routine void MyPIO_ISR(int context) // Main
program int main(void) np_pio pio
na_button_pio / Start up with a
greeting... / printf("\n\nNow running
lcd_demo1.\n") printf("Press the buttons (not
the reset!) to\n") printf("interrupt the
program and show the time.\n") / Set up
the PIO to generate interrupts
/ nr_installuserisr(na_button_pio_irq,MyPIO_ISR
,(int)pio) pio-gtnp_pioedgecapture 0 //
clear any existing IRQ condition pio-gtnp_piodirec
tion 0 // all input pio-gtnp_piointerruptmask
0xff // they all generate irq's!
11LCD_demo1.c Code (cont)
/ Loop forever, or at least until you press
ltEscgt, showing some messages in the
display... / / And, oh, by the way, we
have a nice set of LCD routines already
written... / nr_pio_lcdinit(na_lcd_pio) whil
e(nr_uart_rxchar(0) ! 27) // until ESC
key... nr_pio_lcdwritescreen("Hello!
This is Nios.") nr_delay(1400) nr_pio_lcdw
ritescreen("Your message goes here!") nr_delay(
1400) nr_pio_lcdwritescreen("You could show
another message, too.") nr_delay(300) // only
flash that last one. printf("") // just so we
have some signs of life. return 0 void
MyPIO_ISR(int context) np_pio pio (np_pio
)context char s256 // a
string pio-gtnp_pioedgecapture 0 // clear the
irq condition / Print a message into a
string (RAM) first / sprintf(s,"The time is
now d",nr_timer_milliseconds()) // get
milliseconds... / and print that message to
the LCD / nr_pio_lcdwritescreen(s)
12How do we use it?
- Set up a variable to maintain minor frame counts
e.g. mc - Set up variable to initialize clock count to
proper amount for minor frame time - Start clock
- When interrupt occurs, do the following
- Reset clock
- Increment mc
- If mc gt mcmax, set mc to 1
- Acquire signals for MinorFrame mc
- When finished, return to main
- If clock interrupts before minor frame is
finished, generate an error condition.
13timer_isr_test2.c Sample Code
// file timer_isr_test.c // This routine is
based on lcd_demo1.c and is designed to test the
ability to set the timer and generate an
interrupt include ltstdio.hgt include
"pio_lcd16207.h" //include "nios_peripherals.h"
include "nios.h" include "peripheral_test.h"
// Prototype for Interrupt Service Routine //
Although some of the samples pass a long context,
I was getting an error so I went back to
integers. void Timer_ISR(int context) //
Prototype for Timer Initialization Routine // I
also tried to pass a long timeperiod to the
timerInit routine and got a compile error. I
removed it as // a paramter and set it as a
static. void timerInit(int minCount,int
majCount,int mcmax) // Prototype for Timer
Start Routine void timerStart(void) //
Prototype for simulated application void
SimApp1(void) void SimApp2(void)
14timer_isr_test2.c Sample Code (cont)
// Data definitions static long timePeriod int
mc //minor cycle count int mcmax // of
minor cycles in a major cycle int MCC //major
cycle count long context int c int
frame_overrun // Define a data structure type
named TimerISRContext to hold information for the
ISR typedef struct int minorCycleCount //in
crement with each interrupt int
majorCycleCount //increment when minorCycle
count minorCyclemax int minorCycleMax //numbe
r of minor cycles in a major cycle long
minorCycleLength //period of a minor cycle in 30
nsec counts np_timer timer TimerISRContext /
/Declare tic to be a data structure of type
TimerISRContext //Declare tic as static since I
am having touble passing the pointers. Longs
don't seem to work. static TimerISRContext tic
0,0,0,0,0
15timer_isr_test2.c Sample Code (cont)
// Definition of Timer Initialization
Routine void timerInit(minCount,majCount,mcmax)
long T long timerVal T timePeriod //
Initialize ISR context variables tic.minorCycleC
ount minCount tic.majorCycleCount
majCount tic.minorCycleMax mcmax tic.minorCy
cleLength T tic.timer na_timer_0 printf("
\nISR Context variables initialized") nr_install
clockisr(na_timer_0_irq,Timer_ISR,(long)
tic) //install timer ISR routine //make sure
timer is stopped tic.timer-gtnp_timercontrol
tic.timer-gtnp_timercontrol np_timercontrol_cont
_mask //stop continuous mode tic.timer-gtnp_timer
control (tic.timer-gtnp_timercontrol 3)
np_timercontrol_stop_mask //stop timer //Set
up timer period tic.timer-gtnp_timerperiodh T
gtgt 16 //Load the upper timer register with
period right shifted by 16. //printf("\nTimeperi
od high d",tic.timer-gtnp_timerperiodh) tic.tim
er-gtnp_timerperiodl T 0xffff //Load the
lower timer register with low 16 bits of
period. //printf("\nTimerperiod low d",
tic.timer-gtnp_timerperiodl) //printf("\nTimerCon
trol x", tic.timer-gtnp_timercontrol) //
Enable interrupts tic.timer-gtnp_timercontrol
tic.timer-gtnp_timercontrol np_timercontrol_ito_m
ask //printf("\nInterrupt Enabled
x",tic.timer-gtnp_timercontrol) //moved timer
start here since I wasn't executing the start
routine for some reason //tic.timer-gtnp_timercont
rol (tic.timer-gtnp_timercontrol 3)
np_timercontrol_start_mask timerVal
(tic.timer-gtnp_timersnapl 0x0ffff)
((long)tic.timer-gtnp_timersnaph ltlt
16) printf("\ntimer value is 8ld",
timerVal) printf("\nTimer Status is
x",tic.timer-gtnp_timerstatus)
16timer_isr_test2.c Sample Code (cont)
// Definition of Timer start routine void
timerStart(void) printf("\n In timer start
function") //np_timer timer na_timer_0
//set up pointer to timer data structure tic.tim
er-gtnp_timercontrol (tic.timer-gtnp_timercontrol
3) np_timercontrol_start_mask //Defini
tion of SimApp1() void SimApp1(void) int
i i 1 while(ilt100) i voi
d SimApp2(void) int i i
1 while(ilt1000) i
17timer_isr_test2.c Sample Code (cont)
// Main program int main(void) long
timerVal if NIOS_GDB nios_gdb_install(1) n
ios_gdb_breakpoint() endif / Start up
with a greeting... / printf("\n\nNow
running timer.\n") printf("This routine runs
for 3000 ms\n") printf("Then the timer
interrupts\n") printf("the ISR runs, and
returns. The timer\n") printf("continues to
interrupt at 3000ms intervals\n") / Set
values for the timer / mc0 //minor cycle
count mcmax30 // of minor cycles in a
major cycle MCC0 timePeriod
33000000 //minor cycle period 330000 30 nsec
10 ms. //Initialize the LCD nr_pio_lcdinit(n
a_lcd_pio) / Initialize the timer
/ timerInit(mc,MCC,mcmax) //printf("\nTimer
Initialized")
18timer_isr_test2.c Sample Code (cont)
timerStart() / Loop forever, or at least
until you press ltEscgt, showing some
messages in the display... / while(nr_uart_rx
char(0) ! 27) // until ESC key... nr_pio
_lcdwritescreen("Hello! This is
Nios.") nr_delay(500) nr_pio_lcdwritescr
een("A simple program to test") nr_delay(500)
nr_pio_lcdwritescreen("the timer
interrupt") nr_delay(500) tic.timer-gtnp_t
imersnapl 0 // snapshot timerVal
(tic.timer-gtnp_timersnapl 0x0ffff)
((long)tic.timer-gtnp_timersnaph ltlt
16) printf("\nIn main -- Timer State
Time8ld,Statusd, Controld\n", timerVal,
tic.timer-gtnp_timerstatus, tic.timer-gtn
p_timercontrol) //printf(" main
") // just so we have some signs of
life. return 0
19timer_isr_test2.c Sample Code (cont)
void Timer_ISR(context) //np_timer timer
(np_timer )context char s256 // a
string long timerVal int i,j i 1 j
1 //Increment the minor cycle
counter tic.minorCycleCount printf("\nIn ISR
Minor Cycle d -- Major Cycle d -- Frame
overrun d",tic.minorCycleCount,tic.majorCycleCo
unt, frame_overrun) tic.timer-gtnp_timersnapl
0 // snapshot timerVal (tic.timer-gtnp_timersn
apl 0x0ffff) ((long)tic.timer-gtnp_timersnap
h ltlt 16) tic.timer-gtnp_timerstatus 0 //
clear the irq condition tic.timer-gtnp_timercontr
ol tic.timer-gtnp_timercontrol
np_timercontrol_ito_mask //enable
interrupt printf("\ntimer running d",
tic.timer-gtnp_timerstatus 0x0002) timerStart()
printf("\nTimer State Time8ld,Statusd,
Controld, timeout bitd\n", timerVal,
tic.timer-gtnp_timerstatus, tic.timer-gtnp_tim
ercontrol, tic.timer-gtnp_timerstatus) pri
ntf("\ntimer running d", tic.timer-gtnp_timerstatu
s 0x0002) if (frame_overrun
1) printf("\nFrame overrun in Minor Cycle
d",tic.minorCycleCount - 1) //create a loop
to simulate the schedule loop runs until timer
chimes or tasks finished while (
(tic.timer-gtnp_timerstatus 0x0002)) frame_ov
errun 1 / Print a message into a string
(RAM) first / //set frame overrun to 1 to set
up overrun identification sprintf(s,"Minor
Cycle d Major Cycle d",tic.minorCycleCount,t
ic.majorCycleCount) nr_delay(30)
20timer_isr_test2.c Sample Code (cont)
/ and print that message to the LCD
/ nr_pio_lcdwritescreen(s) //Test to see
if we have completed a major cycle if
(tic.minorCycleCount30) tic.majorCycleCount
tic.minorCycleCount 0
//simulate tasks with a delay
loop SimApp1() SimApp2() //insert a delay
in minor cycle five to force a frame
overrun if (tic.minorCycleCount 5)
timerVal (tic.timer-gtnp_timersnapl
0x0ffff) ((long)tic.timer-gtnp_timersnaph
ltlt 16) printf("\ntimer value is ld, time out
bit is d", timerVal, tic.timer-gtnp_timerstatus)
//force cycle to run long with following
delay while( (tic.timer-gtnp_timerstatus
0x0002)) j printf("\ntimer value
is ld, time out bit is d", timerVal,
tic.timer-gtnp_timerstatus) printf("\ntimer
running d", tic.timer-gtnp_timerstatus
0x0002) //set frame overrun to
zero to indicate we finished frame before time
expired if(tic.timer-gtnp_timerstatus
0x0002) frame_overrun 0 //jump
out of endless loop when tasks are
done break return
21Clock Driven System
22Time Driven Scheduling
- We have discussed ways to implement cyclic and
time driven schedulers and we have alluded to the
task schedules themselves - How do we decide (a priori in the case of a hard
deadline, periodic system) how to schedule?
23Scheduling Strategy for Hard Deadline Systems
- Assumptions
- N periodic tasks in the system (n is fixed while
system operates) - Parameters are known a priori (e.g. period,
execution time, required predecessors and
successors, etc) - Tasks are ready to run when scheduled (that is,
any required predecessor has completed) - Step one Determine minor frame limits
- The minor frame period must bounded by the period
of the highest sampling frequency or
computational frequency required by the system. - In our previous examples, we said that highest
rate signal was a 100 Hz sine wave. We sampled
that at 1000 Hz. This implies that our minor
frame period would be 1 ms. - Formally, let ti be the required sample period
for the ith signal and let tm be the minor cycle
period. Then - tm lt min(ti)
- 1 lt i lt N
24Scheduling Strategy for Hard Deadline
Systems(cont)
- Step 2 Determine major frame limits
- The major frame rate is determined by the lowest
sampling frequency required - For example, if the lowest frequency signal is a
1 Hz sine wave, then our sampling approach says
we sample that at 10 Hz. This implies that the
major frame rate must be at least 10 Hz. - Formally, let tM be the major frame period and ti
be the period of the ith signal, then - tM lt max(ti)
- 1 lt i lt N
25Scheduling Strategy for Hard Deadline
Systems(cont)
- Step 3 Determine minor and major frame periods
- Considerations
- Minor frame period should be as long as possible
without violating our constraint - Reduces computational load
- The number of minor frames should be a power of 2
(scheduling convenience and standard practice) - Formally,
- tM/tm 2k where k is an integer
- This implies that the minor frame periods are
given by - tm , t2m 20 tm , , 2k tm and there are 2k
minor frames per major frame
26Scheduling Strategy for Hard Deadline
Systems(cont)
- Step 4 Map periodic signals/functions to minor
frames - Ensure that signals/functions meet requirements
- Formally,
- 2j tm lt ti
- Where 0 lt j lt k,
- 1 lt i lt N
- ti is the required sampling period
- Note You may need to iterate signal/function
sampling requirements, major frame rates, and
minor frame rates and duration to develop a
working system.
27Scheduling Example Application Parameters
28Scheduling Example Rate Grouping
29Building the Schedule
30Checking Frame Duration
31Signals not on Schedule
32How do we Complete
- Options
- Create more minor frames
- Additional complexity and overhead
- Add unassigned signals/functions to higher rate
group - Uses more time than necessary
- Create subframes
- Adds a little complexity but saves time
- Re-evaluate higher rate signals/functions to
determine if rate could be reduced - Always a good choice since reducing the iteration
rate for the highest rate signals gives most
bang for the buck
33Subframe Approach
34Insert Subframe into one Minor Frame
35Subframe Timing
- Schedule as shown runs the subframe once per
major frame - Our desired schedule would run the subframe every
fourth major frame - Could build a 64 frame schedule for the subframe
and adjust accordingly - Could embed logic in the subframe scheduler to
run it every fourth major frame