Oh my! An Interrupt…

Ahhrg! Again, my microcontroller stopped in an interrupt. And I have no clue why?

Using Processor Expert in MCU10 is a great thing as it takes care about the vector table. Usually the default settings for code generation are fine, but not in my case here. If you run into a spurious and unexpected interrupt, you stop in the Cpu_Interrupt() handler:

PE_ISR(Cpu_Interrupt)
{
  /* This code can be changed using the CPU component property "Build Options / Unhandled int code" */
  PE_DEBUGHALT();
}

Don’t get confused by the PE_ISR thing, this is actually a macro used to hide any microcontroller or compiler specific extensions:

/* Interrupt definition template */
#if !defined(PE_ISR)
  #define PE_ISR(ISR_name) void ISR_name(void)
#endif

Looking at the generated Vectors.c, it shows

  static __declspec(vectortable) tVectorTable __vector_table = { /* Interrupt vector table */
    /* ISR name                             No. Address      Pri Name                           Description */
    __SP_INIT,                         /* 0x00  0x00000000   -   ivINT_Initial_Stack_Pointer    used by PE */
    {
    (tIsrFunc)&__thumb_startup,        /* 0x01  0x00000004   -   ivINT_Initial_Program_Counter  used by PE */
    (tIsrFunc)&Cpu_INT_NMIInterrupt,   /* 0x02  0x00000008   -2   ivINT_NMI                      used by PE */
    (tIsrFunc)&Cpu_Interrupt,          /* 0x03  0x0000000C   -1   ivINT_Hard_Fault               unused by PE */
    (tIsrFunc)&Cpu_Interrupt,          /* 0x04  0x00000010   -   ivINT_Mem_Manage_Fault         unused by PE */
    (tIsrFunc)&Cpu_Interrupt,          /* 0x05  0x00000014   -   ivINT_Bus_Fault                unused by PE */
    (tIsrFunc)&Cpu_Interrupt,          /* 0x06  0x00000018   -   ivINT_Usage_Fault              unused by PE */
    (tIsrFunc)&Cpu_Interrupt,          /* 0x07  0x0000001C   -   ivINT_Reserved7                unused by PE */
...
}

That means that every unhandled interrupt gets routed to the Cpu_Interrupt handler by default. So if the debugger stops in that handler, I have little information to none information what has triggered that interrupt.

But there is a setting how to change that: the way how the interrupt vector table is set up by Processor Expert configured in the Build options of the Component Inspector view:

Processor Expert Component Inspector View to set handler for vectors

Processor Expert Component Inspector View to set handler for vectors

Select the CPU component in the Project Panel view, and change the Unhandled vectors setting to Own handler for every. Now it generates my vector table as:

 static __declspec(vectortable) tVectorTable __vector_table = { /* Interrupt vector table */
    /* ISR name                             No. Address      Pri Name                           Description */
    __SP_INIT,                         /* 0x00  0x00000000   -   ivINT_Initial_Stack_Pointer    used by PE */
    {
    (tIsrFunc)&__thumb_startup,        /* 0x01  0x00000004   -   ivINT_Initial_Program_Counter  used by PE */
    (tIsrFunc)&Cpu_INT_NMIInterrupt,   /* 0x02  0x00000008   -2   ivINT_NMI                      used by PE */
    (tIsrFunc)&Cpu_ivINT_Hard_Fault,   /* 0x03  0x0000000C   -1   ivINT_Hard_Fault               unused by PE */
    (tIsrFunc)&Cpu_ivINT_Mem_Manage_Fault, /* 0x04  0x00000010   -   ivINT_Mem_Manage_Fault         unused by PE */
    (tIsrFunc)&Cpu_ivINT_Bus_Fault,    /* 0x05  0x00000014   -   ivINT_Bus_Fault                unused by PE */
    (tIsrFunc)&Cpu_ivINT_Usage_Fault,  /* 0x06  0x00000018   -   ivINT_Usage_Fault              unused by PE */
    (tIsrFunc)&Cpu_ivINT_Reserved7,    /* 0x07  0x0000001C   -   ivINT_Reserved7                unused by PE */
    (tIsrFunc)&Cpu_ivINT_Reserved8,    /* 0x08  0x00000020   -   ivINT_Reserved8                unused by PE */
    (tIsrFunc)&Cpu_ivINT_Reserved9,    /* 0x09  0x00000024   -   ivINT_Reserved9                unused by PE */
    (tIsrFunc)&Cpu_ivINT_Reserved10,   /* 0x0A  0x00000028   -   ivINT_Reserved10               unused by PE */
    (tIsrFunc)&Cpu_ivINT_SVCall,       /* 0x0B  0x0000002C   -   ivINT_SVCall                   unused by PE */
    (tIsrFunc)&Cpu_ivINT_DebugMonitor, /* 0x0C  0x00000030   -   ivINT_DebugMonitor             unused by PE */
...
}

Now every interrupt will use its own handler, and now it is easy to find out what was the interrupt source.

Happy Interrupting 🙂

Advertisements

30 thoughts on “Oh my! An Interrupt…

  1. Pingback: Traps&Pitfalls: Overlapping Interrupt Priorities | MCU on Eclipse

  2. Nice to know that there’s a easy way. I was just about to read the ARM NVIC manual whole or enable all know interrupts on in PE. Thanks

    Like

  3. That is a good solution and what I had vaguely remembered. But unfortunately I cannot use PE with the current code because I am trying to get the FlexTimer and PIT working on a Kinetis K20 and the PE component for the FLexTimer has no methods to speak of. So I am using Device Initialization without mqx because once I get this to work I will move the code to an MQX project. Do you know if there is anyway in DeviceInitialization to assign the vectors other than manually; also is there a way in MQX?

    Thank you for the above solution in PE. That is helpful when I move everything over to freeRTOS and your components in PE.

    Like

    • To my knowledge, in Device Init for Kinetis mode there is no way to set up other vectors. For non-Kinetis and Processor Expert mode there is as well an IntVector component which is a user interrupt vector: you can provide a name and this will be the vector function. But this does not exist (yet) for Kinetis.
      For MQX: I remember that I have seen something in the documentation to allocate vectors, but I have not used it.

      Like

  4. Hi Erich,

    Situation: I enable the interrupt request option in PE’s Peripheral Initialization (eg. Init_UART) component. When a character is received at the UART and an interrupt is raised, my MQX execution is stuck indefinitely somewhere in “dispatch.S” and tasks are no longer running.

    In MQX, in order to service an device interrupt (eg. UART), suppose I should ONLY install the ISR as described in MQX User Guide?

    Please advise. Thank you.

    Like

    • Hi chiasyan,
      I have not used MQX much. It looks like interrupts are disabled in you case? Or that you have a stack overflow. MQX takes close control over the interrupts, so indeed you probably should follow that MQX User Guide.

      Like

  5. If you use one of the kinetis tower development systems and forget to put in the real time clock coin battery, you will get this error!

    Like

      • Erich, I was using a TWR-K60D100M and only started getting the problem when I created an external interrupt PE bean for an input line from an RFID unit. After changing build options to “Own handler for every” I saw that it was the Cpu_ivINT_Hard_Fault causing the problem and googled this link: https://community.freescale.com/thread/302968 where you had solved the problem for someone else last year.

        i looked in the box that the tower came with and found the small coin cell I had not installed.
        Putting in the battery corrected the problem even though I wasn’t explicitly trying to use the RTC.

        Like

  6. So the question I have here is when in that vector it says used by PE, I cannot use that interrupt on my own?

    (tIsrFunc)&SS1_Interrupt, /* 0x2A 0x000000A8 8 ivINT_SPI0 used by PE */

    I need to access SPI0 send and receive interrupts. Is there any way to do that? and for that should I shut down the interrupts in PE for SPI0?

    Like

    • Hello,
      If it says ‘used’, then it is used by a component. So I assume you have configured that component to use that interrupt? And yes, there are ways you can directly allocate the interrupts (using an interrupt component). Or if a component uses interrupts, typically it offers events so you can add your own code to it.

      Like

  7. Erich, I have my own design board with a KL04Z8 uC on it. It’s brand new, I’m using the internal OSC. After following your tutorial, I kept receiving this error: Cpu_ivINT_Hard_Fault. What could go wrong if my project uses only the generated code from PE without any modification? Many thanks!!

    Like

    • What toolchain are you using? A common hardfault cause is accessing peripherals without the clock enabled. E.g. if you access RTC (Realtime Clock) registers, and you have not enabled/added a clock and added power to the clock power pin, it will cause a hard fault.

      Like

  8. Pingback: C++ with Kinetis Design Studio | MCU on Eclipse

  9. Oh, wow, thanks a ton for this help! I have wasted hours trying to find the source of my problem. Similar to Karibe, I had something connected to NMI pin and was about to pull all of my hair. Thanks thanks thanks 🙂

    Like

  10. Hi Erich sir,
    I am new in RTOS development. I am using FRDM k64f board and I am running 4 tasks in my project. one if task is used for UART communication. At starting of system all tasks are running for infinite time but when I give command through UART controller process the command but after 4 to 5 minutes controller stops working. and gives following debug hault
    PE_ISR(UnhandledInterrupt);
    PE_ISR(UnhandledInterrupt)
    {
    PE_DEBUGHALT();
    }

    please suggest any solution for it..

    Thanks in advance

    Like

    • Hello,
      first you need to know what interrupt has been fired. If you set the setting to ‘own handler for every’ as outlined in this article, you should know which interrupt is causing you the problem.
      It could be that this is a hard fault: in that case, I have created a component to help you deal with it, see https://mcuoneclipse.com/2012/11/24/debugging-hard-faults-on-arm-cortex-m/ and https://mcuoneclipse.com/2012/12/28/a-processor-expert-component-to-help-with-hard-faults/.
      I hope this helps,
      Erich

      Like

      • Hello Erich sir,
        Yes It is actually hard fault. And I am also using hard fault component. Actually after 4-5 min my code comes at –
        uxListRemove function

        UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
        {
        /* The list item knows which list it is in. Obtain the list from the list
        item. */
        List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;

        “””””pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;””””””
        “”””””pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;”””””

        /* Only used during decision coverage testing. */
        mtCOVERAGE_TEST_DELAY();

        /* Make sure the index is left pointing to a valid item. */
        if( pxList->pxIndex == pxItemToRemove )
        {
        pxList->pxIndex = pxItemToRemove->pxPrevious;
        }
        else
        {
        mtCOVERAGE_TEST_MARKER();
        }

        pxItemToRemove->pvContainer = NULL;
        ( pxList->uxNumberOfItems )–;

        return pxList->uxNumberOfItems;
        }

        pxItemToRemove->pxNext->pxPrevious becomes 0x0 though
        pxItemToRemove->pxPrevious; is assigning value 0x8467120 to it….

        I am not able to find why this happening..

        And Sorry for my bad English..

        Thanks

        Like

        • My guess is that something is wrong with your list: you have to debug it somewhow. It could be anything from a dangling pointer, a buffer overflow or some stack overflow. I recommend that you narrow down to what kind of memory gets overwritten by what. Use a hardware watchpoint to check who is writing to that location.
          Good luck!

          Liked by 1 person

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.