uart.c fix from TMK (#7628)
* uart.c fix from TMK Backport from tmk/tmk_keyboard@c41e48a0ab * Avoid deadlock when uart.c is usind in ISR Backport from tmk/tmk_keyboard@55443fabb7
This commit is contained in:
parent
67ee050a0e
commit
1751c3cc25
1 changed files with 44 additions and 10 deletions
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue