Difference between revisions of "Embedded System Tutorial Interrupts"

From Embedded Systems Learning Academy
Jump to: navigation, search
(Created page with "== Introduction == This tutorial demonstrates how to use interrupts on a processor. In general, you will understand the concept behind interrupts on any processor, but we wil...")
(No difference)

Revision as of 20:57, 2 December 2013

Introduction

This tutorial demonstrates how to use interrupts on a processor. In general, you will understand the concept behind interrupts on any processor, but we will use the SJ-One board as an example.

What is an interrupt?

  • Hardware capability to break normal software flow to attend an urgent request
  • "An event that needs immediate attention"

Science

The science behind interrupts lies in the hardware that allows the CPU to be interrupted. Each peripheral in a microcontroller may be able to assert an interrupt to the CPU core, and then the CPU core would jump to the corresponding interrupt service routine (ISR) to service the interrupt.

ISR Procedure

The following steps demonstrate what happens when an interrupt occurs :

  • CPU manipulates the PC (program counter) to jump to the ISR
  • Registers are saved before running the ISR (pushed onto the stack)
  • ISR is run
  • Registers are restored (popped from stack)

On some processors, the savings and restoring of registers is a manual step and the compiler would help you do it. You can google "GCC isr attribute" to study this topic further. On SJ-One board, which uses LPC17xx (ARM Cortex M3), this step is automatically taken care of by the CPU hardware.

The SW to HW Connection

Now that we understand how the CPU hardware services interrupts, we need to define how we inform the CPU WHERE our ISR function is located at. There is something called an Interrupt Vector Table. This table is nothing but addresses of functions that correspond to the microcontroller interrupts. Specific interrupts use specific "slots" in this table, and we have to populate these spots with our software functions that service the interrupts.

SJ-One (LPC17xx) Example

Through some magic of the compiler, and the linker script, the compiler is able to place the software interrupt vector table at a specific location that the CPU expects the interrupt vector table to be located at. This connects the dots about how the CPU is able to determine WHERE your interrupt service routines are located at. From there on, anytime a specific interrupt occurs, the CPU is able to fetch the address and make the JUMP.

GCC Magic

In the SJ-One sample project, each ISR is named, but is labeled as a "weak" function. What this means in the land of GCC (compiler) is that unless the same function name is defined somewhere else, the weak function serves as the ISR function. If you do define the function name somewhere else, it will override the "weak" function and the compiler will place the address of your new function into the interrupt vector table.

Setup ISR on SJ-One =

The first step is to be able to locate the real-name of the "weak" ISR function. For example, you can locate a UART0 ISR function that is weak, and we will override with our new function. The only thing to keep in mind is that due to "C++ Mangling" of function names, if your ISR is located in a *.cpp file, you will need to enclose it into extern "C" tags. See below for examples:

/***************/
/* my_file.cpp */

    extern "C"
    {
        void UART0_IRQHandler()
        {
            /* Your ISR */
        }
    }

/*************/
/* my_file.c */

    /* extern tag not needed for a C file */
    void UART0_IRQHandler()
    {
        /* Your ISR */
    }