Reconfigurable computing
Small Embedded Systems
Unit 3.1 Interrupts
Introduction
Our example has been very simple:
One single task: blink the LED
One connected device: the LED
A real embedded system
has many tasks that must be executed in response to events
simultaneously deals with many inputs and outputs, which may have independent behaviours and timing
Any individual task mustn’t tie up the processor more than is necessary, and should release processor resource as soon as it is complete
We will look at how interrupts help deal with these issues
Our first program wasn’t good
Here is the first piece of code that we looked at
It’s not great: “busy wait” ties up the processor
Other tasks cannot be performed during that time
const int LED_PIN=13;
void setup() { pinMode(LED_PIN, OUTPUT); }
void loop() {
digitalWrite(LED_PIN, HIGH);
delay(1000);
digitalWrite(LED_PIN, LOW);
delay(1000);
}
Processor is tied up for one second
Getting ready to improve it …
To make things easier later on, we’ll introduce a state variable
const int LED_PIN=13;
int LED_STATE=LOW;
void setup() { pinMode(LED_PIN, OUTPUT); }
void loop() {
digitalWrite(LED_PIN, LED_STATE);
LED_STATE = !LED_STATE;
delay(1000);
}
This holds the state of the LED
This flips the state of the LED
Logical not ! and Bitwise not ~
In the units of day 3, it’s important to be clear about the two types of not operator
In C the logical not is !
The logical not of 1 is 0
If x=0b00000001 then
!x=0b00000000
The bitwise not ~ flips all of the bits
If x=0b00000001 then
~x=0b11111110
Arduino values HIGH and LOW are defined as 1 and 0
So LOW is !HIGH
Improved program checking a timer
Use the timer function millis() to improve code
const int LED = 13;
int LED_STATE=LOW;
unsigned long int previousMillis = 0;
unsigned long int currentMillis;
void setup() { pinMode(LED, OUTPUT); }
void loop() {
currentMillis = millis();
if (currentMillis – previousMillis >= 1000) {
previousMillis = currentMillis;
LED_STATE = !LED_STATE;
digitalWrite(LED, LED_STATE);
} }
Get time since start
Time of last flip of LED state
How does this help?
We have avoided a busy wait
Processor has plenty of time to do whatever other tasks we need
void loop() {
currentMillis = millis();
if (currentMillis – previousMillis >= 1000) {
previousMillis = currentMillis;
LED_STATE = !LED_STATE;
digitalWrite(LED, LED_STATE);
} }
We can put other instructions here to do other useful tasks
This block executes every second
This block can execute many times per second
Do we still have a problem?
If the rest of the code has a long run time, then our LED won’t flip until the rest has finished
Not really what we wanted
void loop() {
currentMillis = millis();
if (currentMillis – previousMillis >= 1000) {
previousMillis = currentMillis;
LED_STATE = !LED_STATE;
digitalWrite(LED, LED_STATE);
} }
We can put other instructions here to do other useful tasks
This block could take a long time: say 5 sec
This block will only execute every 5 sec
Interrupts
Inflexibly sticking to a pre-defined sequence can make it hard (or impossible) to do what we need to do
Sometimes it is necessary to interrupt what we are doing in response to an event:
Save current state and suspend current activity
Deal with the event
Reload state and resume what we were doing before
Events can be
External (e.g. input device signals it needs attention)
Internal (e.g. we set a timer to say when a task needs attention)
Saving presentation …
Reloading presentation …
Interrupts
An interrupt is an input to a microcontroller that temporarily redirects program flow. Examples include:
when an input changes state
when timers reach their overflow point
when there is a communication request
when any other asynchronous event takes place
The interrupt handler is initialized and programmed by the system software
Interrupts
The processor controls each interrupt using an Interrupt Service Routine (ISR)
There can be a number of interrupt sources in a processor
Some microcontrollers have different interrupt levels
Establish a priority order if multiple interrupts arrive at the same time
Interrupts
When an interrupt occurs, the CPU:
Saves the program counter on the stack
Executes an interrupt acknowledge cycle
Branches to a predetermined address where the interrupt service routine is located
Interrupts
Store return address to stack
Enter ISR
Exit ISR
Main program
Interrupt request received
Interrupt acknowledge generated
Resume at return address
Interrupt service routine
Interrupt Service Routines
An ISR is a special type of function that has some limitations that “normal” functions do not have:
An ISR cannot have any parameters
An ISR cannot return a value
Normally global variables are used to pass data between an ISR and the main program.
To ensure that variables shared between an ISR and the main program are updated correctly, declare them with “volatile” qualifier
Generally, an ISR should be as short and fast as possible
On some processors (e.g. ESP8266) to ensure speed, ISRs are held in a different memory than normal code
Summary
There are challenges associated with servicing many devices that require attention at differing and irregular intervals
Processes shouldn’t tie up the processor unless necessary
Interrupts are an approach that can be helpful
/docProps/thumbnail.jpeg