Uart bit banging code

Thread Starter

Vindhyachal Takniki

Joined Nov 3, 2014
594
I have made below code. Task is to transmit data to/from two uarts.
One uart is at 9600 baud & other is at 115200 baud.
Whatever data is received at one uart is to be sent to other uart & vice versa.
MCU is 32 bit cortex M3 with two hardware uart's & core is running at 16Mhz.
Have implemented two circular buffers , each of size 27K. Data length could be upto 500KB in one go.
Data is always 1 strt,8-data & 1 stop.

1. Currently I have roughly taken 27K buffer. But how to calcualte how much buffer exactly should be required.
For example, in case of 9600 baud, I will rx 960 bytes of data in 1 sec & 11520 bytes in other uart.

2. Initillay only rx int of both uarts are enabled. Tx int are enabled only when there is data in buffer, & disabled again when head=tail.

C:
const uint32_t g_arr_size = 27648U;
volatile uint8_t g_9600_arr[g_arr_size];
volatile uint32_t g_9600_head;
volatile uint32_t g_9600_tail;

volatile uint8_t g_115200_arr[g_arr_size];
volatile uint32_t g_115200_head;
volatile uint32_t g_115200_tail;



void init_both_uarts(void)
{
    uart2_9600_baud();
    uart2_rx_int_enable();
    uart2_tx_int_disable();

    uart1_115200_baud();
    uart1_rx_int_enable();
    uart1_tx_int_disable();  
  
}

void uart1_isr(void)
{
    uint16_t data;
    uint32_t next_head;
  
/* if data is rx */
    if(uart1_data_rx_nt_full())
    {  
    /* read data */
        data = READ_UART1_DATA();
  
    /* store data in array */  
        /* inc the head cnt */
        next_head = g_115200_head++;
        if(next_head >= g_arr_size)
        {
            next_head = 0U;
        }  
  
        /* check if there is room */
        if(next_head != g_115200_tail)
        {
            g_115200_arr[g_115200_head] = data;
            g_115200_head = next_head;
      
            /* enable other uart interrupt */
            ENABLE_UART2_INT_TX();
        }  
        else
        {
            /* diacrd the byte */
        } 
    }
/* if data is tx */
    if(uart1_data_tx_empty())
    {  
    /* remove the byte from array */
        if(g_9600_head != g_9600_tail)
        {
            while( !UART2_WHILE_TXE_COMPLETE );
            WRITE_UART2_DR_REG( g_9600_arr[g_9600_tail] );

            g_9600_tail++;
            if(g_9600_tail >= g_arr_size)
            {
                g_9600_tail = 0U;
            }  
        } 
    /* disable uart int tx */
        else
        {
            DISABLE_UART1_INT_TX();
        }  
    }  
     
}


void uart2_isr(void)
{
    uint16_t data;
    uint32_t next_head;
  
/* if data is rx */
    if(uart2_data_rx_nt_full())
    {  
    /* read data */
        data = READ_UART2_DATA();
  
    /* store data in array */  
        /* inc the head cnt */
        next_head = g_9600_head++;
        if(next_head >= g_arr_size)
        {
            next_head = 0U;
        }  
  
        /* check if there is room */
        if(next_head != g_9600_tail)
        {
            g_9600_arr[g_9600_head] = data;
            g_9600_head = next_head;
      
            /* enable other uart interrupt */
            ENABLE_UART1_INT_TX();
        }  
        else
        {
            /* diacrd the byte */
        } 
    }
/* if data is tx */
    if(uart2_data_tx_empty())
    {  
    /* remove the byte from array */
        if(g_115200_head != g_115200_tail)
        {
            while( !UART1_WHILE_TXE_COMPLETE );
            WRITE_UART1_DR_REG( g_115200_arr[g_115200_tail] );

            g_115200_tail++;
            if(g_115200_tail >= g_arr_size)
            {
                g_115200_tail = 0U;
            }  
        } 
    /* disable uart int tx */
        else
        {
            DISABLE_UART2_INT_TX();
        }  
    }  
     
}
 
Last edited by a moderator:

NorthGuy

Joined Jun 28, 2014
611
You only need a buffer sending from fast to slow. Slow to fast can go straight through. It is easy to calculate the size. If you want to accept a continuous burst of 500KB, it will take about 50 sec to receive at 11520. During this time, the 9600 line will be able to send out about 50KB of data. Meanwhile (500KB - 50KB) = 450KB must sit somewhere - that's the size of the buffer you need.

There are some extra considerations. It'll take 8 minutes to send out 450KB at 9600. If you expect another 500KB burst during these 8 minutes, you need a bigger buffer.
 

Thread Starter

Vindhyachal Takniki

Joined Nov 3, 2014
594
There were small in my last codes. Correcting that code worked. Two errors, one was increment the head & other was sending data.
Now code is working ok.
Regrading buffer, I understand buffer will get full in case of 115200 baud in 3sec, for that SRAM is required or data on 115200 should be in breaks.
Otherwise above code, where everything is implemented in interrupts in working fine for samll amount of data.

Thanks for help/comments.
 

NorthGuy

Joined Jun 28, 2014
611
If you cannot afford the buffer of necessary size, you can implement CTS/RTS flow control. This would require 2 more pins. Or you can equalize the speed making both working at 9600, in which case you can just by-pass the chip and just lurk instead of re-transmitting.
 
Top