cancel
Showing results for 
Search instead for 
Did you mean: 

STM32CubeMX and BUG in UART_DMATransmitCplt

Davydenko.Sergey
Associate II
Posted on November 02, 2015 at 12:53

STM32CubeMX V4.11

STM32Cube FW_F4 V1.9.0

/**

  ******************************************************************************

  * @file    stm32f4xx_hal_uart.c

  * @author  MCD Application Team

  * @version V1.4.1

  * @date    09-October-2015

  * @brief   UART HAL module driver.

  *          This file provides firmware functions to manage the following 

  *          functionalities of the Universal Asynchronous Receiver Transmitter (UART) peripheral:

  *           + Initialization and de-initialization functions

  *           + IO operation functions

  *           + Peripheral Control functions  

  *           + Peripheral State and Errors functions  

  *           

  @verbatim       

.......

/**

  * @brief  DMA UART transmit process complete callback. 

  * @param  hdma: DMA handle

  * @retval None

  */

static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)

{

  UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;

  /* DMA Normal mode*/

  if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)

  {

    huart->TxXferCount = 0;

    /* Disable the DMA transfer for transmit request by setting the DMAT bit

       in the UART CR3 register */

    huart->Instance->CR3 &= (uint32_t)~((uint32_t)USART_CR3_DMAT);

    /* Enable the UART Transmit Complete Interrupt */

    __HAL_UART_ENABLE_IT(huart, UART_IT_TC);

  }

  /* DMA Circular mode */

  else

  {

    HAL_UART_TxCpltCallback(huart);

  }

}

very similar to that lacks the following code fragment:

    if(huart->State == HAL_UART_STATE_BUSY_TX_RX) 

    {

      huart->State = HAL_UART_STATE_BUSY_RX;

    }

    else

    {

      huart->State = HAL_UART_STATE_READY;

    }

as in

/**

  * @brief  DMA UART receive process complete callback. 

  * @param  hdma: DMA handle

  * @retval None

  */

static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma)  

{

  UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;

  /* DMA Normal mode*/

  if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)

  {

    huart->RxXferCount = 0;

  

    /* Disable the DMA transfer for the receiver request by setting the DMAR bit 

       in the UART CR3 register */

    huart->Instance->CR3 &= (uint32_t)~((uint32_t)USART_CR3_DMAR);

    /* Check if a transmit process is ongoing or not */

    if(huart->State == HAL_UART_STATE_BUSY_TX_RX) 

    {

      huart->State = HAL_UART_STATE_BUSY_TX;

    }

    else

    {

      huart->State = HAL_UART_STATE_READY;

    }

  }

  HAL_UART_RxCpltCallback(huart);

}

7 REPLIES 7
Posted on November 02, 2015 at 16:14

Hi davydenko.sergey,

Did you face any problem when running this code? Could you please explain the reason for giving your proposal?

Kind regards,

-Shahrzad-

Davydenko.Sergey
Associate II
Posted on November 04, 2015 at 18:25

Hello Shahrzad

Yes, I have encountered this problem.

When the DMA USART used in normal mode and a data packet sent by the DMA periodically.

Dispatched only the first packet and a single.

HAL_UART_Transmit_DMA (...)

All subsequent attempts to send a packet, return status HAL_BUSY.

When sending a packet status is set

huart-> State = HAL_UART_STATE_BUSY_TX_RX

or

huart-> State = HAL_UART_STATE_BUSY_TX

This status after completion of sending must be changed to

HAL_UART_STATE_BUSY_RX

or

HAL_UART_STATE_READY

Otherwise, the next attempt to send the packet does not lead to the desired result.

It is necessary to fix the problem in the procedure 

UART_DMATransmitCplt

and also the procedure

HAL_UART_TxCpltCallback (huart)

It will be carried out only in the case of circular DMA that is not right ...

May be next:

static void USER_UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)

{

  UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;

  /* DMA Normal mode*/

  if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)

  {

    huart->TxXferCount = 0;

    /* Disable the DMA transfer for transmit request by setting the DMAT bit

       in the UART CR3 register */

    huart->Instance->CR3 &= (uint32_t)~((uint32_t)USART_CR3_DMAT);

    /* Check if a recieve process is ongoing or not */

    if(huart->State == HAL_UART_STATE_BUSY_TX_RX) 

    {

      huart->State = HAL_UART_STATE_BUSY_RX;

    }

    else

    {

      huart->State = HAL_UART_STATE_READY;

    }

  }

  

  HAL_UART_TxCpltCallback(huart);

}

It worked!!!

But maybe I'm wrong ...

Kind regards,

Sergei Davydenko

Posted on January 28, 2016 at 15:14

Hi davydenko.sergey,

The issue is already treated by our development team, and modifications will be delivered in next releases of STM32Cube.

-Shahrzad-

kaihofmann
Associate II
Posted on June 08, 2016 at 16:10

Hello Shahrzad

,

using the current version of STM32CubeMX 4.15.0 and FWV 1.12.0 the problem is still there (stm32f4xx_hal_uart.c, MCD Application Team, version V1.5.0).

I fixed the UART_DMATransmitCplt function in the same way as Sergey did (just replaced huart->state by huart->gstate) ...and DMA transmit works.

I wonder what is the intended way to make the ''normal DMA'' mode work from scratch? Or did you just missed to fix this bug in this release?

Best regards,

Kai

Amel NASRI
ST Employee
Posted on June 08, 2016 at 16:24

Hi hofmann.kai,

This is not a bug, but you need to enable the USART handler in the it.c file to handle the transfer complete.

You may find more explanation in [DEAD LINK /public/STe2ecommunities/mcu/Lists/STM32Java/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/STM32Java/HAL%20Without%20USART%20interrupt%2c%20HAL_UART_Transmit_DMA%28%29%20will%20work%20only%20once&FolderCTID&currentviews=64]this discussion.

-Mayla-

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

kaihofmann
Associate II
Posted on June 09, 2016 at 11:36

Hi Mayla,

thank you Mayla, for your fast reply. I read the article, but honestly I do not understand where to enable/realize the handler exactly.

Could you please give me some example code?

Thanks in advance.

Kai

Amel NASRI
ST Employee
Posted on June 09, 2016 at 15:37

Hihofmann.kai,

I suggest you refer to any USART example using DMA (Ex:STM32Cube_FW_F4_V1.0\Projects\STM32F4-Discovery\Examples\UART\UART_TwoBoards_ComDMA).

You can see that in the file stm32f4xx_it.c we have:

/**

* @brief This function handles DMA RX interrupt request.

* @param None

* @retval None

*/

void

USARTx_DMA_RX_IRQHandler(

void

)

{

HAL_DMA_IRQHandler(UartHandle.hdmarx);

}

/**

* @brief This function handles DMA TX interrupt request.

* @param None

* @retval None

*/

void

USARTx_DMA_TX_IRQHandler(

void

)

{

HAL_DMA_IRQHandler(UartHandle.hdmatx);

}

/**

* @brief This function handles USARTx interrupt request.

* @param None

* @retval None

*/

void

USARTx_IRQHandler(

void

)

{

HAL_UART_IRQHandler(&UartHandle);

}

-Mayla-

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.