From 70f02c80b2393800adeef6411aefd64c9f26ab17 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Mon, 17 Apr 2023 08:52:45 +0000 Subject: [PATCH] STM32 SIO LLDs ISR revision. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@16225 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c | 56 ++++++++++++------- os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c | 58 ++++++++++++-------- 2 files changed, 71 insertions(+), 43 deletions(-) diff --git a/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c b/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c index 1839e4dda..6ace81008 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c +++ b/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c @@ -206,7 +206,7 @@ __STATIC_INLINE void usart_init(SIODriver *siop) { osalDbgAssert((brr >= 0x300) && (brr < 0x100000), "invalid BRR value"); } - else + else #endif { brr = (uint32_t)((clock / presc) / siop->config->baud); @@ -222,10 +222,10 @@ __STATIC_INLINE void usart_init(SIODriver *siop) { } /* Setting up USART.*/ - u->BRR = brr; u->CR1 = siop->config->cr1 & ~USART_CR1_CFG_FORBIDDEN; u->CR2 = siop->config->cr2 & ~USART_CR2_CFG_FORBIDDEN; u->CR3 = siop->config->cr3 & ~USART_CR3_CFG_FORBIDDEN; + u->BRR = brr; /* Starting operations.*/ u->ICR = u->ISR; @@ -741,21 +741,33 @@ msg_t sio_lld_control(SIODriver *siop, unsigned int operation, void *arg) { */ void sio_lld_serve_interrupt(SIODriver *siop) { USART_TypeDef *u = siop->usart; - sioevents_t events; - uint32_t cr1, cr3; + uint32_t cr1, cr2, cr3, isr, isrmask; osalDbgAssert(siop->state == SIO_READY, "invalid state"); /* Read on control registers.*/ cr1 = u->CR1; + cr2 = u->CR2; cr3 = u->CR3; - /* Events to be processed.*/ - events = sio_lld_get_events(siop) & siop->enabled; - if (events != 0U) { + /* Calculating the mask of status bits that should be processed according + to the state of the various CRx registers.*/ + isrmask = __sio_reloc_field(cr1, USART_CR1_TXEIE, USART_CR1_TXEIE_Pos, USART_ISR_TXE_Pos) | + __sio_reloc_field(cr1, USART_CR1_RXNEIE, USART_CR1_RXNEIE_Pos, USART_ISR_RXNE_Pos) | + __sio_reloc_field(cr1, USART_CR1_IDLEIE, USART_CR1_IDLEIE_Pos, USART_ISR_IDLE_Pos) | + __sio_reloc_field(cr1, USART_CR1_TCIE, USART_CR1_TCIE_Pos, USART_ISR_TC_Pos) | + __sio_reloc_field(cr1, USART_CR1_PEIE, USART_CR1_PEIE_Pos, USART_ISR_PE_Pos) | + __sio_reloc_field(cr2, USART_CR2_LBDIE, USART_CR2_LBDIE_Pos, USART_ISR_LBDF_Pos); + if ((cr3 & USART_CR3_EIE) != 0U) { + isrmask |= USART_ISR_NE | USART_ISR_FE | USART_ISR_ORE; + } - /* Error events handled as a group.*/ - if ((events & SIO_EV_ALL_ERRORS) != 0U) { + /* Status flags to be processed.*/ + isr = u->ISR & isrmask; + if (isr != 0U) { + + /* Error flags handled as a group.*/ + if ((isr & SIO_LLD_ISR_RX_ERRORS) != 0U) { #if SIO_USE_SYNCHRONIZATION /* The idle flag is forcibly cleared when an RX error event is detected.*/ @@ -763,17 +775,18 @@ void sio_lld_serve_interrupt(SIODriver *siop) { #endif /* All RX-related interrupt sources disabled.*/ - cr3 &= ~(USART_CR3_EIE); - cr1 &= ~(USART_CR1_PEIE | USART_CR1_IDLEIE | USART_CR1_RXNEIE); - u->CR2 &= ~(USART_CR2_LBDIE); + cr1 &= ~(USART_CR1_PEIE | USART_CR1_RXNEIE | USART_CR1_IDLEIE); + cr2 &= ~(USART_CR2_LBDIE); + cr3 &= ~(USART_CR3_EIE); /* Waiting thread woken, if any.*/ __sio_wakeup_errors(siop); } - /* If there are no errors then we check for the other RX events.*/ + /* If there are no errors then we check for the other RX-related + status flags.*/ else { - /* Idle RX event.*/ - if ((events & SIO_EV_RXIDLE) != 0U) { + /* Idle RX flag.*/ + if ((isr & USART_ISR_IDLE) != 0U) { /* Interrupt source disabled.*/ cr1 &= ~USART_CR1_IDLEIE; @@ -783,13 +796,13 @@ void sio_lld_serve_interrupt(SIODriver *siop) { } /* RX FIFO is non-empty.*/ - if ((events & SIO_EV_RXNOTEMPY) != 0U) { + if ((isr & USART_ISR_RXNE) != 0U) { - #if SIO_USE_SYNCHRONIZATION +#if SIO_USE_SYNCHRONIZATION /* The idle flag is forcibly cleared when an RX data event is detected.*/ u->ICR = USART_ICR_IDLECF; - #endif +#endif /* Interrupt source disabled.*/ cr1 &= ~USART_CR1_RXNEIE; @@ -800,7 +813,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { } /* TX FIFO is non-full.*/ - if ((events & SIO_EV_TXNOTFULL) != 0U) { + if ((isr & USART_ISR_TXE) != 0U) { /* Interrupt source disabled.*/ cr1 &= ~USART_CR1_TXEIE; @@ -810,7 +823,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { } /* Physical transmission end.*/ - if ((events & SIO_EV_TXDONE) != 0U) { + if ((isr & USART_ISR_TC) != 0U) { /* Interrupt source disabled.*/ cr1 &= ~USART_CR1_TCIE; @@ -821,13 +834,14 @@ void sio_lld_serve_interrupt(SIODriver *siop) { /* Updating control registers, some sources could have been disabled.*/ u->CR1 = cr1; + u->CR2 = cr2; u->CR3 = cr3; /* The callback is invoked.*/ __sio_callback(siop); } else { -// osalDbgAssert(false, "spurious interrupt"); + osalDbgAssert(false, "spurious interrupt"); } } diff --git a/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c b/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c index c0f041a43..994a61355 100644 --- a/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c +++ b/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c @@ -225,7 +225,7 @@ __STATIC_INLINE void usart_init(SIODriver *siop) { osalDbgAssert((brr >= 0x300) && (brr < 0x100000), "invalid BRR value"); } - else + else #endif { brr = (uint32_t)((clock / presc) / siop->config->baud); @@ -241,11 +241,11 @@ __STATIC_INLINE void usart_init(SIODriver *siop) { } /* Setting up USART.*/ - u->PRESC = siop->config->presc; - u->BRR = brr; u->CR1 = (siop->config->cr1 & ~USART_CR1_CFG_FORBIDDEN) | USART_CR1_FIFOEN; u->CR2 = siop->config->cr2 & ~USART_CR2_CFG_FORBIDDEN; u->CR3 = siop->config->cr3 & ~USART_CR3_CFG_FORBIDDEN; + u->PRESC = siop->config->presc; + u->BRR = brr; /* Starting operations.*/ u->ICR = u->ISR; @@ -793,21 +793,33 @@ msg_t sio_lld_control(SIODriver *siop, unsigned int operation, void *arg) { */ void sio_lld_serve_interrupt(SIODriver *siop) { USART_TypeDef *u = siop->usart; - sioevents_t events; - uint32_t cr1, cr3; + uint32_t cr1, cr2, cr3, isr, isrmask; osalDbgAssert(siop->state == SIO_READY, "invalid state"); /* Read on control registers.*/ cr1 = u->CR1; + cr2 = u->CR2; cr3 = u->CR3; - /* Events to be processed.*/ - events = sio_lld_get_events(siop) & siop->enabled; - if (events != 0U) { + /* Calculating the mask of status bits that should be processed according + to the state of the various CRx registers.*/ + isrmask = __sio_reloc_field(cr1, USART_CR1_IDLEIE, USART_CR1_IDLEIE_Pos, USART_ISR_IDLE_Pos) | + __sio_reloc_field(cr1, USART_CR1_TCIE, USART_CR1_TCIE_Pos, USART_ISR_TC_Pos) | + __sio_reloc_field(cr1, USART_CR1_PEIE, USART_CR1_PEIE_Pos, USART_ISR_PE_Pos) | + __sio_reloc_field(cr2, USART_CR2_LBDIE, USART_CR2_LBDIE_Pos, USART_ISR_LBDF_Pos) | + __sio_reloc_field(cr3, USART_CR3_RXFTIE, USART_CR3_RXFTIE_Pos, USART_ISR_RXNE_Pos) | + __sio_reloc_field(cr3, USART_CR3_TXFTIE, USART_CR3_TXFTIE_Pos, USART_ISR_TXE_Pos); + if ((cr3 & USART_CR3_EIE) != 0U) { + isrmask |= USART_ISR_NE | USART_ISR_FE | USART_ISR_ORE; + } - /* Error events handled as a group.*/ - if ((events & SIO_EV_ALL_ERRORS) != 0U) { + /* Status flags to be processed.*/ + isr = u->ISR & isrmask; + if (isr != 0U) { + + /* Error flags handled as a group.*/ + if ((isr & SIO_LLD_ISR_RX_ERRORS) != 0U) { #if SIO_USE_SYNCHRONIZATION /* The idle flag is forcibly cleared when an RX error event is detected.*/ @@ -815,17 +827,18 @@ void sio_lld_serve_interrupt(SIODriver *siop) { #endif /* All RX-related interrupt sources disabled.*/ - cr3 &= ~(USART_CR3_EIE | USART_CR3_RXFTIE); - cr1 &= ~(USART_CR1_PEIE | USART_CR1_IDLEIE); - u->CR2 &= ~(USART_CR2_LBDIE); + cr1 &= ~(USART_CR1_PEIE | USART_CR1_IDLEIE); + cr2 &= ~(USART_CR2_LBDIE); + cr3 &= ~(USART_CR3_EIE | USART_CR3_RXFTIE); /* Waiting thread woken, if any.*/ __sio_wakeup_errors(siop); } - /* If there are no errors then we check for the other RX events.*/ + /* If there are no errors then we check for the other RX-related + status flags.*/ else { - /* Idle RX event.*/ - if ((events & SIO_EV_RXIDLE) != 0U) { + /* Idle RX flag.*/ + if ((isr & USART_ISR_IDLE) != 0U) { /* Interrupt source disabled.*/ cr1 &= ~USART_CR1_IDLEIE; @@ -835,13 +848,13 @@ void sio_lld_serve_interrupt(SIODriver *siop) { } /* RX FIFO is non-empty.*/ - if ((events & SIO_EV_RXNOTEMPY) != 0U) { + if ((isr & USART_ISR_RXNE) != 0U) { - #if SIO_USE_SYNCHRONIZATION +#if SIO_USE_SYNCHRONIZATION /* The idle flag is forcibly cleared when an RX data event is detected.*/ u->ICR = USART_ICR_IDLECF; - #endif +#endif /* Interrupt source disabled.*/ cr3 &= ~USART_CR3_RXFTIE; @@ -852,7 +865,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { } /* TX FIFO is non-full.*/ - if ((events & SIO_EV_TXNOTFULL) != 0U) { + if ((isr & USART_ISR_TXE) != 0U) { /* Interrupt source disabled.*/ cr3 &= ~USART_CR3_TXFTIE; @@ -862,7 +875,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { } /* Physical transmission end.*/ - if ((events & SIO_EV_TXDONE) != 0U) { + if ((isr & USART_ISR_TC) != 0U) { /* Interrupt source disabled.*/ cr1 &= ~USART_CR1_TCIE; @@ -873,13 +886,14 @@ void sio_lld_serve_interrupt(SIODriver *siop) { /* Updating control registers, some sources could have been disabled.*/ u->CR1 = cr1; + u->CR2 = cr2; u->CR3 = cr3; /* The callback is invoked.*/ __sio_callback(siop); } else { -// osalDbgAssert(false, "spurious interrupt"); + osalDbgAssert(false, "spurious interrupt"); } }