2023-07-18 06:46 AM - edited 2023-07-18 07:07 AM
Hi. Setup is simple:
TIM2 creates the ADC_EXTERNALTRIG_T2_TRGO signal, which starts ADC. ADC is configured to use DMA to transfer the data to the buffer.
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.GainCompensation = 0;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T2_TRGO;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc1.Init.OversamplingMode = DISABLE;
DMA works with static number of transfers going to non-circular buffer, and the interrupt on completion, to allow processing of the collected samples:
This actually works fine. When I start the TIM2, the number of samples is transferred to the array, then ADC stops. Unfortunately, the DMA1_Channel1_IRQHandler(void) is executed in the loop, even after disabling TIM2 and clearing the DMA flags. Additional clearing of ADC flags also do not help:
The result is, that ADC flags are cleared correctly, and it's proven that ADC is really stopped, because:
Problem is with DMA IRQ flags - even after the IRQHandler execution they are still set, and not cleared. Probably this causes that the IRQ is fired again - but what keeps the IRQ flags set?
Solved! Go to Solution.
2023-07-19 07:06 AM
The HAL-delivered routine for manual flag clear is bugged.
What works is:
uint32_t *ifcr = DMA1_BASE + 4;
*(ifcr) = DMA_IFCR_CHTIF1;
*(ifcr) = DMA_IFCR_CTCIF1;
As wiser say: never trust the unknown code.
2023-07-18 07:20 AM
Hello ,
It is possible that the DMA IRQ flags are the ones that are not being cleared correctly
try disabling the DMA controller before clearing the flags. This will ensure that the DMA transfer is stopped and the controller is not processing any more data.
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2023-07-18 07:23 AM - edited 2023-07-18 07:36 AM
Thanks, I will check this in a moment.
In general, this should be possible to leave DMA in enabled state? The final idea is to have TIM2 being triggered by external signal which would cause the ADC to collect another bulk of samples. Something similar to triggering the digital oscilloscope.
EDIT:
Test results. Disabling and reenabling the DMA channel is working OK, however the IRQ flags are still not cleared.
DMA1_Channel1->CCR &= ~(DMA_CCR_EN);
hdma->DmaBaseAddress->IFCR = (uint32_t)DMA_ISR_TCIF1;
DMA1_Channel1->CCR |= DMA_CCR_EN;
I am not sure if the flag clear procedure is correct? as it still do not work..
2023-07-18 07:48 AM
Read out and check/post content of DMA and DMAMUX registers.
JW
2023-07-19 02:37 AM - edited 2023-07-19 02:51 AM
Hey Jan,
can you clarify more? Do you mean in the program code, or check it during debugging?
In the debug, I see that none of the DMA flags in the registers are cleared after executing the lines:
Unfortunately, IDE do not provide the direct way to access the registers, like DMA1->IFCR what would make life definitely easier.
@Sarra.S can you verify, if the flag clearing routine is OK?
Dzięki/Thanks,
Michal
2023-07-19 07:06 AM
The HAL-delivered routine for manual flag clear is bugged.
What works is:
uint32_t *ifcr = DMA1_BASE + 4;
*(ifcr) = DMA_IFCR_CHTIF1;
*(ifcr) = DMA_IFCR_CTCIF1;
As wiser say: never trust the unknown code.