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:
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.