Electrical – preventing Rx/Tx data clashing on a xmega USART

interruptsuartxmega

I am using the USART module on an atxmega128a1 to communicate with a PC, and I've noticed that receiving and transmitting a byte uses the same data register address:
USART data register

My question is then, if I am in the middle of transmitting a byte OUT of this data register, how do I prevent an interrupt triggered by a byte coming IN from causing me to lose data?

My current code uses Rx and Tx software FIFO buffers, an interrupt to trigger a byte received and a timer interrupt to output a byte periodically from my TxFIFO:

//interrupt to receive a byte (RS232)
ISR(USARTD0_RXC_vect){                          //ISR for when receive flag is set
    if(FIFO_Put(&RxFIFO, USARTD0_DATA)){        //put data into receive FIFO
        USARTD0_STATUS |= USART_RXCIF_bm;       //write 1 to clear bit
    }
    while(!(USARTD1_STATUS & USART_DREIF_bm));  //wait until data register is empty
}

ISR(TCC1_OVF_vect){
    unsigned char data;
    if(FIFO_Get(&TxFIFO, &data)){                   //place a byte from FIFO into &data
        while(!(USARTD1_STATUS & USART_DREIF_bm));  //if Tx FIFO has data, wait until data register is empty
        USARTD0_DATA = data;                        //put it in the data buffer
        while(!(USARTD0_STATUS & USART_TXCIF_bm));  //wait until transfer complete
        USARTD0_STATUS |= USART_TXCIF_bm;           //write 1 to clear bit
    }
}

BOTH of these interrupts are "low" priority and round robin servicing of interrupts are enabled. I want to increase the period of the timer interrupt but anything faster than 5ms interrupts causes data to be lost. I would use RTS/CTS but I want to know what my options are first as I believe the xmega is capable of doing what I want without data loss.

Best Answer

My question is then, if I am in the middle of transmitting a byte OUT of this data register, how do I prevent an interrupt triggered by a byte coming IN from causing me to lose data?

You don't. There are two separate registers, accessed using the same address but different modes. One holds the last byte pulled from the receive hardware, and the other holds the next byte to put into the transmit hardware.

If you read from DATA you access RXB, and if you write to DATA you access TXB.