15-348 Embedded Systems
What are we doing today
Motivation of accurate timers
SysTick Timer
Interfacing methods
SysTick Timer
24-bit hardware counter that decrements every clock cycle
With clock speed of 80Mhz, each clock tick is 12.5 nano seconds
What is the max time you can measure
What is the precision (Number of values we can select)
Accuracy of the timer depends on the accuracy of the crystal
Configuring SysTick Timer
Three main registers
NVIC_ST_CTRL_R
Count – 1 means SysTick timer has counted to 0
CLK_SRC
0 PIOSC divided by 4 (16MHz/4) 1 System clock (80Mhz)
INTEN – Interrupts enabled (later)
Configuring SysTick Timer
NVIC_ST_CURRENT_R
Counts down every clock cycle
COUNT bit is set in CTRL register when this counter reaches 0
Write any value to clear this register and COUNT bit
The next clock cycle after reaching 0 will reload this counter with value in NVIC_ST_RELOAD_R
NVIC_ST_RELOAD_R 24-bit value
Timer.c
void SystickInit(){ NVIC_ST_CTRL_R = 0; NVIC_ST_RELOAD_R = 0x00FFFFFF; NVIC_ST_CURRENT_R = 0; NVIC_ST_CTRL_R = 0x00000005; }void SysTick_Wait(uint32_t delay){ NVIC_ST_RELOAD_R = delay - 1; NVIC_ST_CURRENT_R = 0;
while ((NVIC_ST_CTRL_R&0x00010000)==0){} }
Timer.c
void SysTick_Wait10ms(uint32_t delay)\{
uint32_t i;
for (i = 0; i <delay;i++)
SysTick_Wait(800000); }
void delayMicroseconds(uint32_t delay){
uint32_t i;
for (i = 0; i <delay;i++)
SysTick_Wait(80); }
Synchronization between devices
Software Latency: The time betweenwhen the I/O device needs service, and the time when service is initiated.
For an input device, latency is the time between new input data ready, and the software reading the data.
For an output device, latency is the time between output device idle, and the software giving the device new data to output.
Periodic events (sampling ADC, outputting to DAC). Latency is the time between - when it is supposed to be run, and when it is actually run.
Synchronization between devices
A real time system is one that can guarantee a worst case software latency. In other words, there is an upper bound on the software response time.
Hardware Latency or device latency is the time between when an I/O device is given a command, and the time when command is completed.
taken from notes by: Jonathan W. Valvano
Synchronization between devices
I/O bound
Bandwidth is limited by speed of I/O device
Making the I/O device faster will increase bandwidth
Making the software run faster will not increase bandwidth
Software often waits for the I/O device
CPU bound
Bandwidth is limited by speed of executing software
Making the I/O device faster will not increase bandwidth
Making the software run faster will increase bandwidth
Software does not have to wait for the I/O device
Hardware Interface
Embedded systems interface with different types of hardware
LCDs Motors DC Stepper motors Servo motors Serial Ports SCI SPI USB I2C Sensors Other devices CAN Bluetooth Wifi
Synchronization
Five ways to synchronize
Blind Cycle counting
Busy Waiting
Interrupt
Periodic Polling
Direct Memory Access
Blind Cycle Counting
taken from notes by: Jonathan W. Valvano
Gadfly or Busy Waiting
Interrupts
When data is read or written, the
processor is interrupted from current task
We will study interrupts in details so let’s leave it for now
Periodic Polling
Write value
Check if value is processed
Do other stuff
Direct Memory Access
I/O device reads/writes directly to RAM
We will not worry about this synchronization in this course
taken from notes by: Jonathan W. Valvano
Going back to timers
How do we keep track of seconds using a timer?
We have several different ways – one way is:
Wait for a roll over
Calculate time taken for one complete roll over
Count number of roll overs
Timer flowchart
Timer Init COUNT BIT = 1 No YesClear Timer Count
If counter is 5, its been 1 second, set counter to 0
Timer rolls over every 0.2097152 seconds Around 5 rolls = 1 second
Is the fraction important?
What fraction do we lose every second?
0.048576 seconds
How much do we lose every hour?
175 seconds
Everyday?
How can we get the fraction back?
Bus clock is 80MHz
16777216 / 80000000COUNT is set every 0.2097152 seconds
To keep seconds we increment every 4 or 5 roll overs We can used fixed point to keep fractions
Keep a 64 bit long (long current_time;)
Upper 32 bits are the seconds
Lower 32 bits are the fractions of seconds
Each count of the lower bit is 1/232seconds =
For each COUNT set add 0.2097152 / 0.00000000023 = 900719925 fractional seconds
COUNT is set then current_time += 900719925;
Seconds are current_time >> 32
Timing Accurary
After 1000 seconds, what is our accuracy?
COUNT has been set: 1000 * 80000000 /16777216 = 4768 times
900719925 fractional seconds added 4768 times
900719925 * 4768 = 4294632602400 = 0x3E7EC0CFB20
Top 32 bits are $3E7= 999 seconds
Synchronization
Five ways to synchronize
Blind Cycle counting
Busy Waiting
Interrupt
Periodic Polling
Direct Memory Access
taken from notes by: Jonathan W. Valvano
Blind Cycle Counting
Gadfly or Busy Waiting
taken from notes by: Jonathan W. Valvano
Interrupts
When data is read or written, the
processor is interrupted from current task
We will study interrupts in details so let’s leave it for now
Periodic Polling
Write value
Check if value is processed
Do other stuff
Come back and check if value is processed
Direct Memory Access
I/O device reads/writes directly to RAM
We will not worry about this synchronization in this course
On to Interrupts
Keeping track of timer COUNT bit was tricky
Interrupts are better approach
Extremely important to understand how interrupts work for systems development
Interrupts – a concept
It would be nice if, instead of continually checking (polling), we are notified of (interrupted for) a condition
Examples:
Wristwatch
Check every 5 minutes Alarm ring at the end of class Cell phone
Check for message Message alert Making Tea
Polling to check if the water is boiling A whistling tea kettle
Interrupts
Two kinds of interrupts
Hardware
Software
Hardware Interrupt
CPU triggers interrupt based on some condition
Finish the current instruction
Save current state of the CPU on the stack
Execute Interrupt Service Routine
Acknowledge the interrupts
Resume execution of the main program
Software Interrupt
Instruction within code causes an interrupt
Hardware Interrupt
Some piece of hardware generates an interrupt
CPU executes an interrupt instruction
Execute Interrupt handing software (ISR)
Return from ISR
What generates an interrupt
Source: http://users.ece.utexas.edu/~valvano/Volume1/E-Book/C12_Interrupts.htm
Back to our Timer Example
Polled Example:
Loop until TCNT rolls over
count the number of rolls
C Implementation
for( ; ; ) {
Wait for COUNT flag to be set timer_count += <fraction_value>; }
Interrupt driven approach
C implementation
for (;;) {
Do whatever you want to do timer_count is the number of sec }
ISR keeps track of COUNT flag set
ISR will increment timer_count by fractional value
How do we execute ISR when timer counts down to 0?
Configuring SysTick Timer
Three main registers
NVIC_ST_CTRL_R
Count – 1 means SysTick timer has counted to 0
CLK_SRC
0 PIOSC divided by 4 (16MHz/4) 1 System clock (80Mhz)
INTEN – Interrupts enabled (later)
C Program with interrupts
unsigned long timer_val=0; // extern so ISR can see symbolvoid main(void) { NVIC_ST_CTRL_R = 9; NVIC_ST_RELOAD_R = 0x00FFFFFF; NVIC_ST_CURRENT_R = 0; NVIC_ST_CTRL_R = 0x00000007; for(;;) {
// code goes here to copy (timer_val>>16) to display } /* loop forever */
}
How do I set the Vector Table to call my ISR? tm4c123gh6pm_startup_ccs.c
// To be added by user extern void SysTickHandler(void);
…
#pragma DATA_SECTION(g_pfnVectors, ".intvecs") void (* const g_pfnVectors[])(void) =
{
(void (*)(void))((uint32_t)&__STACK_TOP), // The initial stack pointer ResetISR, // The reset handler NmiSR, // The NMI handler FaultISR, // The hard fault handler IntDefaultHandler, // The MPU fault handler IntDefaultHandler, // The bus fault handler IntDefaultHandler, // The usage fault handler 0, // Reserved
0, // Reserved 0, // Reserved 0, // Reserved
IntDefaultHandler, // SVCall handler IntDefaultHandler, // Debug monitor handler 0, // Reserved IntDefaultHandler, // The PendSV handler SysTickHandler, // The SysTick handler IntDefaultHandler, // GPIO Port A IntDefaultHandler, // GPIO Port B IntDefaultHandler, // GPIO Port C IntDefaultHandler, // GPIO Port D IntDefaultHandler, // GPIO Port E
ISR for timer overflow
void SysTickHandler() {
timer_val += 900719925; }
What happens at an Interrupt?
When an interrupt occurs:
The current instruction is finished
Eight registers PSR, PC, LR, R12, R3, R2, R1, R0 are pushed on the stack
The Address for ISR is loaded in the PC
IPSR register holds the Interrupt number
Top 24 bits of LR are set to 0xFFFFFF indicating ISR mode
Next 7 bits specify how to return from interrupt
0xF1 Return to another interrupt (Handler mode) 0xF9 Return to normal execution (Thread mode)
When you return from an interrupt
ISR executes BX LRSince top 24 bits are 0xFFFFFF,
processor knows that code is returning from an interrupt
Pops the eight registers
Returns to thread mode or Handler mode depending on bits 1-7 of LR
Interrupt Priority
You can set the priority of an interrupt
Priority registers
Each register holds 8 bits for each interrupt priority Priority is between 0 and 7 depending on which bit
is set
0 highest, 7 lowest
High priority interrupts, interrupt ISR for low priority interrupts