Do’s and Don’ts
This last section describes the major problems that are encountered with
interrupt and exceptions, and, more impor-tantly, how to avoid them.
Always expect the unexpected interrupt
Always include a generic handler for all unused/unex-pected exceptions.
This should record as much information about the processor context such as the
exception/vector table number, the return address and so on. This allows
unexpected exceptions to be detected and recognised instead of causing the
processor and system to crash with little or no hope of finding what has
hap-pened.
Don't expect too much from an interrupt
Bear in mind that an interrupt is not for free and the simple act of
generating one and returning even if the interrupt service routine does
nothing, will consume performance. There will be a point where the number of
interrupts are so high that the system spends more time with the overhead than
actually processing or doing something with the data. It is important to
balance the cost of an interrupt's overhead against the processing it will do.
A good way of thinking about this is using a truck to carry bricks from A to B.
If the truck carries one brick at a time, the time taken to load the truck,
push it and unload it will mean it will be slower than simply picking up the
brick and moving it. Loading the truck with so many bricks so that it is
difficult to push and takes a long time is equally not good. The ideal is a
balance where 10 or 20 bricks are moved at once in the same time it would take
to move one. Don't overload the system with too many interrupts or put too much
into the interrupt service routine.
Use handshaking
Just because an interrupt signal has been applied for the correct number
of clocks, do not assume that it has been recog-nised. It might have been
masked out or not seen for some other reason. Nearly all processor designs use
a handshaking mecha-nism where the interrupt is maintained until it is
explicitly ac-knowledged and removed. This may be a hardware signal or a
constituent of the ISR itself where it will remove the interrupt source by
writing to a register in the peripheral.
Control resource sharing
If a resource such as a variable is used by the normal software and
within an interrupt routine, care must be taken to prevent corruption.
For example, if you have a piece of C code that modifies a variable a as shown in the example, the expected
output would be a=6 if the value of a was 3.
{
read(a);
a=2*a;
printf(“a=“, a);
}
If variable a was used in an interrupt routine
then there is a risk that the original code will fail, e.g. it would print out a=8, or some other incorrect value. The explanation is that the interrupt
routine was executed in the middle of the original code. This changed the value
of a and therefore the wrong value was re-turned.
{
read(a);
Interrupt!
read(a);
Return;
a=2*a;
printf(“a=“, a);
}
Exceptions and interrupts can occur asynchronously and therefore if the
system shares any resource such as data, or access to peripherals and so on, it
is important that any access is handled in such a way that an interrupt cannot
corrupt the program flow. This is normally done by masking interrupts before
access and unmasking them afterwards. The example code has been modi-fied to
include the mask_int and unmask_int calls. The problem is that while the
interrupts are masked out, the interrupt latency is higher and therefore this
is not a good idea for all applications.
{
mask_int();
read(a); a=2*a; printf(“a=“, a); unmask_int();
}
This problem is often the cause of obscure faults where the system works
fine for days and then crashes i.e. the fault only occurs when certain events
happen within certain time frames. The best way to solve the problem in the
first place is to redesign the software so that the sharing is removed or uses
a messaging protocol that copies data to ensure that corruption cannot take
place.
Beware false interrupts
Ensure that all the hardware signals and exception routines do not
generate false interrupts. This can happen in software when the interrupt mask
or the interrupt handler executes the return from interrupt instruction before
the original interrupt source is removed.
In hardware, this can be caused by pulsing the interrupt line and
assuming that the processor will only recognise the first pulse and mask out
the others. Noise and other factors can corrupt the interrupt lines so that the
interrupt is not recognised correctly.
Controlling interrupt levels
This was touched on earlier when controlling resources. It is important
to assign high priority events to high priority inter-rupts. If this does not
happen then priority inversion can occur where the lower priority event is
serviced while higher priority events wait. This is quite a complex topic and
is discussed in more detail in the chapter on real-time operating systems.
Controlling stacks
It is important to prevent stacks from overflowing and exceeding the
storage space, whether it is external or internal memory. Some software, in an
effort to optimise performance, will remove stack frames from the stack so that
the return process can go straight back to the initial program. This is common
with nested routines and can be a big time saver. However, it can also be a
major source of problems if the frames are not correctly removed or if they are
when information must be returned. Another com-mon mistake is to assume that
all exceptions have the same size stack frames for all exceptions and all
processor models within the family. This is not always the case!
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.