cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 UART DMA reception fails to update memory buffer from peripheral

Manju
Associate II

Hello ST,

I'm using STM32H743ZI. Here I'm connected to 2 external devices(1 for PC UART5 and other for another MCU UART7), both are connected via UART.

I'm using DMA with UART7 for receiving data from MCU. UART5 which we use to communicate with PC(Master) sends out some command, based on this command I request some data from MCU-UART7.

So when I receive data from PC, I'll continue to remain in UART5 ISR. In this ISR only we communicate with MCU continuously. When I receive command from PC, I send request to MCU to get back some data as response,

when MCU responds back I wanted to collect that data using UART7-DMA. 

This is basic concept.

Now problem I'm facing is,

When I request for data to MCU, first time I get correct data loaded into my buffer through DMA(where it triggers both half and full complete IRQs) but second time onwards it doesn't update my buffer. 

Whenever I receive data from MCU, I send that to PC-UART5. When again PC sends command and I again request data to MCU, it fails to update my buffere but still half and full IRQs are triggered.

What could be problem here? I tried to reinitialise UART and DMA everytime I request data from MCU, that didn't work.

I'm really stuck here, any help here will be very useful.

Code snippet looks something like below

static void MX_UART5_Init(void)

{

 /* USER CODE BEGIN UART5_Init 0 */

// This UART is towards PC

 /* USER CODE END UART5_Init 0 */

 /* USER CODE BEGIN UART5_Init 1 */

 huart5.RxISR = &UART5_InterruptCallback;

 /* USER CODE END UART5_Init 1 */

 huart5.Instance = UART5;

 huart5.Init.BaudRate = 115200;

 huart5.Init.WordLength = UART_WORDLENGTH_8B;

 huart5.Init.StopBits = UART_STOPBITS_1;

 huart5.Init.Parity = UART_PARITY_NONE;

 huart5.Init.Mode = UART_MODE_TX_RX;

 huart5.Init.HwFlowCtl = UART_HWCONTROL_NONE;

 huart5.Init.OverSampling = UART_OVERSAMPLING_8;

 huart5.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;

 huart5.Init.ClockPrescaler = UART_PRESCALER_DIV1;

 huart5.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_DMADISABLEONERROR_INIT;

 huart5.AdvancedInit.DMADisableonRxError = UART_ADVFEATURE_DMA_DISABLEONRXERROR;

 if (HAL_UART_Init(&huart5) != HAL_OK)

 {

  Error_Handler();

 }

 if (HAL_UARTEx_SetTxFifoThreshold(&huart5, UART_TXFIFO_THRESHOLD_8_8) != HAL_OK)

 {

  Error_Handler();

 }

 if (HAL_UARTEx_SetRxFifoThreshold(&huart5, UART_RXFIFO_THRESHOLD_8_8) != HAL_OK)

 {

  Error_Handler();

 }

 if (HAL_UARTEx_DisableFifoMode(&huart5) != HAL_OK)

 {

  Error_Handler();

 }

 /* USER CODE BEGIN UART5_Init 2 */

 HAL_NVIC_SetPriority(UART5_IRQn, 5, 5);

 HAL_NVIC_EnableIRQ(UART5_IRQn);

 __HAL_UART_ENABLE_IT(&huart5, UART_IT_RXFNE);

 /* USER CODE END UART5_Init 2 */

}

/**

 * @brief UART7 Initialization Function

 * @param None

 * @retval None

 */

static void MX_UART7_Init(void)

{

 /* USER CODE BEGIN UART7_Init 0 */

// This UART is towards Nebo

 /* USER CODE END UART7_Init 0 */

 /* USER CODE BEGIN UART7_Init 1 */

 huart7.RxISR = &HAL_UART_RxCpltCallback;

 /* USER CODE END UART7_Init 1 */

 huart7.Instance = UART7;

 huart7.Init.BaudRate = 2500000;

 huart7.Init.WordLength = UART_WORDLENGTH_8B;

 huart7.Init.StopBits = UART_STOPBITS_1;

 huart7.Init.Parity = UART_PARITY_NONE;

 huart7.Init.Mode = UART_MODE_TX_RX;

 huart7.Init.HwFlowCtl = UART_HWCONTROL_NONE;

 huart7.Init.OverSampling = UART_OVERSAMPLING_8;

 huart7.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_ENABLE;

 huart7.Init.ClockPrescaler = UART_PRESCALER_DIV1;

 huart7.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;

 if (HAL_UART_Init(&huart7) != HAL_OK)

 {

  Error_Handler();

 }

 if (HAL_UARTEx_SetTxFifoThreshold(&huart7, UART_TXFIFO_THRESHOLD_8_8) != HAL_OK)

 {

  Error_Handler();

 }

 if (HAL_UARTEx_SetRxFifoThreshold(&huart7, UART_RXFIFO_THRESHOLD_8_8) != HAL_OK)

 {

  Error_Handler();

 }

 if (HAL_UARTEx_DisableFifoMode(&huart7) != HAL_OK)

 {

  Error_Handler();

 }

 /* USER CODE BEGIN UART7_Init 2 */

 HAL_NVIC_SetPriority(UART7_IRQn, 4, 4);

 /* USER CODE END UART7_Init 2 */

}

static void MX_DMA_Init(void) 

{

 /* DMA controller clock enable */

 __HAL_RCC_DMA1_CLK_ENABLE();

 /* DMA interrupt init */

 /* DMA1_Stream1_IRQn interrupt configuration */

 HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);

 HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);

}

Inside UART5 ISR, I request data from UART7 something like below

HAL_UART_DeInit(&huart7);

HAL_UART_Init(&huart7);

(void)HAL_UART_Receive_DMA(&huart7, &encoder_buffer[0], (uint16_t)11);

Will be waiting for response, Thanks in advance

@STM32H743_User​ 

@STM32Techie​ 

@Human_STM32​ 

@Paul STM32_​ 

@Tilen MAJERLE​ 

@Community member​ 

@Community member​ 

@TDK​ 

@Community member​ 

@JoniS​ 

@Piranha​ 

@BSang​ 

4 REPLIES 4

Not sure it is necessary to tag me into conversations. I will note that I'm not a CubeMX adherent so unlikely to be able to help with issues around that, or the HAL's rat nest of call-backs and interactions, especially on the USART library.

U(S)ART+DMA does work on the H7, but cache-coherency is an ever present issue to be watched and managed.

Cache management is done on 32-byte boundaries, best to keep data within and aligned to that, and other unrelated data outside that scope.

I tend to prefer a scatter-gather method of USART TX DMA, and a continuous circular ring buffer for RX DMA, managing the DMA and IRQ directly in their respective handers.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

Thanks for answer @Community member​ . I added you here for this conversations because I saw you answering some of similar topics, one such was for BSang's questions. Your experience and knowledge was essential for me. 👏 👍

I tried that, but still issue remains same. Basically I need to reload DMA freshly after first reception complete.

Piranha
Chief II

The particular issue indeed seems to be related to D-cache. You can test it easily by not enabling the D-cache.

Take a note that most of the people, who develop something decent and reliable, don't use the buggy bloatware named HAL. Decent UART example can be found there:

https://github.com/MaJerle/stm32-usart-uart-dma-rx-tx

Hi @Piranha​,

Thanks for responding.

I tried disabling DCache and unfortunately when I do that, nothing works :( not even UART reception.

In that github link that you shared, which project exactly suites my application where only DMA reception is enough and everytime I need to reconfigure DMA to receive different number of bytes. Also how to reset DMA configuration to default after first usage?

thank again 🙂