Skip to main content
Explorer II
February 7, 2025
Solved

HAL_UART_Transmit_DMA() trigger reset

  • February 7, 2025
  • 3 replies
  • 693 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

    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.
    Graduate II
    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.  

    QE-NicholasAuthorAnswer
    Explorer 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.