Difference between revisions of "Embedded System Tutorial Interrupts"

From Embedded Systems Learning Academy
Jump to: navigation, search
(ISR Procedure)
(Replaced content with "Socialledge is moving to two portals. * The Wiki will remain here for general references about the SJ-One board, and to document student reports. * The bookstack will...")
 
(9 intermediate revisions by 2 users not shown)
Line 1: Line 1:
== Introduction ==
+
Socialledge is moving to two portals.   
This tutorial demonstrates how to use interrupts on a processorIn general, you will understand the concept behind interrupts on any processor, but we will use the SJ-One board as an example.
+
*  The Wiki will remain here for general references about the SJ-One board, and to document student reports.
 +
*  The bookstack will now be used for SJSU assignments
  
=== What is an interrupt? ===
+
[http://books.socialledge.com/books/embedded-drivers-real-time-operating-systems/chapter/lesson-interrupts This article has been moved here]
*  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
 
*  IMPORTANT: CPU will disable interrupts (or that priority level's interrupts until end of ISR)
 
*  Registers are saved before running the ISR (pushed onto the stack)
 
*  ISR is run
 
*  Registers are restored (popped from stack)
 
*  Interrupts are re-enabled (or that priority level's interrupt is re-enabled)
 
 
 
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.
 
[[File:tutorial_interrupts_vec_table.png|center|frame|HW Interrupt Vector Table]]
 
 
 
=== 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.
 
[[File:tutorial_interrupts_sw_vec_table.png|center|frame|SW Interrupt Vector Table]]
 
 
 
=== 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:
 
 
 
<syntaxhighlight lang="c">
 
/***************/
 
/* 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 */
 
    }
 
 
 
</syntaxhighlight>
 
 
 
<BR/>
 
=== What to do inside an ISR ===
 
Do very little inside an ISR.  When you are inside an ISR, the whole system is blocked (other than higher priority interrupts).  If you spend too much time inside the ISR, then you are destroying the realtime operating system principle and everything gets clogged because of you :(
 
 
 
With that said, here is the general guideline
 
*  Spend as little time as possible. DO NOT POLL FOR ANYTHING.
 
*  If you are using FreeRTOS API, you must use '''FromISR''' functions only!
 
*  Most important: Clear the source of the interrupt
 
*:  For example, if interrupt was for rising edge of a pin, clear the "rising edge" bit such that you will not re-enter into the same interrupt function.
 

Latest revision as of 16:38, 1 March 2018

Socialledge is moving to two portals.

  • The Wiki will remain here for general references about the SJ-One board, and to document student reports.
  • The bookstack will now be used for SJSU assignments

This article has been moved here