Skip to content

Commit

Permalink
drv/uart/stm32f4_ll_irq: only read USARTx->SR once in IRQ handler
Browse files Browse the repository at this point in the history
It appears that reading the USART SR register clears some flags. In
certain cases, this would cause the interrupt handler to go into an
infinite loop.

By reading the SR register only once, we ensure that all flags are
seen and handled properly.

Issue: pybricks/support#304
  • Loading branch information
dlech committed May 1, 2021
1 parent 7d14182 commit c661f6d
Showing 1 changed file with 4 additions and 3 deletions.
7 changes: 4 additions & 3 deletions lib/pbio/drv/uart/uart_stm32f4_ll_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,14 @@ void pbdrv_uart_flush(pbdrv_uart_dev_t *uart_dev) {
void pbdrv_uart_stm32f4_ll_irq_handle_irq(uint8_t id) {
pbdrv_uart_t *uart = &pbdrv_uart[id];
USART_TypeDef *USARTx = uart->pdata->uart;
uint32_t sr = USARTx->SR;

if (LL_USART_IsEnabledIT_RXNE(USARTx) && LL_USART_IsActiveFlag_RXNE(USARTx)) {
if (LL_USART_IsEnabledIT_RXNE(USARTx) && sr & USART_SR_RXNE) {
ringbuf_put(&uart->rx_buf, LL_USART_ReceiveData8(USARTx));
process_poll(&pbdrv_uart_process);
}

if (LL_USART_IsEnabledIT_TXE(USARTx) && LL_USART_IsActiveFlag_TXE(USARTx)) {
if (LL_USART_IsEnabledIT_TXE(USARTx) && sr & USART_SR_TXE) {
LL_USART_TransmitData8(USARTx, uart->write_buf[uart->write_pos++]);
// When all bytes have been written, wait for the Tx complete interrupt.
if (uart->write_pos == uart->write_length) {
Expand All @@ -200,7 +201,7 @@ void pbdrv_uart_stm32f4_ll_irq_handle_irq(uint8_t id) {
}
}

if (LL_USART_IsEnabledIT_TC(USARTx) && LL_USART_IsActiveFlag_TC(USARTx)) {
if (LL_USART_IsEnabledIT_TC(USARTx) && sr & USART_SR_TC) {
LL_USART_DisableIT_TC(USARTx);
process_poll(&pbdrv_uart_process);
}
Expand Down

0 comments on commit c661f6d

Please sign in to comment.