cancel
Showing results for 
Search instead for 
Did you mean: 

I have UART1 and UART2 configured. I am looking to bridge the two together. UART2 (115200) & UART1 (9600). UART2 (PC VIA USB) and UART1 [DMA, Circular (word)] (Connected to external device UART interface).

Ghomi.1
Associate

Code snippet

```while (1) {

         HAL_UART_Receive_DMA (&huart1, UART1_rxBuffer, 100);

         HAL_UART_Transmit (&huart2,UART1_rxBuffer,sizeof(UART1_rxBuffer),100)}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

{

 uint8_t UART1_rxBuffer[100] = {0};

 HAL_UART_Transmit(&huart1, UART1_rxBuffer, 100, 10);

 HAL_UART_Receive_DMA(&huart1, UART1_rxBuffer, 100);

}

```

I am seeing output over UART2 however it looks to be mismatch in either BAUD or just being truncated because I am not using buffers correctly ?

Also I am attempting to change BAUD on uart1 using a menu, will this work ?

Code Snippet

```

   if (*baudrate == '1') { <-----variable baudrate is user defined to capture menu choice

      huart1.Init.BaudRate = 9600;

      valid = 1;

      uint8_t baud9600[] = "\r\n[Baud Rate set to 9600]\r\n";

      HAL_UART_Transmit(&huart2,baud9600,sizeof(baud9600),100);

      HAL_Delay(1000);

```

Any Advice would be great !

3 REPLIES 3
S.Ma
Principal

Well, in bare metal, I would use SW FIFO using a RAM buffer to manage the chocking intermittent communication between 2 asynchroneous serializers. You have the same kind of challenge from USART to SPI, USART to I2C, etc...

here, in u8fifo.c is one implementation of SW fifo. It is a bit richer than it needs to be so statistics can be done to size optimize the buffer from application test in condition.

There is one fifo per data flow direction, one for RX to TX, one for TX to RX.

SIF.C is a bluetooth electronics android app using Bluetooth Serial to make your phone as remote control and remote display, and can also be used to forward from BT.USART to Application.USART.

Maybe it gives some ideas?

KnarfB
Principal III

HAL_UART_Transmit is blocking in the interrupt handler, so you may miss chars before the next Receive.

Never use local (stack) variables as DMA buffers, because DMA runs ansynchronously and your function (handler) will return and the stack space used otherwise before DMA finishes.

If you can use the Cortex core up to its limits, simply copy from one UARTs RDR to other UARTs TDR like:

while (1)
  {
    if( USART2->ISR & USART_ISR_RXNE ) {
      char c = USART2->RDR & 0xFF;
      while( (USART2->ISR & USART_ISR_TXE) == 0 );
        USART2->TDR = c;
    }
  }

but symmetrically for either side.

If you want spare the core and use DMA, use circular DMA with a global buffer (per UART) for receiving and send the received portion of the buffer in the RxHalfCpltCallback and HAL_UART_RxCpltCallback callbacks.

[Edit): https://github.com/MaJerle/stm32-usart-uart-dma-rx-tx

hth

KnarfB

Guenael Cadier
ST Employee

Hi @Ghomi.1​ 

Another option would be to implement something similar to what is shown in UART_ReceptionToIdle_CircularDMA example provided in STM32 Firmware packages.

Example for STM32G0 (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 reception on UART1, and manage the sending of received data on UART2 inside the HAL_UARTEx_RxEventCallback(), using either it or DMA process to no interfere or block the reception.

Regards