From fae48a7fc76f288377fecc64827f31d89d45fdb4 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Sat, 3 Sep 2022 08:15:37 +0000 Subject: [PATCH] STM32-specific SIO optimization. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15754 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- os/hal/include/hal_channels.h | 12 +- os/hal/include/hal_sio.h | 16 +- os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c | 157 ++++++++----------- os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c | 92 +++++------ os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.h | 26 ++- os/hal/ports/sandbox/hal_sio_lld.c | 4 +- 6 files changed, 144 insertions(+), 163 deletions(-) diff --git a/os/hal/include/hal_channels.h b/os/hal/include/hal_channels.h index 38c17580e..7f06cd7ee 100644 --- a/os/hal/include/hal_channels.h +++ b/os/hal/include/hal_channels.h @@ -243,14 +243,16 @@ typedef struct { #define CHN_PARITY_ERROR (eventflags_t)32 /** @brief Framing error.*/ #define CHN_FRAMING_ERROR (eventflags_t)64 -/** @brief Overflow error.*/ -#define CHN_OVERRUN_ERROR (eventflags_t)128 /** @brief Line noise error.*/ -#define CHN_NOISE_ERROR (eventflags_t)256 +#define CHN_NOISE_ERROR (eventflags_t)128 +/** @brief Overflow error.*/ +#define CHN_OVERRUN_ERROR (eventflags_t)256 +/** @brief RX line idle.*/ +#define CHN_IDLE_DETECTED (eventflags_t)512 /** @brief LIN Break.*/ -#define CHN_BREAK_DETECTED (eventflags_t)512 +#define CHN_BREAK_DETECTED (eventflags_t)1024 /**< @brief RX buffer full. */ -#define CHN_BUFFER_FULL_ERROR (eventflags_t)1024 +#define CHN_BUFFER_FULL_ERROR (eventflags_t)2048 /** @} */ /** diff --git a/os/hal/include/hal_sio.h b/os/hal/include/hal_sio.h index 190d5c497..ed5e9ed01 100644 --- a/os/hal/include/hal_sio.h +++ b/os/hal/include/hal_sio.h @@ -41,10 +41,10 @@ #define SIO_EV_ALL_ERRORS_POS SIO_EV_PARITY_ERR_POS #define SIO_EV_PARITY_ERR_POS 5 /* CHN_PARITY_ERROR */ #define SIO_EV_FRAMING_ERR_POS 6 /* CHN_FRAMING_ERROR */ -#define SIO_EV_OVERRUN_ERR_POS 7 /* CHN_OVERRUN_ERROR */ -#define SIO_EV_NOISE_ERR_POS 8 /* CHN_NOISE_ERROR */ -#define SIO_EV_BREAK_POS 9 /* CHN_BREAK_DETECTED */ -#define SIO_EV_RXIDLE_POS 11 /* CHN does not define it */ +#define SIO_EV_NOISE_ERR_POS 7 /* CHN_NOISE_ERROR */ +#define SIO_EV_OVERRUN_ERR_POS 8 /* CHN_OVERRUN_ERROR */ +#define SIO_EV_RXIDLE_POS 9 /* CHN_IDLE_DETECTED */ +#define SIO_EV_RXBREAK_POS 10 /* CHN_BREAK_DETECTED */ /** @} */ /** @@ -58,15 +58,15 @@ #define SIO_EV_TXDONE (1U << SIO_EV_TXDONE_POS) #define SIO_EV_PARITY_ERR (1U << SIO_EV_PARITY_ERR_POS) #define SIO_EV_FRAMING_ERR (1U << SIO_EV_FRAMING_ERR_POS) -#define SIO_EV_OVERRUN_ERR (1U << SIO_EV_OVERRUN_ERR_POS) #define SIO_EV_NOISE_ERR (1U << SIO_EV_NOISE_ERR_POS) -#define SIO_EV_BREAK (1U << SIO_EV_BREAK_POS) +#define SIO_EV_OVERRUN_ERR (1U << SIO_EV_OVERRUN_ERR_POS) +#define SIO_EV_RXIDLE (1U << SIO_EV_RXIDLE_POS) +#define SIO_EV_RXBREAK (1U << SIO_EV_RXBREAK_POS) #define SIO_EV_ALL_ERRORS (SIO_EV_PARITY_ERR | \ SIO_EV_FRAMING_ERR | \ SIO_EV_OVERRUN_ERR | \ SIO_EV_NOISE_ERR | \ - SIO_EV_BREAK) -#define SIO_EV_RXIDLE (1U << SIO_EV_RXIDLE_POS) + SIO_EV_RXBREAK) #define SIO_EV_ALL_EVENTS (SIO_EV_ALL_DATA | \ SIO_EV_ALL_ERRORS | \ SIO_EV_TXDONE | \ 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 554282766..1839e4dda 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c +++ b/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c @@ -46,6 +46,14 @@ USART_CR3_CTSIE | \ USART_CR3_EIE) +/* This mask includes IDLE, ORE, NE, FE, PE bits.*/ +#define USART_ISR_IONFP_Pos USART_ISR_PE_Pos +#define USART_ISR_IONFP_Msk (0x1FUL << USART_ISR_IONFP_Pos) + +/* This mask includes ORE, NE, FE, PE bits.*/ +#define USART_ISR_ONFP_Pos USART_ISR_PE_Pos +#define USART_ISR_ONFP_Msk (0xFUL << USART_ISR_ONFP_Pos) + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ @@ -146,26 +154,16 @@ __STATIC_INLINE void usart_enable_rx_irq(SIODriver *siop) { } __STATIC_INLINE void usart_enable_rx_errors_irq(SIODriver *siop) { - uint32_t cr1, cr2, cr3; - cr1 = siop->usart->CR1; - cr2 = siop->usart->CR2; - cr3 = siop->usart->CR3; - - cr1 |= __sio_reloc_field(siop->enabled, SIO_EV_PARITY_ERR, SIO_EV_PARITY_ERR_POS, USART_CR1_PEIE_Pos); - cr2 |= __sio_reloc_field(siop->enabled, SIO_EV_BREAK, SIO_EV_BREAK_POS, USART_CR2_LBDIE_Pos); + siop->usart->CR1 |= __sio_reloc_field(siop->enabled, SIO_EV_PARITY_ERR, SIO_EV_PARITY_ERR_POS, USART_CR1_PEIE_Pos); + siop->usart->CR2 |= __sio_reloc_field(siop->enabled, SIO_EV_RXBREAK, SIO_EV_RXBREAK_POS, USART_CR2_LBDIE_Pos); /* The following 3 are grouped.*/ if ((siop->enabled & (SIO_EV_FRAMING_ERR | SIO_EV_OVERRUN_ERR | SIO_EV_NOISE_ERR)) != 0U) { - cr3 |= USART_CR3_EIE; + siop->usart->CR3 |= USART_CR3_EIE; } - - /* Setting up the operation.*/ - siop->usart->CR1 = cr1; - siop->usart->CR2 = cr2; - siop->usart->CR3 = cr3; } __STATIC_INLINE void usart_enable_tx_irq(SIODriver *siop) { @@ -477,7 +475,7 @@ void sio_lld_update_enable_flags(SIODriver *siop) { __sio_reloc_field(siop->enabled, SIO_EV_RXIDLE, SIO_EV_RXIDLE_POS, USART_CR1_IDLEIE_Pos) | __sio_reloc_field(siop->enabled, SIO_EV_TXDONE, SIO_EV_TXDONE_POS, USART_CR1_TCIE_Pos) | __sio_reloc_field(siop->enabled, SIO_EV_PARITY_ERR, SIO_EV_PARITY_ERR_POS, USART_CR1_PEIE_Pos); - cr2 |= __sio_reloc_field(siop->enabled, SIO_EV_BREAK, SIO_EV_BREAK_POS, USART_CR2_LBDIE_Pos); + cr2 |= __sio_reloc_field(siop->enabled, SIO_EV_RXBREAK, SIO_EV_RXBREAK_POS, USART_CR2_LBDIE_Pos); /* The following 3 are grouped.*/ if ((siop->enabled & (SIO_EV_FRAMING_ERR | @@ -502,7 +500,7 @@ void sio_lld_update_enable_flags(SIODriver *siop) { */ sioevents_t sio_lld_get_and_clear_errors(SIODriver *siop) { uint32_t isr; - sioevents_t errors = (sioevents_t)0; + sioevents_t errors; /* Getting all error ISR flags (and only those). NOTE: Do not trust the position of other bits in ISR/ICR because @@ -513,16 +511,13 @@ sioevents_t sio_lld_get_and_clear_errors(SIODriver *siop) { /* Clearing captured events.*/ siop->usart->ICR = isr; - /* Status flags cleared, now the RX errors-related interrupts can be + /* Status flags cleared, now the error-related interrupts can be enabled again.*/ usart_enable_rx_errors_irq(siop); /* Translating the status flags in SIO events.*/ - errors |= __sio_reloc_field(isr, USART_ISR_LBDF_Msk, USART_ISR_LBDF_Pos, SIO_EV_BREAK_POS) | - __sio_reloc_field(isr, USART_ISR_PE_Msk, USART_ISR_PE_Pos, SIO_EV_PARITY_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_FE_Msk, USART_ISR_FE_Pos, SIO_EV_FRAMING_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_NE_Msk, USART_ISR_NE_Pos, SIO_EV_NOISE_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_ORE_Msk, USART_ISR_ORE_Pos, SIO_EV_OVERRUN_ERR_POS); + errors = __sio_reloc_field(isr, USART_ISR_ONFP_Msk, USART_ISR_ONFP_Pos, SIO_EV_ALL_ERRORS_POS) | + __sio_reloc_field(isr, USART_ISR_LBDF_Msk, USART_ISR_LBDF_Pos, SIO_EV_RXBREAK_POS); return errors; } @@ -537,7 +532,7 @@ sioevents_t sio_lld_get_and_clear_errors(SIODriver *siop) { */ sioevents_t sio_lld_get_and_clear_events(SIODriver *siop) { uint32_t isr; - sioevents_t events = (sioevents_t)0; + sioevents_t events; /* Getting all ISR flags. NOTE: Do not trust the position of other bits in ISR/ICR because @@ -558,15 +553,11 @@ sioevents_t sio_lld_get_and_clear_events(SIODriver *siop) { usart_enable_rx_errors_irq(siop); /* Translating the status flags in SIO events.*/ - events |= __sio_reloc_field(isr, USART_ISR_RXNE_Msk, USART_ISR_RXNE_Pos, SIO_EV_RXNOTEMPY_POS) | - __sio_reloc_field(isr, USART_ISR_TXE_Msk, USART_ISR_TXE_Pos, SIO_EV_TXNOTFULL_POS) | - __sio_reloc_field(isr, USART_ISR_IDLE_Msk, USART_ISR_IDLE_Pos, SIO_EV_RXIDLE_POS) | - __sio_reloc_field(isr, USART_ISR_TC_Msk, USART_ISR_TC_Pos, SIO_EV_TXDONE_POS) | - __sio_reloc_field(isr, USART_ISR_LBDF_Msk, USART_ISR_LBDF_Pos, SIO_EV_BREAK_POS) | - __sio_reloc_field(isr, USART_ISR_PE_Msk, USART_ISR_PE_Pos, SIO_EV_PARITY_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_FE_Msk, USART_ISR_FE_Pos, SIO_EV_FRAMING_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_NE_Msk, USART_ISR_NE_Pos, SIO_EV_NOISE_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_ORE_Msk, USART_ISR_ORE_Pos, SIO_EV_OVERRUN_ERR_POS); + events = __sio_reloc_field(isr, USART_ISR_RXNE_Msk, USART_ISR_RXNE_Pos, SIO_EV_RXNOTEMPY_POS) | + __sio_reloc_field(isr, USART_ISR_TXE_Msk, USART_ISR_TXE_Pos, SIO_EV_TXNOTFULL_POS) | + __sio_reloc_field(isr, USART_ISR_TC_Msk, USART_ISR_TC_Pos, SIO_EV_TXDONE_POS) | + __sio_reloc_field(isr, USART_ISR_IONFP_Msk, USART_ISR_IONFP_Pos, SIO_EV_ALL_ERRORS_POS) | + __sio_reloc_field(isr, USART_ISR_LBDF_Msk, USART_ISR_LBDF_Pos, SIO_EV_RXBREAK_POS); return events; } @@ -583,10 +574,7 @@ sioevents_t sio_lld_get_events(SIODriver *siop) { uint32_t isr; sioevents_t events; - /* Getting all ISR flags. - NOTE: Do not trust the position of other bits in ISR/ICR because - some scientist decided to use different positions for some - of them.*/ + /* Getting all ISR flags.*/ isr = siop->usart->ISR & (SIO_LLD_ISR_RX_ERRORS | USART_ISR_RXNE | USART_ISR_IDLE | @@ -594,15 +582,11 @@ sioevents_t sio_lld_get_events(SIODriver *siop) { USART_ISR_TC); /* Translating the status flags in SIO events.*/ - events = __sio_reloc_field(isr, USART_ISR_RXNE_Msk, USART_ISR_RXNE_Pos, SIO_EV_RXNOTEMPY_POS) | - __sio_reloc_field(isr, USART_ISR_TXE_Msk, USART_ISR_TXE_Pos, SIO_EV_TXNOTFULL_POS) | - __sio_reloc_field(isr, USART_ISR_IDLE_Msk, USART_ISR_IDLE_Pos, SIO_EV_RXIDLE_POS) | - __sio_reloc_field(isr, USART_ISR_TC_Msk, USART_ISR_TC_Pos, SIO_EV_TXDONE_POS) | - __sio_reloc_field(isr, USART_ISR_LBDF_Msk, USART_ISR_LBDF_Pos, SIO_EV_BREAK_POS) | - __sio_reloc_field(isr, USART_ISR_PE_Msk, USART_ISR_PE_Pos, SIO_EV_PARITY_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_FE_Msk, USART_ISR_FE_Pos, SIO_EV_FRAMING_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_NE_Msk, USART_ISR_NE_Pos, SIO_EV_NOISE_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_ORE_Msk, USART_ISR_ORE_Pos, SIO_EV_OVERRUN_ERR_POS); + events = __sio_reloc_field(isr, USART_ISR_RXNE_Msk, USART_ISR_RXNE_Pos, SIO_EV_RXNOTEMPY_POS) | + __sio_reloc_field(isr, USART_ISR_TXE_Msk, USART_ISR_TXE_Pos, SIO_EV_TXNOTFULL_POS) | + __sio_reloc_field(isr, USART_ISR_TC_Msk, USART_ISR_TC_Pos, SIO_EV_TXDONE_POS) | + __sio_reloc_field(isr, USART_ISR_IONFP_Msk, USART_ISR_IONFP_Pos, SIO_EV_ALL_ERRORS_POS) | + __sio_reloc_field(isr, USART_ISR_LBDF_Msk, USART_ISR_LBDF_Pos, SIO_EV_RXBREAK_POS); return events; } @@ -757,82 +741,66 @@ msg_t sio_lld_control(SIODriver *siop, unsigned int operation, void *arg) { */ void sio_lld_serve_interrupt(SIODriver *siop) { USART_TypeDef *u = siop->usart; - uint32_t isr, isrmask; - uint32_t cr1, cr2, cr3; + sioevents_t events; + uint32_t cr1, cr3; osalDbgAssert(siop->state == SIO_READY, "invalid state"); /* Read on control registers.*/ cr1 = u->CR1; - cr2 = u->CR2; cr3 = u->CR3; - /* Calculating the mask of the interrupts to be processed, BTW, thanks ST - for placing interrupt enable bits randomly in 3 distinct registers - instead of a dedicated IER (ISR, ICR, see the pattern?).*/ - isrmask = __sio_reloc_field(cr3, USART_CR3_EIE_Msk, USART_CR3_EIE_Pos, USART_ISR_NE_Pos) | - __sio_reloc_field(cr3, USART_CR3_EIE_Msk, USART_CR3_EIE_Pos, USART_ISR_FE_Pos) | - __sio_reloc_field(cr3, USART_CR3_EIE_Msk, USART_CR3_EIE_Pos, USART_ISR_ORE_Pos) | - __sio_reloc_field(cr2, USART_CR2_LBDIE_Msk, USART_CR2_LBDIE_Pos, USART_ISR_LBDF_Pos) | - __sio_reloc_field(cr1, USART_CR1_PEIE_Msk, USART_CR1_PEIE_Pos, USART_ISR_PE_Pos) | - __sio_reloc_field(cr1, USART_CR1_IDLEIE_Msk, USART_CR1_IDLEIE_Pos, USART_ISR_IDLE_Pos) | - __sio_reloc_field(cr1, USART_CR1_RXNEIE_Msk, USART_CR1_RXNEIE_Pos, USART_ISR_RXNE_Pos) | - __sio_reloc_field(cr1, USART_CR1_TXEIE_Msk, USART_CR1_TXEIE_Pos, USART_ISR_TXE_Pos) | - __sio_reloc_field(cr1, USART_CR1_TCIE_Msk, USART_CR1_TCIE_Pos, USART_ISR_TC_Pos); - - /* Note, ISR flags are just read but not cleared, ISR sources are - disabled instead.*/ - isr = u->ISR; - isr = isr & isrmask; - if (isr != 0U) { - - /* Error events handled as a group, except ORE.*/ - if ((isr & (USART_ISR_LBDF | USART_ISR_NE | USART_ISR_FE | - USART_ISR_PE | USART_ISR_ORE)) != 0U) { + /* Events to be processed.*/ + events = sio_lld_get_events(siop) & siop->enabled; + if (events != 0U) { + /* Error events handled as a group.*/ + if ((events & SIO_EV_ALL_ERRORS) != 0U) { #if SIO_USE_SYNCHRONIZATION /* The idle flag is forcibly cleared when an RX error event is detected.*/ u->ICR = USART_ICR_IDLECF; #endif - /* Interrupt sources disabled.*/ - cr3 &= ~USART_CR3_EIE; - cr2 &= ~USART_CR2_LBDIE; - cr1 &= ~USART_CR1_PEIE; + /* 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); /* Waiting thread woken, if any.*/ __sio_wakeup_errors(siop); } + /* If there are no errors then we check for the other RX events.*/ + else { + /* Idle RX event.*/ + if ((events & SIO_EV_RXIDLE) != 0U) { - /* Idle RX event.*/ - if ((isr & USART_ISR_IDLE) != 0U) { + /* Interrupt source disabled.*/ + cr1 &= ~USART_CR1_IDLEIE; - /* Interrupt source disabled.*/ - cr1 &= ~USART_CR1_IDLEIE; + /* Waiting thread woken, if any.*/ + __sio_wakeup_rxidle(siop); + } - /* Waiting thread woken, if any.*/ - __sio_wakeup_rxidle(siop); - } + /* RX FIFO is non-empty.*/ + if ((events & SIO_EV_RXNOTEMPY) != 0U) { - /* RX FIFO is non-empty.*/ - if ((isr & USART_ISR_RXNE) != 0U) { + #if SIO_USE_SYNCHRONIZATION + /* The idle flag is forcibly cleared when an RX data event is + detected.*/ + u->ICR = USART_ICR_IDLECF; + #endif -#if SIO_USE_SYNCHRONIZATION - /* The idle flag is forcibly cleared when an RX data event is - detected.*/ - u->ICR = USART_ICR_IDLECF; -#endif + /* Interrupt source disabled.*/ + cr1 &= ~USART_CR1_RXNEIE; - /* Interrupt source disabled.*/ - cr1 &= ~USART_CR1_RXNEIE; - - /* Waiting thread woken, if any.*/ - __sio_wakeup_rx(siop); + /* Waiting thread woken, if any.*/ + __sio_wakeup_rx(siop); + } } /* TX FIFO is non-full.*/ - if ((isr & USART_ISR_TXE) != 0U) { + if ((events & SIO_EV_TXNOTFULL) != 0U) { /* Interrupt source disabled.*/ cr1 &= ~USART_CR1_TXEIE; @@ -842,7 +810,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { } /* Physical transmission end.*/ - if ((isr & USART_ISR_TC) != 0U) { + if ((events & SIO_EV_TXDONE) != 0U) { /* Interrupt source disabled.*/ cr1 &= ~USART_CR1_TCIE; @@ -853,7 +821,6 @@ 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.*/ 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 d456bf138..c0f041a43 100644 --- a/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c +++ b/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c @@ -52,6 +52,14 @@ USART_CR3_CTSIE | \ USART_CR3_EIE) +/* This mask includes IDLE, ORE, NE, FE, PE bits.*/ +#define USART_ISR_IONFP_Pos USART_ISR_PE_Pos +#define USART_ISR_IONFP_Msk (0x1FUL << USART_ISR_IONFP_Pos) + +/* This mask includes ORE, NE, FE, PE bits.*/ +#define USART_ISR_ONFP_Pos USART_ISR_PE_Pos +#define USART_ISR_ONFP_Msk (0xFUL << USART_ISR_ONFP_Pos) + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ @@ -167,7 +175,7 @@ __STATIC_INLINE void usart_enable_rx_irq(SIODriver *siop) { __STATIC_INLINE void usart_enable_rx_errors_irq(SIODriver *siop) { siop->usart->CR1 |= __sio_reloc_field(siop->enabled, SIO_EV_PARITY_ERR, SIO_EV_PARITY_ERR_POS, USART_CR1_PEIE_Pos); - siop->usart->CR2 |= __sio_reloc_field(siop->enabled, SIO_EV_BREAK, SIO_EV_BREAK_POS, USART_CR2_LBDIE_Pos); + siop->usart->CR2 |= __sio_reloc_field(siop->enabled, SIO_EV_RXBREAK, SIO_EV_RXBREAK_POS, USART_CR2_LBDIE_Pos); /* The following 3 are grouped.*/ if ((siop->enabled & (SIO_EV_FRAMING_ERR | @@ -517,7 +525,7 @@ void sio_lld_update_enable_flags(SIODriver *siop) { cr1 |= __sio_reloc_field(siop->enabled, SIO_EV_RXIDLE, SIO_EV_RXIDLE_POS, USART_CR1_IDLEIE_Pos) | __sio_reloc_field(siop->enabled, SIO_EV_TXDONE, SIO_EV_TXDONE_POS, USART_CR1_TCIE_Pos) | __sio_reloc_field(siop->enabled, SIO_EV_PARITY_ERR, SIO_EV_PARITY_ERR_POS, USART_CR1_PEIE_Pos); - cr2 |= __sio_reloc_field(siop->enabled, SIO_EV_BREAK, SIO_EV_BREAK_POS, USART_CR2_LBDIE_Pos); + cr2 |= __sio_reloc_field(siop->enabled, SIO_EV_RXBREAK, SIO_EV_RXBREAK_POS, USART_CR2_LBDIE_Pos); cr3 |= __sio_reloc_field(siop->enabled, SIO_EV_RXNOTEMPY, SIO_EV_RXNOTEMPY_POS, USART_CR3_RXFTIE_Pos) | __sio_reloc_field(siop->enabled, SIO_EV_TXNOTFULL, SIO_EV_TXNOTFULL_POS, USART_CR3_TXFTIE_Pos); @@ -544,7 +552,7 @@ void sio_lld_update_enable_flags(SIODriver *siop) { */ sioevents_t sio_lld_get_and_clear_errors(SIODriver *siop) { uint32_t isr; - sioevents_t errors = (sioevents_t)0; + sioevents_t errors; /* Getting all error ISR flags (and only those). NOTE: Do not trust the position of other bits in ISR/ICR because @@ -560,11 +568,8 @@ sioevents_t sio_lld_get_and_clear_errors(SIODriver *siop) { usart_enable_rx_errors_irq(siop); /* Translating the status flags in SIO events.*/ - errors |= __sio_reloc_field(isr, USART_ISR_LBDF_Msk, USART_ISR_LBDF_Pos, SIO_EV_BREAK_POS) | - __sio_reloc_field(isr, USART_ISR_PE_Msk, USART_ISR_PE_Pos, SIO_EV_PARITY_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_FE_Msk, USART_ISR_FE_Pos, SIO_EV_FRAMING_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_NE_Msk, USART_ISR_NE_Pos, SIO_EV_NOISE_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_ORE_Msk, USART_ISR_ORE_Pos, SIO_EV_OVERRUN_ERR_POS); + errors = __sio_reloc_field(isr, USART_ISR_ONFP_Msk, USART_ISR_ONFP_Pos, SIO_EV_ALL_ERRORS_POS) | + __sio_reloc_field(isr, USART_ISR_LBDF_Msk, USART_ISR_LBDF_Pos, SIO_EV_RXBREAK_POS); return errors; } @@ -579,16 +584,16 @@ sioevents_t sio_lld_get_and_clear_errors(SIODriver *siop) { */ sioevents_t sio_lld_get_and_clear_events(SIODriver *siop) { uint32_t isr; - sioevents_t events = (sioevents_t)0; + sioevents_t events; /* Getting all ISR flags. NOTE: Do not trust the position of other bits in ISR/ICR because some scientist decided to use different positions for some of them.*/ isr = siop->usart->ISR & (SIO_LLD_ISR_RX_ERRORS | - USART_ISR_RXNE_RXFNE | + USART_ISR_RXNE | USART_ISR_IDLE | - USART_ISR_TXE_TXFNF | + USART_ISR_TXE | USART_ISR_TC); /* Clearing captured events.*/ @@ -600,15 +605,11 @@ sioevents_t sio_lld_get_and_clear_events(SIODriver *siop) { usart_enable_rx_errors_irq(siop); /* Translating the status flags in SIO events.*/ - events |= __sio_reloc_field(isr, USART_ISR_RXNE_RXFNE_Msk, USART_ISR_RXNE_RXFNE_Pos, SIO_EV_RXNOTEMPY_POS) | - __sio_reloc_field(isr, USART_ISR_TXE_TXFNF_Msk, USART_ISR_TXE_TXFNF_Pos, SIO_EV_TXNOTFULL_POS) | - __sio_reloc_field(isr, USART_ISR_IDLE_Msk, USART_ISR_IDLE_Pos, SIO_EV_RXIDLE_POS) | - __sio_reloc_field(isr, USART_ISR_TC_Msk, USART_ISR_TC_Pos, SIO_EV_TXDONE_POS) | - __sio_reloc_field(isr, USART_ISR_LBDF_Msk, USART_ISR_LBDF_Pos, SIO_EV_BREAK_POS) | - __sio_reloc_field(isr, USART_ISR_PE_Msk, USART_ISR_PE_Pos, SIO_EV_PARITY_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_FE_Msk, USART_ISR_FE_Pos, SIO_EV_FRAMING_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_NE_Msk, USART_ISR_NE_Pos, SIO_EV_NOISE_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_ORE_Msk, USART_ISR_ORE_Pos, SIO_EV_OVERRUN_ERR_POS); + events = __sio_reloc_field(isr, USART_ISR_RXNE_Msk, USART_ISR_RXNE_Pos, SIO_EV_RXNOTEMPY_POS) | + __sio_reloc_field(isr, USART_ISR_TXE_Msk, USART_ISR_TXE_Pos, SIO_EV_TXNOTFULL_POS) | + __sio_reloc_field(isr, USART_ISR_TC_Msk, USART_ISR_TC_Pos, SIO_EV_TXDONE_POS) | + __sio_reloc_field(isr, USART_ISR_IONFP_Msk, USART_ISR_IONFP_Pos, SIO_EV_ALL_ERRORS_POS) | + __sio_reloc_field(isr, USART_ISR_LBDF_Msk, USART_ISR_LBDF_Pos, SIO_EV_RXBREAK_POS); return events; } @@ -627,21 +628,17 @@ sioevents_t sio_lld_get_events(SIODriver *siop) { /* Getting all ISR flags.*/ isr = siop->usart->ISR & (SIO_LLD_ISR_RX_ERRORS | - USART_ISR_RXNE_RXFNE | + USART_ISR_RXNE | USART_ISR_IDLE | - USART_ISR_TXE_TXFNF | + USART_ISR_TXE | USART_ISR_TC); /* Translating the status flags in SIO events.*/ - events = __sio_reloc_field(isr, USART_ISR_RXNE_RXFNE_Msk, USART_ISR_RXNE_RXFNE_Pos, SIO_EV_RXNOTEMPY_POS) | - __sio_reloc_field(isr, USART_ISR_TXE_TXFNF_Msk, USART_ISR_TXE_TXFNF_Pos, SIO_EV_TXNOTFULL_POS) | - __sio_reloc_field(isr, USART_ISR_IDLE_Msk, USART_ISR_IDLE_Pos, SIO_EV_RXIDLE_POS) | - __sio_reloc_field(isr, USART_ISR_TC_Msk, USART_ISR_TC_Pos, SIO_EV_TXDONE_POS) | - __sio_reloc_field(isr, USART_ISR_LBDF_Msk, USART_ISR_LBDF_Pos, SIO_EV_BREAK_POS) | - __sio_reloc_field(isr, USART_ISR_PE_Msk, USART_ISR_PE_Pos, SIO_EV_PARITY_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_FE_Msk, USART_ISR_FE_Pos, SIO_EV_FRAMING_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_NE_Msk, USART_ISR_NE_Pos, SIO_EV_NOISE_ERR_POS) | - __sio_reloc_field(isr, USART_ISR_ORE_Msk, USART_ISR_ORE_Pos, SIO_EV_OVERRUN_ERR_POS); + events = __sio_reloc_field(isr, USART_ISR_RXNE_Msk, USART_ISR_RXNE_Pos, SIO_EV_RXNOTEMPY_POS) | + __sio_reloc_field(isr, USART_ISR_TXE_Msk, USART_ISR_TXE_Pos, SIO_EV_TXNOTFULL_POS) | + __sio_reloc_field(isr, USART_ISR_TC_Msk, USART_ISR_TC_Pos, SIO_EV_TXDONE_POS) | + __sio_reloc_field(isr, USART_ISR_IONFP_Msk, USART_ISR_IONFP_Pos, SIO_EV_ALL_ERRORS_POS) | + __sio_reloc_field(isr, USART_ISR_LBDF_Msk, USART_ISR_LBDF_Pos, SIO_EV_RXBREAK_POS); return events; } @@ -796,35 +793,31 @@ msg_t sio_lld_control(SIODriver *siop, unsigned int operation, void *arg) { */ void sio_lld_serve_interrupt(SIODriver *siop) { USART_TypeDef *u = siop->usart; - uint32_t isr; - uint32_t cr1, cr2, cr3; + sioevents_t events; + uint32_t cr1, cr3; osalDbgAssert(siop->state == SIO_READY, "invalid state"); /* Read on control registers.*/ cr1 = u->CR1; - cr2 = u->CR2; cr3 = u->CR3; - /* Note, ISR flags are just read but not cleared, ISR sources are - disabled instead.*/ - isr = u->ISR; - if (isr != 0U) { + /* Events to be processed.*/ + events = sio_lld_get_events(siop) & siop->enabled; + if (events != 0U) { /* Error events handled as a group.*/ - if ((isr & (USART_ISR_LBDF | USART_ISR_NE | USART_ISR_FE | - USART_ISR_PE | USART_ISR_ORE)) != 0U) { - + if ((events & SIO_EV_ALL_ERRORS) != 0U) { #if SIO_USE_SYNCHRONIZATION /* The idle flag is forcibly cleared when an RX error event is detected.*/ u->ICR = USART_ICR_IDLECF; #endif - /* RX-related interrupt sources akll disabled.*/ - cr3 &= ~(USART_CR3_EIE | USART_CR3_RXFTIE); - cr2 &= ~(USART_CR2_LBDIE); - cr1 &= ~(USART_CR1_PEIE | USART_CR1_IDLEIE); + /* 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); /* Waiting thread woken, if any.*/ __sio_wakeup_errors(siop); @@ -832,7 +825,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { /* If there are no errors then we check for the other RX events.*/ else { /* Idle RX event.*/ - if ((isr & USART_ISR_IDLE) != 0U) { + if ((events & SIO_EV_RXIDLE) != 0U) { /* Interrupt source disabled.*/ cr1 &= ~USART_CR1_IDLEIE; @@ -842,7 +835,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { } /* RX FIFO is non-empty.*/ - if ((isr & USART_ISR_RXFT) != 0U) { + if ((events & SIO_EV_RXNOTEMPY) != 0U) { #if SIO_USE_SYNCHRONIZATION /* The idle flag is forcibly cleared when an RX data event is @@ -859,7 +852,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { } /* TX FIFO is non-full.*/ - if ((isr & USART_ISR_TXFT) != 0U) { + if ((events & SIO_EV_TXNOTFULL) != 0U) { /* Interrupt source disabled.*/ cr3 &= ~USART_CR3_TXFTIE; @@ -869,7 +862,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { } /* Physical transmission end.*/ - if ((isr & USART_ISR_TC) != 0U) { + if ((events & SIO_EV_TXDONE) != 0U) { /* Interrupt source disabled.*/ cr1 &= ~USART_CR1_TCIE; @@ -880,7 +873,6 @@ 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.*/ diff --git a/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.h b/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.h index b08245701..f1cdfa7e9 100644 --- a/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.h +++ b/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.h @@ -40,6 +40,28 @@ USART_ISR_PE | USART_ISR_ORE | \ USART_ISR_LBDF) +/* Using shorter definitions of USARTv2 in order to make code more + similar.*/ +#if !defined(USART_ISR_RXNE_Pos) +#define USART_ISR_RXNE_Pos USART_ISR_RXNE_RXFNE_Pos +#endif +#if !defined(USART_ISR_RXNE_Msk) +#define USART_ISR_RXNE_Msk USART_ISR_RXNE_RXFNE_Msk +#endif +#if !defined(USART_ISR_RXNE) +#define USART_ISR_RXNE USART_ISR_RXNE_Msk +#endif + +#if !defined(USART_ISR_TXE_Pos) +#define USART_ISR_TXE_Pos USART_ISR_TXE_TXFNF_Pos +#endif +#if !defined(USART_ISR_TXE_Msk) +#define USART_ISR_TXE_Msk USART_ISR_TXE_TXFNF_Msk +#endif +#if !defined(USART_ISR_TXE) +#define USART_ISR_TXE USART_ISR_TXE_Msk +#endif + /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ @@ -341,7 +363,7 @@ * @notapi */ #define sio_lld_is_rx_empty(siop) \ - (bool)(((siop)->usart->ISR & USART_ISR_RXNE_RXFNE) == 0U) + (bool)(((siop)->usart->ISR & USART_ISR_RXNE) == 0U) /** * @brief Determines the activity state of the receiver. @@ -382,7 +404,7 @@ * @notapi */ #define sio_lld_is_tx_full(siop) \ - (bool)(((siop)->usart->ISR & USART_ISR_TXE_TXFNF) == 0U) + (bool)(((siop)->usart->ISR & USART_ISR_TXE) == 0U) /** * @brief Determines the transmission state. diff --git a/os/hal/ports/sandbox/hal_sio_lld.c b/os/hal/ports/sandbox/hal_sio_lld.c index 36d523860..d0735487d 100644 --- a/os/hal/ports/sandbox/hal_sio_lld.c +++ b/os/hal/ports/sandbox/hal_sio_lld.c @@ -454,10 +454,8 @@ void sio_lld_serve_interrupt(SIODriver *siop) { __syscall2rr(201, SB_VUART_GEVT, siop->nvuart); osalDbgAssert((msg_t)r0 == HAL_RET_SUCCESS, "unexpected failure"); - /* Only processing enabled events.*/ - events = (sioevents_t)r1; - /* Processing events, if any.*/ + events = (sioevents_t)r1; if (events != (sioevents_t)0) { /* The callback is finally invoked.*/