aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrashna Jaelre <drashna@live.com>2020-02-21 02:32:30 -0800
committerGitHub <noreply@github.com>2020-02-21 21:32:30 +1100
commit1751c3cc25ecc1734976d9790598d64133ee306d (patch)
treed9e8dea87ccc9379b53718acdde836e43f2ed18f
parent67ee050a0e80359b5b58ea1767adfb96b5bdace5 (diff)
downloadqmk_firmware-1751c3cc25ecc1734976d9790598d64133ee306d.tar.gz
qmk_firmware-1751c3cc25ecc1734976d9790598d64133ee306d.zip
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.c54
1 files changed, 44 insertions, 10 deletions
diff --git a/tmk_core/common/uart.c b/tmk_core/common/uart.c
index f2e4bc4f3..412fcf8e1 100644
--- a/tmk_core/common/uart.c
+++ b/tmk_core/common/uart.c
@@ -31,9 +31,41 @@
31 31
32#include "uart.h" 32#include "uart.h"
33 33
34#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
35# define UDRn UDR0
36# define UBRRn UBRR0
37# define UCSRnA UCSR0A
38# define UCSRnB UCSR0B
39# define UCSRnC UCSR0C
40# define U2Xn U2X0
41# define RXENn RXEN0
42# define TXENn TXEN0
43# define RXCIEn RXCIE0
44# define UCSZn1 UCSZ01
45# define UCSZn0 UCSZ00
46# define UDRIEn UDRIE0
47# define UDRE_vect USART_UDRE_vect
48# define RX_vect USART_RX_vect
49#elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega32U2__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
50# define UDRn UDR1
51# define UBRRn UBRR1
52# define UCSRnA UCSR1A
53# define UCSRnB UCSR1B
54# define UCSRnC UCSR1C
55# define U2Xn U2X1
56# define RXENn RXEN1
57# define TXENn TXEN1
58# define RXCIEn RXCIE1
59# define UCSZn1 UCSZ11
60# define UCSZn0 UCSZ10
61# define UDRIEn UDRIE1
62# define UDRE_vect USART1_UDRE_vect
63# define RX_vect USART1_RX_vect
64#endif
65
34// These buffers may be any size from 2 to 256 bytes. 66// These buffers may be any size from 2 to 256 bytes.
35#define RX_BUFFER_SIZE 64 67#define RX_BUFFER_SIZE 64
36#define TX_BUFFER_SIZE 40 68#define TX_BUFFER_SIZE 256
37 69
38static volatile uint8_t tx_buffer[TX_BUFFER_SIZE]; 70static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
39static volatile uint8_t tx_buffer_head; 71static volatile uint8_t tx_buffer_head;
@@ -45,10 +77,10 @@ static volatile uint8_t rx_buffer_tail;
45// Initialize the UART 77// Initialize the UART
46void uart_init(uint32_t baud) { 78void uart_init(uint32_t baud) {
47 cli(); 79 cli();
48 UBRR0 = (F_CPU / 4 / baud - 1) / 2; 80 UBRRn = (F_CPU / 4 / baud - 1) / 2;
49 UCSR0A = (1 << U2X0); 81 UCSRnA = (1 << U2Xn);
50 UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); 82 UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn);
51 UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); 83 UCSRnC = (1 << UCSZn1) | (1 << UCSZn0);
52 tx_buffer_head = tx_buffer_tail = 0; 84 tx_buffer_head = tx_buffer_tail = 0;
53 rx_buffer_head = rx_buffer_tail = 0; 85 rx_buffer_head = rx_buffer_tail = 0;
54 sei(); 86 sei();
@@ -60,12 +92,14 @@ void uart_putchar(uint8_t c) {
60 92
61 i = tx_buffer_head + 1; 93 i = tx_buffer_head + 1;
62 if (i >= TX_BUFFER_SIZE) i = 0; 94 if (i >= TX_BUFFER_SIZE) i = 0;
95 // return immediately to avoid deadlock when interrupt is disabled(called from ISR)
96 if (tx_buffer_tail == i && (SREG & (1<<SREG_I)) == 0) return;
63 while (tx_buffer_tail == i) 97 while (tx_buffer_tail == i)
64 ; // wait until space in buffer 98 ; // wait until space in buffer
65 // cli(); 99 // cli();
66 tx_buffer[i] = c; 100 tx_buffer[i] = c;
67 tx_buffer_head = i; 101 tx_buffer_head = i;
68 UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0) | (1 << UDRIE0); 102 UCSRB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn) | (1 << UDRIEn);
69 // sei(); 103 // sei();
70} 104}
71 105
@@ -95,12 +129,12 @@ uint8_t uart_available(void) {
95} 129}
96 130
97// Transmit Interrupt 131// Transmit Interrupt
98ISR(USART_UDRE_vect) { 132ISR(UDRE_vect) {
99 uint8_t i; 133 uint8_t i;
100 134
101 if (tx_buffer_head == tx_buffer_tail) { 135 if (tx_buffer_head == tx_buffer_tail) {
102 // buffer is empty, disable transmit interrupt 136 // buffer is empty, disable transmit interrupt
103 UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); 137 UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn);
104 } else { 138 } else {
105 i = tx_buffer_tail + 1; 139 i = tx_buffer_tail + 1;
106 if (i >= TX_BUFFER_SIZE) i = 0; 140 if (i >= TX_BUFFER_SIZE) i = 0;
@@ -110,10 +144,10 @@ ISR(USART_UDRE_vect) {
110} 144}
111 145
112// Receive Interrupt 146// Receive Interrupt
113ISR(USART_RX_vect) { 147ISR(RX_vect) {
114 uint8_t c, i; 148 uint8_t c, i;
115 149
116 c = UDR0; 150 c = UDRn;
117 i = rx_buffer_head + 1; 151 i = rx_buffer_head + 1;
118 if (i >= RX_BUFFER_SIZE) i = 0; 152 if (i >= RX_BUFFER_SIZE) i = 0;
119 if (i != rx_buffer_tail) { 153 if (i != rx_buffer_tail) {