2025-11-17 1:45 AM
I have strange DMA problem with a F303 application, in particular a STM32F303K8 (a STM32F303x6/8 variant).
The concept is relatively straightforward.
A configured ADC sequence is triggered by timer, the ADC in turn triggers DMA transfers of the conversion results, and the DMA raises the TC interrupt when the specified number of transfers is reached.
The problem is, the ADC almost immediately raises the OVR flag (overflow), and the DMA is disabled (CCR.EN is reset).
I can't see the reason why.
Detailed description of used peripherals / resources :
- ADC1_IN1, ADC1_IN2 & ADC1_IN4, 19.5 cycles, with ADC.CCR CKMODE=3 (synchronous, HCLK/4)
- TIM3 TRGO as ADC trigger (ADC1.CFGR EXTSEL=4, EXTEN = 1), at about 11kHz
- assigned DMA is DMA1 Channel 1 (see RM0316 Rev 10, table 77 at page 268)
DMA is configured in circular mode, peripheral-to-memory transfer, memory increment, and half-word transfers.
At the moment I try only one sequence (3 samples, i.e. half-words), instead of a larger buffer.
The sequence of setup is as follows:
- TIM3 is set up, but not yet started;
- DMA is configured (DMA enabled & TC interrupt enabled)
- ADC sequence is configured (ADC1 and common)
- ADC-DMA is enabled (CFGR.DMACFG=1, CFGR.DMAEN=1)
- TIM3 is started
- the ADC is enabled (CFGR.ADEN=1)
- conversion is started (CR.ADSTART=1)
As soon as I start the chain the ADC->ISR.OVL bit is set, DMA is disabled (DMA->CCR.EN is reset, with the number of transfers remains 3 (no transfer happens).
This behavior is described in the RM, although I can't see the reason here.
I have tested the timer configuration and ADC configuration independantly, and both seem to work as expected.
The timer fires at the configured rate (111 interrupts per 10ms systick cycle).
And using the EOC/EOS interrupts, I can see credible ADC conversion results from all channels.
I had been trying ADC2 and DMA1.Ch2 instead of ADC1 + DMA1.CH1, but the result is the same.
And before one asks - no, there is no *.IOC file.
This is not a Cube/HAL application.
This project is loosely based upon SPL code, with many instances of direct register access.
I can share any related code, if it is helpful.
But I think the debugger's register view works equally well.
Here the ADC and DMA register settings right before starting the conversions:
And here the same afterwards: