# DMA request is ony done 1 time in STM32 - Even if I have check marked it as Circular Mode

Cause for writing this question:

I think I found a bug. This happens when I try to enable DMA for SDADC and Input Capture.

Introduction:

I'm using STM32F373VBTx processor and it working great! Except when I try to enable DMA for TIM16 and TIM17 as Input Capture and SDADC1, SDADC2 and SDADC3. What happens is that the values from these peripherals only call DMA request 1 time and never more.

Method - Input Capture:

I enable IC1 (Input Capture 1)

I enable IC0 (Input Capture 0)

Then I start IC with DMA.

volatile static uint16_t input_capture0[2] = {0};
volatile static uint16_t input_capture1[2] = {0};

void STM32_PLC_Start_Input_Capture(TIM_HandleTypeDef* htim17, TIM_HandleTypeDef* htim16) {
/*
* Input capture for measuring frequency
* For TIM17 and TIM16
* Timer clock: 48 Mhz
* Prescaler: 4799
* Counter: 65535 (0xffff)
* Update frequency: 0.1526 Hz (1/0.1526 = 6.5535 seconds)
* Example: For every second, it will count 10000
* Lowest frequency measurement: 1/(0xFFFF*0.0001) = 0.1526 Hz
* Highest frequency measurement: 1/(1*0.0001) = 10000 Hz
*/
if(HAL_TIM_IC_Start_DMA(htim16, TIM_CHANNEL_1, (uint32_t*)input_capture1, 2) != HAL_OK)
Error_Handler();
if(HAL_TIM_IC_Start_DMA(htim17, TIM_CHANNEL_1, (uint32_t*)input_capture0, 2) != HAL_OK)
Error_Handler();
}


I enable Sigma Delta ADC 1

And for timer 12 and timer 13

Results - Input Capture

When I call to read the arrays input_capture0, input_capture1 then the DMA has only filled the arrays 1 time only. Only the first element has a value, the rest of the elements has 0 value. I try to pulse 3.3V onto the Input Capture pin, but it only react once.

static float compute_frequency(uint16_t input_capture[]) {
/*
* Typical worst case scenarios:
* T1: 0xFFFF - T0: 0x0
* T1: 0x0    - T0: 0xFFFF
* T1: 0x7FFF - T0: 0x7FFF
* T1: 0x0    - T0: 0x0
*/
uint16_t difference;
if(input_capture[1] > input_capture[0]) {
difference = input_capture[1] - input_capture[0];
return (float) 1/(difference*0.0001f);
} else if(input_capture[1] < input_capture[0]) {
difference = 0xFFFF - input_capture[1] + input_capture[0] + 1;
return (float) 1/(difference*0.0001f);
} else {
return 1/(65335*0.0001f);
}
}

float STM32_PLC_Input_Capture_Get(uint8_t i) {
if(i == 0)
return compute_frequency((uint16_t*)input_capture0);
else
return compute_frequency((uint16_t*)input_capture1);
}


When I try to read the arrays SDADC1_Single, SDADC2_Single, SDADC3_Differential, only the first element has a value, the rest of the elements has 0 values.

/* Get raw ADC0 to ADC11 */
if(i < 9)
else
}

}


Discussion:

If I enable change Circular Mode to

Normal Mode

It will give me the same results. The first element get a value, the rest of the elements are zero.

Question:

What do you think causing this issue? Why does not the whole array completes?

Here is my main.c configuration file.

Update 1:

I tried to change the gain and offset at SDADC1 and this is how it goes. To change the gain, you need to call

HAL_StatusTypeDef HAL_SDADC_InjectedStop_DMA(SDADC_HandleTypeDef *hsdadc)
{
HAL_StatusTypeDef status;

/* Check parameters */

{
/* Return error status */
status = HAL_ERROR;
}
else
{
/* Clear JDMAEN bit in SDADC_CR1 register */

/* Stop current DMA transfer */
{
/* Set SDADC in error state */
status = HAL_ERROR;
}
else
{
/* Stop injected conversion */
}
}
/* Return function status */
return status;
}


Then it will call this function to abort DMA.

HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
{
if(hdma->State != HAL_DMA_STATE_BUSY)
{
/* no transfer ongoing */
hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;

/* Process Unlocked */
__HAL_UNLOCK(hdma);

return HAL_ERROR;
}
else
{
/* Disable DMA IT */
hdma->Instance->CCR &= ~(DMA_IT_TC | DMA_IT_HT | DMA_IT_TE);

/* Disable the channel */
hdma->Instance->CCR &= ~DMA_CCR_EN;

/* Clear all flags */
}
/* Change the DMA state*/

/* Process Unlocked */
__HAL_UNLOCK(hdma);

return HAL_OK;
}


Here we can clearly see that the DMA wasn't started, even if I got values from DMA once.

Update 2:

Here is the complete project. Import it with STM32CubeIDE.

• What have you done to debug the problem? I’d be looking at the dma registers to see what is really happening. You’ll only get so far relying on cubemx configuration. Aug 18, 2021 at 13:14
• I think its about time you grab the reference manual and start reading. The dma controller is not that difficult. At some point you’ll need to escape the grip of cubemx and get your hands dirty. Assuming you’ve got a debugger, you can look at the hardware registers. You can look at how cubemx configures the dma and the state of the dma after 1 transfer. Does the dma think it is finished? Or is it the timer not playing ball. ST is usually quite simple compared to some of the TI nightmares I’ve had to contend with. Aug 18, 2021 at 13:23
• Try not using HAL or CubeMX if you run into such problems. This is why I don't even bother to look at questions trying to debug using HAL or CubeMX. Not enough people read the Reference Manual which says what the details are and on top of that you don't know exactly what HAL or CubeMX is actually doing. Aug 18, 2021 at 13:23
• @MrYui You would only think the STM32 manual is complex if you never actually tried to read the manual for other microcontrollers. Most are...worse unless you are comparing to PICs which are simpler processors in general. Aug 18, 2021 at 13:31
• There really is no API. You're not coding an application. You're generating c-code and header files using a GUI provided by the manufacturer. Sometimes it gets it right, sometimes there are subtle issues with the generated code. When this happens, you need to go through the generated headers, line by line, until you understand them and find the issues. Aug 18, 2021 at 13:48

I found the solution! It's a BUG in CubeMX. And it's very easy to solve!

Just move MX_DMA_Init(); to the beginning.

  /* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init(); <--- To here
MX_DAC1_Init();
MX_DAC2_Init();
MX_RTC_Init();
MX_SPI2_Init();
MX_TIM2_Init();
MX_TIM5_Init();
MX_SPI1_Init();
MX_TIM4_Init();
MX_CAN_Init();
MX_USART1_UART_Init();
MX_TIM6_Init();
MX_TIM12_Init();
MX_TIM13_Init();
MX_TIM16_Init();
MX_USB_DEVICE_Init();
MX_FATFS_Init();
MX_TIM17_Init();
<--- From here
MX_TIM19_Init();
/* USER CODE BEGIN 2 */


This results:

• Input Capture + DMA works
• SDADC + DMA works, but I only get -0x8000 = -32768 (int16_t) because all my inputs are attached to GND. It seems that even if I have circular buffer, it still acts like it's Normal Mode. I can't change these values if I apply higher voltage onto the SDADC inputs. Hm.....

Update 1:

I removed the volatile keyword for SDADC arrays.

static int16_t SDADC1_Single[9];