0
votes

is there a simple way to "bridge" 2 U(S)ART Lines (USART1 & UART5 on STM32F107) by software?

I need to forward the data which are incoming at USART1 to the UART5 and reverse.

Current MCU is STM32F107VCT7

Main reason why I want to do that is to update a Device over UART which is connected to my MCU. The MCU is connected to PC.

PC --- STM32 --- Other Device

3
If both I/O lines of each UART are connected to the other, where is the data coming from? - Lee Daniel Crocker
No both uart lines connected to ST32, the ST32 have to handle the Data forwarding. The Connection is Like: PC - ST32 - other Device - guenthernagel
Are the 2 UARTs operating (nominally) at the same baudrate? - followed Monica to Codidact
I need to update a UART Device, but my STM32 is between pc and the other device. PC --- STM -- Other Device A direct connection is not possible - guenthernagel
@berendi Haha, dont worry that's not the only task of the MCU. But the environment do not allow a direct connection from the other device and the PC. - guenthernagel

3 Answers

1
votes

Could you just write the data the data to the appropriate usart registers? That is, if you have a byte come through on the usart1 line and it is stored in the usart1 data register, read it and write it to the usart5 data register and set the bit to let the chip know it is ready transfer the byte. Do the same for the usart5 to usart1 bridge.

If you are concerned about reading/writing multiple bytes consider adding transmit and receive buffers to handle this.

If we were to do a polling method, the code would look something like (note: I mainly deal with AVR so I may be off with my register names but the method should be along these lines):



// Check to see if data has been written to usart1 and transfer it usart5.
if(USART1_CR1&(1 << USART1_SR_RXNE))
{
    // May want to avoid race conditions, so disable interrupts.
    // Write the data in usart1 to usart5
    USART5_DR = USART1_DR;

    // Set the data ready bit on the usart5 control register.
    USART5_CR1 |= (1 << USART_SR_RXNE);
    // Enable interrupts.
}

I used this tutorial for STM32 language. Not the point about disabling interrupts. You may also want to write to a buffer.

0
votes

Simply copying bytes from one UART to the other will not work.

If the sending side (PC serial adapter) is just by 0.1% faster than the MCU, it will start dropping bytes after the 1000th byte. The frequency accuracy of the STM32F107 internal clock is given as -1.1% to +1.8% at room temperature in the datasheet, so it might as well happen earlier, and the other two participants might not be perfectly accurate either.

Dropping bytes in the middle of a firmware update to an otherwise inaccessible part is not going to be funny.

You need circular (FIFO) buffers both ways

The size of the buffer is determined by the size of the data packets, and the sum of the frequency inaccuracies in the participating devices. E.g. if there is 64 kB data in one block, and both devices have +/- 2% frequency accuracy, then you'd need at least 65536*0.04 ~ 2622 bytes buffer.

Do this in an endless loop,

  • check for RXNE in USART1->SR
  • if set, read the data from USART1->DR and put it at the head of the buffer (complain loudly if the buffer is full)
  • check for TXE in UART5->SR`
  • if set, AND the buffer is not empty, write the byte at the tail of the buffer into UART5->DR
  • do the same for the other direction
0
votes

Simple both way communication method assuming the same speed of the both UARTs.

volatile uint8_t data[2];

void USART1_IRQHandler(void)
{
    if(USART1 -> SR & USART_SR_RXNE)
    {
        data[0] = USART1 -> DR;
        USART5 -> CR1 |= USART_CR1_TXEIE;
    }

    if( (USART1 -> CR1 & USART_CR_TXEIE) && (USART1 -> SR & USART_SR_TXE))
    {
        USART1 -> CR1 &= ~USART_CR1_TXEIE;
        USART1 -> DR = data[1];
    }
}

void USART5_IRQHandler(void)
{
    if(USART5 -> SR & USART_SR_RXNE)
    {
        data[1] = USART5 -> DR;
        USART1 -> CR1 |= USART_CR1_TXEIE;
    }

    if( (USART5 -> CR1 & USART_CR_TXEIE) && (USART5 -> SR & USART_SR_TXE))
    {
        USART5 -> CR1 &= ~USART_CR1_TXEIE;
        USART5 -> DR = data[0];
    }
}