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:
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 🙂
Pingback: Traps&Pitfalls: Overlapping Interrupt Priorities | MCU on Eclipse
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
LikeLike
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.
LikeLike
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.
LikeLike
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.
LikeLike
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.
LikeLike
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!
LikeLike
Hi Jeff,
interesting, I have used K60/K70 tower systems, never put in the batteries and have not seen this. Which module are you using?
LikeLike
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 in freescale community 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.
LikeLike
intesting, I did not remember that I solved exactly that problem a year ago 😉
LikeLike
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?
LikeLike
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.
LikeLike
Woooo, I have spent an hour with this, seriously you have found every problem am currently finding in the process of learning to use ProcessorExpert
LikeLiked by 1 person
Yes, this is a classic one. I hope you do not spend too much time on other possible issues.
LikeLike
yeah, I had wired the NMI_b (PTB5) to an output (LED). So i figured out it was an NMI interrupt and cut the trace and everything worked. Is it possible to use this pin for GPOI while NMI pin is disabled in the cpu properties?
LikeLike
Yes, that shold be possible (disable the NMI function in the CPU properties). It should work similar as what I did for the reset pin:
It could be that you need to disable things in two places, see https://mcuoneclipse.com/2013/02/16/using-the-reset-button-on-the-freedom-board-as-user-button/
LikeLike
Thank you, thank you, thank you, hehe. I am emailing you the screenshot :), right under the reset function you had to disable, and it was right there in your screenshot, but wrong spellings, don know why… MNI… NMI?? sigh.. This is a relief.
LikeLike
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!!
LikeLike
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.
LikeLike
Hey Erich, I am having exactly this problem when initializing the Clock Pin on the SDHC_LDD component; it throws a Hard fault, but I don’t know which clock should I enable.
LikeLike
Are you using Processor Expert? It will enable all the needed clocks. Even if you are not using it, you can look at its code to see what you are missing?
LikeLike
And thanks a lot for this blog. It is amazing! Every time I am working on my K64f I keep coming here.
LikeLike
Thanks Erich!
LikeLike
Pingback: C++ with Kinetis Design Studio | MCU on Eclipse
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 🙂
LikeLike
Well, I hope you still have some hair left 🙂
LikeLiked by 1 person
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
LikeLike
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
LikeLike
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
LikeLike
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!
LikeLiked by 1 person