Wednesday, January 10, 2007
ISR Efficiency
If the ISR is called often and the total processing is small, then the overhead of setting up the stack may come into play. A big part of this overhead, not readily obivious in C or C++, is setting up the stack. The number of registers the compiler decides to protect can be a large part of the processing.
Check the assemble code to see how many registers the ISR protects. Below is a list of things that can reduce the overhead in C.
1. Try to simplify the code as much as possible
2. Reduce the number of variable accesses, both local and global
3. Don't make subroutine calls - This may cause the compiler to save every register
4. In-line any subroutine calls you have to make.
5. Put subroutines you have to call but can't in-line into the same module as the ISR. Some compiler are smart enough to peek at all subroutine calls to figure out what registers are used instead of blinding assuming every register will be used.
6. If an ISR only calls a routine sometimes, then it may be more efficient to put that routine in a different ISR and trigger the irq in the original ISR when the calls is needed.
Let the disassembled code be your guide. Remember that in an ISR, even scratch pad and temporary registers that are normally not saved in subroutine calls have to be saved.
Another method an ISR can reduce the processing to overhead ratio is to increase processing instead of reducing overhead. For example, if you're writing a driver that's getting data from a piece of hardware and the data usually comes in brust, consider polling for more data in the ISR. Even if there's no data now, retry a couple of times before exiting this ISR. This depends heavily on the application, but is another useful tool to have.
References:
Embedded Systems Programming (latest issues)
Check the assemble code to see how many registers the ISR protects. Below is a list of things that can reduce the overhead in C.
1. Try to simplify the code as much as possible
2. Reduce the number of variable accesses, both local and global
3. Don't make subroutine calls - This may cause the compiler to save every register
4. In-line any subroutine calls you have to make.
5. Put subroutines you have to call but can't in-line into the same module as the ISR. Some compiler are smart enough to peek at all subroutine calls to figure out what registers are used instead of blinding assuming every register will be used.
6. If an ISR only calls a routine sometimes, then it may be more efficient to put that routine in a different ISR and trigger the irq in the original ISR when the calls is needed.
Let the disassembled code be your guide. Remember that in an ISR, even scratch pad and temporary registers that are normally not saved in subroutine calls have to be saved.
Another method an ISR can reduce the processing to overhead ratio is to increase processing instead of reducing overhead. For example, if you're writing a driver that's getting data from a piece of hardware and the data usually comes in brust, consider polling for more data in the ISR. Even if there's no data now, retry a couple of times before exiting this ISR. This depends heavily on the application, but is another useful tool to have.
References:
Embedded Systems Programming (latest issues)