STM32 The HAL UART Transmit DMA function does not work

Stone STM32F103C8, create a project in CubeMX, configure standard-USART2 in Asynchronous mode, activate its global interrupt, create a DMA channel:Creating a DMA channel

I generate a project and add the following code to while:

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
      HAL_UART_Transmit_DMA(&huart2, buff, 100);
      HAL_Delay(100);
  }

I compile, flash and... nothing! On the Tx leg, the level is always high, no hint of transmission. At the same time, the HAL_UART_Transmit_IT function works perfectly, the same code with a similar setting works on STM32F407VG(Discovery). I tried other stones F103C8, tried in different places to call HAL_UART_Abort, HAL_DMA_Abort-without success.


Noticed that immediately after calling HAL_UART_Transmit_DMA, the DMA interrupt handler is called, in which HAL gives a verdict that the transfer is complete, what would that mean? HAL broke down?


P.S. Here is the initialization code for USART-a and DMA

static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 100;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_2;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */

}

/** 
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void) 
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel7_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);

}
 0
Author: Артём, 2020-03-03

1 answers

DMA is not initialized in your code. Below is a piece of my code:

void StandardUart::initialize()
{

    ...
    // инициализируем сам Uart
    mHUart->Init.BaudRate = UART_BAUD_RATE;
    mHUart->Init.WordLength = UART_WORDLENGTH_8B;
    mHUart->Init.StopBits = UART_STOPBITS_1;
    mHUart->Init.Parity = UART_PARITY_NONE;
    mHUart->Init.Mode = UART_MODE_TX_RX;
    mHUart->Init.HwFlowCtl = UART_HWCONTROL_NONE;
    mHUart->Init.OverSampling = UART_OVERSAMPLING_16;

    //NOTE: Покамест оставил без дополнительной инициаизации
    // DMA initialization
    /* DMA controller clock enable */
    __HAL_RCC_DMA1_CLK_ENABLE();

    /*##-3- Configure the DMA ##################################################*/
    /* Configure the DMA handler for Transmission process */
    static DMA_HandleTypeDef hdma_tx; //никуда не должен деться
    hdma_tx.Instance                 = DMA1_Channel4;
    hdma_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
    hdma_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
    hdma_tx.Init.MemInc              = DMA_MINC_ENABLE;
    hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_tx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
    hdma_tx.Init.Mode                = DMA_NORMAL;
    hdma_tx.Init.Priority            = DMA_PRIORITY_LOW;

    HAL_DMA_Init(&hdma_tx);

    /* Associate the initialized DMA handle to the UART handle */
    __HAL_LINKDMA(mHUart, hdmatx, hdma_tx);

    /* Configure the DMA handler for reception process */
    static DMA_HandleTypeDef hdma_rx;
    hdma_rx.Instance                 = DMA1_Channel5;
    hdma_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
    hdma_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
    hdma_rx.Init.MemInc              = DMA_MINC_ENABLE;
    hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_rx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
    hdma_rx.Init.Mode                = DMA_CIRCULAR;
    hdma_rx.Init.Priority            = DMA_PRIORITY_HIGH;

    HAL_DMA_Init(&hdma_rx);
    /* Associate the initialized DMA handle to the the UART handle */
    __HAL_LINKDMA(mHUart, hdmarx, hdma_rx);


    /* DMA interrupt init */
    /* DMA1_Channel4_IRQn interrupt configuration */
    HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
    /* DMA1_Channel5_IRQn interrupt configuration */
    HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);

    // UART initialization
    // подключаем тактирование самого USART
    IRQn_Type Irq = USART1_IRQn;
    if (mHUart->Instance == USART2){
        __HAL_RCC_USART2_CLK_ENABLE();
        Irq = USART2_IRQn;
    }
    if (mHUart->Instance == USART3){
        __HAL_RCC_USART3_CLK_ENABLE();
        Irq = USART3_IRQn;
    }

    HAL_UART_DeInit(mHUart);
    HAL_UART_Init(mHUart);

    /* Peripheral interrupt init */
    HAL_NVIC_SetPriority(Irq, 0, 0);
    HAL_NVIC_EnableIRQ(Irq);

    HAL_UART_Receive_DMA(mHUart,
                         mRxBuffer,
                         MaxBufferSize);
} 

What is visible:

  • no DMA initialization. HAL_DMA_Init(&hdma_tx)
  • no DMA linking with UART __HAL_LINKDMA(mHUart, hdmatx, hdma_tx)
  • I don't see UART clocking enabled in the code __HAL_RCC_USART2_CLK_ENABLE();
 2
Author: Roman Ozhegov, 2020-03-03 13:59:35