cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_UART_Transmit_DMA() trigger reset

QE-Nicholas
Associate II

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.

1 ACCEPTED SOLUTION

Accepted Solutions
QE-Nicholas
Associate II

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. 

View solution in original post

3 REPLIES 3
Saket_Om
ST Employee

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.
If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar
Karl Yamashita
Lead III

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.  

Don't worry, I won't byte.
TimerCallback tutorial! | UART and DMA Idle tutorial!

If you find my solution useful, please click the Accept as Solution so others see the solution.
QE-Nicholas
Associate II

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.