diff options
author | Drashna Jaelre <drashna@live.com> | 2020-02-21 02:32:30 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-21 21:32:30 +1100 |
commit | 1751c3cc25ecc1734976d9790598d64133ee306d (patch) | |
tree | d9e8dea87ccc9379b53718acdde836e43f2ed18f | |
parent | 67ee050a0e80359b5b58ea1767adfb96b5bdace5 (diff) |
uart.c fix from TMK (#7628)
* uart.c fix from TMK
Backport from tmk/tmk_keyboard@c41e48a0ab0712d2667feb6b5dd8a4d5491cfcc5
* Avoid deadlock when uart.c is usind in ISR
Backport from tmk/tmk_keyboard@55443fabb731459e21b45781c6d951edac5d75f4
-rw-r--r-- | tmk_core/common/uart.c | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/tmk_core/common/uart.c b/tmk_core/common/uart.c index f2e4bc4f34..412fcf8e1a 100644 --- a/tmk_core/common/uart.c +++ b/tmk_core/common/uart.c @@ -31,9 +31,41 @@ #include "uart.h" +#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) +# define UDRn UDR0 +# define UBRRn UBRR0 +# define UCSRnA UCSR0A +# define UCSRnB UCSR0B +# define UCSRnC UCSR0C +# define U2Xn U2X0 +# define RXENn RXEN0 +# define TXENn TXEN0 +# define RXCIEn RXCIE0 +# define UCSZn1 UCSZ01 +# define UCSZn0 UCSZ00 +# define UDRIEn UDRIE0 +# define UDRE_vect USART_UDRE_vect +# define RX_vect USART_RX_vect +#elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega32U2__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) +# define UDRn UDR1 +# define UBRRn UBRR1 +# define UCSRnA UCSR1A +# define UCSRnB UCSR1B +# define UCSRnC UCSR1C +# define U2Xn U2X1 +# define RXENn RXEN1 +# define TXENn TXEN1 +# define RXCIEn RXCIE1 +# define UCSZn1 UCSZ11 +# define UCSZn0 UCSZ10 +# define UDRIEn UDRIE1 +# define UDRE_vect USART1_UDRE_vect +# define RX_vect USART1_RX_vect +#endif + // These buffers may be any size from 2 to 256 bytes. #define RX_BUFFER_SIZE 64 -#define TX_BUFFER_SIZE 40 +#define TX_BUFFER_SIZE 256 static volatile uint8_t tx_buffer[TX_BUFFER_SIZE]; static volatile uint8_t tx_buffer_head; @@ -45,10 +77,10 @@ static volatile uint8_t rx_buffer_tail; // Initialize the UART void uart_init(uint32_t baud) { cli(); - UBRR0 = (F_CPU / 4 / baud - 1) / 2; - UCSR0A = (1 << U2X0); - UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); - UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); + UBRRn = (F_CPU / 4 / baud - 1) / 2; + UCSRnA = (1 << U2Xn); + UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn); + UCSRnC = (1 << UCSZn1) | (1 << UCSZn0); tx_buffer_head = tx_buffer_tail = 0; rx_buffer_head = rx_buffer_tail = 0; sei(); @@ -60,12 +92,14 @@ void uart_putchar(uint8_t c) { i = tx_buffer_head + 1; if (i >= TX_BUFFER_SIZE) i = 0; + // return immediately to avoid deadlock when interrupt is disabled(called from ISR) + if (tx_buffer_tail == i && (SREG & (1<<SREG_I)) == 0) return; while (tx_buffer_tail == i) ; // wait until space in buffer // cli(); tx_buffer[i] = c; tx_buffer_head = i; - UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0) | (1 << UDRIE0); + UCSRB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn) | (1 << UDRIEn); // sei(); } @@ -95,12 +129,12 @@ uint8_t uart_available(void) { } // Transmit Interrupt -ISR(USART_UDRE_vect) { +ISR(UDRE_vect) { uint8_t i; if (tx_buffer_head == tx_buffer_tail) { // buffer is empty, disable transmit interrupt - UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); + UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn); } else { i = tx_buffer_tail + 1; if (i >= TX_BUFFER_SIZE) i = 0; @@ -110,10 +144,10 @@ ISR(USART_UDRE_vect) { } // Receive Interrupt -ISR(USART_RX_vect) { +ISR(RX_vect) { uint8_t c, i; - c = UDR0; + c = UDRn; i = rx_buffer_head + 1; if (i >= RX_BUFFER_SIZE) i = 0; if (i != rx_buffer_tail) { |