0
\$\begingroup\$

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.

\$\endgroup\$
3
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Could you shed some light as to why I may be losing data? the baud rate is 19200 which equates to 512us per byte being placed into DATA(RXB) - but I cannot output 1 byte from DATA(TXB) quicker than a 5ms interrupt? Do i have to do more flag checking? What sort of procedure would you recommend?? \$\endgroup\$ – Sam Bucca Nov 15 '16 at 1:51
1
\$\begingroup\$

I figured out what was wrong - My timer interrupt needed to be disabled during my "FIFO_Get" and "FIFO_Put" functions.

What was happening was the timer was interrupting whilst in the middle of these functions which corrupts the data being output.

The above code is correct, and thank you to @Ignacio for helping me realize the issue lie elsewhere.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.