Skip to main content
Associate II
February 7, 2025
Solved

HAL_UART_Transmit_DMA() trigger reset

  • February 7, 2025
  • 3 replies
  • 724 views

Hi guys, I was trying to implement HAL_UART_Transmit_DMA() since I am using freeRTOS. It auto trigger a reset for my stm32f427.

Tried HAL_UART_Transmit(), everything works well. Only HAL_UART_Transmit_DMA() causing the reset, Did I missed anything?

 

			 for (uint8_t j=1; j!=CPH_MAX_N_PORTS; ++j)													// can change to +1 after disabling drone troubleshoot port
			 {
				 if(byte_1 == j)
				 {
						if ((ports_handle[j-1])->hdmatx == NULL)
						{
						 USER_LOG_ERROR("TX DMA not linked for UART!");
						}
						HAL_UART_DMAStop(ports_handle[j-1]); 												// Stop RX DMA before TX
					 ports_handle[j-1]->gState = HAL_UART_STATE_READY;
					 __HAL_DMA_ENABLE_IT(ports_handle[j-1]->hdmatx, DMA_IT_TC); 						// TX Complete Interrupt
					 __HAL_DMA_ENABLE_IT(ports_handle[j-1]->hdmatx, DMA_IT_TE); 						// TX Error Interrupt
					 if (ports_handle[j-1]->hdmatx == NULL) {
					 USER_LOG_ERROR("TX DMA not linked for UART!");
					 }

					 if (ports_handle[j-1]->gState != HAL_UART_STATE_READY) {
					 USER_LOG_ERROR("UART TX is busy (State: %d)", ports_handle[j-1]->gState);
					 }

					 if (!(ports_handle[j-1]->hdmatx->Instance->CR & DMA_SxCR_TCIE)) {
					 USER_LOG_WARN("TX DMA Interrupts not enabled! Enabling now...");
					 __HAL_DMA_ENABLE_IT(ports_handle[j-1]->hdmatx, DMA_IT_TC);
					 __HAL_DMA_ENABLE_IT(ports_handle[j-1]->hdmatx, DMA_IT_TE);
					 }
					 USER_LOG_INFO("UART TX State: %d", HAL_UART_GetState(ports_handle[j-1]));
						if (HAL_UART_GetState(ports_handle[j-1]) == HAL_UART_STATE_READY)
						{
							 if(HAL_UART_Transmit(ports_handle[j-1], USB_recv_buf+cur_msg_pos+MSD_HEADER, totalBufLen-MSD_HEADER,10) != HAL_OK) // forward the buffer
							 {
								 USER_LOG_ERROR("UART transmission failed for port %d!", j); 				
							 }
						}
						else
						{
							USER_LOG_ERROR("UART transmission busy for port %d!", j);
							USER_LOG_ERROR("UART state -> %d!", HAL_UART_GetState(ports_handle[j-1]));
						}
						HAL_UARTEx_ReceiveToIdle_DMA(ports_handle[j-1], DMARxBuf[j], BUFFER_SIZE);			// restart the DMA
						__HAL_DMA_DISABLE_IT(DMAs_handle[j-1],DMA_IT_HT);									// disable the interrupt as we don’t need the Half Transfer interrupt
						valid_port_found = true;
						break;
				 }
			 }

 

* none of the error log was triggered. Initially, I tried without the non-essential code as below and I got the state value of 0x22 which is HAL_UART_STATE_BUSY_RX and that is why I am adding those extra lines of code.

 

						if (HAL_UART_GetState(ports_handle[j-1]) == HAL_UART_STATE_READY)
						{
							 if(HAL_UART_Transmit(ports_handle[j-1], USB_recv_buf+cur_msg_pos+MSD_HEADER, totalBufLen-MSD_HEADER,10) != HAL_OK) // forward the buffer
							 {
								 USER_LOG_ERROR("UART transmission failed for port %d!", j); 				
							 }
						}
						else
						{
							USER_LOG_ERROR("UART transmission busy for port %d!", j);
							USER_LOG_ERROR("UART state -> %d!", HAL_UART_GetState(ports_handle[j-1]));
						}

 

From my perspective, DMA for RX works fine, which I do receive what I want. Only calling the following will cause the HAL_UART_Transmit_DMA() reset:

 

HAL_UART_DMAStop(ports_handle[j-1]); 

 

The line of code when calling HAL_UART_Transmit_DMA:

 

if(HAL_UART_Transmit_DMA(ports_handle[j-1], USB_recv_buf+cur_msg_pos+MSD_HEADER, totalBufLen-MSD_HEADER) != HAL_OK)

 

OR should I ask what is the correct way to do this if we detect HAL_UART_STATE_BUSY_RX.

This topic has been closed for replies.
Best answer by QE-Nicholas

Thanks everyone for the help, I think I have found the issue>

HAL_UART_Transmit_DMA(ports_handle[j-1], USB_recv_buf+cur_msg_pos+MSD_HEADER, totalBufLen-MSD_HEADER)

is reading on the buffer and I am continuing parsing the buffer in the loop.

My hypothesis, 
since it is not a blocking function, and the cur_msg_pos is continuously incrementing while I parsing the message, the system might read random memory causing overflow and reset.

Solution:
Make a copy for everything AND place a flag within HAL_UART_TxCpltCallback()
Then check for the flag before sending stuff. 

3 replies

ST Technical Moderator
February 10, 2025

Hello @QE-Nicholas 

>> Hi guys, I was trying to implement HAL_UART_Transmit_DMA() since I am using freeRTOS. It auto trigger a reset for my stm32f427.

  1. What do you mean by "reset"? Is it a system reset?
  2. Did you try to run the UART transfer without FreeRTOS, please?

>> OR should I ask what is the correct way to do this if we detect HAL_UART_STATE_BUSY_RX.

  1. You should investigate if the bus is really busy (A transfer is ongoing).
  2. Also, you need to be sure that the process before calling HAL_UART_Transmit_DMA is done correctly and the state is reset to ready.
In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Saket_Om
Karl Yamashita
Principal
February 11, 2025

Did you enable the DMA for Transmit? I know I've forgotten to enable it for transmit. Though I vaguely remember it hard faulting, not resetting the STM32.  

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
QE-NicholasAuthorBest answer
Associate II
February 11, 2025

Thanks everyone for the help, I think I have found the issue>

HAL_UART_Transmit_DMA(ports_handle[j-1], USB_recv_buf+cur_msg_pos+MSD_HEADER, totalBufLen-MSD_HEADER)

is reading on the buffer and I am continuing parsing the buffer in the loop.

My hypothesis, 
since it is not a blocking function, and the cur_msg_pos is continuously incrementing while I parsing the message, the system might read random memory causing overflow and reset.

Solution:
Make a copy for everything AND place a flag within HAL_UART_TxCpltCallback()
Then check for the flag before sending stuff.