diff --git a/chip/stm32l/uart.c b/chip/stm32l/uart.c index 988dea9e5f..46fbf9cda8 100644 --- a/chip/stm32l/uart.c +++ b/chip/stm32l/uart.c @@ -20,15 +20,19 @@ /* Console USART index */ #define UARTN CONFIG_CONSOLE_UART +/* record last TX control action */ +static int should_stop; + void uart_tx_start(void) { STM32L_USART_CR1(UARTN) |= 0x80; - task_trigger_irq(STM32L_IRQ_USART(UARTN)); + should_stop = 0; } void uart_tx_stop(void) { STM32L_USART_CR1(UARTN) &= ~0x80; + should_stop = 1; } int uart_tx_stopped(void) @@ -75,8 +79,21 @@ void uart_enable_interrupt(void) /* Interrupt handler for console USART */ static void uart_interrupt(void) { + /* + * Disable the TX empty interrupt before filling the TX buffer since it + * needs an actual write to DR to be cleared. + */ + STM32L_USART_CR1(UARTN) &= ~0x80; + /* Read input FIFO until empty, then fill output FIFO */ uart_process(); + + /* + * Re-enable TX empty interrupt only if it was not disabled by + * uart_process. + */ + if (!should_stop) + STM32L_USART_CR1(UARTN) |= 0x80; } DECLARE_IRQ(STM32L_IRQ_USART(UARTN), uart_interrupt, 1); @@ -97,9 +114,9 @@ int uart_init(void) STM32L_RCC_APB1ENR |= 1 << 18; /* USART3 */ /* UART enabled, 8 Data bits, oversampling x16, no parity, - * TXE and RXNE interrupts, TX and RX enabled. + * RXNE interrupt, TX and RX enabled. */ - STM32L_USART_CR1(UARTN) = 0x20AC; + STM32L_USART_CR1(UARTN) = 0x202C; /* 1 stop bit, no fancy stuff */ STM32L_USART_CR2(UARTN) = 0x0000;