This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hello,
I'm running into an issue where, after about an hour of running my program on my TM4C123GH6PZ, the microcontroller goes into the Fault ISR. I want to walk through the steps I've taken so far and look for some advice or tips moving forward.
I attempted to use this document here to debug the fault. I've determined from the NVIC_FAULT_STAT register that I'm running into an invalid state usage fault. The NVIC_FAULT_ADDR is reading address 0xE000EDF8. From the TM4C123GH6PZ datasheet, this appears to be within the memory reserved for the Cortex-M4F peripherals (sys stick, NVIC, MPU, FPU, and SCB). Looking at the Cortex-M4F data sheet, 0xE000EDF8 appears to be the "debug core register data register." I've come to a dead end here, as I'm not entirely sure if this is a correct fault address.
It sounds like the most common cause of the invalid state usage fault is stack overflow or stack corruption. I read this document and added a hardware watchpoint to monitor __stack. So far, I haven't hit this watchpoint yet but I still hit the FaultISR. I had previously read that sometimes debugging a stackoverflow can be done by setting the entire stack to a specific known value and seeing if/when all the values get modified in memory. I read that this can be done in the linker file but I'm not sure how.
I also noticed that inside my linker file (.cmd), there is the statement
__STACK_TOP = __stack + 1900;
This is carry-over from an old project. My stack size is actually set to 2600. What is the effect of the above statement? From a previous thread on the forums, __STACK_TOP and __STACK_END start as the lowest value of the stack. As the stack is filled, __STACK_TOP decreases towards the value __stack. By setting __STACK_TOP = __stack + 1900, am I incidentally setting my stack to only 1900? My map file shows a stack size of 0xA28 (2600), but it seems like I'm offsetting the stack top at the beginning of the program.
Any help, tips, or thoughts would be widely appreciated! This is my first time really digging into stack usage, so please be light if I'm missing something obvious!
Regards,
CamK
Hi all,
I'm not doing any dynamic allocation (heap is set to 0) and I have optimization turned off.
I ran the program and waited for it to crash. I went to the address stored in the SP - which appears to be a valid address within the bounds of the stack - and found the LR stored on the stack. I went to the address of the LR (0x3A35) and viewed the dissassembly at that address. My last instruction appears to be a str instruction.
I see the blx instruction as 0x3A32. The value of R2 stored on the exception stack frame (SP + 0x08) is 0x00000000. Could this be the culprit?
Regards,
CamK
So, after doing some modifications, every time I run, I consistently get the instruction access violation fault (NVIC_FAULT_STAT register = 0x00000001). NVIC_MM_AADR = 0xE000EDF8 (that same debug data register). The system crashes much quicker but it is much more consistent and always results in the same stack pointer (0x20005238). If I follow that address, I can see the same LR address on the stack (0x10DD3) every run. The PC register on the stack is 0xFFFFFF30 - this can't be valid, can it? It looks like R0 was 0x00000000.
Within my UART 4 interrupt, I can see the following code from the disassembly at the LR address. I'm using the ring buffer RingBufUsed function provided by TivaWare (2.1.3.156, I believe) to check if there is data in the ring buffer.
Does an offending instruction or anything stand out? ulMode is just a standard unsigned 32-bit integer. circTxBuffer is ring buffer of size 256 (using the struct provided in TivaWare). I'll also attach my entire UART4 interrupt in case I'm overlooking something. This issue has really got me scratching my head. Interestingly, my debug screen has a small window with the message 0xFFFFFFF0 (no symbols are defined for 0xFFFFFFF0). Are there any other registers I could check to help point me in the right direction?
void UART4IntHandler(void) { uint32 intStatus; uint32 ulMode = 0; schEvent event; uint8 recChar[16]; uint8 index = 0; intStatus = MAP_UARTIntStatus(UART4_BASE, true); MAP_UARTIntClear(UART4_BASE, intStatus); if(intStatus & (UART_IM_RTIM | UART_IM_RXIM) ) { while(MAP_UARTCharsAvail(UART4_BASE)) { recChar[index++] = MAP_UARTCharGetNonBlocking(UART4_BASE); } if(index) { RingBufWrite(&circRxBuffer, recChar, index); event.sig = UART_SIG; sch_post_isr(UART4_TASK_PRIO, event); MAP_IntMasterEnable(); } RxInt++; } ulMode = RingBufUsed(&circTxBuffer); if(ulMode) { for(index=0; index < ulMode; index++) { if(MAP_UARTSpaceAvail(UART4_BASE)) { MAP_UARTCharPut(UART4_BASE, RingBufReadOne(&circTxBuffer)); } else { index = ulMode; } } } }
CamK
Gotta say it... "Told you!"
"...eventually the problem was on an array index - it was an almost impossible combination of data received, which caused a bad code to try to write way far from the array declared size..."
Take another look into your code - even if the communication is fast, you should not let the interrupt dance allow that to happen. The "worst" that should happen would be unprocessed or lost data, but no array corruption; certainly, it ain't the hardware FIFO who has run out of space.
Still, glad you found it, thanks for sharing the outcome.
Bruno