2025-01-19 01:27 AM - edited 2025-01-19 02:28 AM
Hi,
i have an issue, where i implemented using DMA. The DMA works seemingly without issues, but when debugging and using the start/pause buttons, the hard fault happens.
Would the be a smart way to *simulate* a pause/start of a debug session??
EDIT:
I found out, that this issue only happens when the interrupt is activated:
volatile uint16_t adcArray[12]
void DMA1_Channel2_IRQHandler(){
ADC_TEST_2_ON
// Transfer complete
if( READ_BIT(DMA1->IFCR, DMA_IFCR_CTCIF2) ){
DMA1->IFCR |= (DMA_IFCR_CTCIF2); // Clear bit transfer complete
// tempFETBits = 0;
// battVoltBits = 0;
// throttleBits = 0;
// buttonSensBits = 0;
tempFETBits = adcArray[0];
ADC_TEST_2_OFF;
}
// Transfer error
if( READ_BIT(DMA1->IFCR, DMA_IFCR_CTEIF2) ){
DMA1->IFCR |= (DMA_IFCR_CTEIF2); // Clear bit
//TODO: save event
while(1);
}
ADC_TEST_2_OFF;
}
2025-01-21 09:32 AM - edited 2025-01-21 09:33 AM
Avoid while(1) loops in the IRQ Handler. Avoid dying quietly and break-pointing.
Instrument the code, so you can understand dynamic flow without dead-stopping everything.
Perhaps output a single char to UART or ITM_SendChar() so it's significantly less disruptive and blocking. For longer messages enqueue the data in a buffer, and feed out via a UART IRQ
Output enough information to diagnose what's happening, if you'd be using the break-point to check registers, do that same thing in code so you can see them without billions of cycles elapsing.
2025-01-21 09:51 AM
@Tobe wrote:Even worse, when you have to debug the debug session!
You have to use the debug tools appropriately.
As already noted, halting debug (stepping, breakpoints) will severely disrupt the realtime behaviour.
So, as @Tesla DeLorean said, you need to adopt a different approach when that disruption breaks things.
Stepping & breakpoints can be great tools when used appropriately - but they are not appropriate in all situations.
2025-01-21 12:29 PM
2025-01-21 12:59 PM - edited 2025-01-21 01:01 PM
Avoid while(1) loops in IRQ?
I might have some of those in IRQs. But they work as expected: Letting the program stay at a fault.
Would avoid using auto/local for DMA buffers
I guess if i dont know much about this, then im doing it right? ;-)).
I have implement an eventlog, but havent done much with the DMA on it. I think the issue stems from having the DMA IRQ active, and like the DMA beeing fired. As i said, there is no problem, if inside the DMA interrupt, but while other interrupts were active.
2025-01-21 01:45 PM
Local variables are defined inside function.
You want DMA buffers be defined as globals (i.e. outside functions) and volatile.
Make sure they are big enough to accommodate all data from DMA (taking into account the memory-side transfer size set in DMA, times number of transfers).
JW
2025-01-21 03:37 PM - edited 2025-01-21 03:38 PM
@waclawek.jan wrote:You want DMA buffers be defined as globals (i.e. outside functions) and volatile.
More specifically, you want them to be defined with static duration; ie, they exist for the entire duration of the program.
Unless qualified as static, local variables have automatic duration; ie, they cease to exist as soon as the function exits.
Clearly, if a DMA operation is still using an automatic variable when the function exits - that's going to cause trouble!
https://en.cppreference.com/w/cpp/language/storage_duration
2025-01-21 09:40 PM
I was considering the "local" in "auto/local" so describe something else. I would never ever consider using DMA with local variables. Then DMA would barely make any sense. I am aware, that local variables vanish.
That variable is declared as volatile. I have checked that the DMA was not writing outside of the allocated memory of the variable.
I have a faily stable program running. I had no such issues for a long time (about 500 hours).
2025-01-22 12:17 AM
I said, debug the hardfault. The only information you gave back was, that it's an invalid PC, from which I draw the conclusion that you may have thrashed stack.
If this is not the case, debug the hardfault. Check content of the fault registers (SCB_CFSR and its components). If you are using an IDE which provides you a backtrace (call stack, whateverisitcalled), look at the point where the fault handler was called (taking into mind that imprecise error happens a couple of instructions before that point), in mixed C-disasm view, to see what was the cause of fault. If in doubts, post info relevant to these points.
JW