cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G0B1 USART3 DMA receiving whole data and set it to application layer for process on FreeRTOS?

E-John
Associate III

Dear SIR,

I am trying to STM32G0B1 USART3 DMA receiving data from PC and do processing on MCU.

I add code in callback function HAL_UARTEx_RxEventCallback()

these code are try to get the whole package ending with '\r' and set a flag to notice the FreeRTOS get the whole package and do process in FreeRTOS.

After running some times, No more flag set in the callback. In my test, 1st send "test", 2nd send "this is a test of stm32", 2nd callback is not triggerred.

Is there any wrong? Or what is the right procedure to get the whole package in DMA callback and set flag to FreeRTOS Application layer to do future process?

Thanks.

 

 

 

#include "stm32g0xx_hal.h"
#include "FreeRTOS.h"
#include "task.h"
#include "stm32g0xx_hal_uart_ex.h"
#include "stm32g0xx_hal_dma.h"

#define RX_BUFFER_SIZE 128

extern UART_HandleTypeDef huart3;
extern DMA_HandleTypeDef hdma_usart3_rx;

uint8_t rx_buffer[RX_BUFFER_SIZE];
uint8_t cmd_terminated = 0;
volatile uint8_t rx_size = 0;

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
  /* Prevent unused argument(s) compilation warning */
  //UNUSED(huart);
  //UNUSED(Size);
  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_UARTEx_RxEventCallback can be implemented in the user file.
   */
  if (huart->Instance == USART3)
  {
    if (huart->RxEventType == HAL_UART_RXEVENT_IDLE) {
      rx_size = Size;
      //HAL_UART_Transmit_DMA(&huart3, rx_buffer, RX_BUFFER_SIZE);
      if (Size <= RX_BUFFER_SIZE) {
        HAL_UARTEx_ReceiveToIdle_DMA(&huart3, rx_buffer, Size);
        __HAL_DMA_DISABLE_IT(&hdma_usart3_rx, DMA_IT_HT);

        cmd_terminated = 1;
      }
    }
  }
}

void PCUartTask(void const * argument)
{
    /* init code for USART3 */
    //MX_USART3_UART_Init();
    /* init code for DMA */
    //MX_DMA_Init();
    /* Start receiving data over UART in DMA mode */
    HAL_UARTEx_ReceiveToIdle_DMA(&huart3, rx_buffer, RX_BUFFER_SIZE);
    __HAL_DMA_DISABLE_IT(&hdma_usart3_rx, DMA_IT_HT);

    for(;;)
    {
        char *cmd;
        char *arg;

        /* Check if we received any data */
        if (cmd_terminated == 1)
        {
            HAL_UART_Transmit_DMA(&huart3, rx_buffer, rx_size);

            /* Reset the UART state */
            cmd_terminated = 0;
        }
    }
}

 

EJohn_0-1706420440960.png

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions

Hi Sarra,

It works after changing below,

 

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    if (huart->Instance == USART3)
    {
        // Update the write pointer
        taskENTER_CRITICAL();
        wr_pointer = Size;
        HAL_UARTEx_ReceiveToIdle_DMA(&huart3, (uint8_t *)ring_buffer, BUFFER_SIZE);
        taskEXIT_CRITICAL();
    }
}

void PCUartTask(void *pvParameters) {

    HAL_UARTEx_ReceiveToIdle_DMA(&huart3, (uint8_t *)ring_buffer, BUFFER_SIZE);

    while (1) {
        if (wr_pointer != rd_pointer) {
            taskENTER_CRITICAL();
            char c = ring_buffer[rd_pointer++];
            HAL_UART_Transmit_DMA(&huart3, ring_buffer, wr_pointer);
            if (rd_pointer == BUFFER_SIZE) {
                rd_pointer = 0;
            }
            taskEXIT_CRITICAL();
            // Process the character c

            taskENTER_CRITICAL();
            wr_pointer = rd_pointer;
            taskEXIT_CRITICAL();
        }
        vTaskDelay(pdMS_TO_TICKS(10)); // Delay for 10ms
    }
}

 

STM32_UART_USING_DMA.gif

View solution in original post

2 REPLIES 2
Sarra.S
ST Employee

Hello @E-John 

The code for HAL_UARTEx_ReceiveToIdle_DMA() will enable the IDLEIE bit, hence enable the IDLE interrupt source within the UART instance. Now, to be generated and processed, the UART IRQ on the NVIC side must also be activated.

Have you enabled the USART3 interrupt in NVIC? 

If you generate your code using the STM32CubeMx tool, make sure to do so in your UART settings panel.

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.

Hi Sarra,

It works after changing below,

 

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    if (huart->Instance == USART3)
    {
        // Update the write pointer
        taskENTER_CRITICAL();
        wr_pointer = Size;
        HAL_UARTEx_ReceiveToIdle_DMA(&huart3, (uint8_t *)ring_buffer, BUFFER_SIZE);
        taskEXIT_CRITICAL();
    }
}

void PCUartTask(void *pvParameters) {

    HAL_UARTEx_ReceiveToIdle_DMA(&huart3, (uint8_t *)ring_buffer, BUFFER_SIZE);

    while (1) {
        if (wr_pointer != rd_pointer) {
            taskENTER_CRITICAL();
            char c = ring_buffer[rd_pointer++];
            HAL_UART_Transmit_DMA(&huart3, ring_buffer, wr_pointer);
            if (rd_pointer == BUFFER_SIZE) {
                rd_pointer = 0;
            }
            taskEXIT_CRITICAL();
            // Process the character c

            taskENTER_CRITICAL();
            wr_pointer = rd_pointer;
            taskEXIT_CRITICAL();
        }
        vTaskDelay(pdMS_TO_TICKS(10)); // Delay for 10ms
    }
}

 

STM32_UART_USING_DMA.gif