From dbbc93f7df28c0eee83d64090a7b453b37ec7460 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Thu, 3 Sep 2020 10:54:54 +0000 Subject: [PATCH] SIO STM32 implementation for USARTs without FIFO in USARTv2, with FIFO in USARTv3. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@13830 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- .../LLD/{USARTv2 => USART}/stm32_lpuart1.inc | 2 +- .../LLD/{USARTv2 => USART}/stm32_uart4.inc | 2 +- .../LLD/{USARTv2 => USART}/stm32_uart5.inc | 2 +- .../LLD/{USARTv2 => USART}/stm32_uart7.inc | 2 +- .../LLD/{USARTv2 => USART}/stm32_uart8.inc | 2 +- .../LLD/{USARTv2 => USART}/stm32_usart1.inc | 2 +- .../LLD/{USARTv2 => USART}/stm32_usart2.inc | 2 +- .../LLD/{USARTv2 => USART}/stm32_usart3.inc | 2 +- .../{USARTv2 => USART}/stm32_usart3_4_lp1.inc | 2 +- .../LLD/{USARTv2 => USART}/stm32_usart4_5.inc | 2 +- .../LLD/{USARTv2 => USART}/stm32_usart6.inc | 2 +- os/hal/ports/STM32/LLD/USARTv2/driver.mk | 3 +- os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c | 56 +- os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.h | 14 +- os/hal/ports/STM32/LLD/USARTv2/stm32_usart.h | 4 +- os/hal/ports/STM32/LLD/USARTv3/driver.mk | 19 + os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c | 826 ++++++++++++++++++ os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.h | 358 ++++++++ os/hal/ports/STM32/STM32G4xx/platform.mk | 2 +- os/readme.txt | 14 +- 20 files changed, 1260 insertions(+), 58 deletions(-) rename os/hal/ports/STM32/LLD/{USARTv2 => USART}/stm32_lpuart1.inc (98%) rename os/hal/ports/STM32/LLD/{USARTv2 => USART}/stm32_uart4.inc (99%) rename os/hal/ports/STM32/LLD/{USARTv2 => USART}/stm32_uart5.inc (99%) rename os/hal/ports/STM32/LLD/{USARTv2 => USART}/stm32_uart7.inc (99%) rename os/hal/ports/STM32/LLD/{USARTv2 => USART}/stm32_uart8.inc (99%) rename os/hal/ports/STM32/LLD/{USARTv2 => USART}/stm32_usart1.inc (98%) rename os/hal/ports/STM32/LLD/{USARTv2 => USART}/stm32_usart2.inc (98%) rename os/hal/ports/STM32/LLD/{USARTv2 => USART}/stm32_usart3.inc (98%) rename os/hal/ports/STM32/LLD/{USARTv2 => USART}/stm32_usart3_4_lp1.inc (99%) rename os/hal/ports/STM32/LLD/{USARTv2 => USART}/stm32_usart4_5.inc (99%) rename os/hal/ports/STM32/LLD/{USARTv2 => USART}/stm32_usart6.inc (98%) create mode 100644 os/hal/ports/STM32/LLD/USARTv3/driver.mk create mode 100644 os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c create mode 100644 os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.h diff --git a/os/hal/ports/STM32/LLD/USARTv2/stm32_lpuart1.inc b/os/hal/ports/STM32/LLD/USART/stm32_lpuart1.inc similarity index 98% rename from os/hal/ports/STM32/LLD/USARTv2/stm32_lpuart1.inc rename to os/hal/ports/STM32/LLD/USART/stm32_lpuart1.inc index d311d38a0..8c42fdd01 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/stm32_lpuart1.inc +++ b/os/hal/ports/STM32/LLD/USART/stm32_lpuart1.inc @@ -15,7 +15,7 @@ */ /** - * @file USARTv2/stm32_lpuart1.inc + * @file USART/stm32_lpuart1.inc * @brief Shared LPUART1 handler. * * @addtogroup STM32_LPUART1_HANDLER diff --git a/os/hal/ports/STM32/LLD/USARTv2/stm32_uart4.inc b/os/hal/ports/STM32/LLD/USART/stm32_uart4.inc similarity index 99% rename from os/hal/ports/STM32/LLD/USARTv2/stm32_uart4.inc rename to os/hal/ports/STM32/LLD/USART/stm32_uart4.inc index 9dfe32328..7e6431c55 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/stm32_uart4.inc +++ b/os/hal/ports/STM32/LLD/USART/stm32_uart4.inc @@ -15,7 +15,7 @@ */ /** - * @file USARTv2/stm32_uart4.inc + * @file USART/stm32_uart4.inc * @brief Shared UART4 handler. * * @addtogroup STM32_UART4_HANDLER diff --git a/os/hal/ports/STM32/LLD/USARTv2/stm32_uart5.inc b/os/hal/ports/STM32/LLD/USART/stm32_uart5.inc similarity index 99% rename from os/hal/ports/STM32/LLD/USARTv2/stm32_uart5.inc rename to os/hal/ports/STM32/LLD/USART/stm32_uart5.inc index 4cfd5ca71..524e0b945 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/stm32_uart5.inc +++ b/os/hal/ports/STM32/LLD/USART/stm32_uart5.inc @@ -15,7 +15,7 @@ */ /** - * @file USARTv2/stm32_uart5.inc + * @file USART/stm32_uart5.inc * @brief Shared UART5 handler. * * @addtogroup STM32_UART5_HANDLER diff --git a/os/hal/ports/STM32/LLD/USARTv2/stm32_uart7.inc b/os/hal/ports/STM32/LLD/USART/stm32_uart7.inc similarity index 99% rename from os/hal/ports/STM32/LLD/USARTv2/stm32_uart7.inc rename to os/hal/ports/STM32/LLD/USART/stm32_uart7.inc index e0df9efc9..11282cb8a 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/stm32_uart7.inc +++ b/os/hal/ports/STM32/LLD/USART/stm32_uart7.inc @@ -15,7 +15,7 @@ */ /** - * @file USARTv2/stm32_uart7.inc + * @file USART/stm32_uart7.inc * @brief Shared UART7 handler. * * @addtogroup STM32_UART7_HANDLER diff --git a/os/hal/ports/STM32/LLD/USARTv2/stm32_uart8.inc b/os/hal/ports/STM32/LLD/USART/stm32_uart8.inc similarity index 99% rename from os/hal/ports/STM32/LLD/USARTv2/stm32_uart8.inc rename to os/hal/ports/STM32/LLD/USART/stm32_uart8.inc index 1ef88e867..f3eddcf7d 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/stm32_uart8.inc +++ b/os/hal/ports/STM32/LLD/USART/stm32_uart8.inc @@ -15,7 +15,7 @@ */ /** - * @file USARTv2/stm32_uart8.inc + * @file USART/stm32_uart8.inc * @brief Shared UART8 handler. * * @addtogroup STM32_UART8_HANDLER diff --git a/os/hal/ports/STM32/LLD/USARTv2/stm32_usart1.inc b/os/hal/ports/STM32/LLD/USART/stm32_usart1.inc similarity index 98% rename from os/hal/ports/STM32/LLD/USARTv2/stm32_usart1.inc rename to os/hal/ports/STM32/LLD/USART/stm32_usart1.inc index 5466f7ae1..43d0b0cd1 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/stm32_usart1.inc +++ b/os/hal/ports/STM32/LLD/USART/stm32_usart1.inc @@ -15,7 +15,7 @@ */ /** - * @file USARTv2/stm32_usart1.inc + * @file USART/stm32_usart1.inc * @brief Shared USART1 handler. * * @addtogroup STM32_USART1_HANDLER diff --git a/os/hal/ports/STM32/LLD/USARTv2/stm32_usart2.inc b/os/hal/ports/STM32/LLD/USART/stm32_usart2.inc similarity index 98% rename from os/hal/ports/STM32/LLD/USARTv2/stm32_usart2.inc rename to os/hal/ports/STM32/LLD/USART/stm32_usart2.inc index 793ac0cfe..31b3cdd79 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/stm32_usart2.inc +++ b/os/hal/ports/STM32/LLD/USART/stm32_usart2.inc @@ -15,7 +15,7 @@ */ /** - * @file USARTv2/stm32_usart2.inc + * @file USART/stm32_usart2.inc * @brief Shared USART2 handler. * * @addtogroup STM32_USART2_HANDLER diff --git a/os/hal/ports/STM32/LLD/USARTv2/stm32_usart3.inc b/os/hal/ports/STM32/LLD/USART/stm32_usart3.inc similarity index 98% rename from os/hal/ports/STM32/LLD/USARTv2/stm32_usart3.inc rename to os/hal/ports/STM32/LLD/USART/stm32_usart3.inc index a25ea9ae5..4c989c3c6 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/stm32_usart3.inc +++ b/os/hal/ports/STM32/LLD/USART/stm32_usart3.inc @@ -15,7 +15,7 @@ */ /** - * @file USARTv2/stm32_usart3.inc + * @file USART/stm32_usart3.inc * @brief Shared USART3 handler. * * @addtogroup STM32_USART3_HANDLER diff --git a/os/hal/ports/STM32/LLD/USARTv2/stm32_usart3_4_lp1.inc b/os/hal/ports/STM32/LLD/USART/stm32_usart3_4_lp1.inc similarity index 99% rename from os/hal/ports/STM32/LLD/USARTv2/stm32_usart3_4_lp1.inc rename to os/hal/ports/STM32/LLD/USART/stm32_usart3_4_lp1.inc index 76ac9bc6d..96a5e404f 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/stm32_usart3_4_lp1.inc +++ b/os/hal/ports/STM32/LLD/USART/stm32_usart3_4_lp1.inc @@ -15,7 +15,7 @@ */ /** - * @file USARTv2/stm32_usart3_4_lp1.inc + * @file USART/stm32_usart3_4_lp1.inc * @brief Shared USART3, USART4, LPUART1 handler. * * @addtogroup STM32_USART3_4_LP1_HANDLER diff --git a/os/hal/ports/STM32/LLD/USARTv2/stm32_usart4_5.inc b/os/hal/ports/STM32/LLD/USART/stm32_usart4_5.inc similarity index 99% rename from os/hal/ports/STM32/LLD/USARTv2/stm32_usart4_5.inc rename to os/hal/ports/STM32/LLD/USART/stm32_usart4_5.inc index c2179bc9a..931fbc38b 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/stm32_usart4_5.inc +++ b/os/hal/ports/STM32/LLD/USART/stm32_usart4_5.inc @@ -15,7 +15,7 @@ */ /** - * @file USARTv2/stm32_usart4_5.inc + * @file USART/stm32_usart4_5.inc * @brief Shared USART4, USART5 handler. * * @addtogroup STM32_USART4_5_HANDLER diff --git a/os/hal/ports/STM32/LLD/USARTv2/stm32_usart6.inc b/os/hal/ports/STM32/LLD/USART/stm32_usart6.inc similarity index 98% rename from os/hal/ports/STM32/LLD/USARTv2/stm32_usart6.inc rename to os/hal/ports/STM32/LLD/USART/stm32_usart6.inc index 3dbf1d886..ec9250204 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/stm32_usart6.inc +++ b/os/hal/ports/STM32/LLD/USART/stm32_usart6.inc @@ -15,7 +15,7 @@ */ /** - * @file USARTv2/stm32_usart6.inc + * @file USART/stm32_usart6.inc * @brief Shared USART6 handler. * * @addtogroup STM32_USART6_HANDLER diff --git a/os/hal/ports/STM32/LLD/USARTv2/driver.mk b/os/hal/ports/STM32/LLD/USARTv2/driver.mk index 3af9034d0..62d46ea04 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/driver.mk +++ b/os/hal/ports/STM32/LLD/USARTv2/driver.mk @@ -14,4 +14,5 @@ PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.c endif -PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2 +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USART \ + $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2 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 959c0dfcb..eeba3bcec 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c +++ b/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c @@ -15,8 +15,8 @@ */ /** - * @file hal_sio_lld.c - * @brief PLATFORM SIO subsystem low level driver source. + * @file USARTv2/hal_sio_lld.c + * @brief STM32 SIO subsystem low level driver source. * * @addtogroup SIO * @{ @@ -30,25 +30,19 @@ /* Driver local definitions. */ /*===========================================================================*/ -#define USART_CR1_CFG_FORBIDDEN (USART_CR1_RXFFIE | \ - USART_CR1_TXFEIE | \ - USART_CR1_FIFOEN | \ - USART_CR1_EOBIE | \ +#define USART_CR1_CFG_FORBIDDEN (USART_CR1_EOBIE | \ USART_CR1_RTOIE | \ USART_CR1_CMIE | \ USART_CR1_PEIE | \ - USART_CR1_TXEIE_TXFNFIE | \ + USART_CR1_TXEIE | \ USART_CR1_TCIE | \ - USART_CR1_RXNEIE_RXFNEIE | \ + USART_CR1_RXNEIE | \ 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 | \ +#define USART_CR3_CFG_FORBIDDEN (USART_CR3_WUFIE | \ USART_CR3_CTSIE | \ USART_CR3_EIE) @@ -125,15 +119,13 @@ SIODriver LPSIOD1; /** * @brief Driver default configuration. - * @note In this implementation it is: 38400-8-N-1, RX and TX FIFO - * thresholds set to 50%. + * @note In this implementation it is: 38400-8-N-1. */ static const SIOConfig default_config = { .baud = SIO_DEFAULT_BITRATE, - .presc = USART_PRESC1, .cr1 = USART_CR1_DATA8 | USART_CR1_OVER16, .cr2 = USART_CR2_STOP1_BITS, - .cr3 = USART_CR3_TXFTCFG_1H | USART_CR3_RXFTCFG_1H + .cr3 = 0U }; /*===========================================================================*/ @@ -143,10 +135,10 @@ static const SIOConfig default_config = { __STATIC_INLINE void usart_enable_rx_irq(SIODriver *siop) { #if HAL_SIO_USE_SYNCHRONIZATION == TRUE - siop->usart->CR3 |= USART_CR3_RXFTIE; + siop->usart->CR1 |= USART_CR1_RXNEIE; #else if (siop->operation->rx_cb != NULL) { - siop->usart->CR3 |= USART_CR3_RXFTIE; + siop->usart->CR1 |= USART_CR1_RXNEIE; } #endif } @@ -169,10 +161,10 @@ __STATIC_INLINE void usart_enable_rx_evt_irq(SIODriver *siop) { __STATIC_INLINE void usart_enable_tx_irq(SIODriver *siop) { #if HAL_SIO_USE_SYNCHRONIZATION == TRUE - siop->usart->CR3 |= USART_CR3_TXFTIE; + siop->usart->CR1 |= USART_CR1_TXEIE; #else if (siop->operation->tx_cb != NULL) { - siop->usart->CR3 |= USART_CR3_TXFTIE; + siop->usart->CR1 |= USART_CR1_TXEIE; } #endif } @@ -229,9 +221,8 @@ __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->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; } @@ -484,22 +475,23 @@ void sio_lld_start_operation(SIODriver *siop) { #if HAL_SIO_USE_SYNCHRONIZATION == TRUE /* With synchronization all interrupts are required.*/ - cr1irq = USART_CR1_PEIE | USART_CR1_TCIE | USART_CR1_IDLEIE; + cr1irq = USART_CR1_RXNEIE | USART_CR1_TXEIE | USART_CR1_PEIE | + USART_CR1_TCIE | USART_CR1_IDLEIE; cr2irq = USART_CR2_LBDIE; - cr3irq = USART_CR3_RXFTIE | USART_CR3_TXFTIE | USART_CR3_EIE; + cr3irq = USART_CR3_EIE; #else /* When using just callbacks we can select only those really required.*/ cr1irq = 0U; cr2irq = 0U; cr3irq = 0U; if (siop->operation->rx_cb != NULL) { - cr3irq |= USART_CR3_RXFTIE; + cr1irq |= USART_CR1_RXNEIE; } if (siop->operation->rx_idle_cb != NULL) { cr1irq |= USART_CR1_IDLEIE; } if (siop->operation->tx_cb != NULL) { - cr3irq |= USART_CR3_TXFTIE; + cr1irq |= USART_CR1_TXEIE; } if (siop->operation->tx_end_cb != NULL) { cr1irq |= USART_CR1_TCIE; @@ -761,8 +753,8 @@ void sio_lld_serve_interrupt(SIODriver *siop) { } /* RX FIFO is non-empty.*/ - if (((cr3 & USART_CR3_RXFTIE) != 0U) && - (isr & USART_ISR_RXFT) != 0U) { + if (((cr1 & USART_CR1_RXNEIE) != 0U) && + (isr & USART_ISR_RXNE) != 0U) { /* The callback is invoked if defined.*/ __sio_callback_rx(siop); @@ -771,7 +763,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { __sio_wakeup_rx(siop, MSG_OK); /* Called once then the interrupt source is disabled.*/ - cr3 &= ~USART_CR3_RXFTIE; + cr1 &= ~USART_CR1_RXNEIE; } /* RX idle condition.*/ @@ -789,8 +781,8 @@ void sio_lld_serve_interrupt(SIODriver *siop) { } /* TX FIFO is non-full.*/ - if (((cr3 & USART_CR3_TXFTIE) != 0U) && - (isr & USART_ISR_TXFT) != 0U) { + if (((cr1 & USART_CR1_TXEIE) != 0U) && + (isr & USART_ISR_TXE) != 0U) { /* The callback is invoked if defined.*/ __sio_callback_tx(siop); @@ -799,7 +791,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { __sio_wakeup_tx(siop, MSG_OK); /* Called once then the interrupt is disabled.*/ - cr3 &= ~USART_CR3_TXFTIE; + cr1 &= ~USART_CR1_TXEIE; } /* Physical transmission end.*/ 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 981c2443c..4f1bc6e72 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.h +++ b/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.h @@ -15,8 +15,8 @@ */ /** - * @file hal_sio_lld.h - * @brief PLATFORM SIO subsystem low level driver header. + * @file USARTv3/hal_sio_lld.h + * @brief STM32 SIO subsystem low level driver header. * * @addtogroup SIO * @{ @@ -38,7 +38,7 @@ /*===========================================================================*/ /** - * @name PLATFORM configuration options + * @name STM32 configuration options * @{ */ /** @@ -127,10 +127,6 @@ /* Derived constants and error checks. */ /*===========================================================================*/ -#if !defined(USART_CR1_FIFOEN) -#error "FIFO mode not supported in this device" -#endif - #if STM32_SIO_USE_USART1 && !STM32_HAS_USART1 #error "USART1 not present in the selected device" #endif @@ -264,7 +260,7 @@ typedef uint32_t sio_events_mask_t; * @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 state of the TX FIFO. @@ -277,7 +273,7 @@ typedef uint32_t sio_events_mask_t; * @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/STM32/LLD/USARTv2/stm32_usart.h b/os/hal/ports/STM32/LLD/USARTv2/stm32_usart.h index 4f43e6898..4cdbd5e01 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/stm32_usart.h +++ b/os/hal/ports/STM32/LLD/USARTv2/stm32_usart.h @@ -15,10 +15,10 @@ */ /** - * @file USARTv2/stm32_usart.h + * @file /stm32_usart.h * @brief STM32 USART helpers header. * - * @addtogroup STM32_USARTv2 + * @addtogroup STM32_ * @{ */ diff --git a/os/hal/ports/STM32/LLD/USARTv3/driver.mk b/os/hal/ports/STM32/LLD/USARTv3/driver.mk new file mode 100644 index 000000000..c647e7455 --- /dev/null +++ b/os/hal/ports/STM32/LLD/USARTv3/driver.mk @@ -0,0 +1,19 @@ +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.c +endif +ifneq ($(findstring HAL_USE_SIO TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c +endif +ifneq ($(findstring HAL_USE_UART TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.c +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USART \ + $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2 \ + $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv3 diff --git a/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c b/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c new file mode 100644 index 000000000..e6273d144 --- /dev/null +++ b/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c @@ -0,0 +1,826 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file USARTv3/hal_sio_lld.c + * @brief STM32 SIO subsystem low level driver source. + * + * @addtogroup SIO + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_SIO == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* 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 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. */ +/*===========================================================================*/ + +/** + * @brief Driver default configuration. + * @note In this implementation it is: 38400-8-N-1, RX and TX FIFO + * thresholds set to 50%. + */ +static const SIOConfig default_config = { + .baud = SIO_DEFAULT_BITRATE, + .presc = USART_PRESC1, + .cr1 = USART_CR1_DATA8 | USART_CR1_OVER16, + .cr2 = USART_CR2_STOP1_BITS, + .cr3 = USART_CR3_TXFTCFG_1H | USART_CR3_RXFTCFG_1H +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +__STATIC_INLINE void usart_enable_rx_irq(SIODriver *siop) { + +#if HAL_SIO_USE_SYNCHRONIZATION == TRUE + siop->usart->CR3 |= USART_CR3_RXFTIE; +#else + if (siop->operation->rx_cb != NULL) { + siop->usart->CR3 |= USART_CR3_RXFTIE; + } +#endif +} + +__STATIC_INLINE void usart_enable_rx_evt_irq(SIODriver *siop) { + +#if HAL_SIO_USE_SYNCHRONIZATION == TRUE + siop->usart->CR1 |= USART_CR1_PEIE; + siop->usart->CR2 |= USART_CR2_LBDIE; + siop->usart->CR3 |= USART_CR3_EIE; +#else + if (siop->operation->rx_evt_cb != NULL) { + siop->usart->CR1 |= USART_CR1_PEIE; + siop->usart->CR2 |= USART_CR2_LBDIE; + siop->usart->CR3 |= USART_CR3_EIE; + } +#endif +} + +__STATIC_INLINE void usart_enable_tx_irq(SIODriver *siop) { + +#if HAL_SIO_USE_SYNCHRONIZATION == TRUE + siop->usart->CR3 |= USART_CR3_TXFTIE; +#else + if (siop->operation->tx_cb != NULL) { + siop->usart->CR3 |= USART_CR3_TXFTIE; + } +#endif +} + +__STATIC_INLINE void usart_enable_tx_end_irq(SIODriver *siop) { + +#if HAL_SIO_USE_SYNCHRONIZATION == TRUE + siop->usart->CR1 |= USART_CR1_TCIE; +#else + if (siop->operation->tx_end_cb != NULL) { + siop->usart->CR1 |= USART_CR1_TCIE; + } +#endif +} + +/** + * @brief USART initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] siop pointer to a @p SIODriver object + */ +__STATIC_INLINE void usart_init(SIODriver *siop) { + USART_TypeDef *u = siop->usart; + uint32_t 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->baud); + + 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; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level SIO driver initialization. + * + * @notapi + */ +void sio_lld_init(void) { + + /* Driver instances initialization.*/ +#if STM32_SIO_USE_USART1 == TRUE + 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 + +} + +/** + * @brief Configures and activates the SIO peripheral. + * + * @param[in] siop pointer to the @p SIODriver object + * @return The operation status. + * @retval false if the driver has been correctly started. + * @retval true if an error occurred. + * + * @notapi + */ +bool sio_lld_start(SIODriver *siop) { + + /* Using the default configuration if the application passed a + NULL pointer.*/ + if (siop->config == NULL) { + siop->config = &default_config; + } + + if (siop->state == SIO_STOP) { + + /* 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. + * + * @param[in] siop pointer to an @p SIODriver structure + * + * @api + */ +void sio_lld_start_operation(SIODriver *siop) { + uint32_t cr1irq, cr2irq, cr3irq; + +#if HAL_SIO_USE_SYNCHRONIZATION == TRUE + /* With synchronization all interrupts are required.*/ + cr1irq = USART_CR1_PEIE | USART_CR1_TCIE | USART_CR1_IDLEIE; + cr2irq = USART_CR2_LBDIE; + cr3irq = USART_CR3_RXFTIE | USART_CR3_TXFTIE | USART_CR3_EIE; +#else + /* When using just callbacks we can select only those really required.*/ + cr1irq = 0U; + cr2irq = 0U; + cr3irq = 0U; + if (siop->operation->rx_cb != NULL) { + cr3irq |= USART_CR3_RXFTIE; + } + if (siop->operation->rx_idle_cb != NULL) { + cr1irq |= USART_CR1_IDLEIE; + } + if (siop->operation->tx_cb != NULL) { + cr3irq |= USART_CR3_TXFTIE; + } + if (siop->operation->tx_end_cb != NULL) { + cr1irq |= USART_CR1_TCIE; + } + if (siop->operation->rx_evt_cb != NULL) { + cr1irq |= USART_CR1_PEIE; + cr2irq |= USART_CR2_LBDIE; + cr3irq |= USART_CR3_EIE; + } +#endif + + /* Setting up the operation.*/ + siop->usart->ICR = siop->usart->ISR; + siop->usart->CR2 |= cr2irq; + siop->usart->CR3 |= cr3irq; + siop->usart->CR1 |= cr1irq | USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; +} + +/** + * @brief Stops an ongoing SIO operation, if any. + * + * @param[in] siop pointer to an @p SIODriver structure + * + * @api + */ +void sio_lld_stop_operation(SIODriver *siop) { + + /* Stop operation.*/ + siop->usart->CR1 &= USART_CR1_CFG_FORBIDDEN; + siop->usart->CR2 &= USART_CR2_CFG_FORBIDDEN; + siop->usart->CR3 &= USART_CR3_CFG_FORBIDDEN; +} + +/** + * @brief Return the pending SIO events flags. + * + * @param[in] siop pointer to the @p SIODriver object + * @return The pending event flags. + * + * @notapi + */ +sio_events_mask_t sio_lld_get_and_clear_events(SIODriver *siop) { + sio_events_mask_t evtmask; + uint32_t isr; + + /* Getting and clearing all relevant ISR flags (and only those).*/ + isr = siop->usart->ISR & (USART_ISR_PE | USART_ISR_LBDF | USART_ISR_FE | + USART_ISR_ORE | USART_ISR_NE); + siop->usart->ICR = isr; + + /* Status flags cleared, now the related interrupts can be enabled again.*/ + usart_enable_rx_evt_irq(siop); + + /* Translating the status flags in SIO events.*/ + evtmask = 0U; + if ((isr & USART_ISR_LBDF) != 0U) { + evtmask |= SIO_BREAK_DETECTED; + } + if ((isr & USART_ISR_ORE) != 0U) { + evtmask |= SIO_OVERRUN_ERROR; + } + if ((isr & USART_ISR_NE) != 0U) { + evtmask |= SIO_NOISE_ERROR; + } + if ((isr & USART_ISR_FE) != 0U) { + evtmask |= SIO_FRAMING_ERROR; + } + if ((isr & USART_ISR_PE) != 0U) { + evtmask |= SIO_PARITY_ERROR; + } + + return evtmask; +} + +/** + * @brief Reads data from the RX FIFO. + * @details The function is not blocking, it writes frames until there + * is space available without waiting. + * + * @param[in] siop pointer to an @p SIODriver structure + * @param[in] buffer pointer to the buffer for read frames + * @param[in] n maximum number of frames to be read + * @return The number of frames copied from the buffer. + * @retval 0 if the TX FIFO is full. + */ +size_t sio_lld_read(SIODriver *siop, uint8_t *buffer, size_t n) { + size_t rd; + + rd = 0U; + while (true) { + + /* If the RX FIFO has been emptied then the interrupt is enabled again.*/ + if (sio_lld_is_rx_empty(siop)) { + usart_enable_rx_irq(siop); + break; + } + + /* Buffer filled condition.*/ + if (rd > n) { + break; + } + + *buffer++ = (uint8_t)siop->usart->RDR; + rd++; + } + + return rd; +} + +/** + * @brief Writes data into the TX FIFO. + * @details The function is not blocking, it writes frames until there + * is space available without waiting. + * + * @param[in] siop pointer to an @p SIODriver structure + * @param[in] buffer pointer to the buffer for read frames + * @param[in] n maximum number of frames to be written + * @return The number of frames copied from the buffer. + * @retval 0 if the TX FIFO is full. + */ +size_t sio_lld_write(SIODriver *siop, const uint8_t *buffer, size_t n) { + size_t wr; + + wr = 0U; + while (true) { + + /* If the TX FIFO has been filled then the interrupt is enabled again.*/ + if (sio_lld_is_tx_full(siop)) { + usart_enable_tx_irq(siop); + break; + } + + /* Buffer emptied condition.*/ + if (wr >= n) { + break; + } + + siop->usart->TDR = (uint32_t)*buffer++; + wr++; + } + + /* The transmit complete interrupt is always re-enabled on write.*/ + usart_enable_tx_end_irq(siop); + + return wr; +} + +/** + * @brief Returns one frame from the RX FIFO. + * @note If the FIFO is empty then the returned value is unpredictable. + * + * @param[in] siop pointer to the @p SIODriver object + * @return The frame from RX FIFO. + * + * @notapi + */ +msg_t sio_lld_get(SIODriver *siop) { + msg_t msg; + + msg = (msg_t)siop->usart->RDR; + + /* If the RX FIFO has been emptied then the interrupt is enabled again.*/ + if (sio_lld_is_rx_empty(siop)) { + usart_enable_rx_irq(siop); + } + + return msg; +} + +/** + * @brief Pushes one frame into the TX FIFO. + * @note If the FIFO is full then the behavior is unpredictable. + * + * @param[in] siop pointer to the @p SIODriver object + * @param[in] data frame to be written + * + * @notapi + */ +void sio_lld_put(SIODriver *siop, uint_fast16_t data) { + + siop->usart->TDR = data; + + /* If the TX FIFO has been filled then the interrupt is enabled again.*/ + if (sio_lld_is_tx_full(siop)) { + usart_enable_tx_irq(siop); + } + + /* The transmit complete interrupt is always re-enabled on write.*/ + usart_enable_tx_end_irq(siop); +} + +/** + * @brief Control operation on a serial port. + * + * @param[in] siop pointer to the @p SIODriver object + * @param[in] operation control operation code + * @param[in,out] arg operation argument + * + * @return The control operation status. + * @retval MSG_OK in case of success. + * @retval MSG_TIMEOUT in case of operation timeout. + * @retval MSG_RESET in case of operation reset. + * + * @notapi + */ +msg_t sio_lld_control(SIODriver *siop, unsigned int operation, void *arg) { + + (void)siop; + (void)operation; + (void)arg; + + return MSG_OK; +} + +/** + * @brief Serves an USART interrupt. + * + * @param[in] siop pointer to the @p SIODriver object + * + * @notapi + */ +void sio_lld_serve_interrupt(SIODriver *siop) { + USART_TypeDef *u = siop->usart; + uint32_t isr, cr1, cr3, evtmask; + + osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); + + /* Note, ISR flags are just read but not cleared, ISR sources are + disabled instead.*/ + isr = u->ISR; + + /* One read on control registers.*/ + cr1 = u->CR1; + cr3 = u->CR3; + + /* Enabled errors/events handling.*/ + evtmask = isr & (USART_ISR_PE | USART_ISR_LBDF | USART_ISR_FE | + USART_ISR_ORE | USART_ISR_NE); + if (evtmask != 0U) { + uint32_t cr2; + + /* One read on control registers.*/ + cr2 = u->CR2; + + /* The callback is invoked if defined.*/ + __sio_callback_rx_evt(siop); + + /* Waiting thread woken, if any.*/ + __sio_wakeup_rx(siop, SIO_MSG_ERRORS); + + /* Disabling event sources until errors are recognized by the + application.*/ + cr1 &= ~USART_CR1_PEIE; + cr2 &= ~USART_CR2_LBDIE; + cr3 &= ~USART_CR3_EIE; + + /* One write on control registers.*/ + u->CR2 = cr2; + } + + /* RX FIFO is non-empty.*/ + if (((cr3 & USART_CR3_RXFTIE) != 0U) && + (isr & USART_ISR_RXFT) != 0U) { + + /* The callback is invoked if defined.*/ + __sio_callback_rx(siop); + + /* Waiting thread woken, if any.*/ + __sio_wakeup_rx(siop, MSG_OK); + + /* Called once then the interrupt source is disabled.*/ + cr3 &= ~USART_CR3_RXFTIE; + } + + /* RX idle condition.*/ + if (((cr1 & USART_CR1_IDLEIE) != 0U) && + (isr & USART_ISR_IDLE) != 0U) { + + /* The callback is invoked if defined.*/ + __sio_callback_rx_idle(siop); + + /* Waiting thread woken, if any.*/ + __sio_wakeup_rx(siop, SIO_MSG_IDLE); + + /* The idle flag requires clearing, it stays enabled.*/ + u->ICR = USART_ISR_IDLE; + } + + /* TX FIFO is non-full.*/ + if (((cr3 & USART_CR3_TXFTIE) != 0U) && + (isr & USART_ISR_TXFT) != 0U) { + + /* The callback is invoked if defined.*/ + __sio_callback_tx(siop); + + /* Waiting thread woken, if any.*/ + __sio_wakeup_tx(siop, MSG_OK); + + /* Called once then the interrupt is disabled.*/ + cr3 &= ~USART_CR3_TXFTIE; + } + + /* Physical transmission end.*/ + if (((cr1 & USART_CR1_TCIE) != 0U) && + (isr & USART_ISR_TC) != 0U) { + + /* The callback is invoked if defined.*/ + __sio_callback_tx_end(siop); + + /* Waiting thread woken, if any.*/ + __sio_wakeup_txend(siop, MSG_OK); + + /* Called once then the interrupt is disabled.*/ + cr1 &= ~USART_CR1_TCIE; + } + + /* One write on control registers.*/ + u->CR1 = cr1; + u->CR3 = cr3; +} + +#endif /* HAL_USE_SIO == TRUE */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.h b/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.h new file mode 100644 index 000000000..412fd32cb --- /dev/null +++ b/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.h @@ -0,0 +1,358 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file USARTv3/hal_sio_lld.h + * @brief STM32 SIO subsystem low level driver header. + * + * @addtogroup SIO + * @{ + */ + +#ifndef HAL_SIO_LLD_H +#define HAL_SIO_LLD_H + +#if (HAL_USE_SIO == TRUE) || defined(__DOXYGEN__) + +#include "stm32_usart.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name PLATFORM configuration options + * @{ + */ +/** + * @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_LPUART1) || defined(__DOXYGEN__) +#define STM32_SIO_USE_LPUART1 FALSE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(USART_CR1_FIFOEN) +#error "FIFO mode not supported in this device" +#endif + +#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. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Type of a SIO events mask. + */ +typedef uint32_t sio_events_mask_t; + +/** + * @brief Low level fields of the SIO driver structure. + */ +#define sio_lld_driver_fields \ + /* Pointer to the USARTx registers block.*/ \ + USART_TypeDef *usart; \ + /* USART clock frequency.*/ \ + uint32_t clock + +/** + * @brief Low level fields of the SIO configuration structure. + */ +#define sio_lld_config_fields \ + /* Desired baud rate.*/ \ + uint32_t baud; \ + /* USART PRESC register initialization data.*/ \ + uint32_t presc; \ + /* USART CR1 register initialization data.*/ \ + uint32_t cr1; \ + /* USART CR2 register initialization data.*/ \ + uint32_t cr2; \ + /* USART CR3 register initialization data.*/ \ + uint32_t cr3 + +/** + * @brief Determines the state of the RX FIFO. + * + * @param[in] siop pointer to the @p SIODriver object + * @return The RX FIFO state. + * @retval false if RX FIFO is not empty + * @retval true if RX FIFO is empty + * + * @notapi + */ +#define sio_lld_is_rx_empty(siop) \ + (bool)(((siop)->usart->ISR & USART_ISR_RXNE_RXFNE) == 0U) + +/** + * @brief Determines the state of the TX FIFO. + * + * @param[in] siop pointer to the @p SIODriver object + * @return The TX FIFO state. + * @retval false if TX FIFO is not full + * @retval true if TX FIFO is full + * + * @notapi + */ +#define sio_lld_is_tx_full(siop) \ + (bool)(((siop)->usart->ISR & USART_ISR_TXE_TXFNF) == 0U) + +/** + * @brief Determines the transmission state. + * + * @param[in] siop pointer to the @p SIODriver object + * @return The TX FIFO state. + * @retval false if transmission is idle + * @retval true if transmission is ongoing + * + * @notapi + */ +#define sio_lld_is_tx_ongoing(siop) \ + (bool)(((siop)->usart->ISR & USART_ISR_TC) == 0U) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if (STM32_SIO_USE_USART1 == TRUE) && !defined(__DOXYGEN__) +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 + void sio_lld_init(void); + bool sio_lld_start(SIODriver *siop); + void sio_lld_stop(SIODriver *siop); + void sio_lld_start_operation(SIODriver *siop); + void sio_lld_stop_operation(SIODriver *siop); + sio_events_mask_t sio_lld_get_and_clear_events(SIODriver *siop); + size_t sio_lld_read(SIODriver *siop, uint8_t *buffer, size_t n); + size_t sio_lld_write(SIODriver *siop, const uint8_t *buffer, size_t n); + msg_t sio_lld_get(SIODriver *siop); + void sio_lld_put(SIODriver *siop, uint_fast16_t data); + msg_t sio_lld_control(SIODriver *siop, unsigned int operation, void *arg); + void sio_lld_serve_interrupt(SIODriver *siop); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SIO == TRUE */ + +#endif /* HAL_SIO_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/STM32G4xx/platform.mk b/os/hal/ports/STM32/STM32G4xx/platform.mk index f1d83a141..80bd39208 100644 --- a/os/hal/ports/STM32/STM32G4xx/platform.mk +++ b/os/hal/ports/STM32/STM32G4xx/platform.mk @@ -37,7 +37,7 @@ include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk -include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk +include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv3/driver.mk include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk diff --git a/os/readme.txt b/os/readme.txt index 46ff6c7e0..237a592b8 100644 --- a/os/readme.txt +++ b/os/readme.txt @@ -16,6 +16,11 @@ | | +--templates/ - Nil kernel port template files. | | +--ports/ - Nil kernel port files. | | +--osal/ - Nil kernel OSAL module for HAL interface. + | +--oslib/ - ChibiOS/LIB product. + | | +--include/ - OSLIB headers. + | | +--src/ - OSLIB sources. + | +--sb/ - ChibiOS/SB product. + | +--ex/ - ChibiOS/EX product. | +--hal/ - ChibiOS/HAL product. | | +--include/ - HAL high level headers. | | +--src/ - HAL high level sources. @@ -23,7 +28,12 @@ | | +--ports/ - HAL port files (low level drivers implementations). | | +--boards/ - HAL board files. | +--common/ - Files used by multiple ChibiOS products. - | | +--ports - Common port files for various architectures and + | | +--abstractions/- Emulation of other API. + | | +--ext/ - Vendor files used by ChibiOS products. + | | +--portability/ - Compilers abstraction support files. + | | +--ports - RT/NIL port files for various architectures and | | compilers. + | | +--startup/ - Startup, linker and make support for various + | | architectures and compilers. | +--various/ - Various portable support files. - | +--ext/ - Vendor files used by ChibiOS products. + \ No newline at end of file