Skip to main content
Graduate
January 28, 2024
Solved

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

  • January 28, 2024
  • 1 reply
  • 1431 views

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

 

 

 

    This topic has been closed for replies.
    Best answer by E-John

    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

    1 reply

    ST Employee
    January 29, 2024

    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.

    E-JohnAuthorAnswer
    Graduate
    January 31, 2024

    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