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