4 interrupts l.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
4 Interrupts PowerPoint Presentation
Download Presentation
4 Interrupts

Loading in 2 Seconds...

play fullscreen
1 / 59

4 Interrupts - PowerPoint PPT Presentation


  • 344 Views
  • Uploaded on

4 Interrupts the response problem is the difficult one of making sure that the embedded system reacts rapidly to external events, even if it is in the middle of doing something else.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about '4 Interrupts' - issac


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide2
the response problem is the difficult one of making sure that the embedded system reacts rapidly to external events, even if it is in the middle of doing something else.
  • Interrupts cause the microprocessor in the embedded system to suspend doing whatever it is doing and to execute some different code instead, code that will respond to whatever event caused the interrupt.
4 1 microprocessor architecture
4.1 Microprocessor Architecture
  • Assembly language is the human-readable form of the instructions that the microprocessor really knows how to do.
  • A program called an assembler translates the assembly language into binary numbers
  • each assembly-language instruction turns into just one instruction for the microprocessor.
  • When the compiler translates C, most statements become multiple instructions for the microprocessor to execute.
  • Every family of microprocessors has a different assembly language
  • Within each family, the assembly languages are almost identical to one another.
slide4
The typical microprocessor has a set of registers, sometimes called general-purpose registers
  • Before doing any operation on data, microprocessors must move the data into registers.
  • assume our microprocessor has registers called R1, R2, R3, and so on.
  • a program counter: keeps track of the address of the next instruction that the microprocessor is to execute.
  • a stack pointer: stores the memory address of the top of the stack.
  • address of variable: the name of a variable appears in an instruction
  • value of a variable: the name of the variable in parentheses
  • a comment: follows by a semicolon
slide5
moves data from one place to another:

copies value in register R2 into register R3

MOVE R3,R2

  • copy the value of iTemperature from the memory into register R5

MOVE R5,(iTemperature)

  • places the addressof iTemperature into register R5

MOVE R5,iTemperature

accumulator
accumulator
  • a special register called the accumulator, many can do standard arithmetic or bit-oriented operations in any register.
  • adds the contents of register R3 into register R7

ADD R7,R3

  • inverts all of the bits in register R4

NOT R4

jump instruction
jump instruction

ADD R1,R2

JUMP NO_ADD

MORE_ADDITION:

ADD R1,R3 ; These are skipped

ADD R1,R4

NO_ADD:

MOVE (xyz),R1

conditional jump instructions
conditional jump instructions
  • instructions that jump if a certain condition is true.
  • Most microprocessors can test conditions such as whether the results of a previous arithmetic operation was 0 or greater than 0 and other similar, simple things.

SUBTRACT R1, R5

JCOND ZERO, NO_MORE

MOVE R3,(xyz)

NO_MORE:

stack
stack
  • The PUSH instruction adjusts the stack pointer and adds a data item to the stack.
  • The POP instruction retrieves the data and adjusts the stack pointer back.
subroutines
subroutines
  • CALL instruction for getting to subroutines or functions
  • RETURN instruction for getting back.

CALL ADD_EM_UP

MOVE (xyz), R1

ADD_EM_UP:

ADD R1, R3

ADD R1, R4

ADD R1, R5

RETURN

slide11
x = y + 133;
  • MOVE R1, (y) ;Get the value of y into R1
  • ADD R1, 133 ;Add 133
  • MOVE (X),R1 ;Save the result in x
  • If (x >= z)
  • MOVE R2,(z) ;Get the value of z
  • SUBTRACT R1,R2 ;Subtract z from x
  • JCOND NEG,L101 ;Skip if the result is negative
  • Z += y;
  • MOVE R1,(y) ;Get the value of y into R1
  • ADD R2,R1 ;Add it to z.
  • MOVE (z),R2 ;Save the result in z
  • w= sqrt (z);
  • L101:
  • MOVE R1,(z) ;Get the value of Z into R1
  • PUSH R1 ;Put the parameter on the stack
  • CALL SQRT ;Call the sqrt function
  • MOVE (w), R1 ;The result comes back in R1
  • POP R1 ;Throw away the parameter
4 2 interrupt basics
4.2 Interrupt Basics
  • what interrupts are,
  • what microprocessors typically do when an interrupt happens,
  • what interrupt routines typically do,
  • how they are usually written.
  • To begin with, interrupts start with a signal from the hardware.
  • Most I/O chips, such as ones that drive serial ports or network interfaces, need attention when certain events occur.
slide13
Each of these chips has a pin that it asserts when it requires service. The hardware engineer attaches this pin to an input pin on the microprocessor called an interrupt request, or IRQ
slide14
When the microprocessor detects its interrupt request pins is asserted, it stops executing the sequence of instructions it was executing, saves on the stack the address of the instruction that would have been next, and jumps to an interrupt routine.
  • Interrupt routines do whatever needs to be done when the interrupt signal occurs.
  • A serial port interrupt routine must read the character from the serial port chip and put it into memory
  • interrupt routines also must do some miscellaneous housekeeping chores, such as resetting the interrupt-detecting hardware within the microprocessor to be ready for the next interrupt.
slide15
An interrupt routine is sometimes called an interrupt handleror an interrupt service routine. Itis also sometimes called by the abbreviation ISR.
  • The last instruction to be executed in an interrupt routine is an assembly language RETURN instruction. When it gets there, the microprocessor retrieves from the stack the address of the next instruction
  • There is no CALL instruction; the microprocessor does the call automatically in response to the hardware signal.
saving and restoring the context
Saving and Restoring the Context
  • It is difficult or impossible for a microprocessor to get much done without using at least some of the registers.
  • most microprocessors must move data values into the registers before they can operate on them
  • it is unreasonable to expect anyone to write an interrupt routine that doesn't touch any of the registers.
  • this problem is for the interrupt routine to save the contents of the registers it uses at the start of the routine and to restore those contents at the end.
  • the contents of the registers are saved on the stack
slide18
Pushing all of the registers at the beginning of an interrupt routine is known as saving the context; popping them at the end, as restoring the context.
  • you must write your interrupt service routines to push and pop all of the registers they use, since you have no way of knowing what registers will have important values in them when the interrupt occurs.
disabling interrupts
Disabling Interrupts
  • Almost every system allows you to disable interrupts
  • This stops the interrupt signal at the source
  • Most microprocessors have a nonmaskable interrupt, an input pin that causes an interrupt that cannot be disabled.
  • the nonmaskable interrupt is most commonly used for events that are completely beyond the normal range of the ordinary processing
a different mechanism for disabling and enabling interrupts
a different mechanism for disabling and enabling interrupts.
  • microprocessors assign a priority to each interrupt request signal and allow your program to specify the priority of the lowest-priority interrupt that it is willing to handle at any given time.
  • disable all interrupts by setting the acceptable priority higher than that of any interrupt,
  • enable all interrupts by setting the acceptable priority very low
some common questions
Some Common Questions
  • How does the microprocessor know where to find the interrupt routine when the interrupt occurs?
  • Some microprocessors assume that the interrupt service routine is at a fixed location.
  • The most typical is that a table somewhere in memory contains interrupt vectors, the addresses of the interrupt routines.
  • When an interrupt occurs, the microprocessor will look up the address of the interrupt routine in this interrupt vector table.
slide22
How do microprocessors that use an interrupt vector table know where the table is?
  • the table is always at the same location in memory, at 0x00000 for the Intel 80186
  • Can a microprocessor be interrupted in the middle of an instruction?
  • Usually not. In almost every case, the microprocessor will finish the instruction that it is working on before jumping to the interrupt routine.
slide23
If two interrupts happen at the same time, which interrupt routine does the microprocessor do first?
  • Almost every microprocessor assigns a priority to each interrupt signal, and the microprocessor will do the interrupt routine associated with the higher-priority signal first.
  • What happens if an interrupt is signaled while the interrupts are disabled?
  • In most cases the microprocessor will remember the interrupt until interrupts are reenabled, at which point it will jump to the interrupt routine.
  • If more than one interrupt is signaled while interrupts are disabled, the microprocessor will do them in priority order when interrupts are reenabled.
slide24
Can an interrupt request signal interrupt another interrupt routine?
  • On most micro­processors, yes. interrupt nesting happens automatically
  • The Intel x86 microprocessors disable all interrupts automatically whenever they enter any interrupt routine; therefore, the interrupt routines must reenable interrupts to allow interrupt nesting.
  • a higher-priority interrupt can interrupt a lower-priority interrupt routine
slide25
What happens if I disable interrupts and then forget to reenable them?
  • The micro­processor will execute no more interrupt routines,
  • What happens if I disable interrupts when they are already disabled or enable interrupts when they are already enabled?
  • Nothing.
  • Are interrupts enabled or disabled when the microprocessor first starts up?
  • Disabled.
slide26
Can I write my interrupt routines in C?
  • Yes, usually. Most compilers used for embedded-systems code allows you to tell the compiler that a particular function is an interrupt routine. For example:

void interrupt vHandieTimerlRQ (void) {

}

  • The most common reason for writing interrupt routines in assembly language is that on many micro­processors you can write faster code in assembly language than you can in C.
  • If speed is not an issue, writing your interrupt routines in C is a good idea.
4 3 the shared data problem
4.3 The Shared-Data Problem
  • interrupt routines need to communicate with the rest of your code.
  • Microprocessor do not complete all its work in interrupt routines.
  • the interrupt routines and the task code must share one or more variables that they can use to communicate with one another.
data sharing problem
data-sharing problem
  • Figure 4.4 Classic Shared-Data Problem

static int iTemperatures[2];

void interrupt vReadTemperatures (void)

{ //中斷時讀入2個溫度值

iTemperatures[0] = !! read in value from hardware

iTemperatures[1] = !! read in value from hardware

}

void main (void) {

int iTemp0, iTemp1;

while (TRUE) {

iTemp0 = iTemperatures[0]; //溫度來自於中斷服務程式

iTemp1 = iTemperatures[1];

if (iTemp0 != iTemp1) //比較2個溫度是否相同

!! Set off howling alarm;

}

}

what is the problem with the program in figure 4 4
What is the problem with the program in Figure 4.4?
  • suppose that both temperatures have been 73 degrees
  • iTemp0 = iTemperatures[0];
  • interrupt occurs
  • both temperatures have changed to 74 degrees
  • iTemp1 = iTemperatures[1];
  • they will differ 73≠74 and the system will set off the alarm
figure 4 5 harder shared data
Figure 4.5 Harder Shared-Data
  • Problem static int iTemperatures[2];

void interrupt vReadTemperatures (void)

{

iTemperatures[0] = !! read in value from hardware

iTemperatures[1] = !! read in value from hardware

}

void main (void) {

while (TRUE) {

if (iTemperatures[0] != iTernperatures[1]) !!

Set off howling alarm;

}

}

what is the problem with the program in figure 4 5
What is the problem with the program in Figure 4.5?
  • the same bug that was in Figure 4.4 is also in Figure 4.5
  • the statement

iTemperatures[0] = iTernperatures[1]

can be interrupted, since the compiler translates the statement into multiple assembly-language instructions.

figure 4 6 assembly language equivalent of figure 4 5
Figure 4.6 Assembly Language Equivalent of Figure 4.5

MOVE R1, iTemperatures[0])

MOVE R2, (iTemperatures[1])

SUBTRACT R1,R2

JCOND ZERO, TEMPERATURES_0K

; Code goes here to set off the alarm

TEMPERATURES OK:

characteristics of the shared data bug
Characteristics of the Shared-Data Bug
  • The problem with the code in Figure 4.4 and in Figure 4.5 is that the iTemperatures array is shared between the interrupt routine and the task code.
  • Bugs are difficult to find, because they do not happen every time the code runs
  • The assembly-language code in Figure 4.6 shows that the bug appears only if the interrupt occurs between the two critical instructions.
  • Whenever an interrupt routine and your task code share data, be suspicious and analyze the situation to ensure that you do not have a shared-data bug.
solving the shared data problem
Solving the Shared-Data Problem
  • The first method of solving the shared-data problem is to disable interrupts whenever your task code uses the shared data.
  • The hardware can assert the interrupt signal requesting service, but the microprocessor will not jump to the interrupt routine while the interrupts are disabled.
  • the code in Figure 4.7 always compares two temperatures that were read at the same time.
figure 4 7 disabling interrupts solves the shared data problem
Figure 4.7 Disabling Interrupts Solves the Shared Data Problem

static int iTemperatures[2];

void interrupt vReadTemperatures (void){

iTemperatures[0] = !! read in value from hardware

iTemperatures[1] = !! read in value from hardware }

void main (void) {

int iTemp0, iTempi;

while (TRUE) {

disable (); /* Disable interrupts while we use the array */

iTemp0 = iTemperatures[0];

iTemp1 = iTemperatures[1];

enable ();

if (iTemp0 != iTemp1)!! Set off howling alarm;

}

}

figure 4 8 disabling interrupts in assembly language
Figure 4.8 Disabling Interrupts in Assembly Language

DI ; disable interrupts while we use the array

MOVE R1,(iTemperature[0])

MOVE R2,(iTemperature[l])

EI ; enable interrupts again

SUBTRACT R1, R2

JCOND ZERO, TEMPERATURES_OK

; Code goes here to set off the alarm

TEMPERATURES_OK:

  • no C compilers or assemblers are smart enough to figure out when it is necessary to disable interrupts.
atomic and critical section
"Atomic" and "Critical Section"
  • A part of a program is said to be atomic if it cannot be interrupted.
  • the shared-data problem arises when an interrupt routine and the task code share data, and the task code uses the shared data in a way that is not atomic.
  • disable interrupts around the lines of the task code that use the shared data, made that collection of lines atomic
  • A set of instructions that must be atomic for the system to work properly is often called a critical section.
a few more examples
A Few More Examples
  • the function ISecondsSinceMidnight returns the number of seconds since midnight.
  • A hardware timer asserts an interrupt signal every second, which causes the microprocessor to run the interrupt routine vUpdateTime to update the static variables that keep track of the time.
  • If the hardware timer interrupts while the microprocessor is doing the arithmetic in ISecondsSinceMidnight, then the result might be wrong.
figure 4 9 interrupts with a timer
Figure 4.9 Interrupts with a Timer

static int iSeconds, iMinutes, iHours;

void interrupt vUpdateTime (void) {

++iSeconds;

if (iSeconds >= 60)

{

iSeconds = 0;

++iMinutes;

if (iMinutes >= 60)

{

iMinutes = 0; ++iHours;

if (iHours >= 24) iHours = 0;

}

}

!! Do whatever needs to be done to the hardware

}

long ISecondsSinceMidnight (void) {

return ( (((iHours * 60) + iMinutes) * 60) + iSeconds);

}

is the program okay
is the program okay?
  • Suppose that the time is 3:59:59.
  • The function ISecondsSinceMidnight might read iHours as 3,
  • but then if the interrupt occurs and changes the time to 4:00:00,
  • ISecondsSinceMidnight will read iMinutes, and iSeconds as 0
  • and return a value that makes it look as though the time is 3:00:00,
  • almost an hour off.
called from within a critical section
called from within a critical section

long ISecondsSinceMidnight (void) {

disable ();

return ( (((iHours * 60) + iMinutes) * 60) + iSeconds);

enable (); /* WRONG: This never gets executed! */

}

  • Better, do it like this:

long ISecondsSinceMidnight (void) {

long IReturnVal;

disable ();

IReturnVal =(((iHours * 60) + iMinutes) * 60) + iSeconds;

enable ();/* original interrupt is enable?*/

return (IReturnVal);

}

disabling and restoring interrupts
Disabling and Restoring Interrupts

long lSecondsSinceMidnight (void) {

long lReturnVal;

BOOL fInterruptStateOld; /* Interrupts already disabled? */

fInterruptStateOld = disable ();

IReturnVal =(((iHours * 60) + iMinutes) * 60) + iSeconds;

/* Restore interrupts to previous state */

if (flnterruptStateOld)

enable ();

return (lReturnVal);

}

another potential solution
Another Potential Solution
  • Figure 4.11 Another Shared-Data Problem Solution

static long int lSecondsToday;

void interrupt vllpdateTime (void) {

++lSecondsToday;

if (lSecondsToday == 60 * 60 * 24) lSecondsToday = 0L;

}

long lSecondsSinceMidnight (void) {

return (lSecondsToday);

}

the shared data problem
the shared-data problem
  • the problem arises if the task code uses the shared variable in a nonatomic way.
  • If the microprocessor's registers are large enough to hold a long integer, then the assembly language is likely to be

MOVE R1, (lSecondsToday)

RETURN

  • which is atomic.
  • If the microprocessor's registers are too small to hold a long integer, then the assembly language will be something like:

MOVE R1, (lSecondsToday) ; Get first byte or word

MOVE R2, (lSecondsToday+1) ; Get second byte or word

  • RETURN
  • This is not atomic, and it can cause a bug, because if the interrupt occurs while the registers are being loaded, you can get a wildly incorrect result.
  • The interrupt routine in Figure 4.11 is more efficient than the one in Figure 4.9
the volati1e keyword
The volati1e Keyword
  • Most compilers assume that a value stays in memory unless the program changes it, and they use that assumption for optimization. This can cause problems.
  • the code in Figure 4.12 is an attempt to fix the shared-data problem in lSecondsSinceMidnight without disabling interrupts.
  • The idea is that if lSecondsSinceMidnight reads the same value from ISecondsToday twice, then no interrupt can have occurred in the middle of the read, and the value must be valid.
a program that needs the volatile keyword
A Program That Needs the volatile Keyword

static long int lSecondsToday;

void interrupt vUpdateTime (void) {

++lSecondsToday;

if (lSecondsToday == 60L * 60L * 24L) lSecondsToday = 0L;

}

long lSecondsSinceMidnight (void) {

long 1Return;

/* When we read the same value twice, it must be good. */

1Return = lSecondsToday;

while (lReturn != lSecondsToday) 1Return = lSecondsToday;

return (IReturn);

}

slide47
Some compilers will cause a new problem. For this line of code

lReturn = lSecondsToday;

  • the compiler will produce code to read the value of lSecondsToday into registers and save that value in lReturn.
  • whi1e statement, the optimizer in the compiler will notice that it read the value of lSecondsToday once already and that that value is still in the registers.
  • Instead of re-reading the value from memory, the compiler produces code to use the value in the registers,
  • the two must be equal and that the condition in the while statement will therefore always be false
slide48
To avoid this, you need to declare 1SecondsToday to be volatile.
  • The volatile keyword allows you to warn your compiler that certain variables may change because of interrupt routines or other things the compiler doesn't know about.

static volatile long int lSecondsToday;

  • With the volatile keyword in the declaration the compiler knows that the microprocessor must read the value of 1SecondsToday from memory every time it is referenced.
  • The compiler is not allowed to optimize reads or writes of lSecondsToday out of existence.
  • If your compiler doesn't support the volati1e keyword, you should be able to obtain the same result by turning off the compiler optimizations.
4 4 interrupt latency
4.4 Interrupt Latency
  • How fast does my system respond to each interrupt?

1. The longest period of time during which that interrupt is (or all interrupts are) disabled

2. The period of time it takes to execute any interrupt routines for interrupts that are of higher priority than the one in question

3. How long it takes the microprocessor to stop what it is doing, do the necessary bookkeeping, and start executing instructions within the interrupt routine

4. How long it takes the interrupt routine to save the context and then do enough work that what it has accomplished counts as a "response"

slide50
How do I get the times associated with the four factors listed above?
  • microprocessor documentation
  • write the code and measure how long it takes to execute
  • count the instructions of various types, how long each type of instruction takes
  • the shorter the period during which interrupts are disabled, the better your response will be.
disabling interrupts51
Disabling Interrupts
  • Suppose that the requirements for your system are as follows:
  • disable interrupts for 125 microseconds (μsec) for your task code to use a pair of temperature variables it shares with the interrupt routine that reads the temperatures
  • disable interrupts for 250 μsec for your task code to get the time accurately
  • respond within 625μsec when you get a special signal from another processor in your system; the interprocessor interrupt routine takes 300 μsec to execute.
  • Can this be made to work?
slide52
The interrupt routine needs 300 μsec, for a total, worst-case time of 550 μsec, within the 625-μsec limit.
slide53
Suppose to cut costs, the hardware group proposes to replace the microprocessor with one that runs only half as fast.
  • Now, all the processing times are doubled, interrupts are disabled for twice as long, the interrupt service routine takes twice as long, but the 625-μsec deadline remains the same. Now will the system meet its deadline?
  • The answer is no.
  • Interrupts will be disabled for up to 500 μsee at a time, and the interrupt service routine needs 600 μsec to do its work. The total of these two is 1100 μsec, much longer than the 625-μsec deadline.
slide54
It depends. If you can assign the network interrupt a lower priority than the interprocessor interrupt
alternatives to disabling interrupts
Alternatives to Disabling Interrupts
  • Since disabling interrupts increases interrupt latency, a few alternative methods for dealing with shared data.
  • in most cases simply disabling interrupts is more robust than the techniques discussed below
  • The interrupt routine always writes to whichever set the task code is not using. This simple mechanism solves the shared-data problem, because the interrupt routine will never write into the set of temperatures that the task code is reading.
slide56
int iTemperaturesA[2];

static int iTemperaturesB[2];

static BOOL fTaskCodeUsingTempsB = FALSE;

void interrupt vReadTemperatures (void) {

if (fTaskCodeUsingTempsB) {

iTemperaturesA[0] = !! read in value from hardware;

iTemperaturesA[l] = !! read in value from hardware; )

}else {

iTemperaturesB[0] = !! read in value from hardware;

iTemperaturesB[l] = !! read in value from hardware;

}

void main (void) {

while (TRUE) {

if (fTaskCodeUsingTempsB)

if (iTemperaturesB[0] != iTemperaturesB[l]) !! Set off howling alarm; else

if (iTemperaturesA[0] != iTemperaturesA[l]) !! Set off howling alarm;

fTaskCodeUsingTempsB = ! fTaskCodeUsingTempsB;

}

}

figure 4 16 a circular queue without disabling interrupts
Figure 4.16 A Circular Queue Without Disabling Interrupts
  • Because the iHead pointer and the iTail pointer ensure that the interrupt routine will be writing to different locations in the queue than the ones from which the task code is reading, the shared-data problem with the temperatures themselves is eliminated.
  • Because of the fragility of this code, it would make sense to write it this way only if disabling interrupts is really not an option.
slide58
#define QUEUE_SIZE 100

int iTemperatureQueue[QUEUE_SIZE];

int iHead = 0; /* Place to add next item */

int iTail = 0; /* Place to read next item */

void interrupt vReadTemperatures (void) {

/* If the queue is not full . . . */

if (!(( iHead+2 == iTail) || (iHead==QUEUE_SIZE-2 && iTail==0)))

{

iTemperatureQueue[iHead] = !!read one temperature;

iTemperatureQueue[iHead + 1] = !!read other temperature;

iHead += 2;

if (iHead == QUEUE_SIZE)

iHead = 0;

} else

!!throw away next value

}

slide59
void main (void) {

int iTemperaturel, iTemperatureZ;

while (TRUE) {

/* If there is any data. . . */

if (iTail != iHead)

{

iTemperaturel= iTemperatureQueue[iTai1];

iTemperature2= iTemperatureQueue[iTail + 1];

iTail += 2;

if (iTail = QUEUE_SIZE)

iTail = 0; .'.' Do something with iValue;

}

}