From 11c7c2bf2a766695284f08a5586b41dfc304daa3 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Fri, 2 Sep 2022 12:01:53 +0000 Subject: [PATCH] Tentative SIO optimization (STM32 USARTv3-only so far). git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15749 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c | 67 ++++++++------------ os/hal/src/hal_sio.c | 8 +-- testhal/STM32/multi/SIO/main.c | 8 --- 3 files changed, 32 insertions(+), 51 deletions(-) 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 042d1786b..f8d8af43c 100644 --- a/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c +++ b/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c @@ -565,8 +565,9 @@ 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 RX-related interrupts can be enabled again.*/ + usart_enable_rx_irq(siop); usart_enable_rx_errors_irq(siop); /* Translating the status flags in SIO events.*/ @@ -806,7 +807,7 @@ 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 isr; uint32_t cr1, cr2, cr3; osalDbgAssert(siop->state == SIO_READY, "invalid state"); @@ -816,23 +817,9 @@ void sio_lld_serve_interrupt(SIODriver *siop) { 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(cr1, USART_CR1_PEIE_Msk, USART_CR1_PEIE_Pos, USART_ISR_PE_Pos) | - __sio_reloc_field(cr2, USART_CR2_LBDIE_Msk, USART_CR2_LBDIE_Pos, USART_ISR_LBDF_Pos) | - __sio_reloc_field(cr1, USART_CR1_IDLEIE_Msk, USART_CR1_IDLEIE_Pos, USART_ISR_IDLE_Pos) | - __sio_reloc_field(cr3, USART_CR3_RXFTIE_Msk, USART_CR3_RXFTIE_Pos, USART_ISR_RXFT_Pos) | - __sio_reloc_field(cr3, USART_CR3_TXFTIE_Msk, USART_CR3_TXFTIE_Pos, USART_ISR_TXFT_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.*/ @@ -845,39 +832,41 @@ void sio_lld_serve_interrupt(SIODriver *siop) { u->ICR = USART_ICR_IDLECF; #endif - /* Interrupt sources disabled.*/ - cr3 &= ~USART_CR3_EIE; - cr2 &= ~USART_CR2_LBDIE; - cr1 &= ~USART_CR1_PEIE; + /* RX-related interrupt sources akll disabled.*/ + cr3 &= ~(USART_CR3_EIE | USART_CR3_RXFTIE); + cr2 &= ~(USART_CR2_LBDIE); + cr1 &= ~(USART_CR1_PEIE | USART_CR1_IDLEIE); /* 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 ((isr & USART_ISR_IDLE) != 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 ((isr & USART_ISR_RXFT) != 0U) { - /* RX FIFO is non-empty.*/ - if ((isr & USART_ISR_RXFT) != 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.*/ + cr3 &= ~USART_CR3_RXFTIE; - /* Interrupt source disabled.*/ - cr3 &= ~USART_CR3_RXFTIE; - - /* Waiting thread woken, if any.*/ - __sio_wakeup_rx(siop); + /* Waiting thread woken, if any.*/ + __sio_wakeup_rx(siop); + } } /* TX FIFO is non-full.*/ diff --git a/os/hal/src/hal_sio.c b/os/hal/src/hal_sio.c index 216d50674..b990cae9b 100644 --- a/os/hal/src/hal_sio.c +++ b/os/hal/src/hal_sio.c @@ -518,7 +518,7 @@ size_t sioAsyncWrite(SIODriver *siop, const uint8_t *buffer, size_t n) { * @retval MSG_OK if there is data in the RX FIFO. * @retval MSG_TIMEOUT if synchronization timed out. * @retval MSG_RESET it the operation has been stopped while waiting. - * @retval SIO_MSG_ERRORS if RX errors occurred during wait. + * @retval SIO_MSG_ERRORS if RX errors occurred before or during wait. * * @api */ @@ -532,7 +532,7 @@ msg_t sioSynchronizeRX(SIODriver *siop, sysinterval_t timeout) { osalDbgAssert(siop->state == SIO_READY, "invalid state"); /* Checking for errors before going to sleep.*/ - if (((siop->enabled & SIO_EV_ALL_ERRORS) != 0U) && sioHasRXErrorsX(siop)) { + if (sioHasRXErrorsX(siop)) { osalSysUnlock(); return SIO_MSG_ERRORS; } @@ -563,7 +563,7 @@ msg_t sioSynchronizeRX(SIODriver *siop, sysinterval_t timeout) { * @retval MSG_OK if RW went idle. * @retval MSG_TIMEOUT if synchronization timed out. * @retval MSG_RESET it the operation has been stopped while waiting. - * @retval SIO_MSG_ERRORS if RX errors occurred during wait. + * @retval SIO_MSG_ERRORS if RX errors occurred before or during wait. * * @api */ @@ -577,7 +577,7 @@ msg_t sioSynchronizeRXIdle(SIODriver *siop, sysinterval_t timeout) { osalDbgAssert(siop->state == SIO_READY, "invalid state"); /* Checking for errors before going to sleep.*/ - if (((siop->enabled & SIO_EV_ALL_ERRORS) != 0U) && sioHasRXErrorsX(siop)) { + if (sioHasRXErrorsX(siop)) { osalSysUnlock(); return SIO_MSG_ERRORS; } diff --git a/testhal/STM32/multi/SIO/main.c b/testhal/STM32/multi/SIO/main.c index 73f24769f..03f5e2d34 100644 --- a/testhal/STM32/multi/SIO/main.c +++ b/testhal/STM32/multi/SIO/main.c @@ -60,15 +60,7 @@ static void cmd_write(BaseSequentialStream *chp, int argc, char *argv[]) { } while (chnGetTimeout((BaseChannel *)chp, TIME_IMMEDIATE) == Q_TIMEOUT) { -#if 1 - /* Writing in channel mode.*/ chnWrite(&bsio1, buf, sizeof buf - 1); -#else - /* Writing in buffer mode.*/ - (void) obqGetEmptyBufferTimeout(&PORTAB_SDU1.obqueue, TIME_INFINITE); - memcpy(PORTAB_SDU1.obqueue.ptr, buf, SERIAL_USB_BUFFERS_SIZE); - obqPostFullBuffer(&PORTAB_SDU1.obqueue, SERIAL_USB_BUFFERS_SIZE); -#endif } chprintf(chp, "\r\n\nstopped\r\n"); }