Search code examples
stm32uartdmabridgestm32f0

STM32 Uart Bridge


I am workin in a proyect where i need to make a bridge between to uart's. I am using the STM32F072CB Basically, all the data that I receive to the uart1 rx must be sent by uart2 tx. In the same way, what I receive in uart2 rx I must send through uart1 tx.(Both UARTs have the same baudrate). I am not aware of how much data I can receive on the rx uarts.

This is the idea

Uart1 rx --------> Uart2 tx
Uart1 tx <-------- Uart2 rx

I am using DMA with HAL_UARTEx_ReceiveToIdle_DMA to reduce cpu processing.

UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart2_rx;

#define RXBuffSize 10

uint8_t RxBuff1[RxBuffSize];
uint8_t RxBuff2[RxBuffSize];

int main(void)
{
HAL_Init();
SystemClock_Config();

MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();

HAL_UARTEx_ReceiveToIdle_DMA(&huart1,RxBuff1,RxBuffSize);
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);
HAL_UARTEx_ReceiveToIdle_DMA(&huart2,RxBuff2,RxBuffSize);
__HAL_DMA_DISABLE_IT(&hdma_usart2_rx,DMA_IT_HT);

while (1)
 {}
}

Here is my DMA interruption callback function

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    if (huart->Instance == USART1)
    {   
    HAL_UART_Transmit(&huart2,RxBuff1,RxBuffSize,1);
    HAL_UARTEx_ReceiveToIdle_DMA(&huart1,RxBuff1,RxBuffSize);
    __HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);
    } 
    else if (huart->Instance == USART2)
    {
    HAL_UART_Transmit(&huart1,RxBuff2,RxBuffSize,1);
    HAL_UARTEx_ReceiveToIdle_DMA(&huart2,RxBuff2,RxBuffSize);
    __HAL_DMA_DISABLE_IT(&hdma_usart2_rx,DMA_IT_HT);
    }
}

The code runs when the data input to rx is low. If I send too much data in the tx of the other uart I get the first bytes but lose the last ones. I also tried doing the RXBuffSize = 1 , that is to say receive a character and send it but I get the same result.


Solution

  • Because HAL_UART_Transmit operates in a "polling" method, it stops at the point until all strings are transmitted.

    Therefore, if another string comes in while HAL_UART_Transmit is being executed, the interrupt is not executed and the entered string is lost.

    After activating the TX DMA of each uart in cubemx, try applying the code as shown below.

    #include <string.h>
    
    uint8_t TxBuff1[RxBuffSize];
    uint8_t TxBuff2[RxBuffSize];
    
    void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
    {
        Size = Size > RxBuffSize ? RxBuffSize : Size;
    
        if (huart->Instance == USART1)
        {   
            memcpy(TxBuff2, RxBuff1, Size);
            HAL_UART_Transmit_DMA(&huart2, TxBuff2, Size);
            HAL_UARTEx_ReceiveToIdle_DMA(&huart1, RxBuff1, RxBuffSize);
            __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
        } 
        else if (huart->Instance == USART2)
        {
            memcpy(TxBuff1, RxBuff2, Size);
            HAL_UART_Transmit_DMA(&huart1, TxBuff1, Size);
            HAL_UARTEx_ReceiveToIdle_DMA(&huart2, RxBuff2, RxBuffSize);
            __HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);
        }
    }
    

    Transmitting RxBuff directly is dangerous. When a character is received from the UART while sending, an incorrect value may be sent by the TX DMA because RX DMA changes the value in the corresponding memory.

    Therefore, when RX DMA is deactivated, it is better to enable it after copying the corresponding memory value to another location.