From 0ae2cadff832553841a3fa2fb659495645937d83 Mon Sep 17 00:00:00 2001 From: Ali Shah Date: Fri, 16 Feb 2024 10:30:12 -0500 Subject: [PATCH] Fix serial corruption on x7 chips - We never clear LTXOK when we finish transmission of the ring buffer. This means that on the next pass, when new data needs transmission, enabling the Transmit Performed Interrupt fires the interrupt handler immediately, which then proceeds to load data from pointers that are stale as they haven't been set to the correct indexing. - Don't enable Transmit Performed Interrupt prior to setting the correct tail index and prior to loading data in LINDAT reg --- avr/cores/tiny/HardwareSerial.cpp | 5 +++-- avr/cores/tiny/Serial0.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/avr/cores/tiny/HardwareSerial.cpp b/avr/cores/tiny/HardwareSerial.cpp index 633102b9..47bb98ba 100644 --- a/avr/cores/tiny/HardwareSerial.cpp +++ b/avr/cores/tiny/HardwareSerial.cpp @@ -179,11 +179,12 @@ *_ucsrb |= _udrie; #else if(!(LINENIR & _BV(LENTXOK))){ - //The buffer was previously empty, so enable TX Complete interrupt and load first byte. - LINENIR = _BV(LENTXOK) | _BV(LENRXOK); + // The buffer was previously empty, so load the first byte, then enable + // the TX Complete interrupt unsigned char c = _tx_buffer->buffer[_tx_buffer->tail]; _tx_buffer->tail = (_tx_buffer->tail + 1) & (SERIAL_BUFFER_SIZE - 1); LINDAT = c; + LINENIR = _BV(LENTXOK) | _BV(LENRXOK); } #endif diff --git a/avr/cores/tiny/Serial0.cpp b/avr/cores/tiny/Serial0.cpp index 4dcdc4bf..636e9b50 100644 --- a/avr/cores/tiny/Serial0.cpp +++ b/avr/cores/tiny/Serial0.cpp @@ -37,7 +37,7 @@ if(LINSIR & _BV(LTXOK)) { //PINA |= _BV(PINA5); //debug if (tx_buffer.head == tx_buffer.tail) { - // Buffer empty, so disable interrupts + // Buffer empty, so disable the Transmit Performed Interrupt LINENIR = LENRXOK; //unset LENTXOK } else { // There is more data in the output buffer. Send the next byte