From 13cb769b9d377af8443dd190e913aee7b24a0fe2 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Thu, 19 Aug 2021 09:46:09 +0000 Subject: [PATCH] Fixed bug #1177. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@14672 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- os/hal/ports/STM32/LLD/USARTv2/stm32_usart.h | 2 +- os/hal/ports/STM32/LLD/USARTv3/driver.mk | 11 +- .../ports/STM32/LLD/USARTv3/hal_serial_lld.c | 917 ++++++++++++++ .../ports/STM32/LLD/USARTv3/hal_serial_lld.h | 599 +++++++++ os/hal/ports/STM32/LLD/USARTv3/hal_uart_lld.c | 1083 +++++++++++++++++ os/hal/ports/STM32/LLD/USARTv3/hal_uart_lld.h | 903 ++++++++++++++ os/hal/ports/STM32/LLD/USARTv3/stm32_usart.h | 120 ++ readme.txt | 2 + 8 files changed, 3630 insertions(+), 7 deletions(-) create mode 100644 os/hal/ports/STM32/LLD/USARTv3/hal_serial_lld.c create mode 100644 os/hal/ports/STM32/LLD/USARTv3/hal_serial_lld.h create mode 100644 os/hal/ports/STM32/LLD/USARTv3/hal_uart_lld.c create mode 100644 os/hal/ports/STM32/LLD/USARTv3/hal_uart_lld.h create mode 100644 os/hal/ports/STM32/LLD/USARTv3/stm32_usart.h diff --git a/os/hal/ports/STM32/LLD/USARTv2/stm32_usart.h b/os/hal/ports/STM32/LLD/USARTv2/stm32_usart.h index 4a9880434..fce0abd73 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/stm32_usart.h +++ b/os/hal/ports/STM32/LLD/USARTv2/stm32_usart.h @@ -15,7 +15,7 @@ */ /** - * @file /stm32_usart.h + * @file USARTv2/stm32_usart.h * @brief STM32 USART helpers header. * * @addtogroup STM32_ diff --git a/os/hal/ports/STM32/LLD/USARTv3/driver.mk b/os/hal/ports/STM32/LLD/USARTv3/driver.mk index 133818d86..0c5cc149e 100644 --- a/os/hal/ports/STM32/LLD/USARTv3/driver.mk +++ b/os/hal/ports/STM32/LLD/USARTv3/driver.mk @@ -1,19 +1,18 @@ ifeq ($(USE_SMART_BUILD),yes) ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),) -PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.c +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv3/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 +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv3/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_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 +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv3/hal_uart_lld.c endif PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USART \ - $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv3 \ - $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2 + $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv3 diff --git a/os/hal/ports/STM32/LLD/USARTv3/hal_serial_lld.c b/os/hal/ports/STM32/LLD/USARTv3/hal_serial_lld.c new file mode 100644 index 000000000..43bc57127 --- /dev/null +++ b/os/hal/ports/STM32/LLD/USARTv3/hal_serial_lld.c @@ -0,0 +1,917 @@ +/* + 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_serial_lld.c + * @brief STM32 low level serial driver code. + * + * @addtogroup SERIAL + * @{ + */ + +#include "hal.h" + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/* For compatibility for those devices without LIN support in the USARTs.*/ +#if !defined(USART_ISR_LBDF) +#define USART_ISR_LBDF 0 +#endif + +#if !defined(USART_CR2_LBDIE) +#define USART_CR2_LBDIE 0 +#endif + +/* Differences in L4+ headers.*/ +#if !defined(USART_CR1_TXEIE) +#define USART_CR1_TXEIE USART_CR1_TXEIE_TXFNFIE +#endif + +#if !defined(USART_CR1_RXNEIE) +#define USART_CR1_RXNEIE USART_CR1_RXNEIE_RXFNEIE +#endif + +#if !defined(USART_ISR_TXE) +#define USART_ISR_TXE USART_ISR_TXE_TXFNF +#endif + +#if !defined(USART_ISR_RXNE) +#define USART_ISR_RXNE USART_ISR_RXNE_RXFNE +#endif + +/* STM32L0xx/STM32F7xx ST headers difference.*/ +#if !defined(USART_ISR_LBDF) +#define USART_ISR_LBDF USART_ISR_LBD +#endif + +/* Handling differences in frame size bits.*/ +#if !defined(USART_CR1_M_0) +#define USART_CR1_M_0 (1 << 12) +#endif + +#if !defined(USART_CR1_M_1) +#define USART_CR1_M_1 (1 << 28) +#endif + +/* Workarounds for those devices where UARTs are USARTs.*/ +#if defined(USART4) +#define UART4 USART4 +#endif +#if defined(USART5) +#define UART5 USART5 +#endif +#if defined(USART7) +#define UART7 USART7 +#endif +#if defined(USART8) +#define UART8 USART8 +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief USART1 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +SerialDriver SD1; +#endif + +/** @brief USART2 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +SerialDriver SD2; +#endif + +/** @brief USART3 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +SerialDriver SD3; +#endif + +/** @brief UART4 serial driver identifier.*/ +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +SerialDriver SD4; +#endif + +/** @brief UART5 serial driver identifier.*/ +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +SerialDriver SD5; +#endif + +/** @brief USART6 serial driver identifier.*/ +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +SerialDriver SD6; +#endif + +/** @brief UART7 serial driver identifier.*/ +#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) +SerialDriver SD7; +#endif + +/** @brief UART8 serial driver identifier.*/ +#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) +SerialDriver SD8; +#endif + +/** @brief LPUART1 serial driver identifier.*/ +#if STM32_SERIAL_USE_LPUART1 || defined(__DOXYGEN__) +SerialDriver LPSD1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** @brief Driver default configuration.*/ +static const SerialConfig default_config = +{ + SERIAL_DEFAULT_BITRATE, + 0, + USART_CR2_STOP1_BITS, + 0 +}; + +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +/** @brief Input buffer for SD1.*/ +static uint8_t sd_in_buf1[STM32_SERIAL_USART1_IN_BUF_SIZE]; + +/** @brief Output buffer for SD1.*/ +static uint8_t sd_out_buf1[STM32_SERIAL_USART1_OUT_BUF_SIZE]; +#endif + +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +/** @brief Input buffer for SD2.*/ +static uint8_t sd_in_buf2[STM32_SERIAL_USART2_IN_BUF_SIZE]; + +/** @brief Output buffer for SD2.*/ +static uint8_t sd_out_buf2[STM32_SERIAL_USART2_OUT_BUF_SIZE]; +#endif + +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +/** @brief Input buffer for SD3.*/ +static uint8_t sd_in_buf3[STM32_SERIAL_USART3_IN_BUF_SIZE]; + +/** @brief Output buffer for SD3.*/ +static uint8_t sd_out_buf3[STM32_SERIAL_USART3_OUT_BUF_SIZE]; +#endif + +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +/** @brief Input buffer for SD4.*/ +static uint8_t sd_in_buf4[STM32_SERIAL_UART4_IN_BUF_SIZE]; + +/** @brief Output buffer for SD4.*/ +static uint8_t sd_out_buf4[STM32_SERIAL_UART4_OUT_BUF_SIZE]; +#endif + +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +/** @brief Input buffer for SD5.*/ +static uint8_t sd_in_buf5[STM32_SERIAL_UART5_IN_BUF_SIZE]; + +/** @brief Output buffer for SD5.*/ +static uint8_t sd_out_buf5[STM32_SERIAL_UART5_OUT_BUF_SIZE]; +#endif + +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +/** @brief Input buffer for SD6.*/ +static uint8_t sd_in_buf6[STM32_SERIAL_USART6_IN_BUF_SIZE]; + +/** @brief Output buffer for SD6.*/ +static uint8_t sd_out_buf6[STM32_SERIAL_USART6_OUT_BUF_SIZE]; +#endif + +#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) +/** @brief Input buffer for SD7.*/ +static uint8_t sd_in_buf7[STM32_SERIAL_UART7_IN_BUF_SIZE]; + +/** @brief Output buffer for SD7.*/ +static uint8_t sd_out_buf7[STM32_SERIAL_UART7_OUT_BUF_SIZE]; +#endif + +#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) +/** @brief Input buffer for SD8.*/ +static uint8_t sd_in_buf8[STM32_SERIAL_UART8_IN_BUF_SIZE]; + +/** @brief Output buffer for SD8.*/ +static uint8_t sd_out_buf8[STM32_SERIAL_UART8_OUT_BUF_SIZE]; +#endif + +#if STM32_SERIAL_USE_LPUART1 || defined(__DOXYGEN__) +/** @brief Input buffer for LPSD1.*/ +static uint8_t sd_in_buflp1[STM32_SERIAL_LPUART1_IN_BUF_SIZE]; + +/** @brief Output buffer for LPSD1.*/ +static uint8_t sd_out_buflp1[STM32_SERIAL_LPUART1_OUT_BUF_SIZE]; +#endif + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief USART initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] config the architecture-dependent serial driver configuration + * @param[in] clock base clock for the USART + */ +static void usart_init(SerialDriver *sdp, + const SerialConfig *config, + uint32_t clock) { + uint32_t brr; + USART_TypeDef *u = sdp->usart; + + /* Baud rate setting.*/ +#if STM32_SERIAL_USE_LPUART1 + if (sdp == &LPSD1) { + osalDbgAssert((clock >= config->speed * 3U) && + (clock <= config->speed * 4096U), + "invalid baud rate vs input clock"); + + brr = (uint32_t)(((uint64_t)clock * 256) / config->speed); + + osalDbgAssert((brr >= 0x300) && (brr < 0x100000), "invalid BRR value"); + } + else +#endif + { + brr = (uint32_t)(clock / config->speed); + + /* 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 (config->cr1 & USART_CR1_OVER8) + brr = ((brr & ~7) * 2) | (brr & 7); + + osalDbgAssert(brr < 0x10000, "invalid BRR value"); + } + u->BRR = brr; + + /* Note that some bits are enforced.*/ + u->CR2 = config->cr2 | USART_CR2_LBDIE; + u->CR3 = config->cr3 | USART_CR3_EIE; + u->CR1 = config->cr1 | USART_CR1_UE | USART_CR1_PEIE | + USART_CR1_RXNEIE | USART_CR1_TE | + USART_CR1_RE; + u->ICR = 0xFFFFFFFFU; + + /* Deciding mask to be applied on the data register on receive, this is + required in order to mask out the parity bit.*/ + if ((config->cr1 & USART_CR1_PCE) != 0U) { + switch (config->cr1 & (USART_CR1_M_1 | USART_CR1_M_0)) { + case 0: + sdp->rxmask = 0x7F; + break; + case USART_CR1_M_1: + sdp->rxmask = 0x3F; + break; + default: + sdp->rxmask = 0xFF; + } + } + else { + sdp->rxmask = 0xFF; + } +} + +/** + * @brief USART de-initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] u pointer to an USART I/O block + */ +static void usart_deinit(USART_TypeDef *u) { + + u->CR1 = 0; + u->CR2 = 0; + u->CR3 = 0; +} + +/** + * @brief Error handling routine. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] isr USART ISR register value + */ +static void set_error(SerialDriver *sdp, uint32_t isr) { + eventflags_t sts = 0; + + if (isr & USART_ISR_ORE) + sts |= SD_OVERRUN_ERROR; + if (isr & USART_ISR_PE) + sts |= SD_PARITY_ERROR; + if (isr & USART_ISR_FE) + sts |= SD_FRAMING_ERROR; + if (isr & USART_ISR_NE) + sts |= SD_NOISE_ERROR; + osalSysLockFromISR(); + chnAddFlagsI(sdp, sts); + osalSysUnlockFromISR(); +} + +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +static void notify1(io_queue_t *qp) { + + (void)qp; + USART1->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +static void notify2(io_queue_t *qp) { + + (void)qp; + USART2->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +static void notify3(io_queue_t *qp) { + + (void)qp; + USART3->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +static void notify4(io_queue_t *qp) { + + (void)qp; + UART4->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +static void notify5(io_queue_t *qp) { + + (void)qp; + UART5->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +static void notify6(io_queue_t *qp) { + + (void)qp; + USART6->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) +static void notify7(io_queue_t *qp) { + + (void)qp; + UART7->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) +static void notify8(io_queue_t *qp) { + + (void)qp; + UART8->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +#if STM32_SERIAL_USE_LPUART1 || defined(__DOXYGEN__) +static void notifylp1(io_queue_t *qp) { + + (void)qp; + LPUART1->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; +} +#endif + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__) +#if !defined(STM32_USART1_SUPPRESS_ISR) +#if !defined(STM32_USART1_HANDLER) +#error "STM32_USART1_HANDLER not defined" +#endif +/** + * @brief USART1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&SD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__) +#if !defined(STM32_USART2_SUPPRESS_ISR) +#if !defined(STM32_USART2_HANDLER) +#error "STM32_USART2_HANDLER not defined" +#endif +/** + * @brief USART2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&SD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__) +#if !defined(STM32_USART3_SUPPRESS_ISR) +#if !defined(STM32_USART3_HANDLER) +#error "STM32_USART3_HANDLER not defined" +#endif +/** + * @brief USART3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&SD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__) +#if !defined(STM32_UART4_SUPPRESS_ISR) +#if !defined(STM32_UART4_HANDLER) +#error "STM32_UART4_HANDLER not defined" +#endif +/** + * @brief UART4 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&SD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__) +#if !defined(STM32_UART5_SUPPRESS_ISR) +#if !defined(STM32_UART5_HANDLER) +#error "STM32_UART5_HANDLER not defined" +#endif +/** + * @brief UART5 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&SD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__) +#if !defined(STM32_USART6_SUPPRESS_ISR) +#if !defined(STM32_USART6_HANDLER) +#error "STM32_USART6_HANDLER not defined" +#endif +/** + * @brief USART6 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&SD6); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__) +#if !defined(STM32_UART7_SUPPRESS_ISR) +#if !defined(STM32_UART7_HANDLER) +#error "STM32_UART7_HANDLER not defined" +#endif +/** + * @brief UART7 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART7_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&SD7); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__) +#if !defined(STM32_UART8_SUPPRESS_ISR) +#if !defined(STM32_UART8_HANDLER) +#error "STM32_UART8_HANDLER not defined" +#endif +/** + * @brief UART8 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART8_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&SD8); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_SERIAL_USE_LPUART1 || defined(__DOXYGEN__) +#if !defined(STM32_LPUART1_SUPPRESS_ISR) +#if !defined(STM32_LPUART1_HANDLER) +#error "STM32_LPUART1_HANDLER not defined" +#endif +/** + * @brief LPUART1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_LPUART1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + sd_lld_serve_interrupt(&LPSD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level serial driver initialization. + * + * @notapi + */ +void sd_lld_init(void) { + +#if STM32_SERIAL_USE_USART1 + sdObjectInit(&SD1); + iqObjectInit(&SD1.iqueue, sd_in_buf1, sizeof sd_in_buf1, NULL, &SD1); + oqObjectInit(&SD1.oqueue, sd_out_buf1, sizeof sd_out_buf1, notify1, &SD1); + SD1.usart = USART1; +#if !defined(STM32_USART1_SUPPRESS_ISR) && defined(STM32_USART1_NUMBER) + nvicEnableVector(STM32_USART1_NUMBER, STM32_SERIAL_USART1_PRIORITY); +#endif +#endif + +#if STM32_SERIAL_USE_USART2 + sdObjectInit(&SD2); + iqObjectInit(&SD2.iqueue, sd_in_buf2, sizeof sd_in_buf2, NULL, &SD2); + oqObjectInit(&SD2.oqueue, sd_out_buf2, sizeof sd_out_buf2, notify2, &SD2); + SD2.usart = USART2; +#if !defined(STM32_USART2_SUPPRESS_ISR) && defined(STM32_USART2_NUMBER) + nvicEnableVector(STM32_USART2_NUMBER, STM32_SERIAL_USART2_PRIORITY); +#endif +#endif + +#if STM32_SERIAL_USE_USART3 + sdObjectInit(&SD3); + iqObjectInit(&SD3.iqueue, sd_in_buf3, sizeof sd_in_buf3, NULL, &SD3); + oqObjectInit(&SD3.oqueue, sd_out_buf3, sizeof sd_out_buf3, notify3, &SD3); + SD3.usart = USART3; +#if !defined(STM32_USART3_SUPPRESS_ISR) && defined(STM32_USART3_NUMBER) + nvicEnableVector(STM32_USART3_NUMBER, STM32_SERIAL_USART3_PRIORITY); +#endif +#endif + +#if STM32_SERIAL_USE_UART4 + sdObjectInit(&SD4); + iqObjectInit(&SD4.iqueue, sd_in_buf4, sizeof sd_in_buf4, NULL, &SD4); + oqObjectInit(&SD4.oqueue, sd_out_buf4, sizeof sd_out_buf4, notify4, &SD4); + SD4.usart = UART4; +#if !defined(STM32_UART4_SUPPRESS_ISR) && defined(STM32_UART4_NUMBER) + nvicEnableVector(STM32_UART4_NUMBER, STM32_SERIAL_UART4_PRIORITY); +#endif +#endif + +#if STM32_SERIAL_USE_UART5 + sdObjectInit(&SD5); + iqObjectInit(&SD5.iqueue, sd_in_buf5, sizeof sd_in_buf5, NULL, &SD5); + oqObjectInit(&SD5.oqueue, sd_out_buf5, sizeof sd_out_buf5, notify5, &SD5); + SD5.usart = UART5; +#if !defined(STM32_UART5_SUPPRESS_ISR) && defined(STM32_UART5_NUMBER) + nvicEnableVector(STM32_UART5_NUMBER, STM32_SERIAL_UART5_PRIORITY); +#endif +#endif + +#if STM32_SERIAL_USE_USART6 + sdObjectInit(&SD6); + iqObjectInit(&SD6.iqueue, sd_in_buf6, sizeof sd_in_buf6, NULL, &SD6); + oqObjectInit(&SD6.oqueue, sd_out_buf6, sizeof sd_out_buf6, notify6, &SD6); + SD6.usart = USART6; +#if !defined(STM32_USART6_SUPPRESS_ISR) && defined(STM32_USART6_NUMBER) + nvicEnableVector(STM32_USART6_NUMBER, STM32_SERIAL_USART6_PRIORITY); +#endif +#endif + +#if STM32_SERIAL_USE_UART7 + sdObjectInit(&SD7); + iqObjectInit(&SD7.iqueue, sd_in_buf7, sizeof sd_in_buf7, NULL, &SD7); + oqObjectInit(&SD7.oqueue, sd_out_buf7, sizeof sd_out_buf7, notify7, &SD7); + SD7.usart = UART7; +#if !defined(STM32_UART7_SUPPRESS_ISR) && defined(STM32_UART7_NUMBER) + nvicEnableVector(STM32_UART7_NUMBER, STM32_SERIAL_UART7_PRIORITY); +#endif +#endif + +#if STM32_SERIAL_USE_UART8 + sdObjectInit(&SD8); + iqObjectInit(&SD8.iqueue, sd_in_buf8, sizeof sd_in_buf8, NULL, &SD8); + oqObjectInit(&SD8.oqueue, sd_out_buf8, sizeof sd_out_buf8, notify8, &SD8); + SD8.usart = UART8; +#if !defined(STM32_UART8_SUPPRESS_ISR) && defined(STM32_UART8_NUMBER) + nvicEnableVector(STM32_UART8_NUMBER, STM32_SERIAL_UART8_PRIORITY); +#endif +#endif + +#if STM32_SERIAL_USE_LPUART1 + sdObjectInit(&LPSD1); + iqObjectInit(&LPSD1.iqueue, sd_in_buflp1, sizeof sd_in_buflp1, NULL, &LPSD1); + oqObjectInit(&LPSD1.oqueue, sd_out_buflp1, sizeof sd_out_buflp1, notifylp1, &LPSD1); + LPSD1.usart = LPUART1; +#if !defined(STM32_LPUART1_SUPPRESS_ISR) && defined(STM32_LPUART1_NUMBER) + nvicEnableVector(STM32_LPUART1_NUMBER, STM32_SERIAL_LPUART1_PRIORITY); +#endif +#endif +} + +/** + * @brief Low level serial driver configuration and (re)start. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] config the architecture-dependent serial driver configuration. + * If this parameter is set to @p NULL then a default + * configuration is used. + * + * @notapi + */ +void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) { + uint32_t clock = 0U; + + if (config == NULL) + config = &default_config; + + if (sdp->state == SD_STOP) { +#if STM32_SERIAL_USE_USART1 + if (&SD1 == sdp) { + clock = STM32_USART1CLK; + rccEnableUSART1(true); + } +#endif +#if STM32_SERIAL_USE_USART2 + if (&SD2 == sdp) { + clock = STM32_USART2CLK; + rccEnableUSART2(true); + } +#endif +#if STM32_SERIAL_USE_USART3 + if (&SD3 == sdp) { + clock = STM32_USART3CLK; + rccEnableUSART3(true); + } +#endif +#if STM32_SERIAL_USE_UART4 + if (&SD4 == sdp) { + clock = STM32_UART4CLK; + rccEnableUART4(true); + } +#endif +#if STM32_SERIAL_USE_UART5 + if (&SD5 == sdp) { + clock = STM32_UART5CLK; + rccEnableUART5(true); + } +#endif +#if STM32_SERIAL_USE_USART6 + if (&SD6 == sdp) { + clock = STM32_USART6CLK; + rccEnableUSART6(true); + } +#endif +#if STM32_SERIAL_USE_UART7 + if (&SD7 == sdp) { + clock = STM32_UART7CLK; + rccEnableUART7(true); + } +#endif +#if STM32_SERIAL_USE_UART8 + if (&SD8 == sdp) { + clock = STM32_UART8CLK; + rccEnableUART8(true); + } +#endif +#if STM32_SERIAL_USE_LPUART1 + if (&LPSD1 == sdp) { + clock = STM32_LPUART1CLK; + rccEnableLPUART1(true); + } +#endif + } + usart_init(sdp, config, clock); +} + +/** + * @brief Low level serial driver stop. + * @details De-initializes the USART, stops the associated clock, resets the + * interrupt vector. + * + * @param[in] sdp pointer to a @p SerialDriver object + * + * @notapi + */ +void sd_lld_stop(SerialDriver *sdp) { + + if (sdp->state == SD_READY) { + /* UART is de-initialized then clocks are disabled.*/ + usart_deinit(sdp->usart); + +#if STM32_SERIAL_USE_USART1 + if (&SD1 == sdp) { + rccDisableUSART1(); + return; + } +#endif +#if STM32_SERIAL_USE_USART2 + if (&SD2 == sdp) { + rccDisableUSART2(); + return; + } +#endif +#if STM32_SERIAL_USE_USART3 + if (&SD3 == sdp) { + rccDisableUSART3(); + return; + } +#endif +#if STM32_SERIAL_USE_UART4 + if (&SD4 == sdp) { + rccDisableUART4(); + return; + } +#endif +#if STM32_SERIAL_USE_UART5 + if (&SD5 == sdp) { + rccDisableUART5(); + return; + } +#endif +#if STM32_SERIAL_USE_USART6 + if (&SD6 == sdp) { + rccDisableUSART6(); + return; + } +#endif +#if STM32_SERIAL_USE_UART7 + if (&SD7 == sdp) { + rccDisableUART7(); + return; + } +#endif +#if STM32_SERIAL_USE_UART8 + if (&SD8 == sdp) { + rccDisableUART8(); + return; + } +#endif +#if STM32_SERIAL_USE_LPUART1 + if (&LPSD1 == sdp) { + rccDisableLPUART1(); + return; + } +#endif + } +} + +/** + * @brief Common IRQ handler. + * + * @param[in] sdp communication channel associated to the USART + */ +void sd_lld_serve_interrupt(SerialDriver *sdp) { + USART_TypeDef *u = sdp->usart; + uint32_t cr1 = u->CR1; + uint32_t isr; + + /* Reading and clearing status.*/ + isr = u->ISR; + u->ICR = isr; + + /* Error condition detection.*/ + if (isr & (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE)) + set_error(sdp, isr); + + /* Special case, LIN break detection.*/ + if (isr & USART_ISR_LBDF) { + osalSysLockFromISR(); + chnAddFlagsI(sdp, SD_BREAK_DETECTED); + osalSysUnlockFromISR(); + } + + /* Data available, note it is a while in order to handle two situations: + 1) Another byte arrived after removing the previous one, this would cause + an extra interrupt to serve. + 2) FIFO mode is enabled on devices that support it, we need to empty + the FIFO.*/ + while (isr & USART_ISR_RXNE) { + osalSysLockFromISR(); + sdIncomingDataI(sdp, (uint8_t)u->RDR & sdp->rxmask); + osalSysUnlockFromISR(); + + isr = u->ISR; + } + + /* Transmission buffer empty, note it is a while in order to handle two + situations: + 1) The data registers has been emptied immediately after writing it, this + would cause an extra interrupt to serve. + 2) FIFO mode is enabled on devices that support it, we need to fill + the FIFO.*/ + if (cr1 & USART_CR1_TXEIE) { + while (isr & USART_ISR_TXE) { + msg_t b; + + osalSysLockFromISR(); + b = oqGetI(&sdp->oqueue); + if (b < MSG_OK) { + chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); + u->CR1 = cr1 & ~USART_CR1_TXEIE; + osalSysUnlockFromISR(); + break; + } + u->TDR = b; + osalSysUnlockFromISR(); + + isr = u->ISR; + } + } + + /* Physical transmission end.*/ + if ((cr1 & USART_CR1_TCIE) && (isr & USART_ISR_TC)) { + osalSysLockFromISR(); + if (oqIsEmptyI(&sdp->oqueue)) { + chnAddFlagsI(sdp, CHN_TRANSMISSION_END); + u->CR1 = cr1 & ~USART_CR1_TCIE; + } + osalSysUnlockFromISR(); + } +} + +#endif /* HAL_USE_SERIAL */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/USARTv3/hal_serial_lld.h b/os/hal/ports/STM32/LLD/USARTv3/hal_serial_lld.h new file mode 100644 index 000000000..e016ca3eb --- /dev/null +++ b/os/hal/ports/STM32/LLD/USARTv3/hal_serial_lld.h @@ -0,0 +1,599 @@ +/* + 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_serial_lld.h + * @brief STM32 low level serial driver header. + * + * @addtogroup SERIAL + * @{ + */ + +#ifndef HAL_SERIAL_LLD_H +#define HAL_SERIAL_LLD_H + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +#include "stm32_usart.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Advanced buffering support switch. + * @details This constants enables the advanced buffering support in the + * low level driver, the queue buffer is no more part of the + * @p SerialDriver structure, each driver can have a different + * queue size. + */ +#define SERIAL_ADVANCED_BUFFERING_SUPPORT TRUE + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief USART1 driver enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_USART1) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART1 FALSE +#endif + +/** + * @brief USART2 driver enable switch. + * @details If set to @p TRUE the support for USART2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_USART2) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART2 FALSE +#endif + +/** + * @brief USART3 driver enable switch. + * @details If set to @p TRUE the support for USART3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_USART3) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART3 FALSE +#endif + +/** + * @brief UART4 driver enable switch. + * @details If set to @p TRUE the support for UART4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_UART4) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_UART4 FALSE +#endif + +/** + * @brief UART5 driver enable switch. + * @details If set to @p TRUE the support for UART5 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_UART5) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_UART5 FALSE +#endif + +/** + * @brief USART6 driver enable switch. + * @details If set to @p TRUE the support for USART6 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_USART6) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_USART6 FALSE +#endif + +/** + * @brief UART7 driver enable switch. + * @details If set to @p TRUE the support for UART7 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_UART7) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_UART7 FALSE +#endif + +/** + * @brief UART8 driver enable switch. + * @details If set to @p TRUE the support for UART8 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_UART8) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_UART8 FALSE +#endif + +/** + * @brief LPUART1 driver enable switch. + * @details If set to @p TRUE the support for LPUART is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SERIAL_USE_LPUART1) || defined(__DOXYGEN__) +#define STM32_SERIAL_USE_LPUART1 FALSE +#endif + +/** + * @brief USART1 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART1_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART1_PRIORITY 12 +#endif + +/** + * @brief USART2 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART2_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART2_PRIORITY 12 +#endif + +/** + * @brief USART3 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART3_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART3_PRIORITY 12 +#endif + +/** + * @brief UART4 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART4_PRIORITY 12 +#endif + +/** + * @brief UART5 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART5_PRIORITY 12 +#endif + +/** + * @brief USART6 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_USART6_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART6_PRIORITY 12 +#endif + +/** + * @brief UART7 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_UART7_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART7_PRIORITY 12 +#endif + +/** + * @brief UART8 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_UART8_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART8_PRIORITY 12 +#endif + +/** + * @brief LPUART1 interrupt priority level setting. + */ +#if !defined(STM32_SERIAL_LPUART1_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SERIAL_LPUART1_PRIORITY 12 +#endif + +/** + * @brief Input buffer size for USART1. + */ +#if !defined(STM32_SERIAL_USART1_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART1_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for USART1. + */ +#if !defined(STM32_SERIAL_USART1_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART1_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for USART2. + */ +#if !defined(STM32_SERIAL_USART2_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART2_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for USART2. + */ +#if !defined(STM32_SERIAL_USART2_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART2_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for USART3. + */ +#if !defined(STM32_SERIAL_USART3_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART3_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for USART3. + */ +#if !defined(STM32_SERIAL_USART3_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART3_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for UART4. + */ +#if !defined(STM32_SERIAL_UART4_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART4_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for UART4. + */ +#if !defined(STM32_SERIAL_UART4_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART4_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for UART5. + */ +#if !defined(STM32_SERIAL_UART5_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART5_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for UART5. + */ +#if !defined(STM32_SERIAL_UART5_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART5_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for USART6. + */ +#if !defined(STM32_SERIAL_USART6_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART6_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for USART6. + */ +#if !defined(STM32_SERIAL_USART6_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_USART6_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for UART7. + */ +#if !defined(STM32_SERIAL_UART7_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART7_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for UART7. + */ +#if !defined(STM32_SERIAL_UART7_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART7_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for UART8. + */ +#if !defined(STM32_SERIAL_UART8_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART8_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for UART8. + */ +#if !defined(STM32_SERIAL_UART8_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_UART8_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for LPUART1. + */ +#if !defined(STM32_SERIAL_LPUART1_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_LPUART1_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for LPUART1. + */ +#if !defined(STM32_SERIAL_LPUART1_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define STM32_SERIAL_LPUART1_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_SERIAL_USE_USART1 && !STM32_HAS_USART1 +#error "USART1 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_USART2 && !STM32_HAS_USART2 +#error "USART2 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_USART3 && !STM32_HAS_USART3 +#error "USART3 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_UART4 && !STM32_HAS_UART4 +#error "UART4 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_UART5 && !STM32_HAS_UART5 +#error "UART5 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_USART6 && !STM32_HAS_USART6 +#error "USART6 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_UART7 && !STM32_HAS_UART7 +#error "UART7 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_UART8 && !STM32_HAS_UART8 +#error "UART8 not present in the selected device" +#endif + +#if STM32_SERIAL_USE_LPUART1 && !STM32_HAS_LPUART1 +#error "LPUART1 not present in the selected device" +#endif + +#if !STM32_SERIAL_USE_USART1 && !STM32_SERIAL_USE_USART2 && \ + !STM32_SERIAL_USE_USART3 && !STM32_SERIAL_USE_UART4 && \ + !STM32_SERIAL_USE_UART5 && !STM32_SERIAL_USE_USART6 && \ + !STM32_SERIAL_USE_UART7 && !STM32_SERIAL_USE_UART8 && \ + !STM32_SERIAL_USE_LPUART1 +#error "SERIAL driver activated but no USART/UART peripheral assigned" +#endif + +#if !defined(STM32_USART1_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_USART1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART1_PRIORITY) +#error "Invalid IRQ priority assigned to USART1" +#endif + +#if !defined(STM32_USART2_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_USART2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART2_PRIORITY) +#error "Invalid IRQ priority assigned to USART2" +#endif + +#if !defined(STM32_USART3_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_USART3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART3_PRIORITY) +#error "Invalid IRQ priority assigned to USART3" +#endif + +#if !defined(STM32_UART4_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_UART4 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART4_PRIORITY) +#error "Invalid IRQ priority assigned to UART4" +#endif + +#if !defined(STM32_UART5_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_UART5 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART5_PRIORITY) +#error "Invalid IRQ priority assigned to UART5" +#endif + +#if !defined(STM32_USART6_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_USART6 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART6_PRIORITY) +#error "Invalid IRQ priority assigned to USART6" +#endif + +#if !defined(STM32_UART7_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_UART7 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART7_PRIORITY) +#error "Invalid IRQ priority assigned to UART7" +#endif + +#if !defined(STM32_UART8_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_UART8 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART8_PRIORITY) +#error "Invalid IRQ priority assigned to UART8" +#endif + +#if !defined(STM32_LPUART1_SUPPRESS_ISR) && \ + STM32_SERIAL_USE_LPUART1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_LPUART1_PRIORITY) +#error "Invalid IRQ priority assigned to LPUART1" +#endif + +/* Checks on allocation of USARTx units.*/ +#if STM32_SERIAL_USE_USART1 +#if defined(STM32_USART1_IS_USED) +#error "SD1 requires USART1 but it is already used" +#else +#define STM32_USART1_IS_USED +#endif +#endif + +#if STM32_SERIAL_USE_USART2 +#if defined(STM32_USART2_IS_USED) +#error "SD2 requires USART2 but it is already used" +#else +#define STM32_USART2_IS_USED +#endif +#endif + +#if STM32_SERIAL_USE_USART3 +#if defined(STM32_USART3_IS_USED) +#error "SD3 requires USART3 but it is already used" +#else +#define STM32_USART3_IS_USED +#endif +#endif + +#if STM32_SERIAL_USE_UART4 +#if defined(STM32_UART4_IS_USED) +#error "SD4 requires UART4 but it is already used" +#else +#define STM32_UART4_IS_USED +#endif +#endif + +#if STM32_SERIAL_USE_UART5 +#if defined(STM32_UART5_IS_USED) +#error "SD5 requires UART5 but it is already used" +#else +#define STM32_UART5_IS_USED +#endif +#endif + +#if STM32_SERIAL_USE_USART6 +#if defined(STM32_USART6_IS_USED) +#error "SD6 requires USART6 but it is already used" +#else +#define STM32_USART6_IS_USED +#endif +#endif + +#if STM32_SERIAL_USE_UART7 +#if defined(STM32_UART7_IS_USED) +#error "SD7 requires UART7 but it is already used" +#else +#define STM32_UART7_IS_USED +#endif +#endif + +#if STM32_SERIAL_USE_UART8 +#if defined(STM32_UART8_IS_USED) +#error "SD8 requires UART8 but it is already used" +#else +#define STM32_UART8_IS_USED +#endif +#endif + +#if STM32_SERIAL_USE_LPUART1 +#if defined(STM32_LPUART1_IS_USED) +#error "LPSD1 requires LPUART1 but it is already used" +#else +#define STM32_LPUART1_IS_USED +#endif +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 Serial Driver configuration structure. + * @details An instance of this structure must be passed to @p sdStart() + * in order to configure and start a serial driver operations. + * @note This structure content is architecture dependent, each driver + * implementation defines its own version and the custom static + * initializers. + */ +typedef struct hal_serial_config { + /** + * @brief Bit rate. + */ + uint32_t speed; + /* End of the mandatory fields.*/ + /** + * @brief Initialization value for the CR1 register. + */ + uint32_t cr1; + /** + * @brief Initialization value for the CR2 register. + */ + uint32_t cr2; + /** + * @brief Initialization value for the CR3 register. + */ + uint32_t cr3; +} SerialConfig; + +/** + * @brief @p SerialDriver specific data. + */ +#define _serial_driver_data \ + _base_asynchronous_channel_data \ + /* Driver state.*/ \ + sdstate_t state; \ + /* Input queue.*/ \ + input_queue_t iqueue; \ + /* Output queue.*/ \ + output_queue_t oqueue; \ + /* End of the mandatory fields.*/ \ + /* Pointer to the USART registers block.*/ \ + USART_TypeDef *usart; \ + /* Mask to be applied on received frames.*/ \ + uint8_t rxmask; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_SERIAL_USE_USART1 && !defined(__DOXYGEN__) +extern SerialDriver SD1; +#endif +#if STM32_SERIAL_USE_USART2 && !defined(__DOXYGEN__) +extern SerialDriver SD2; +#endif +#if STM32_SERIAL_USE_USART3 && !defined(__DOXYGEN__) +extern SerialDriver SD3; +#endif +#if STM32_SERIAL_USE_UART4 && !defined(__DOXYGEN__) +extern SerialDriver SD4; +#endif +#if STM32_SERIAL_USE_UART5 && !defined(__DOXYGEN__) +extern SerialDriver SD5; +#endif +#if STM32_SERIAL_USE_USART6 && !defined(__DOXYGEN__) +extern SerialDriver SD6; +#endif +#if STM32_SERIAL_USE_UART7 && !defined(__DOXYGEN__) +extern SerialDriver SD7; +#endif +#if STM32_SERIAL_USE_UART8 && !defined(__DOXYGEN__) +extern SerialDriver SD8; +#endif +#if STM32_SERIAL_USE_LPUART1 && !defined(__DOXYGEN__) +extern SerialDriver LPSD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void sd_lld_init(void); + void sd_lld_start(SerialDriver *sdp, const SerialConfig *config); + void sd_lld_stop(SerialDriver *sdp); + void sd_lld_serve_interrupt(SerialDriver *sdp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SERIAL */ + +#endif /* HAL_SERIAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/USARTv3/hal_uart_lld.c b/os/hal/ports/STM32/LLD/USARTv3/hal_uart_lld.c new file mode 100644 index 000000000..2045be401 --- /dev/null +++ b/os/hal/ports/STM32/LLD/USARTv3/hal_uart_lld.c @@ -0,0 +1,1083 @@ +/* + 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_uart_lld.c + * @brief STM32 low level UART driver code. + * + * @addtogroup UART + * @{ + */ + +#include "hal.h" + +#if HAL_USE_UART || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/* For compatibility for those devices without LIN support in the USARTs.*/ +#if !defined(USART_ISR_LBDF) +#define USART_ISR_LBDF 0 +#endif + +#if !defined(USART_CR2_LBDIE) +#define USART_CR2_LBDIE 0 +#endif + +/* STM32L0xx/STM32F7xx ST headers difference.*/ +#if !defined(USART_ISR_LBDF) +#define USART_ISR_LBDF USART_ISR_LBD +#endif + +/* STM32L0xx/STM32F7xx ST headers difference.*/ +#if !defined(USART_ISR_LBDF) +#define USART_ISR_LBDF USART_ISR_LBD +#endif + +#define USART1_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART1_RX_DMA_STREAM, \ + STM32_USART1_RX_DMA_CHN) + +#define USART1_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART1_TX_DMA_STREAM, \ + STM32_USART1_TX_DMA_CHN) + +#define USART2_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART2_RX_DMA_STREAM, \ + STM32_USART2_RX_DMA_CHN) + +#define USART2_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART2_TX_DMA_STREAM, \ + STM32_USART2_TX_DMA_CHN) + +#define USART3_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART3_RX_DMA_STREAM, \ + STM32_USART3_RX_DMA_CHN) + +#define USART3_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART3_TX_DMA_STREAM, \ + STM32_USART3_TX_DMA_CHN) + +#define UART4_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART4_RX_DMA_STREAM, \ + STM32_UART4_RX_DMA_CHN) + +#define UART4_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART4_TX_DMA_STREAM, \ + STM32_UART4_TX_DMA_CHN) + +#define UART5_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART5_RX_DMA_STREAM, \ + STM32_UART5_RX_DMA_CHN) + +#define UART5_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART5_TX_DMA_STREAM, \ + STM32_UART5_TX_DMA_CHN) + +#define USART6_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART6_RX_DMA_STREAM, \ + STM32_USART6_RX_DMA_CHN) + +#define USART6_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_USART6_TX_DMA_STREAM, \ + STM32_USART6_TX_DMA_CHN) + +#define UART7_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART7_RX_DMA_STREAM, \ + STM32_UART7_RX_DMA_CHN) + +#define UART7_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART7_TX_DMA_STREAM, \ + STM32_UART7_TX_DMA_CHN) + +#define UART8_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART8_RX_DMA_STREAM, \ + STM32_UART8_RX_DMA_CHN) + +#define UART8_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_UART_UART8_TX_DMA_STREAM, \ + STM32_UART8_TX_DMA_CHN) + +/* Workarounds for those devices where UARTs are USARTs.*/ +#if defined(USART4) +#define UART4 USART4 +#endif +#if defined(USART5) +#define UART5 USART5 +#endif +#if defined(USART7) +#define UART7 USART7 +#endif +#if defined(USART8) +#define UART8 USART8 +#endif + +/* Workaround for more differences in headers.*/ +#if !defined(USART_CR1_M0) +#define USART_CR1_M0 USART_CR1_M +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief USART1 UART driver identifier.*/ +#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) +UARTDriver UARTD1; +#endif + +/** @brief USART2 UART driver identifier.*/ +#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) +UARTDriver UARTD2; +#endif + +/** @brief USART3 UART driver identifier.*/ +#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) +UARTDriver UARTD3; +#endif + +/** @brief UART4 UART driver identifier.*/ +#if STM32_UART_USE_UART4 || defined(__DOXYGEN__) +UARTDriver UARTD4; +#endif + +/** @brief UART5 UART driver identifier.*/ +#if STM32_UART_USE_UART5 || defined(__DOXYGEN__) +UARTDriver UARTD5; +#endif + +/** @brief USART6 UART driver identifier.*/ +#if STM32_UART_USE_USART6 || defined(__DOXYGEN__) +UARTDriver UARTD6; +#endif + +/** @brief UART7 UART driver identifier.*/ +#if STM32_UART_USE_UART7 || defined(__DOXYGEN__) +UARTDriver UARTD7; +#endif + +/** @brief UART8 UART driver identifier.*/ +#if STM32_UART_USE_UART8 || defined(__DOXYGEN__) +UARTDriver UARTD8; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Status bits translation. + * + * @param[in] isr USART SR register value + * + * @return The error flags. + */ +static uartflags_t translate_errors(uint32_t isr) { + uartflags_t sts = 0; + + if (isr & USART_ISR_ORE) + sts |= UART_OVERRUN_ERROR; + if (isr & USART_ISR_PE) + sts |= UART_PARITY_ERROR; + if (isr & USART_ISR_FE) + sts |= UART_FRAMING_ERROR; + if (isr & USART_ISR_NE) + sts |= UART_NOISE_ERROR; + if (isr & USART_ISR_LBDF) + sts |= UART_BREAK_DETECTED; + return sts; +} + +/** + * @brief Puts the receiver in the UART_RX_IDLE state. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void uart_enter_rx_idle_loop(UARTDriver *uartp) { + uint32_t mode; + + /* RX DMA channel preparation, if the char callback is defined then the + TCIE interrupt is enabled too.*/ + if (uartp->config->rxchar_cb == NULL) + mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC; + else + mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC | STM32_DMA_CR_TCIE; + dmaStreamSetMemory0(uartp->dmarx, &uartp->rxbuf); + dmaStreamSetTransactionSize(uartp->dmarx, 1); + dmaStreamSetMode(uartp->dmarx, uartp->dmarxmode | mode); + dmaStreamEnable(uartp->dmarx); +} + +/** + * @brief USART de-initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_stop(UARTDriver *uartp) { + + /* Stops RX and TX DMA channels.*/ + dmaStreamDisable(uartp->dmarx); + dmaStreamDisable(uartp->dmatx); + + /* Stops USART operations.*/ + uartp->usart->CR1 = 0; + uartp->usart->CR2 = 0; + uartp->usart->CR3 = 0; +} + +/** + * @brief USART initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] clock base clock for the USART + */ +static void usart_start(UARTDriver *uartp, uint32_t clock) { + uint32_t fck; + uint32_t cr1; + const uint32_t tmo = uartp->config->timeout; + USART_TypeDef *u = uartp->usart; + + /* Defensive programming, starting from a clean state.*/ + usart_stop(uartp); + + /* Baud rate setting.*/ + fck = (uint32_t)(clock / uartp->config->speed); + + /* Correcting USARTDIV 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 (uartp->config->cr1 & USART_CR1_OVER8) + fck = ((fck & ~7) * 2) | (fck & 7); + u->BRR = fck; + + /* Resetting eventual pending status flags.*/ + u->ICR = 0xFFFFFFFFU; + + /* Note that some bits are enforced because required for correct driver + operations.*/ + u->CR2 = uartp->config->cr2 | USART_CR2_LBDIE; + u->CR3 = uartp->config->cr3 | USART_CR3_DMAT | USART_CR3_DMAR | + USART_CR3_EIE; + + /* Mustn't ever set TCIE here - if done, it causes an immediate + interrupt.*/ + cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE; + u->CR1 = uartp->config->cr1 | cr1; + + /* Set receive timeout and checks if it is really applied.*/ + if (tmo > 0) { + osalDbgAssert(tmo <= USART_RTOR_RTO, "Timeout overflow"); + u->RTOR = tmo; + osalDbgAssert(tmo == u->RTOR, "Timeout feature unsupported in this UART"); + } + + /* Starting the receiver idle loop.*/ + uart_enter_rx_idle_loop(uartp); +} + +/** + * @brief RX DMA common service routine. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_UART_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_UART_DMA_ERROR_HOOK(uartp); + } +#else + (void)flags; +#endif + + if (uartp->rxstate == UART_RX_IDLE) { + /* Receiver in idle state, a callback is generated, if enabled, for each + received character and then the driver stays in the same state.*/ + _uart_rx_idle_code(uartp); + } + else { + /* Receiver in active state, a callback is generated, if enabled, after + a completed transfer.*/ + dmaStreamDisable(uartp->dmarx); + _uart_rx_complete_isr_code(uartp); + } +} + +/** + * @brief TX DMA common service routine. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_UART_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_UART_DMA_ERROR_HOOK(uartp); + } +#else + (void)flags; +#endif + + dmaStreamDisable(uartp->dmatx); + + /* A callback is generated, if enabled, after a completed transfer.*/ + _uart_tx1_isr_code(uartp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_UART_USE_USART1 || defined(__DOXYGEN__) +#if !defined(STM32_USART1_SUPPRESS_ISR) +#if !defined(STM32_USART1_HANDLER) +#error "STM32_USART1_HANDLER not defined" +#endif +/** + * @brief USART1 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uart_lld_serve_interrupt(&UARTD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_UART_USE_USART2 || defined(__DOXYGEN__) +#if !defined(STM32_USART2_SUPPRESS_ISR) +#if !defined(STM32_USART2_HANDLER) +#error "STM32_USART2_HANDLER not defined" +#endif +/** + * @brief USART2 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uart_lld_serve_interrupt(&UARTD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_UART_USE_USART3 || defined(__DOXYGEN__) +#if !defined(STM32_USART3_SUPPRESS_ISR) +#if !defined(STM32_USART3_HANDLER) +#error "STM32_USART3_HANDLER not defined" +#endif +/** + * @brief USART3 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uart_lld_serve_interrupt(&UARTD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_UART_USE_UART4 || defined(__DOXYGEN__) +#if !defined(STM32_UART4_SUPPRESS_ISR) +#if !defined(STM32_UART4_HANDLER) +#error "STM32_UART4_HANDLER not defined" +#endif +/** + * @brief UART4 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uart_lld_serve_interrupt(&UARTD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_UART_USE_UART5 || defined(__DOXYGEN__) +#if !defined(STM32_UART5_SUPPRESS_ISR) +#if !defined(STM32_UART5_HANDLER) +#error "STM32_UART5_HANDLER not defined" +#endif +/** + * @brief UART5 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uart_lld_serve_interrupt(&UARTD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_UART_USE_USART6 || defined(__DOXYGEN__) +#if !defined(STM32_USART6_SUPPRESS_ISR) +#if !defined(STM32_USART6_HANDLER) +#error "STM32_USART6_HANDLER not defined" +#endif +/** + * @brief USART6 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uart_lld_serve_interrupt(&UARTD6); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_UART_USE_UART7 || defined(__DOXYGEN__) +#if !defined(STM32_UART7_SUPPRESS_ISR) +#if !defined(STM32_UART7_HANDLER) +#error "STM32_UART7_HANDLER not defined" +#endif +/** + * @brief UART7 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART7_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uart_lld_serve_interrupt(&UARTD7); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +#if STM32_UART_USE_UART8 || defined(__DOXYGEN__) +#if !defined(STM32_UART8_SUPPRESS_ISR) +#if !defined(STM32_UART8_HANDLER) +#error "STM32_UART8_HANDLER not defined" +#endif +/** + * @brief UART8 IRQ handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_UART8_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uart_lld_serve_interrupt(&UARTD8); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level UART driver initialization. + * + * @notapi + */ +void uart_lld_init(void) { + +#if STM32_UART_USE_USART1 + uartObjectInit(&UARTD1); + UARTD1.usart = USART1; + UARTD1.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD1.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD1.dmarx = NULL; + UARTD1.dmatx = NULL; +#if !defined(STM32_USART1_SUPPRESS_ISR) && defined(STM32_USART1_NUMBER) + nvicEnableVector(STM32_USART1_NUMBER, STM32_UART_USART1_IRQ_PRIORITY); +#endif +#endif + +#if STM32_UART_USE_USART2 + uartObjectInit(&UARTD2); + UARTD2.usart = USART2; + UARTD2.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD2.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD2.dmarx = NULL; + UARTD2.dmatx = NULL; +#if !defined(STM32_USART2_SUPPRESS_ISR) && defined(STM32_USART2_NUMBER) + nvicEnableVector(STM32_USART2_NUMBER, STM32_UART_USART2_IRQ_PRIORITY); +#endif +#endif + +#if STM32_UART_USE_USART3 + uartObjectInit(&UARTD3); + UARTD3.usart = USART3; + UARTD3.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD3.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD3.dmarx = NULL; + UARTD3.dmatx = NULL; +#if !defined(STM32_USART3_SUPPRESS_ISR) && defined(STM32_USART3_NUMBER) + nvicEnableVector(STM32_USART3_NUMBER, STM32_UART_USART3_IRQ_PRIORITY); +#endif +#endif + +#if STM32_UART_USE_UART4 + uartObjectInit(&UARTD4); + UARTD4.usart = UART4; + UARTD4.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD4.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD4.dmarx = NULL; + UARTD4.dmatx = NULL; +#if !defined(STM32_UART4_SUPPRESS_ISR) && defined(STM32_UART4_NUMBER) + nvicEnableVector(STM32_UART4_NUMBER, STM32_UART_UART4_IRQ_PRIORITY); +#endif +#endif + +#if STM32_UART_USE_UART5 + uartObjectInit(&UARTD5); + UARTD5.usart = UART5; + UARTD5.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD5.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD5.dmarx = NULL; + UARTD5.dmatx = NULL; +#if !defined(STM32_UART5_SUPPRESS_ISR) && defined(STM32_UART5_NUMBER) + nvicEnableVector(STM32_UART5_NUMBER, STM32_UART_UART5_IRQ_PRIORITY); +#endif +#endif + +#if STM32_UART_USE_USART6 + uartObjectInit(&UARTD6); + UARTD6.usart = USART6; + UARTD6.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD6.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD6.dmarx = NULL; + UARTD6.dmatx = NULL; +#if !defined(STM32_USART6_SUPPRESS_ISR) && defined(STM32_USART6_NUMBER) + nvicEnableVector(STM32_USART6_NUMBER, STM32_UART_USART6_IRQ_PRIORITY); +#endif +#endif + +#if STM32_UART_USE_UART7 + uartObjectInit(&UARTD7); + UARTD7.usart = UART7; + UARTD7.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD7.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD7.dmarx = NULL; + UARTD7.dmatx = NULL; +#if !defined(STM32_UART7_SUPPRESS_ISR) && defined(STM32_UART7_NUMBER) + nvicEnableVector(STM32_UART7_NUMBER, STM32_UART_UART7_IRQ_PRIORITY); +#endif +#endif + +#if STM32_UART_USE_UART8 + uartObjectInit(&UARTD8); + UARTD8.usart = UART8; + UARTD8.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD8.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE; + UARTD8.dmarx = NULL; + UARTD8.dmatx = NULL; +#if !defined(STM32_UART8_SUPPRESS_ISR) && defined(STM32_UART8_NUMBER) + nvicEnableVector(STM32_UART8_NUMBER, STM32_UART_UART8_IRQ_PRIORITY); +#endif +#endif +} + +/** + * @brief Configures and activates the UART peripheral. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +void uart_lld_start(UARTDriver *uartp) { + uint32_t clock = 0U; + + if (uartp->state == UART_STOP) { + + if (false) { + } +#if STM32_UART_USE_USART1 + else if (&UARTD1 == uartp) { + clock = STM32_USART1CLK; + uartp->dmarx = dmaStreamAllocI(STM32_UART_USART1_RX_DMA_STREAM, + STM32_UART_USART1_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_USART1_TX_DMA_STREAM, + STM32_UART_USART1_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUSART1(true); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART1_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART1_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_USART1_RX); + dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_USART1_TX); +#endif + } +#endif + +#if STM32_UART_USE_USART2 + else if (&UARTD2 == uartp) { + clock = STM32_USART2CLK; + uartp->dmarx = dmaStreamAllocI(STM32_UART_USART2_RX_DMA_STREAM, + STM32_UART_USART2_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_USART2_TX_DMA_STREAM, + STM32_UART_USART2_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUSART2(true); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART2_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART2_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_USART2_RX); + dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_USART2_TX); +#endif + } +#endif + +#if STM32_UART_USE_USART3 + else if (&UARTD3 == uartp) { + clock = STM32_USART3CLK; + uartp->dmarx = dmaStreamAllocI(STM32_UART_USART3_RX_DMA_STREAM, + STM32_UART_USART3_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_USART3_TX_DMA_STREAM, + STM32_UART_USART3_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUSART3(true); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART3_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART3_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_USART3_RX); + dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_USART3_TX); +#endif + } +#endif + +#if STM32_UART_USE_UART4 + else if (&UARTD4 == uartp) { + clock = STM32_UART4CLK; + uartp->dmarx = dmaStreamAllocI(STM32_UART_UART4_RX_DMA_STREAM, + STM32_UART_UART4_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_UART4_TX_DMA_STREAM, + STM32_UART_UART4_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUART4(true); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART4_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART4_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_UART4_RX); + dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_UART4_TX); +#endif + } +#endif + +#if STM32_UART_USE_UART5 + else if (&UARTD5 == uartp) { + clock = STM32_UART5CLK; + uartp->dmarx = dmaStreamAllocI(STM32_UART_UART5_RX_DMA_STREAM, + STM32_UART_UART5_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_UART5_TX_DMA_STREAM, + STM32_UART_UART5_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUART5(true); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART5_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART5_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_UART5_RX); + dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_UART5_TX); +#endif + } +#endif + +#if STM32_UART_USE_USART6 + else if (&UARTD6 == uartp) { + clock = STM32_USART6CLK; + uartp->dmarx = dmaStreamAllocI(STM32_UART_USART6_RX_DMA_STREAM, + STM32_UART_USART6_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_USART6_TX_DMA_STREAM, + STM32_UART_USART6_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUSART6(true); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART6_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART6_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_USART6_RX); + dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_USART6_TX); +#endif + } +#endif + +#if STM32_UART_USE_UART7 + else if (&UARTD7 == uartp) { + clock = STM32_UART7CLK; + uartp->dmarx = dmaStreamAllocI(STM32_UART_UART7_RX_DMA_STREAM, + STM32_UART_UART7_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_UART7_TX_DMA_STREAM, + STM32_UART_UART7_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUART7(true); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART7_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART7_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART7_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART7_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_UART7_RX); + dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_UART7_TX); +#endif + } +#endif + +#if STM32_UART_USE_UART8 + else if (&UARTD8 == uartp) { + clock = STM32_UART8CLK; + uartp->dmarx = dmaStreamAllocI(STM32_UART_UART8_RX_DMA_STREAM, + STM32_UART_UART8_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_rx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream"); + uartp->dmatx = dmaStreamAllocI(STM32_UART_UART8_TX_DMA_STREAM, + STM32_UART_UART8_IRQ_PRIORITY, + (stm32_dmaisr_t)uart_lld_serve_tx_end_irq, + (void *)uartp); + osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream"); + + rccEnableUART8(true); + uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART8_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART8_DMA_PRIORITY); + uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART8_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_UART_UART8_DMA_PRIORITY); +#if STM32_DMA_SUPPORTS_DMAMUX + dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_UART8_RX); + dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_UART8_TX); +#endif + } +#endif + else { + osalDbgAssert(false, "invalid USART instance"); + } + + /* Static DMA setup, the transfer size depends on the USART settings, + it is 16 bits if M=1 and PCE=0 else it is 8 bits.*/ + if ((uartp->config->cr1 & (USART_CR1_M | USART_CR1_PCE)) == USART_CR1_M0) { + uartp->dmarxmode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + uartp->dmatxmode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; + } + dmaStreamSetPeripheral(uartp->dmarx, &uartp->usart->RDR); + dmaStreamSetPeripheral(uartp->dmatx, &uartp->usart->TDR); + uartp->rxbuf = 0; + } + + uartp->rxstate = UART_RX_IDLE; + uartp->txstate = UART_TX_IDLE; + usart_start(uartp, clock); +} + +/** + * @brief Deactivates the UART peripheral. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +void uart_lld_stop(UARTDriver *uartp) { + + if (uartp->state == UART_READY) { + usart_stop(uartp); + dmaStreamFreeI(uartp->dmarx); + dmaStreamFreeI(uartp->dmatx); + uartp->dmarx = NULL; + uartp->dmatx = NULL; + +#if STM32_UART_USE_USART1 + if (&UARTD1 == uartp) { + rccDisableUSART1(); + return; + } +#endif + +#if STM32_UART_USE_USART2 + if (&UARTD2 == uartp) { + rccDisableUSART2(); + return; + } +#endif + +#if STM32_UART_USE_USART3 + if (&UARTD3 == uartp) { + rccDisableUSART3(); + return; + } +#endif + +#if STM32_UART_USE_UART4 + if (&UARTD4 == uartp) { + rccDisableUART4(); + return; + } +#endif + +#if STM32_UART_USE_UART5 + if (&UARTD5 == uartp) { + rccDisableUART5(); + return; + } +#endif + +#if STM32_UART_USE_USART6 + if (&UARTD6 == uartp) { + rccDisableUSART6(); + return; + } +#endif + +#if STM32_UART_USE_UART7 + if (&UARTD7 == uartp) { + rccDisableUART7(); + return; + } +#endif + +#if STM32_UART_USE_UART8 + if (&UARTD8 == uartp) { + rccDisableUART8(); + return; + } +#endif + } +} + +/** + * @brief Starts a transmission on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @notapi + */ +void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { + + /* TX DMA channel preparation.*/ + dmaStreamSetMemory0(uartp->dmatx, txbuf); + dmaStreamSetTransactionSize(uartp->dmatx, n); + dmaStreamSetMode(uartp->dmatx, uartp->dmatxmode | STM32_DMA_CR_DIR_M2P | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); + + /* Only enable TC interrupt if there's a callback attached to it or + if called from uartSendFullTimeout(). Also we need to clear TC flag + which could be set before.*/ +#if UART_USE_WAIT == TRUE + if ((uartp->config->txend2_cb != NULL) || (uartp->early == false)) { +#else + if (uartp->config->txend2_cb != NULL) { +#endif + uartp->usart->ICR = USART_ICR_TCCF; + uartp->usart->CR1 |= USART_CR1_TCIE; + } + + /* Starting transfer.*/ + dmaStreamEnable(uartp->dmatx); +} + +/** + * @brief Stops any ongoing transmission. + * @note Stopping a transmission also suppresses the transmission callbacks. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not transmitted by the + * stopped transmit operation. + * + * @notapi + */ +size_t uart_lld_stop_send(UARTDriver *uartp) { + + dmaStreamDisable(uartp->dmatx); + + return dmaStreamGetTransactionSize(uartp->dmatx); +} + +/** + * @brief Starts a receive operation on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) { + + /* Stopping previous activity (idle state).*/ + dmaStreamDisable(uartp->dmarx); + + /* RX DMA channel preparation.*/ + dmaStreamSetMemory0(uartp->dmarx, rxbuf); + dmaStreamSetTransactionSize(uartp->dmarx, n); + dmaStreamSetMode(uartp->dmarx, uartp->dmarxmode | STM32_DMA_CR_DIR_P2M | + STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); + + /* Starting transfer.*/ + dmaStreamEnable(uartp->dmarx); +} + +/** + * @brief Stops any ongoing receive operation. + * @note Stopping a receive operation also suppresses the receive callbacks. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not received by the + * stopped receive operation. + * + * @notapi + */ +size_t uart_lld_stop_receive(UARTDriver *uartp) { + size_t n; + + dmaStreamDisable(uartp->dmarx); + n = dmaStreamGetTransactionSize(uartp->dmarx); + uart_enter_rx_idle_loop(uartp); + + return n; +} + +/** + * @brief USART common service routine. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +void uart_lld_serve_interrupt(UARTDriver *uartp) { + uint32_t isr; + USART_TypeDef *u = uartp->usart; + uint32_t cr1 = u->CR1; + + /* Reading and clearing status.*/ + isr = u->ISR; + u->ICR = isr; + + if (isr & (USART_ISR_LBDF | USART_ISR_ORE | USART_ISR_NE | + USART_ISR_FE | USART_ISR_PE)) { + _uart_rx_error_isr_code(uartp, translate_errors(isr)); + } + + if ((isr & USART_ISR_TC) && (cr1 & USART_CR1_TCIE)) { + /* TC interrupt disabled.*/ + u->CR1 = cr1 & ~USART_CR1_TCIE; + + /* End of transmission, a callback is generated.*/ + _uart_tx2_isr_code(uartp); + } + + /* Timeout interrupt sources are only checked if enabled in CR1.*/ + if (((cr1 & USART_CR1_IDLEIE) && (isr & USART_ISR_IDLE)) || + ((cr1 & USART_CR1_RTOIE) && (isr & USART_ISR_RTOF))) { + _uart_timeout_isr_code(uartp); + } +} + +#endif /* HAL_USE_UART */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/USARTv3/hal_uart_lld.h b/os/hal/ports/STM32/LLD/USARTv3/hal_uart_lld.h new file mode 100644 index 000000000..c6a398c26 --- /dev/null +++ b/os/hal/ports/STM32/LLD/USARTv3/hal_uart_lld.h @@ -0,0 +1,903 @@ +/* + 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_uart_lld.h + * @brief STM32 low level UART driver header. + * + * @addtogroup UART + * @{ + */ + +#ifndef HAL_UART_LLD_H +#define HAL_UART_LLD_H + +#if HAL_USE_UART || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief UART driver on USART1 enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART1) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART1 FALSE +#endif + +/** + * @brief UART driver on USART2 enable switch. + * @details If set to @p TRUE the support for USART2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART2) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART2 FALSE +#endif + +/** + * @brief UART driver on USART3 enable switch. + * @details If set to @p TRUE the support for USART3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART3) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART3 FALSE +#endif + +/** + * @brief UART driver on UART4 enable switch. + * @details If set to @p TRUE the support for UART4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_UART4) || defined(__DOXYGEN__) +#define STM32_UART_USE_UART4 FALSE +#endif + +/** + * @brief UART driver on UART5 enable switch. + * @details If set to @p TRUE the support for UART5 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_UART5) || defined(__DOXYGEN__) +#define STM32_UART_USE_UART5 FALSE +#endif + +/** + * @brief UART driver on USART6 enable switch. + * @details If set to @p TRUE the support for USART6 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_USART6) || defined(__DOXYGEN__) +#define STM32_UART_USE_USART6 FALSE +#endif + +/** + * @brief UART driver on UART7 enable switch. + * @details If set to @p TRUE the support for UART7 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_UART7) || defined(__DOXYGEN__) +#define STM32_UART_USE_UART7 FALSE +#endif + +/** + * @brief UART driver on UART8 enable switch. + * @details If set to @p TRUE the support for UART8 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_UART_USE_UART8) || defined(__DOXYGEN__) +#define STM32_UART_USE_UART8 FALSE +#endif + +/** + * @brief USART1 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART2 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART3 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#endif + +/** + * @brief UART4 interrupt priority level setting. + */ +#if !defined(STM32_UART_UART4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#endif + +/** + * @brief UART5 interrupt priority level setting. + */ +#if !defined(STM32_UART_UART5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART6 interrupt priority level setting. + */ +#if !defined(STM32_UART_USART6_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#endif + +/** + * @brief UART7 interrupt priority level setting. + */ +#if !defined(STM32_UART_UART7_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART7_IRQ_PRIORITY 12 +#endif + +/** + * @brief UART8 interrupt priority level setting. + */ +#if !defined(STM32_UART_UART8_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART8_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART1 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART1_DMA_PRIORITY 0 +#endif + +/** + * @brief USART2 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART2_DMA_PRIORITY 0 +#endif + +/** + * @brief USART3 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART3_DMA_PRIORITY 0 +#endif + +/** + * @brief UART4 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_UART4_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART4_DMA_PRIORITY 0 +#endif + +/** + * @brief UART5 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_UART5_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART5_DMA_PRIORITY 0 +#endif + +/** + * @brief USART6 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_USART6_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_USART6_DMA_PRIORITY 0 +#endif + +/** + * @brief UART7 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_UART7_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART7_DMA_PRIORITY 0 +#endif + +/** + * @brief UART8 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(STM32_UART_UART8_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_UART_UART8_DMA_PRIORITY 0 +#endif + +/** + * @brief UART DMA error hook. + * @note The default action for DMA errors is a system halt because DMA + * error can only happen because programming errors. + */ +#if !defined(STM32_UART_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_UART_USE_USART1 && !STM32_HAS_USART1 +#error "USART1 not present in the selected device" +#endif + +#if STM32_UART_USE_USART2 && !STM32_HAS_USART2 +#error "USART2 not present in the selected device" +#endif + +#if STM32_UART_USE_USART3 && !STM32_HAS_USART3 +#error "USART3 not present in the selected device" +#endif + +#if STM32_UART_USE_UART4 && !STM32_HAS_UART4 +#error "UART4 not present in the selected device" +#endif + +#if STM32_UART_USE_UART5 && !STM32_HAS_UART5 +#error "UART5 not present in the selected device" +#endif + +#if STM32_UART_USE_UART7 && !STM32_HAS_UART7 +#error "UART7 not present in the selected device" +#endif + +#if STM32_UART_USE_UART8 && !STM32_HAS_UART8 +#error "UART8 not present in the selected device" +#endif + +#if !STM32_UART_USE_USART1 && !STM32_UART_USE_USART2 && \ + !STM32_UART_USE_USART3 && !STM32_UART_USE_UART4 && \ + !STM32_UART_USE_UART5 && !STM32_UART_USE_USART6 && \ + !STM32_UART_USE_UART7 && !STM32_UART_USE_UART8 +#error "UART driver activated but no USART/UART peripheral assigned" +#endif + +#if !defined(STM32_USART1_SUPPRESS_ISR) && \ + STM32_UART_USE_USART1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART1" +#endif + +#if !defined(STM32_USART2_SUPPRESS_ISR) && \ + STM32_UART_USE_USART2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART2" +#endif + +#if !defined(STM32_USART3_SUPPRESS_ISR) && \ + STM32_UART_USE_USART3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART3" +#endif + +#if !defined(STM32_UART4_SUPPRESS_ISR) && \ + STM32_UART_USE_UART4 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to UART4" +#endif + +#if !defined(STM32_UART5_SUPPRESS_ISR) && \ + STM32_UART_USE_UART5 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to UART5" +#endif + +#if !defined(STM32_USART6_SUPPRESS_ISR) && \ + STM32_UART_USE_USART6 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART6_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to USART6" +#endif + +#if !defined(STM32_UART7_SUPPRESS_ISR) && \ + STM32_UART_USE_UART7 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART7_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to UART7" +#endif + +#if !defined(STM32_UART8_SUPPRESS_ISR) && \ + STM32_UART_USE_UART8 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART8_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to UART8" +#endif + +/* Check on DMA priorities.*/ +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART1" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART2" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART3" +#endif + +#if STM32_UART_USE_UART4 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART4_DMA_PRIORITY) +#error "Invalid DMA priority assigned to UART4" +#endif + +#if STM32_UART_USE_UART5 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART5_DMA_PRIORITY) +#error "Invalid DMA priority assigned to UART5" +#endif + +#if STM32_UART_USE_USART6 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART6_DMA_PRIORITY) +#error "Invalid DMA priority assigned to USART6" +#endif + +#if STM32_UART_USE_UART7 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART7_DMA_PRIORITY) +#error "Invalid DMA priority assigned to UART7" +#endif + +#if STM32_UART_USE_UART8 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART8_DMA_PRIORITY) +#error "Invalid DMA priority assigned to UART8" +#endif + +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_UART_USE_USART1 && (!defined(STM32_UART_USART1_RX_DMA_STREAM) || \ + !defined(STM32_UART_USART1_TX_DMA_STREAM)) +#error "USART1 DMA streams not defined" +#endif + +#if STM32_UART_USE_USART2 && (!defined(STM32_UART_USART2_RX_DMA_STREAM) || \ + !defined(STM32_UART_USART2_TX_DMA_STREAM)) +#error "USART2 DMA streams not defined" +#endif + +#if STM32_UART_USE_USART3 && (!defined(STM32_UART_USART3_RX_DMA_STREAM) || \ + !defined(STM32_UART_USART3_TX_DMA_STREAM)) +#error "USART3 DMA streams not defined" +#endif + +#if STM32_UART_USE_UART4 && (!defined(STM32_UART_UART4_RX_DMA_STREAM) || \ + !defined(STM32_UART_UART4_TX_DMA_STREAM)) +#error "UART4 DMA streams not defined" +#endif + +#if STM32_UART_USE_UART5 && (!defined(STM32_UART_UART5_RX_DMA_STREAM) || \ + !defined(STM32_UART_UART5_TX_DMA_STREAM)) +#error "UART5 DMA streams not defined" +#endif + +#if STM32_UART_USE_USART6 && (!defined(STM32_UART_USART6_RX_DMA_STREAM) || \ + !defined(STM32_UART_USART6_TX_DMA_STREAM)) +#error "USART6 DMA streams not defined" +#endif + +#if STM32_UART_USE_UART7 && (!defined(STM32_UART_UART7_RX_DMA_STREAM) || \ + !defined(STM32_UART_UART7_TX_DMA_STREAM)) +#error "UART7 DMA streams not defined" +#endif + +#if STM32_UART_USE_UART8 && (!defined(STM32_UART_UART8_RX_DMA_STREAM) || \ + !defined(STM32_UART_UART8_TX_DMA_STREAM)) +#error "UART8 DMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART1_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to USART1 RX" +#endif + +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART1_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to USART1 TX" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART2_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to USART2 RX" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART2_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to USART2 TX" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART3_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to USART3 RX" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART3_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to USART3 TX" +#endif + +#if STM32_UART_USE_UART4 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART4_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to UART4 RX" +#endif + +#if STM32_UART_USE_UART4 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART4_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to UART4 TX" +#endif + +#if STM32_UART_USE_UART5 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART5_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to UART5 RX" +#endif + +#if STM32_UART_USE_UART5 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART5_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to UART5 TX" +#endif + +#if STM32_UART_USE_USART6 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART6_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to USART6 RX" +#endif + +#if STM32_UART_USE_USART6 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART6_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to USART6 TX" +#endif + +#if STM32_UART_USE_UART7 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART7_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to UART7 RX" +#endif + +#if STM32_UART_USE_UART7 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART7_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to UART7 TX" +#endif + +#if STM32_UART_USE_UART8 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART8_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to UART8 RX" +#endif + +#if STM32_UART_USE_UART8 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART8_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to UART8 TX" +#endif + +/* Devices without DMAMUX require an additional check.*/ +#if STM32_ADVANCED_DMA && !STM32_DMA_SUPPORTS_DMAMUX + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_RX_DMA_STREAM, \ + STM32_USART1_RX_DMA_MSK) +#error "invalid DMA stream associated to USART1 RX" +#endif + +#if STM32_UART_USE_USART1 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_TX_DMA_STREAM, \ + STM32_USART1_TX_DMA_MSK) +#error "invalid DMA stream associated to USART1 TX" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_RX_DMA_STREAM, \ + STM32_USART2_RX_DMA_MSK) +#error "invalid DMA stream associated to USART2 RX" +#endif + +#if STM32_UART_USE_USART2 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_TX_DMA_STREAM, \ + STM32_USART2_TX_DMA_MSK) +#error "invalid DMA stream associated to USART2 TX" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_RX_DMA_STREAM, \ + STM32_USART3_RX_DMA_MSK) +#error "invalid DMA stream associated to USART3 RX" +#endif + +#if STM32_UART_USE_USART3 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_TX_DMA_STREAM, \ + STM32_USART3_TX_DMA_MSK) +#error "invalid DMA stream associated to USART3 TX" +#endif + +#if STM32_UART_USE_UART4 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_RX_DMA_STREAM, \ + STM32_UART4_RX_DMA_MSK) +#error "invalid DMA stream associated to UART4 RX" +#endif + +#if STM32_UART_USE_UART4 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_TX_DMA_STREAM, \ + STM32_UART4_TX_DMA_MSK) +#error "invalid DMA stream associated to UART4 TX" +#endif + +#if STM32_UART_USE_UART5 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_RX_DMA_STREAM, \ + STM32_UART5_RX_DMA_MSK) +#error "invalid DMA stream associated to UART5 RX" +#endif + +#if STM32_UART_USE_UART5 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_TX_DMA_STREAM, \ + STM32_UART5_TX_DMA_MSK) +#error "invalid DMA stream associated to UART5 TX" +#endif + +#if STM32_UART_USE_USART6 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_RX_DMA_STREAM, \ + STM32_USART6_RX_DMA_MSK) +#error "invalid DMA stream associated to USART6 RX" +#endif + +#if STM32_UART_USE_USART6 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_TX_DMA_STREAM, \ + STM32_USART6_TX_DMA_MSK) +#error "invalid DMA stream associated to USART6 TX" +#endif + +#if STM32_UART_USE_UART7 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART7_RX_DMA_STREAM, \ + STM32_UART7_RX_DMA_MSK) +#error "invalid DMA stream associated to UART7 RX" +#endif + +#if STM32_UART_USE_UART7 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART7_TX_DMA_STREAM, \ + STM32_UART7_TX_DMA_MSK) +#error "invalid DMA stream associated to UART7 TX" +#endif + +#if STM32_UART_USE_UART8 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART8_RX_DMA_STREAM, \ + STM32_UART8_RX_DMA_MSK) +#error "invalid DMA stream associated to UART8 RX" +#endif + +#if STM32_UART_USE_UART8 && \ + !STM32_DMA_IS_VALID_ID(STM32_UART_UART8_TX_DMA_STREAM, \ + STM32_UART8_TX_DMA_MSK) +#error "invalid DMA stream associated to UART8 TX" +#endif + +#endif /* STM32_ADVANCED_DMA && !STM32_DMA_SUPPORTS_DMAMUX */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/* Checks on allocation of USARTx units.*/ +#if STM32_UART_USE_USART1 +#if defined(STM32_USART1_IS_USED) +#error "SD1 requires USART1 but it is already used" +#else +#define STM32_USART1_IS_USED +#endif +#endif + +#if STM32_UART_USE_USART2 +#if defined(STM32_USART2_IS_USED) +#error "SD2 requires USART2 but it is already used" +#else +#define STM32_USART2_IS_USED +#endif +#endif + +#if STM32_UART_USE_USART3 +#if defined(STM32_USART3_IS_USED) +#error "SD3 requires USART3 but it is already used" +#else +#define STM32_USART3_IS_USED +#endif +#endif + +#if STM32_UART_USE_UART4 +#if defined(STM32_UART4_IS_USED) +#error "SD4 requires UART4 but it is already used" +#else +#define STM32_UART4_IS_USED +#endif +#endif + +#if STM32_UART_USE_UART5 +#if defined(STM32_UART5_IS_USED) +#error "SD5 requires UART5 but it is already used" +#else +#define STM32_UART5_IS_USED +#endif +#endif + +#if STM32_UART_USE_USART6 +#if defined(STM32_USART6_IS_USED) +#error "SD6 requires USART6 but it is already used" +#else +#define STM32_USART6_IS_USED +#endif +#endif + +#if STM32_UART_USE_UART7 +#if defined(STM32_UART7_IS_USED) +#error "SD7 requires UART7 but it is already used" +#else +#define STM32_UART7_IS_USED +#endif +#endif + +#if STM32_UART_USE_UART8 +#if defined(STM32_UART8_IS_USED) +#error "SD8 requires UART8 but it is already used" +#else +#define STM32_UART8_IS_USED +#endif +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief UART driver condition flags type. + */ +typedef uint32_t uartflags_t; + +/** + * @brief Type of an UART driver. + */ +typedef struct hal_uart_driver UARTDriver; + +/** + * @brief Generic UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +typedef void (*uartcb_t)(UARTDriver *uartp); + +/** + * @brief Character received UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] c received character + */ +typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c); + +/** + * @brief Receive error UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] e receive error mask + */ +typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e); + +/** + * @brief Type of an UART configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct hal_uart_config { + /** + * @brief End of transmission buffer callback. + */ + uartcb_t txend1_cb; + /** + * @brief Physical end of transmission callback. + */ + uartcb_t txend2_cb; + /** + * @brief Receive buffer filled callback. + */ + uartcb_t rxend_cb; + /** + * @brief Character received while out if the @p UART_RECEIVE state. + */ + uartccb_t rxchar_cb; + /** + * @brief Receive error callback. + */ + uartecb_t rxerr_cb; + /* End of the mandatory fields.*/ + /** + * @brief Receiver timeout callback. + * @details Handles both idle and timeout interrupts depending on configured + * flags in CR registers and supported hardware features. + */ + uartcb_t timeout_cb; + /** + * @brief Receiver timeout value in terms of number of bit duration. + * @details Set it to 0 when you want to handle idle interrupt instead of + * hardware timeout. + */ + uint32_t timeout; + /** + * @brief Bit rate. + */ + uint32_t speed; + /** + * @brief Initialization value for the CR1 register. + */ + uint32_t cr1; + /** + * @brief Initialization value for the CR2 register. + */ + uint32_t cr2; + /** + * @brief Initialization value for the CR3 register. + */ + uint32_t cr3; +} UARTConfig; + +/** + * @brief Structure representing an UART driver. + */ +struct hal_uart_driver { + /** + * @brief Driver state. + */ + uartstate_t state; + /** + * @brief Transmitter state. + */ + uarttxstate_t txstate; + /** + * @brief Receiver state. + */ + uartrxstate_t rxstate; + /** + * @brief Current configuration data. + */ + const UARTConfig *config; +#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__) + /** + * @brief Synchronization flag for transmit operations. + */ + bool early; + /** + * @brief Waiting thread on RX. + */ + thread_reference_t threadrx; + /** + * @brief Waiting thread on TX. + */ + thread_reference_t threadtx; +#endif /* UART_USE_WAIT */ +#if (UART_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) + /** + * @brief Mutex protecting the peripheral. + */ + mutex_t mutex; +#endif /* UART_USE_MUTUAL_EXCLUSION */ +#if defined(UART_DRIVER_EXT_FIELDS) + UART_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the USART registers block. + */ + USART_TypeDef *usart; + /** + * @brief Receive DMA mode bit mask. + */ + uint32_t dmarxmode; + /** + * @brief Send DMA mode bit mask. + */ + uint32_t dmatxmode; + /** + * @brief Receive DMA channel. + */ + const stm32_dma_stream_t *dmarx; + /** + * @brief Transmit DMA channel. + */ + const stm32_dma_stream_t *dmatx; + /** + * @brief Default receive buffer while into @p UART_RX_IDLE state. + */ + volatile uint16_t rxbuf; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_UART_USE_USART1 && !defined(__DOXYGEN__) +extern UARTDriver UARTD1; +#endif + +#if STM32_UART_USE_USART2 && !defined(__DOXYGEN__) +extern UARTDriver UARTD2; +#endif + +#if STM32_UART_USE_USART3 && !defined(__DOXYGEN__) +extern UARTDriver UARTD3; +#endif + +#if STM32_UART_USE_UART4 && !defined(__DOXYGEN__) +extern UARTDriver UARTD4; +#endif + +#if STM32_UART_USE_UART5 && !defined(__DOXYGEN__) +extern UARTDriver UARTD5; +#endif + +#if STM32_UART_USE_USART6 && !defined(__DOXYGEN__) +extern UARTDriver UARTD6; +#endif + +#if STM32_UART_USE_UART7 && !defined(__DOXYGEN__) +extern UARTDriver UARTD7; +#endif + +#if STM32_UART_USE_UART8 && !defined(__DOXYGEN__) +extern UARTDriver UARTD8; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void uart_lld_init(void); + void uart_lld_start(UARTDriver *uartp); + void uart_lld_stop(UARTDriver *uartp); + void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf); + size_t uart_lld_stop_send(UARTDriver *uartp); + void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf); + size_t uart_lld_stop_receive(UARTDriver *uartp); + void uart_lld_serve_interrupt(UARTDriver *uartp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_UART */ + +#endif /* HAL_UART_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/USARTv3/stm32_usart.h b/os/hal/ports/STM32/LLD/USARTv3/stm32_usart.h new file mode 100644 index 000000000..7abedbfb6 --- /dev/null +++ b/os/hal/ports/STM32/LLD/USARTv3/stm32_usart.h @@ -0,0 +1,120 @@ +/* + 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/stm32_usart.h + * @brief STM32 USART helpers header. + * + * @addtogroup STM32_ + * @{ + */ + +#ifndef STM32_USART_H +#define STM32_USART_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name CR2 register additional macros + * @{ + */ +#define USART_CR1_DATA7 (USART_CR1_M1) +#define USART_CR1_DATA8 (0U) +#define USART_CR1_DATA9 (USART_CR1_M0) +#define USART_CR1_OVER16 (0) +/** @} */ + +/** + * @name CR2 register additional macros + * @{ + */ +#define USART_CR2_STOP1_BITS (0U << 12) +#define USART_CR2_STOP0P5_BITS (1U << 12) +#define USART_CR2_STOP2_BITS (2U << 12) +#define USART_CR2_STOP1P5_BITS (3U << 12) +/** @} */ + +/** + * @name CR3 register additional macros + * @{ + */ +#define USART_CR3_TXFTCFG_NONFULL (0U) +#define USART_CR3_TXFTCFG_1Q (USART_CR3_TXFTCFG_0) +#define USART_CR3_TXFTCFG_1H (USART_CR3_TXFTCFG_1) +#define USART_CR3_TXFTCFG_3Q (USART_CR3_TXFTCFG_1 | USART_CR3_TXFTCFG_0) +#define USART_CR3_TXFTCFG_7E (USART_CR3_TXFTCFG_2) +#define USART_CR3_TXFTCFG_EMPTY (USART_CR3_TXFTCFG_2 | USART_CR3_TXFTCFG_0) + +#define USART_CR3_RXFTCFG_NONEMPTY (0U) +#define USART_CR3_RXFTCFG_1Q (USART_CR3_RXFTCFG_0) +#define USART_CR3_RXFTCFG_1H (USART_CR3_RXFTCFG_1) +#define USART_CR3_RXFTCFG_3Q (USART_CR3_RXFTCFG_1 | USART_CR3_RXFTCFG_0) +#define USART_CR3_RXFTCFG_7E (USART_CR3_RXFTCFG_2) +#define USART_CR3_RXFTCFG_FULL (USART_CR3_RXFTCFG_2 | USART_CR3_RXFTCFG_0) +/** @} */ + +/** + * @name PRESC register additional macros + * @{ + */ +#define USART_PRESC_N(n) ((n) << USART_PRESC_PRESCALER_Pos) +#define USART_PRESC1 USART_PRESC_N(0U) +#define USART_PRESC2 USART_PRESC_N(1U) +#define USART_PRESC4 USART_PRESC_N(2U) +#define USART_PRESC6 USART_PRESC_N(3U) +#define USART_PRESC8 USART_PRESC_N(4U) +#define USART_PRESC10 USART_PRESC_N(5U) +#define USART_PRESC12 USART_PRESC_N(6U) +#define USART_PRESC16 USART_PRESC_N(7U) +#define USART_PRESC32 USART_PRESC_N(8U) +#define USART_PRESC64 USART_PRESC_N(9U) +#define USART_PRESC128 USART_PRESC_N(10U) +#define USART_PRESC256 USART_PRESC_N(11U) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* STM32_USART_H */ + +/** @} */ diff --git a/readme.txt b/readme.txt index 9377b3e4e..69de2856d 100644 --- a/readme.txt +++ b/readme.txt @@ -77,6 +77,8 @@ - NEW: EFL driver and demo for STM32F3xx. - NEW: New unitary test subsystem under /os/test. Now it is officially ChibiOS/TEST. +- FIX: Fixed path ambiguity between STM32 USARTv2 and USARTv3 drivers + (bug #1177)(TBP). - FIX: Fixed invalid DMAMUX settings in DMAv1 for some devices (bug #1176)(TBP). - FIX: Fixed wrong macro in the demo STM32F7xx-SPI-ADXL355 (bug #1175) (backported to 21.6.1).