2021-10-29 06:05 AM
Hola, i have been succesfully using DMA+ADC in stm32f072/f103/f105.
ADC in Scan+Continuous mode. (15 channels enabled)
But now im trying to use stm32f207 (NUCLEO-f207zg) , the DMA works one time(first channel) and dies.
DMA interrupt IRQ is only triggered 2 times (mid transfer and transfer completed of the first adc channel)
What am i missing , what is different in stm32f207?
Solved! Go to Solution.
2021-11-04 03:58 AM
As @Bruno_ST pointed out here all this buzz happened because cubeMx tries to config the DMA before its clock is enabled.
I just changed the order of how DMA and ADC are initialiced and it works now.
2021-10-29 12:56 PM
Javier,
Look at the ADCx_CR2.DDS bit description in RM. I don't use CubeMX so you have to find how this maps there, I'd guess it is the DMA Continuous Requests tickbox.
JW
2021-10-29 04:18 PM
DMA would need to be in circular mode, so it restarts after TC
Double check DMA error/status.
Avoid blocking code in the interrupt. Toggle a GPIO, it is far less invasive and time consuming, especially with short buffers.
Check none of the call-back code stops the DMA/ADC
2021-10-30 08:49 AM
I had the same symptoms.
When I used TIM3 as an ADC trigger and enabled TIM3 global interrupts, I had the same symptoms as you.
At this time, disabling TIM3's global interrupt solved the problem.
2021-11-03 09:32 AM
From RM003 page 224
...
10.8.1 Using the DMA
Since converted regular channel values are stored into a unique data register, it is useful to
use DMA for conversion of more than one regular channel. This avoids the loss of the data
already stored in the ADC_DR register.
When the DMA mode is enabled (DMA bit set to 1 in the ADC_CR2 register), after each
conversion of a regular channel, a DMA request is generated. This allows the transfer of the
converted data from the ADC_DR register to the destination location selected by the
software.
Despite this, if data are lost (overrun), the OVR bit in the ADC_SR register is set and an
interrupt is generated (if the OVRIE enable bit is set). DMA transfers are then disabled and
DMA requests are no longer accepted. In this case, if a DMA request is made, the regular
conversion in progress is aborted and further regular triggers are ignored. It is then
necessary to clear the OVR flag and the DMAEN bit in the used DMA stream, and to reinitialize
both the DMA and the ADC to have the wanted converted channel data transferred
to the right memory location. Only then can the conversion be resumed and the data
transfer, enabled again. Injected channel conversions are not impacted by overrun errors.
When OVR = 1 in DMA mode, the DMA requests are blocked after the last valid data have
been transferred, which means that all the data transferred to the RAM can be considered
as valid.
At the end of the last DMA transfer (number of transfers configured in the DMA controller’s
DMA_SxNDTR register):
• No new DMA request is issued to the DMA controller if the DDS bit is cleared to 0 in the
ADC_CR2 register (this avoids generating an overrun error). However the DMA bit is
not cleared by hardware. It must be written to 0, then to 1 to start a new transfer.
• Requests can continue to be generated if the DDS bit is set to 1. This allows
configuring the DMA in double-buffer circular mode.
To recover the ADC from OVR state when the DMA is used, follow the steps below:
1. Reinitialize the DMA (adjust destination address and NDTR counter)
2. Clear the ADC OVR bit in ADC_SR register
3. Trigger the ADC to start the conversion.
...
I am debugging that ADC1->CR2.DDS register but it appears to be set to 0 the whole time
2021-11-03 09:38 AM
> DMA would need to be in circular mode, so it restarts after TC
it already is
>Avoid blocking code in the interrupt. Toggle a GPIO, it is far less invasive and time consuming, especially with short buffers.
the error was there before i placed the uart print code, but i took it out again just in case.
>Check none of the call-back code stops the DMA/ADC
So far all callbacks are default generated by cubeMX, ill check
2021-11-03 09:42 AM
im trying different triggers ,even continuous mode (triggerless)
NVIC interrupts for the triggers are not enabled in any of my tests.
So note taken but it must be something else
2021-11-04 01:49 AM
I tried different trigger sources
HAL_TIM_Base_Start(&htim2);//TIMER2 Trigger out event
//HAL_TIM_Base_Start_IT(&htim2);//TIMER2 Trigger out event, the TIM2_IRQHandler is reached prediodically as expected
//HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);//TIMER2 Trigger out event
//HAL_TIM_OC_Start(&htim2, TIM_CHANNEL_2);//TIMER2 Trigger capture compare 2 event
The DMA is set to retrieve 16bits because ADC resolution is 12bits
//in main.c
/* USER CODE BEGIN PV */
uint16_t ADC_buffer[16];
....
/* USER CODE BEGIN 2 */
HAL_ADC_Start_DMA(&hadc1, (uint16_t*) ADC_buffer, 16);
...
hdma_adc1->ErrorCode returns always 0
2021-11-04 02:30 AM
...
/* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
if((hdma->Instance->CR & DMA_SxCR_CIRC) == RESET)
{
/* Disable the half transfer interrupt */
hdma->Instance->CR &= ~(DMA_IT_HT);//this code is reached but my DMA mode IS CIRCULAR
}
....
... ...
/* Disable the transfer complete interrupt if the DMA mode is not CIRCULAR */
else
{
if((hdma->Instance->CR & DMA_SxCR_CIRC) == RESET)
{
/* Disable the transfer complete interrupt */
hdma->Instance->CR &= ~(DMA_IT_TC);//this code is also reached but my DMA mode IS CIRCULAR
.....
/* ADC1 DMA Init */
/* ADC1 Init */
hdma_adc1.Instance = DMA2_Stream0;
hdma_adc1.Init.Channel = DMA_CHANNEL_0;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;//<----------------------------------------------------:D
hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
/* Write to DMA Stream CR register */
hdma->Instance->CR = tmp;// <---- hdma->Instance->CR doesnt get tmp value for some reason, it remains 0
I cannot change the value manually in the Debugger Expressions window.......
Something is preventing this memory to being written, something is preventing the init code to write the configurations in the DMA2 Stream0 registers.That memory addr 0x40026410 happens to be where DMA2 Stream 0 peripheral is mapped, as expected in my cubeMX configuration.
I just opened a question about this https://community.st.com/s/question/0D53W00001B0menSAB/why-cant-i-write-into-mem-0x40026410
2021-11-04 03:58 AM
As @Bruno_ST pointed out here all this buzz happened because cubeMx tries to config the DMA before its clock is enabled.
I just changed the order of how DMA and ADC are initialiced and it works now.