cancel
Showing results for 
Search instead for 
Did you mean: 

[STM32F401][HAL][UART DMA][QnA]

AjayMikrotroniks
Associate

Hey folks, I am using UART RX in DMA mode using 512 byte buffer. My code sippest working fine. I have one question.

Q. Suppose you have recevied 12 bytes but you have set 512 length so, rxCmplt() callback will not called. Right? But I wanted to stop UART RX DMA and don't wanted to waste this 12 bytes also. How I can archive this?

 

 

#include "main.h"
 
uint8_t UART1_rxBuffer[512] = {0};
 
UART_HandleTypeDef huart1;
 
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
 
int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART1_UART_Init();
 
    HAL_UART_Receive_DMA (&huart1, UART1_rxBuffer, 12);
 
    while (1)
    {
         if(BTN()){
            // I want to stop manually and read received data.
            // Assume that 5 bytes in DMA to read.
            HAL_UART_Abort();
         }
    }
 
}
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    HAL_UART_Transmit(&huart1, UART1_rxBuffer, 512, 100);
    HAL_UART_Receive_DMA(&huart1, UART1_rxBuffer, 512);
}

 

 

 
3 REPLIES 3
gbm
Lead III

I think it's generally a bad idea to use DMA for UART reception. It's much more difficult to design than ordinary "interrupt on character received" approach with a state machine. DMA reception is good if you have full control over what you receive. That's the case of SPI, ADC, usually I2C, but definitely nor UART. With UART, you must be ready for everything, like missing or unexpected data.

There is a good example of DMA UART RX by Tilen Majerle.

Guenael Cadier
ST Employee

Hi @AjayMikrotroniks 

In case of receiving data of unknown length, another option would be to implement something similar to what is shown in UART_ReceptionToIdle_CircularDMA example provided in STM32 Firmware packages.

Example for STM32F4 (but also provided on other STM32 series) could be found here.

This example shows use of HAL_UARTEx_ReceiveToIdle_DMA() API.

Using a circular DMA, this API allows user to get notified thanks to a HAL_UARTEx_RxEventCallback callback on 3 types of events :

   - HT (Half Transfer) : Half of Rx buffer is filled

   - TC (Transfer Complete) : Rx buffer is full.

     (In case of Circular DMA, reception could go on, and next reception data will be stored in index 0 of reception buffer by DMA).

   - Idle Event on Rx line : Triggered when RX line has been in idle state (normally high state) for 1 frame time, after last received byte.

On your use case, you should be able to use this mechanism for retrieving all received data from UART1 Rx, without need to abort. When your 12 bytes are received, and then an Idle time occurs, an IDLE event will occur.
Received data could be collected when HAL_UARTEx_RxEventCallback() will be executed.

Hope this could help.

In case of receiving data of unknown length...

On your use case...


So years later you are still spreading this disinformation even when it was explained to you particularly that there is no other case for UART interfaces:

https://community.st.com/t5/stm32-mcus-products/how-to-use-the-hal-uart-receive-it-within-a-function/m-p/242067/highlight/true#M54659

 

In case you think I'm wrong, show/describe for us a use case of any of the following three HAL functions with 8-bit data and a buffer size larger than a single byte, which is not broken - doesn't loose data in software and doesn't get stuck. @Guenael Cadier , I dare you!

HAL_UART_Receive();
HAL_UART_Receive_IT();
HAL_UART_Receive_DMA();