From 3ae922fc324ced235ae73b6a82db72e5465e3925 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Sat, 29 Aug 2020 14:41:43 +0000 Subject: [PATCH] More work on SIO driver. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@13814 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- os/hal/include/hal_sio.h | 9 +- os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c | 352 +++++++++++++++++-- os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.h | 203 ++++++++++- os/hal/src/hal_sio.c | 2 +- 4 files changed, 528 insertions(+), 38 deletions(-) diff --git a/os/hal/include/hal_sio.h b/os/hal/include/hal_sio.h index f64b6db9c..09fac7bba 100644 --- a/os/hal/include/hal_sio.h +++ b/os/hal/include/hal_sio.h @@ -157,12 +157,17 @@ struct hal_sio_driver { */ struct hal_sio_operation { /** - * @brief Receive buffer filled callback. + * @brief Receive non-empty callback. * @note Can be @p NULL. */ siocb_t rx_cb; /** - * @brief End of transmission buffer callback. + * @brief Receive idle callback. + * @note Can be @p NULL. + */ + siocb_t rx_idle_cb; + /** + * @brief Transmission buffer non-full callback. * @note Can be @p NULL. */ siocb_t tx_cb; 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 99b53ec09..ec94ed12b 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c +++ b/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c @@ -30,17 +30,95 @@ /* Driver local definitions. */ /*===========================================================================*/ +#define USART_CR1_CFG_FORBIDDEN (USART_CR1_RXFFIE | \ + USART_CR1_TXFEIE | \ + USART_CR1_FIFOEN | \ + USART_CR1_EOBIE | \ + USART_CR1_RTOIE | \ + USART_CR1_CMIE | \ + USART_CR1_PEIE | \ + USART_CR1_TXEIE_TXFNFIE | \ + USART_CR1_TCIE | \ + USART_CR1_RXNEIE_RXFNEIE | \ + USART_CR1_IDLEIE | \ + USART_CR1_TE | \ + USART_CR1_RE | \ + USART_CR1_UE) +#define USART_CR2_CFG_FORBIDDEN (USART_CR2_LBDIE) +#define USART_CR3_CFG_FORBIDDEN (USART_CR3_RXFTIE | \ + USART_CR3_TCBGTIE | \ + USART_CR3_TXFTIE | \ + USART_CR3_WUFIE | \ + USART_CR3_CTSIE | \ + USART_CR3_EIE) + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ /** - * @brief SIO1 driver identifier. + * @brief USART1 SIO driver identifier. */ #if (STM32_SIO_USE_USART1 == TRUE) || defined(__DOXYGEN__) SIODriver SIOD1; #endif +/** + * @brief USART2 SIO driver identifier. + */ +#if (STM32_SIO_USE_USART2 == TRUE) || defined(__DOXYGEN__) +SIODriver SIOD2; +#endif + +/** + * @brief USART3 SIO driver identifier. + */ +#if (STM32_SIO_USE_USART3 == TRUE) || defined(__DOXYGEN__) +SIODriver SIOD3; +#endif + +/** + * @brief UART4 SIO driver identifier. + */ +#if (STM32_SIO_USE_UART4 == TRUE) || defined(__DOXYGEN__) +SIODriver SIOD4; +#endif + +/** + * @brief UART5 SIO driver identifier. + */ +#if (STM32_SIO_USE_UART5 == TRUE) || defined(__DOXYGEN__) +SIODriver SIOD5; +#endif + +/** + * @brief USART6 SIO driver identifier. + */ +#if (STM32_SIO_USE_USART6 == TRUE) || defined(__DOXYGEN__) +SIODriver SIOD6; +#endif + +/** + * @brief UART7 SIO driver identifier. + */ +#if (STM32_SIO_USE_UART7 == TRUE) || defined(__DOXYGEN__) +SIODriver SIOD7; +#endif + +/** + * @brief UART8 SIO driver identifier. + */ +#if (STM32_SIO_USE_UART8 == TRUE) || defined(__DOXYGEN__) +SIODriver SIOD8; +#endif + +/** + * @brief LPUART1 SIO driver identifier. + */ +#if (STM32_SIO_USE_LPUART1 == TRUE) || defined(__DOXYGEN__) +SIODriver LPSIOD1; +#endif + /*===========================================================================*/ /* Driver local variables and types. */ /*===========================================================================*/ @@ -49,6 +127,55 @@ SIODriver SIOD1; /* Driver local functions. */ /*===========================================================================*/ +/** + * @brief USART initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] siop pointer to a @p SIODriver object + */ +static void usart_init(SIODriver *siop) { + USART_TypeDef *u = siop->usart; + uint32_t cr1, presc, brr; + + /* Prescaler calculation.*/ + static const uint32_t prescvals[] = {1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256}; + presc = prescvals[siop->config->presc]; + + /* Baud rate setting.*/ +#if STM32_SIO_USE_LPUART1 + if (siop == &LPSIOD1) { + osalDbgAssert((siop->clock >= siop->config->baud * 3U) && + (siop->clock <= siop->config->baud * 4096U), + "invalid baud rate vs input clock"); + + brr = (uint32_t)(((uint64_t)(siop->clock / presc) * (uint64_t)256) / siop->config->speed); + + osalDbgAssert((brr >= 0x300) && (brr < 0x100000), "invalid BRR value"); + } + else +#endif + { + brr = (uint32_t)((siop->clock / presc) / siop->config->baud); + + /* Correcting BRR value when oversampling by 8 instead of 16. + Fraction is still 4 bits wide, but only lower 3 bits used. + Mantissa is doubled, but Fraction is left the same.*/ + if ((siop->config->cr1 & USART_CR1_OVER8) != 0U) { + brr = ((brr & ~7U) * 2U) | (brr & 7U); + } + + osalDbgAssert(brr < 0x10000, "invalid BRR value"); + } + + /* 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->ICR = u->ISR; +} + /*===========================================================================*/ /* Driver interrupt handlers. */ /*===========================================================================*/ @@ -64,10 +191,53 @@ SIODriver SIOD1; */ void sio_lld_init(void) { + /* Driver instances initialization.*/ #if STM32_SIO_USE_USART1 == TRUE - /* Driver initialization.*/ sioObjectInit(&SIOD1); + SIOD1.usart = USART1; + SIOD1.clock = STM32_USART1CLK; #endif +#if STM32_SIO_USE_USART2 == TRUE + sioObjectInit(&SIOD2); + SIOD2.usart = USART2; + SIOD2.clock = STM32_USART2CLK; +#endif +#if STM32_SIO_USE_USART3 == TRUE + sioObjectInit(&SIOD3); + SIOD3.usart = USART3; + SIOD3.clock = STM32_USART3CLK; +#endif +#if STM32_SIO_USE_UART4 == TRUE + sioObjectInit(&SIOD4); + SIOD4.usart = UART4; + SIOD4.clock = STM32_UART4CLK; +#endif +#if STM32_SIO_USE_UART5 == TRUE + sioObjectInit(&SIOD5); + SIOD5.usart = UART5; + SIOD5.clock = STM32_UART5CLK; +#endif +#if STM32_SIO_USE_USART6 == TRUE + sioObjectInit(&SIOD6); + SIOD6.usart = USART6; + SIOD6.clock = STM32_USART6CLK; +#endif +#if STM32_SIO_USE_UART7 == TRUE + sioObjectInit(&SIOD7); + SIOD7.usart = UART7; + SIOD7.clock = STM32_UART7CLK; +#endif +#if STM32_SIO_USE_UART8 == TRUE + sioObjectInit(&SIOD8); + SIOD8.usart = UART8; + SIOD8.clock = STM32_UART8CLK; +#endif +#if STM32_SIO_USE_LPUART1 == TRUE + sioObjectInit(&LPSIOD1); + LPSIOD1.usart = LPUART1; + LPSIOD1.clock = STM32_LPUART1CLK; +#endif + } /** @@ -83,17 +253,159 @@ void sio_lld_init(void) { bool sio_lld_start(SIODriver *siop) { if (siop->state == SIO_STOP) { - /* Enables the peripheral.*/ -#if STM32_SIO_USE_USART1 == TRUE - if (&SIOD1 == siop) { + /* Enables the peripheral.*/ + if (false) { + } +#if STM32_SIO_USE_USART1 == TRUE + else if (&SIOD1 == siop) { + rccResetUSART1(); + rccEnableUSART1(true); } +#endif +#if STM32_SIO_USE_USART2 == TRUE + else if (&SIOD2 == siop) { + rccResetUSART2(); + rccEnableUSART2(true); + } +#endif +#if STM32_SIO_USE_USART3 == TRUE + else if (&SIOD3 == siop) { + rccResetUSART3(); + rccEnableUSART3(true); + } +#endif +#if STM32_SIO_USE_UART4 == TRUE + else if (&SIOD4 == siop) { + rccResetUART4(); + rccEnableUART4(true); + } +#endif +#if STM32_SIO_USE_UART5 == TRUE + else if (&SIOD5 == siop) { + rccResetUART5(); + rccEnableUART5(true); + } +#endif +#if STM32_SIO_USE_USART6 == TRUE + else if (&SIOD6 == siop) { + rccResetUSART6(); + rccEnableUSART6(true); + } +#endif +#if STM32_SIO_USE_UART7 == TRUE + else if (&SIOD7 == siop) { + rccResetUART7(); + rccEnableUART7(true); + } +#endif +#if STM32_SIO_USE_UART8 == TRUE + else if (&SIOD8 == siop) { + rccResetUART8(); + rccEnableUART8(true); + } +#endif +#if STM32_SIO_USE_LPUART1 == TRUE + else if (&LPSIOD1 == siop) { + rccResetLPUART1(); + rccEnableLPUART1(true); + } +#endif + else { + osalDbgAssert(false, "invalid USART instance"); + } + + /* Driver object low level initializations.*/ +#if HAL_SIO_USE_SYNCHRONIZATION + siop->sync_rx = NULL; + siop->sync_tx = NULL; + siop->sync_txend = NULL; + siop->events = 0U; #endif } + /* Configures the peripheral.*/ + usart_init(siop); return false; } + + +/** + * @brief Deactivates the SIO peripheral. + * + * @param[in] siop pointer to the @p SIODriver object + * + * @notapi + */ +void sio_lld_stop(SIODriver *siop) { + + if (siop->state == SIO_READY) { + /* Resets the peripheral.*/ + + /* Disables the peripheral.*/ + if (false) { + } +#if STM32_SIO_USE_USART1 == TRUE + else if (&SIOD1 == siop) { + rccResetUSART1(); + rccDisableUSART1(); + } +#endif +#if STM32_SIO_USE_USART2 == TRUE + else if (&SIOD2 == siop) { + rccResetUSART2(); + rccDisableUSART2(); + } +#endif +#if STM32_SIO_USE_USART3 == TRUE + else if (&SIOD3 == siop) { + rccResetUSART3(); + rccDisableUSART3(); + } +#endif +#if STM32_SIO_USE_UART4 == TRUE + else if (&SIOD4 == siop) { + rccResetUART4(); + rccDisableUART4(); + } +#endif +#if STM32_SIO_USE_UART5 == TRUE + else if (&SIOD5 == siop) { + rccResetUART5(); + rccDisableUART5(); + } +#endif +#if STM32_SIO_USE_USART6 == TRUE + else if (&SIOD6 == siop) { + rccResetUSART6(); + rccDisableUSART6(); + } +#endif +#if STM32_SIO_USE_UART7 == TRUE + else if (&SIOD7 == siop) { + rccResetUART7(); + rccDisableUART7(); + } +#endif +#if STM32_SIO_USE_UART8 == TRUE + else if (&SIOD8 == siop) { + rccResetUART8(); + rccDisableUART8(); + } +#endif +#if STM32_SIO_USE_LPUART1 == TRUE + else if (&LPSIOD1 == siop) { + rccResetLPUART1(); + rccDisableLPUART1(); + } +#endif + else { + osalDbgAssert(false, "invalid USART instance"); + } + } +} + /** * @brief Starts a SIO operation. * @@ -114,26 +426,6 @@ void sio_lld_start_operation(SIODriver *siop) { void sio_lld_stop_operation(SIODriver *siop) { } -/** - * @brief Deactivates the SIO peripheral. - * - * @param[in] siop pointer to the @p SIODriver object - * - * @notapi - */ -void sio_lld_stop(SIODriver *siop) { - - if (siop->state == SIO_READY) { - /* Resets the peripheral.*/ - - /* Disables the peripheral.*/ -#if STM32_SIO_USE_USART1 == TRUE - if (&SIOD1 == siop) { - - } -#endif - } -} /** * @brief Reads data from the RX FIFO. * @details The function is not blocking, it writes frames until there @@ -152,11 +444,11 @@ size_t sio_lld_read(SIODriver *siop, size_t n, uint8_t *buffer) { while (true) { #if USART_ENABLE_INTERRUPTS == TRUE - /* If the RX FIFO has been emptied then the interrupt is enabled again.*/ - if (sio_lld_is_rx_empty(siop)) { - siop->usart->CR3 |= USART_CR3_RXFTIE; - break; - } + /* If the RX FIFO has been emptied then the interrupt is enabled again.*/ + if (sio_lld_is_rx_empty(siop)) { + siop->usart->CR3 |= USART_CR3_RXFTIE; + break; + } #endif /* Buffer filled condition.*/ diff --git a/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.h b/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.h index 7226f91af..3904ce1c6 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.h +++ b/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.h @@ -40,19 +40,176 @@ * @{ */ /** - * @brief SIO driver enable switch. - * @details If set to @p TRUE the support for SIO1 is included. + * @brief SIO driver 1 enable switch. + * @details If set to @p TRUE the support for USART1 is included. * @note The default is @p FALSE. */ #if !defined(STM32_SIO_USE_USART1) || defined(__DOXYGEN__) #define STM32_SIO_USE_USART1 FALSE #endif + +/** + * @brief SIO driver 2 enable switch. + * @details If set to @p TRUE the support for USART2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SIO_USE_USART2) || defined(__DOXYGEN__) +#define STM32_SIO_USE_USART2 FALSE +#endif + +/** + * @brief SIO driver 3 enable switch. + * @details If set to @p TRUE the support for USART3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SIO_USE_USART3) || defined(__DOXYGEN__) +#define STM32_SIO_USE_USART3 FALSE +#endif + +/** + * @brief SIO driver 4 enable switch. + * @details If set to @p TRUE the support for UART4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SIO_USE_UART4) || defined(__DOXYGEN__) +#define STM32_SIO_USE_UART4 FALSE +#endif + +/** + * @brief SIO driver 5 enable switch. + * @details If set to @p TRUE the support for UART5 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SIO_USE_UART5) || defined(__DOXYGEN__) +#define STM32_SIO_USE_UART5 FALSE +#endif + +/** + * @brief SIO driver 6 enable switch. + * @details If set to @p TRUE the support for USART6 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SIO_USE_USART6) || defined(__DOXYGEN__) +#define STM32_SIO_USE_USART6 FALSE +#endif + +/** + * @brief SIO driver 7 enable switch. + * @details If set to @p TRUE the support for UART7 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SIO_USE_UART7) || defined(__DOXYGEN__) +#define STM32_SIO_USE_UART7 FALSE +#endif + +/** + * @brief SIO driver 8 enable switch. + * @details If set to @p TRUE the support for UART8 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SIO_USE_UART8) || defined(__DOXYGEN__) +#define STM32_SIO_USE_UART8 FALSE +#endif + +/** + * @brief SIO driver 8 enable switch. + * @details If set to @p TRUE the support for LPUART1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SIO_USE_ULPUART1) || defined(__DOXYGEN__) +#define STM32_SIO_USE_LPUART1 FALSE +#endif /** @} */ /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ +#if STM32_SIO_USE_USART1 && !STM32_HAS_USART1 +#error "USART1 not present in the selected device" +#endif + +#if !STM32_SIO_USE_USART1 && !STM32_SIO_USE_USART2 && \ + !STM32_SIO_USE_USART3 && !STM32_SIO_USE_UART4 && \ + !STM32_SIO_USE_UART5 && !STM32_SIO_USE_USART6 && \ + !STM32_SIO_USE_UART7 && !STM32_SIO_USE_UART8 && \ + !STM32_SIO_USE_LPUART1 +#error "SIO driver activated but no USART/UART peripheral assigned" +#endif + +/* Checks on allocation of USARTx units.*/ +#if STM32_SIO_USE_USART1 +#if defined(STM32_USART1_IS_USED) +#error "SIOD1 requires USART1 but it is already used" +#else +#define STM32_USART1_IS_USED +#endif +#endif + +#if STM32_SIO_USE_USART2 +#if defined(STM32_USART2_IS_USED) +#error "SIOD2 requires USART2 but it is already used" +#else +#define STM32_USART2_IS_USED +#endif +#endif + +#if STM32_SIO_USE_USART3 +#if defined(STM32_USART3_IS_USED) +#error "SIOD3 requires USART3 but it is already used" +#else +#define STM32_USART3_IS_USED +#endif +#endif + +#if STM32_SIO_USE_UART4 +#if defined(STM32_UART4_IS_USED) +#error "SIOD4 requires UART4 but it is already used" +#else +#define STM32_UART4_IS_USED +#endif +#endif + +#if STM32_SIO_USE_UART5 +#if defined(STM32_UART5_IS_USED) +#error "SIOD5 requires UART5 but it is already used" +#else +#define STM32_UART5_IS_USED +#endif +#endif + +#if STM32_SIO_USE_USART6 +#if defined(STM32_USART6_IS_USED) +#error "SIOD6 requires USART6 but it is already used" +#else +#define STM32_USART6_IS_USED +#endif +#endif + +#if STM32_SIO_USE_UART7 +#if defined(STM32_UART7_IS_USED) +#error "SIOD7 requires UART7 but it is already used" +#else +#define STM32_UART7_IS_USED +#endif +#endif + +#if STM32_SIO_USE_UART8 +#if defined(STM32_UART8_IS_USED) +#error "SIOD8 requires UART8 but it is already used" +#else +#define STM32_UART8_IS_USED +#endif +#endif + +#if STM32_SIO_USE_LPUART1 +#if defined(STM32_LPUART1_IS_USED) +#error "LPSIOD1 requires LPUART1 but it is already used" +#else +#define STM32_LPUART1_IS_USED +#endif +#endif + /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ @@ -66,7 +223,11 @@ */ #define sio_lld_driver_fields \ /* Pointer to the USARTx registers block.*/ \ - USART_TypeDef *usart + USART_TypeDef *usart; \ + /* USART clock frequency.*/ \ + uint32_t clock; \ + /* Pending USART events.*/ \ + uint32_t events /** * @brief Low level fields of the SIO configuration structure. @@ -78,9 +239,9 @@ uint32_t presc; \ /* USART CR1 register initialization data.*/ \ uint32_t cr1; \ - /* USART CR1 register initialization data.*/ \ + /* USART CR2 register initialization data.*/ \ uint32_t cr2; \ - /* USART CR1 register initialization data.*/ \ + /* USART CR3 register initialization data.*/ \ uint32_t cr3 /** @@ -152,6 +313,38 @@ extern SIODriver SIOD1; #endif +#if (STM32_SIO_USE_USART2 == TRUE) && !defined(__DOXYGEN__) +extern SIODriver SIOD2; +#endif + +#if (STM32_SIO_USE_USART3 == TRUE) && !defined(__DOXYGEN__) +extern SIODriver SIOD3; +#endif + +#if (STM32_SIO_USE_UART4 == TRUE) && !defined(__DOXYGEN__) +extern SIODriver SIOD4; +#endif + +#if (STM32_SIO_USE_UART5 == TRUE) && !defined(__DOXYGEN__) +extern SIODriver SIOD5; +#endif + +#if (STM32_SIO_USE_USART6 == TRUE) && !defined(__DOXYGEN__) +extern SIODriver SIOD6; +#endif + +#if (STM32_SIO_USE_UART7 == TRUE) && !defined(__DOXYGEN__) +extern SIODriver SIOD7; +#endif + +#if (STM32_SIO_USE_UART8 == TRUE) && !defined(__DOXYGEN__) +extern SIODriver SIOD8; +#endif + +#if (STM32_SIO_USE_LPUART1 == TRUE) && !defined(__DOXYGEN__) +extern SIODriver LPSIOD1; +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/os/hal/src/hal_sio.c b/os/hal/src/hal_sio.c index 2a4864818..9a1b4c5d9 100644 --- a/os/hal/src/hal_sio.c +++ b/os/hal/src/hal_sio.c @@ -191,7 +191,7 @@ void sioStopOperation(SIODriver *siop) { * * @api */ -size_t sioAsyncReadI(SIODriver *siop, size_t n, uint8_t *buffer) { +size_t sioAsyncRead(SIODriver *siop, size_t n, uint8_t *buffer) { osalDbgCheck((siop != NULL) && (buffer));