diff options
author | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2014-01-24 14:25:46 +0000 |
---|---|---|
committer | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2014-01-24 14:25:46 +0000 |
commit | 156a9e9fa71badb88476ac2bbc1219587ea8e7bb (patch) | |
tree | 8e6adb5c968a6ac67a188c094ca062e196ddf19f /os/hal/ports/STM32/LLD/USARTv1 | |
parent | cd98598fd8dda30d4ff002a451eae569d8a56f1e (diff) | |
download | ChibiOS-156a9e9fa71badb88476ac2bbc1219587ea8e7bb.tar.gz ChibiOS-156a9e9fa71badb88476ac2bbc1219587ea8e7bb.tar.bz2 ChibiOS-156a9e9fa71badb88476ac2bbc1219587ea8e7bb.zip |
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6643 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal/ports/STM32/LLD/USARTv1')
-rw-r--r-- | os/hal/ports/STM32/LLD/USARTv1/serial_lld.c | 525 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/USARTv1/serial_lld.h | 303 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/USARTv1/uart_lld.c | 813 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/USARTv1/uart_lld.h | 603 |
4 files changed, 2244 insertions, 0 deletions
diff --git a/os/hal/ports/STM32/LLD/USARTv1/serial_lld.c b/os/hal/ports/STM32/LLD/USARTv1/serial_lld.c new file mode 100644 index 000000000..87be9bbb6 --- /dev/null +++ b/os/hal/ports/STM32/LLD/USARTv1/serial_lld.c @@ -0,0 +1,525 @@ +/*
+ ChibiOS/RT - Copyright (C) 2006-2013 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 STM32/USARTv1/serial_lld.c
+ * @brief STM32 low level serial driver code.
+ *
+ * @addtogroup SERIAL
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_SERIAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* 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
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/** @brief Driver default configuration.*/
+static const SerialConfig default_config =
+{
+ SERIAL_DEFAULT_BITRATE,
+ 0,
+ USART_CR2_STOP1_BITS | USART_CR2_LINEN,
+ 0
+};
+
+/*===========================================================================*/
+/* 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
+ */
+static void usart_init(SerialDriver *sdp, const SerialConfig *config) {
+ USART_TypeDef *u = sdp->usart;
+
+ /* Baud rate setting.*/
+#if STM32_HAS_USART6
+ if ((sdp->usart == USART1) || (sdp->usart == USART6))
+#else
+ if (sdp->usart == USART1)
+#endif
+ u->BRR = STM32_PCLK2 / config->speed;
+ else
+ u->BRR = STM32_PCLK1 / config->speed;
+
+ /* 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->SR = 0;
+ (void)u->SR; /* SR reset step 1.*/
+ (void)u->DR; /* SR reset step 2.*/
+}
+
+/**
+ * @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] sr USART SR register value
+ */
+static void set_error(SerialDriver *sdp, uint16_t sr) {
+ eventflags_t sts = 0;
+
+ if (sr & USART_SR_ORE)
+ sts |= SD_OVERRUN_ERROR;
+ if (sr & USART_SR_PE)
+ sts |= SD_PARITY_ERROR;
+ if (sr & USART_SR_FE)
+ sts |= SD_FRAMING_ERROR;
+ if (sr & USART_SR_NE)
+ sts |= SD_NOISE_ERROR;
+ chnAddFlagsI(sdp, sts);
+}
+
+/**
+ * @brief Common IRQ handler.
+ *
+ * @param[in] sdp communication channel associated to the USART
+ */
+static void serve_interrupt(SerialDriver *sdp) {
+ USART_TypeDef *u = sdp->usart;
+ uint16_t cr1 = u->CR1;
+ uint16_t sr = u->SR;
+
+ /* Special case, LIN break detection.*/
+ if (sr & USART_SR_LBD) {
+ osalSysLockFromISR();
+ chnAddFlagsI(sdp, SD_BREAK_DETECTED);
+ osalSysUnlockFromISR();
+ u->SR = ~USART_SR_LBD;
+ }
+
+ /* Data available.*/
+ osalSysLockFromISR();
+ while (sr & USART_SR_RXNE) {
+ /* Error condition detection.*/
+ if (sr & (USART_SR_ORE | USART_SR_NE | USART_SR_FE | USART_SR_PE))
+ set_error(sdp, sr);
+ sdIncomingDataI(sdp, u->DR);
+ sr = u->SR;
+ }
+ osalSysUnlockFromISR();
+
+ /* Transmission buffer empty.*/
+ if ((cr1 & USART_CR1_TXEIE) && (sr & USART_SR_TXE)) {
+ msg_t b;
+ osalSysLockFromISR();
+ b = oqGetI(&sdp->oqueue);
+ if (b < Q_OK) {
+ chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
+ u->CR1 = (cr1 & ~USART_CR1_TXEIE) | USART_CR1_TCIE;
+ }
+ else
+ u->DR = b;
+ osalSysUnlockFromISR();
+ }
+
+ /* Physical transmission end.*/
+ if (sr & USART_SR_TC) {
+ osalSysLockFromISR();
+ chnAddFlagsI(sdp, CHN_TRANSMISSION_END);
+ osalSysUnlockFromISR();
+ u->CR1 = cr1 & ~(USART_CR1_TXEIE | USART_CR1_TCIE);
+ u->SR = ~USART_SR_TC;
+ }
+}
+
+#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
+static void notify1(io_queue_t *qp) {
+
+ (void)qp;
+ USART1->CR1 |= USART_CR1_TXEIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__)
+static void notify2(io_queue_t *qp) {
+
+ (void)qp;
+ USART2->CR1 |= USART_CR1_TXEIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__)
+static void notify3(io_queue_t *qp) {
+
+ (void)qp;
+ USART3->CR1 |= USART_CR1_TXEIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__)
+static void notify4(io_queue_t *qp) {
+
+ (void)qp;
+ UART4->CR1 |= USART_CR1_TXEIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__)
+static void notify5(io_queue_t *qp) {
+
+ (void)qp;
+ UART5->CR1 |= USART_CR1_TXEIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__)
+static void notify6(io_queue_t *qp) {
+
+ (void)qp;
+ USART6->CR1 |= USART_CR1_TXEIE;
+}
+#endif
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
+#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();
+
+ serve_interrupt(&SD1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__)
+#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();
+
+ serve_interrupt(&SD2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__)
+#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();
+
+ serve_interrupt(&SD3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__)
+#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();
+
+ serve_interrupt(&SD4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__)
+#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();
+
+ serve_interrupt(&SD5);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__)
+#if !defined(STM32_USART6_HANDLER)
+#error "STM32_USART6_HANDLER not defined"
+#endif
+/**
+ * @brief USART1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD6);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level serial driver initialization.
+ *
+ * @notapi
+ */
+void sd_lld_init(void) {
+
+#if STM32_SERIAL_USE_USART1
+ sdObjectInit(&SD1, NULL, notify1);
+ SD1.usart = USART1;
+#endif
+
+#if STM32_SERIAL_USE_USART2
+ sdObjectInit(&SD2, NULL, notify2);
+ SD2.usart = USART2;
+#endif
+
+#if STM32_SERIAL_USE_USART3
+ sdObjectInit(&SD3, NULL, notify3);
+ SD3.usart = USART3;
+#endif
+
+#if STM32_SERIAL_USE_UART4
+ sdObjectInit(&SD4, NULL, notify4);
+ SD4.usart = UART4;
+#endif
+
+#if STM32_SERIAL_USE_UART5
+ sdObjectInit(&SD5, NULL, notify5);
+ SD5.usart = UART5;
+#endif
+
+#if STM32_SERIAL_USE_USART6
+ sdObjectInit(&SD6, NULL, notify6);
+ SD6.usart = USART6;
+#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) {
+
+ if (config == NULL)
+ config = &default_config;
+
+ if (sdp->state == SD_STOP) {
+#if STM32_SERIAL_USE_USART1
+ if (&SD1 == sdp) {
+ rccEnableUSART1(FALSE);
+ nvicEnableVector(STM32_USART1_NUMBER, STM32_SERIAL_USART1_PRIORITY);
+ }
+#endif
+#if STM32_SERIAL_USE_USART2
+ if (&SD2 == sdp) {
+ rccEnableUSART2(FALSE);
+ nvicEnableVector(STM32_USART2_NUMBER, STM32_SERIAL_USART2_PRIORITY);
+ }
+#endif
+#if STM32_SERIAL_USE_USART3
+ if (&SD3 == sdp) {
+ rccEnableUSART3(FALSE);
+ nvicEnableVector(STM32_USART3_NUMBER, STM32_SERIAL_USART3_PRIORITY);
+ }
+#endif
+#if STM32_SERIAL_USE_UART4
+ if (&SD4 == sdp) {
+ rccEnableUART4(FALSE);
+ nvicEnableVector(STM32_UART4_NUMBER, STM32_SERIAL_UART4_PRIORITY);
+ }
+#endif
+#if STM32_SERIAL_USE_UART5
+ if (&SD5 == sdp) {
+ rccEnableUART5(FALSE);
+ nvicEnableVector(STM32_UART5_NUMBER, STM32_SERIAL_UART5_PRIORITY);
+ }
+#endif
+#if STM32_SERIAL_USE_USART6
+ if (&SD6 == sdp) {
+ rccEnableUSART6(FALSE);
+ nvicEnableVector(STM32_USART6_NUMBER, STM32_SERIAL_USART6_PRIORITY);
+ }
+#endif
+ }
+ usart_init(sdp, config);
+}
+
+/**
+ * @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) {
+ usart_deinit(sdp->usart);
+#if STM32_SERIAL_USE_USART1
+ if (&SD1 == sdp) {
+ rccDisableUSART1(FALSE);
+ nvicDisableVector(STM32_USART1_NUMBER);
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_USART2
+ if (&SD2 == sdp) {
+ rccDisableUSART2(FALSE);
+ nvicDisableVector(STM32_USART2_NUMBER);
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_USART3
+ if (&SD3 == sdp) {
+ rccDisableUSART3(FALSE);
+ nvicDisableVector(STM32_USART3_NUMBER);
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_UART4
+ if (&SD4 == sdp) {
+ rccDisableUART4(FALSE);
+ nvicDisableVector(STM32_UART4_NUMBER);
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_UART5
+ if (&SD5 == sdp) {
+ rccDisableUART5(FALSE);
+ nvicDisableVector(STM32_UART5_NUMBER);
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_USART6
+ if (&SD6 == sdp) {
+ rccDisableUSART6(FALSE);
+ nvicDisableVector(STM32_USART6_NUMBER);
+ return;
+ }
+#endif
+ }
+}
+
+#endif /* HAL_USE_SERIAL */
+
+/** @} */
diff --git a/os/hal/ports/STM32/LLD/USARTv1/serial_lld.h b/os/hal/ports/STM32/LLD/USARTv1/serial_lld.h new file mode 100644 index 000000000..bdf8e9bdb --- /dev/null +++ b/os/hal/ports/STM32/LLD/USARTv1/serial_lld.h @@ -0,0 +1,303 @@ +/*
+ ChibiOS/RT - Copyright (C) 2006-2013 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 STM32/USARTv1/serial_lld.h
+ * @brief STM32 low level serial driver header.
+ *
+ * @addtogroup SERIAL
+ * @{
+ */
+
+#ifndef _SERIAL_LLD_H_
+#define _SERIAL_LLD_H_
+
+#if HAL_USE_SERIAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* 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 TRUE.
+ */
+#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 TRUE.
+ */
+#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 TRUE.
+ */
+#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 TRUE.
+ */
+#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 TRUE.
+ */
+#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 TRUE.
+ */
+#if !defined(STM32_SERIAL_USE_USART6) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_USART6 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
+/** @} */
+
+/*===========================================================================*/
+/* 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_USART1 && !STM32_SERIAL_USE_USART2 && \
+ !STM32_SERIAL_USE_USART3 && !STM32_SERIAL_USE_UART4 && \
+ !STM32_SERIAL_USE_UART5 && !STM32_SERIAL_USE_USART6
+#error "SERIAL driver activated but no USART/UART peripheral assigned"
+#endif
+
+#if STM32_SERIAL_USE_USART1 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART1_PRIORITY)
+#error "Invalid IRQ priority assigned to USART1"
+#endif
+
+#if STM32_SERIAL_USE_USART2 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART2_PRIORITY)
+#error "Invalid IRQ priority assigned to USART2"
+#endif
+
+#if STM32_SERIAL_USE_USART3 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART3_PRIORITY)
+#error "Invalid IRQ priority assigned to USART3"
+#endif
+
+#if STM32_SERIAL_USE_UART4 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_UART4_PRIORITY)
+#error "Invalid IRQ priority assigned to UART4"
+#endif
+
+#if STM32_SERIAL_USE_UART5 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_UART5_PRIORITY)
+#error "Invalid IRQ priority assigned to UART5"
+#endif
+
+#if STM32_SERIAL_USE_USART6 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART6_PRIORITY)
+#error "Invalid IRQ priority assigned to USART6"
+#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 {
+ /**
+ * @brief Bit rate.
+ */
+ uint32_t speed;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Initialization value for the CR1 register.
+ */
+ uint16_t cr1;
+ /**
+ * @brief Initialization value for the CR2 register.
+ */
+ uint16_t cr2;
+ /**
+ * @brief Initialization value for the CR3 register.
+ */
+ uint16_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; \
+ /* Input circular buffer.*/ \
+ uint8_t ib[SERIAL_BUFFERS_SIZE]; \
+ /* Output circular buffer.*/ \
+ uint8_t ob[SERIAL_BUFFERS_SIZE]; \
+ /* End of the mandatory fields.*/ \
+ /* Pointer to the USART registers block.*/ \
+ USART_TypeDef *usart;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*
+ * Extra USARTs definitions here (missing from the ST header file).
+ */
+#define USART_CR2_STOP1_BITS (0 << 12) /**< @brief CR2 1 stop bit value.*/
+#define USART_CR2_STOP0P5_BITS (1 << 12) /**< @brief CR2 0.5 stop bit value.*/
+#define USART_CR2_STOP2_BITS (2 << 12) /**< @brief CR2 2 stop bit value.*/
+#define USART_CR2_STOP1P5_BITS (3 << 12) /**< @brief CR2 1.5 stop bit value.*/
+
+/*===========================================================================*/
+/* 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
+
+#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);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SERIAL */
+
+#endif /* _SERIAL_LLD_H_ */
+
+/** @} */
diff --git a/os/hal/ports/STM32/LLD/USARTv1/uart_lld.c b/os/hal/ports/STM32/LLD/USARTv1/uart_lld.c new file mode 100644 index 000000000..b1856366c --- /dev/null +++ b/os/hal/ports/STM32/LLD/USARTv1/uart_lld.c @@ -0,0 +1,813 @@ +/*
+ ChibiOS/RT - Copyright (C) 2006-2013 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 STM32/USARTv1/uart_lld.c
+ * @brief STM32 low level UART driver code.
+ *
+ * @addtogroup UART
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_UART || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#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 STM32_UART45_CR2_CHECK_MASK \
+ (USART_CR2_STOP_0 | USART_CR2_CLKEN | USART_CR2_CPOL | USART_CR2_CPHA | \
+ USART_CR2_LBCL)
+
+#define STM32_UART45_CR3_CHECK_MASK \
+ (USART_CR3_CTSIE | USART_CR3_CTSE | USART_CR3_RTSE | USART_CR3_SCEN | \
+ USART_CR3_NACK)
+
+/*===========================================================================*/
+/* 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
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Status bits translation.
+ *
+ * @param[in] sr USART SR register value
+ *
+ * @return The error flags.
+ */
+static uartflags_t translate_errors(uint16_t sr) {
+ uartflags_t sts = 0;
+
+ if (sr & USART_SR_ORE)
+ sts |= UART_OVERRUN_ERROR;
+ if (sr & USART_SR_PE)
+ sts |= UART_PARITY_ERROR;
+ if (sr & USART_SR_FE)
+ sts |= UART_FRAMING_ERROR;
+ if (sr & USART_SR_NE)
+ sts |= UART_NOISE_ERROR;
+ if (sr & USART_SR_LBD)
+ 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 set_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->dmamode | 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
+ */
+static void usart_start(UARTDriver *uartp) {
+ uint16_t cr1;
+ USART_TypeDef *u = uartp->usart;
+
+ /* Defensive programming, starting from a clean state.*/
+ usart_stop(uartp);
+
+ /* Baud rate setting.*/
+#if STM32_HAS_USART6
+ if ((uartp->usart == USART1) || (uartp->usart == USART6))
+#else
+ if (uartp->usart == USART1)
+#endif
+ u->BRR = STM32_PCLK2 / uartp->config->speed;
+ else
+ u->BRR = STM32_PCLK1 / uartp->config->speed;
+
+ /* Resetting eventual pending status flags.*/
+ (void)u->SR; /* SR reset step 1.*/
+ (void)u->DR; /* SR reset step 2.*/
+ u->SR = 0;
+
+ /* 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;
+ if (uartp->config->txend2_cb == NULL)
+ cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE;
+ else
+ cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE |
+ USART_CR1_TCIE;
+ u->CR1 = uartp->config->cr1 | cr1;
+
+ /* Starting the receiver idle loop.*/
+ set_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.*/
+ if (uartp->config->rxchar_cb != NULL)
+ uartp->config->rxchar_cb(uartp, uartp->rxbuf);
+ }
+ else {
+ /* Receiver in active state, a callback is generated, if enabled, after
+ a completed transfer.*/
+ dmaStreamDisable(uartp->dmarx);
+ uartp->rxstate = UART_RX_COMPLETE;
+ if (uartp->config->rxend_cb != NULL)
+ uartp->config->rxend_cb(uartp);
+
+ /* If the callback didn't explicitly change state then the receiver
+ automatically returns to the idle state.*/
+ if (uartp->rxstate == UART_RX_COMPLETE) {
+ uartp->rxstate = UART_RX_IDLE;
+ set_rx_idle_loop(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.*/
+ uartp->txstate = UART_TX_COMPLETE;
+ if (uartp->config->txend1_cb != NULL)
+ uartp->config->txend1_cb(uartp);
+
+ /* If the callback didn't explicitly change state then the transmitter
+ automatically returns to the idle state.*/
+ if (uartp->txstate == UART_TX_COMPLETE)
+ uartp->txstate = UART_TX_IDLE;
+}
+
+/**
+ * @brief USART common service routine.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+static void serve_usart_irq(UARTDriver *uartp) {
+ uint16_t sr;
+ USART_TypeDef *u = uartp->usart;
+
+ sr = u->SR; /* SR reset step 1.*/
+ (void)u->DR; /* SR reset step 2.*/
+ if (sr & (USART_SR_LBD | USART_SR_ORE | USART_SR_NE |
+ USART_SR_FE | USART_SR_PE)) {
+ u->SR = ~USART_SR_LBD;
+ if (uartp->config->rxerr_cb != NULL)
+ uartp->config->rxerr_cb(uartp, translate_errors(sr));
+ }
+ if (sr & USART_SR_TC) {
+ u->SR = ~USART_SR_TC;
+
+ /* End of transmission, a callback is generated.*/
+ if (uartp->config->txend2_cb != NULL)
+ uartp->config->txend2_cb(uartp);
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_UART_USE_USART1 || defined(__DOXYGEN__)
+#if !defined(STM32_USART1_HANDLER)
+#error "STM32_USART1_HANDLER not defined"
+#endif
+/**
+ * @brief USART1 IRQ handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(STM32_USART1_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ serve_usart_irq(&UARTD1);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* STM32_UART_USE_USART1 */
+
+#if STM32_UART_USE_USART2 || defined(__DOXYGEN__)
+#if !defined(STM32_USART2_HANDLER)
+#error "STM32_USART2_HANDLER not defined"
+#endif
+/**
+ * @brief USART2 IRQ handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(STM32_USART2_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ serve_usart_irq(&UARTD2);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* STM32_UART_USE_USART2 */
+
+#if STM32_UART_USE_USART3 || defined(__DOXYGEN__)
+#if !defined(STM32_USART3_HANDLER)
+#error "STM32_USART3_HANDLER not defined"
+#endif
+/**
+ * @brief USART3 IRQ handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(STM32_USART3_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ serve_usart_irq(&UARTD3);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* STM32_UART_USE_USART3 */
+
+#if STM32_UART_USE_UART4 || defined(__DOXYGEN__)
+#if !defined(STM32_UART4_HANDLER)
+#error "STM32_UART4_HANDLER not defined"
+#endif
+/**
+ * @brief UART4 IRQ handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(STM32_UART4_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ serve_usart_irq(&UARTD4);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* STM32_UART_USE_UART4 */
+
+#if STM32_UART_USE_UART5 || defined(__DOXYGEN__)
+#if !defined(STM32_UART5_HANDLER)
+#error "STM32_UART5_HANDLER not defined"
+#endif
+/**
+ * @brief UART5 IRQ handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(STM32_UART5_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ serve_usart_irq(&UARTD5);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* STM32_UART_USE_UART5 */
+
+#if STM32_UART_USE_USART6 || defined(__DOXYGEN__)
+#if !defined(STM32_USART6_HANDLER)
+#error "STM32_USART6_HANDLER not defined"
+#endif
+/**
+ * @brief USART6 IRQ handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(STM32_USART6_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ serve_usart_irq(&UARTD6);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* STM32_UART_USE_USART6 */
+
+/*===========================================================================*/
+/* 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.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD1.dmarx = STM32_DMA_STREAM(STM32_UART_USART1_RX_DMA_STREAM);
+ UARTD1.dmatx = STM32_DMA_STREAM(STM32_UART_USART1_TX_DMA_STREAM);
+#endif
+
+#if STM32_UART_USE_USART2
+ uartObjectInit(&UARTD2);
+ UARTD2.usart = USART2;
+ UARTD2.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD2.dmarx = STM32_DMA_STREAM(STM32_UART_USART2_RX_DMA_STREAM);
+ UARTD2.dmatx = STM32_DMA_STREAM(STM32_UART_USART2_TX_DMA_STREAM);
+#endif
+
+#if STM32_UART_USE_USART3
+ uartObjectInit(&UARTD3);
+ UARTD3.usart = USART3;
+ UARTD3.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD3.dmarx = STM32_DMA_STREAM(STM32_UART_USART3_RX_DMA_STREAM);
+ UARTD3.dmatx = STM32_DMA_STREAM(STM32_UART_USART3_TX_DMA_STREAM);
+#endif
+
+#if STM32_UART_USE_UART4
+ uartObjectInit(&UARTD4);
+ UARTD4.usart = UART4;
+ UARTD4.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD4.dmarx = STM32_DMA_STREAM(STM32_UART_UART4_RX_DMA_STREAM);
+ UARTD4.dmatx = STM32_DMA_STREAM(STM32_UART_UART4_TX_DMA_STREAM);
+#endif
+
+#if STM32_UART_USE_UART5
+ uartObjectInit(&UARTD5);
+ UARTD5.usart = UART5;
+ UARTD5.dmamode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD5.dmarx = STM32_DMA_STREAM(STM32_UART_UART5_RX_DMA_STREAM);
+ UARTD5.dmatx = STM32_DMA_STREAM(STM32_UART_UART5_TX_DMA_STREAM);
+#endif
+
+#if STM32_UART_USE_USART6
+ uartObjectInit(&UARTD6);
+ UARTD6.usart = USART6;
+ UARTD6.dmarx = STM32_DMA_STREAM(STM32_UART_USART6_RX_DMA_STREAM);
+ UARTD6.dmatx = STM32_DMA_STREAM(STM32_UART_USART6_TX_DMA_STREAM);
+#endif
+}
+
+/**
+ * @brief Configures and activates the UART peripheral.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+void uart_lld_start(UARTDriver *uartp) {
+
+ if (uartp->state == UART_STOP) {
+#if STM32_UART_USE_USART1
+ if (&UARTD1 == uartp) {
+ bool b;
+ b = dmaStreamAllocate(uartp->dmarx,
+ STM32_UART_USART1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(!b, "stream already allocated");
+ b = dmaStreamAllocate(uartp->dmatx,
+ STM32_UART_USART1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(!b, "stream already allocated");
+ rccEnableUSART1(FALSE);
+ nvicEnableVector(STM32_USART1_NUMBER, STM32_UART_USART1_IRQ_PRIORITY);
+ uartp->dmamode |= STM32_DMA_CR_CHSEL(USART1_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY);
+ }
+#endif
+
+#if STM32_UART_USE_USART2
+ if (&UARTD2 == uartp) {
+ bool b;
+ b = dmaStreamAllocate(uartp->dmarx,
+ STM32_UART_USART2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(!b, "stream already allocated");
+ b = dmaStreamAllocate(uartp->dmatx,
+ STM32_UART_USART2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(!b, "stream already allocated");
+ rccEnableUSART2(FALSE);
+ nvicEnableVector(STM32_USART2_NUMBER, STM32_UART_USART2_IRQ_PRIORITY);
+ uartp->dmamode |= STM32_DMA_CR_CHSEL(USART2_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY);
+ }
+#endif
+
+#if STM32_UART_USE_USART3
+ if (&UARTD3 == uartp) {
+ bool b;
+ b = dmaStreamAllocate(uartp->dmarx,
+ STM32_UART_USART3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(!b, "stream already allocated");
+ b = dmaStreamAllocate(uartp->dmatx,
+ STM32_UART_USART3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(!b, "stream already allocated");
+ rccEnableUSART3(FALSE);
+ nvicEnableVector(STM32_USART3_NUMBER, STM32_UART_USART3_IRQ_PRIORITY);
+ uartp->dmamode |= STM32_DMA_CR_CHSEL(USART3_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY);
+ }
+#endif
+
+#if STM32_UART_USE_UART4
+ if (&UARTD4 == uartp) {
+ bool b;
+
+ chDbgAssert((uartp->config->cr2 & STM32_UART45_CR2_CHECK_MASK) == 0,
+ "specified invalid bits in UART4 CR2 register settings");
+ chDbgAssert((uartp->config->cr3 & STM32_UART45_CR3_CHECK_MASK) == 0,
+ "specified invalid bits in UART4 CR3 register settings");
+
+ b = dmaStreamAllocate(uartp->dmarx,
+ STM32_UART_UART4_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(!b, "stream already allocated");
+ b = dmaStreamAllocate(uartp->dmatx,
+ STM32_UART_UART4_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(!b, "stream already allocated");
+ rccEnableUART4(FALSE);
+ nvicEnableVector(STM32_UART4_NUMBER, STM32_UART_UART4_IRQ_PRIORITY);
+ uartp->dmamode |= STM32_DMA_CR_CHSEL(UART4_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY);
+ }
+#endif
+
+#if STM32_UART_USE_UART5
+ if (&UARTD5 == uartp) {
+ bool b;
+
+ chDbgAssert((uartp->config->cr2 & STM32_UART45_CR2_CHECK_MASK) == 0,
+ "specified invalid bits in UART5 CR2 register settings");
+ chDbgAssert((uartp->config->cr3 & STM32_UART45_CR3_CHECK_MASK) == 0,
+ "specified invalid bits in UART5 CR3 register settings");
+
+ b = dmaStreamAllocate(uartp->dmarx,
+ STM32_UART_UART5_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(!b, "stream already allocated");
+ b = dmaStreamAllocate(uartp->dmatx,
+ STM32_UART_UART5_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(!b, "stream already allocated");
+ rccEnableUART5(FALSE);
+ nvicEnableVector(STM32_UART5_NUMBER, STM32_UART_UART5_IRQ_PRIORITY);
+ uartp->dmamode |= STM32_DMA_CR_CHSEL(UART5_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY);
+ }
+#endif
+
+#if STM32_UART_USE_USART6
+ if (&UARTD6 == uartp) {
+ bool b;
+ b = dmaStreamAllocate(uartp->dmarx,
+ STM32_UART_USART6_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(!b, "stream already allocated");
+ b = dmaStreamAllocate(uartp->dmatx,
+ STM32_UART_USART6_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(!b, "stream already allocated");
+ rccEnableUSART6(FALSE);
+ nvicEnableVector(STM32_USART6_NUMBER, STM32_UART_USART6_IRQ_PRIORITY);
+ uartp->dmamode |= STM32_DMA_CR_CHSEL(USART6_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY);
+ }
+#endif
+
+ /* 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_M)
+ uartp->dmamode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
+ dmaStreamSetPeripheral(uartp->dmarx, &uartp->usart->DR);
+ dmaStreamSetPeripheral(uartp->dmatx, &uartp->usart->DR);
+ uartp->rxbuf = 0;
+ }
+
+ uartp->rxstate = UART_RX_IDLE;
+ uartp->txstate = UART_TX_IDLE;
+ usart_start(uartp);
+}
+
+/**
+ * @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);
+ dmaStreamRelease(uartp->dmarx);
+ dmaStreamRelease(uartp->dmatx);
+
+#if STM32_UART_USE_USART1
+ if (&UARTD1 == uartp) {
+ nvicDisableVector(STM32_USART1_NUMBER);
+ rccDisableUSART1(FALSE);
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_USART2
+ if (&UARTD2 == uartp) {
+ nvicDisableVector(STM32_USART2_NUMBER);
+ rccDisableUSART2(FALSE);
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_USART3
+ if (&UARTD3 == uartp) {
+ nvicDisableVector(STM32_USART3_NUMBER);
+ rccDisableUSART3(FALSE);
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_UART4
+ if (&UARTD4 == uartp) {
+ nvicDisableVector(STM32_UART4_NUMBER);
+ rccDisableUART4(FALSE);
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_UART5
+ if (&UARTD5 == uartp) {
+ nvicDisableVector(STM32_UART5_NUMBER);
+ rccDisableUART5(FALSE);
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_USART6
+ if (&UARTD6 == uartp) {
+ nvicDisableVector(STM32_USART6_NUMBER);
+ rccDisableUSART6(FALSE);
+ 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 and start.*/
+ dmaStreamSetMemory0(uartp->dmatx, txbuf);
+ dmaStreamSetTransactionSize(uartp->dmatx, n);
+ dmaStreamSetMode(uartp->dmatx, uartp->dmamode | STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE);
+ 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 and start.*/
+ dmaStreamSetMemory0(uartp->dmarx, rxbuf);
+ dmaStreamSetTransactionSize(uartp->dmarx, n);
+ dmaStreamSetMode(uartp->dmarx, uartp->dmamode | STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE);
+ 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);
+ set_rx_idle_loop(uartp);
+ return n;
+}
+
+#endif /* HAL_USE_UART */
+
+/** @} */
diff --git a/os/hal/ports/STM32/LLD/USARTv1/uart_lld.h b/os/hal/ports/STM32/LLD/USARTv1/uart_lld.h new file mode 100644 index 000000000..b5992b340 --- /dev/null +++ b/os/hal/ports/STM32/LLD/USARTv1/uart_lld.h @@ -0,0 +1,603 @@ +/*
+ ChibiOS/RT - Copyright (C) 2006-2013 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 STM32/USARTv1/uart_lld.h
+ * @brief STM32 low level UART driver header.
+ *
+ * @addtogroup UART
+ * @{
+ */
+
+#ifndef _UART_LLD_H_
+#define _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 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 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 USART 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
+#if !STM32_HAS_UART4
+#error "UART4 not present in the selected device"
+#endif
+
+#if !defined(STM32F2XX) && !defined(STM32F4XX)
+#error "UART4 DMA access not supported in this platform"
+#endif
+#endif /* STM32_UART_USE_UART4 */
+
+#if STM32_UART_USE_UART5
+#if !STM32_HAS_UART5
+#error "UART5 not present in the selected device"
+#endif
+
+#if !defined(STM32F2XX) && !defined(STM32F4XX)
+#error "UART5 DMA access not supported in this platform"
+#endif
+#endif /* STM32_UART_USE_UART5 */
+
+#if STM32_UART_USE_USART6 && !STM32_HAS_USART6
+#error "USART6 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
+#error "UART driver activated but no USART/UART peripheral assigned"
+#endif
+
+#if STM32_UART_USE_USART1 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USART1"
+#endif
+
+#if STM32_UART_USE_USART2 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USART2"
+#endif
+
+#if STM32_UART_USE_USART3 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USART3"
+#endif
+
+#if STM32_UART_USE_UART4 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_UART4_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to UART4"
+#endif
+
+#if STM32_UART_USE_UART5 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_UART5_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to UART5"
+#endif
+
+#if STM32_UART_USE_USART6 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_UART_USART6_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USART6"
+#endif
+
+#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
+
+/* The following checks are only required when there is a DMA able to
+ reassign streams to different channels.*/
+#if STM32_ADVANCED_DMA
+/* 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
+
+/* 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
+#endif /* STM32_ADVANCED_DMA */
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief UART driver condition flags type.
+ */
+typedef uint32_t uartflags_t;
+
+/**
+ * @brief Structure representing an UART driver.
+ */
+typedef struct UARTDriver 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 Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ /**
+ * @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 Bit rate.
+ */
+ uint32_t speed;
+ /**
+ * @brief Initialization value for the CR1 register.
+ */
+ uint16_t cr1;
+ /**
+ * @brief Initialization value for the CR2 register.
+ */
+ uint16_t cr2;
+ /**
+ * @brief Initialization value for the CR3 register.
+ */
+ uint16_t cr3;
+} UARTConfig;
+
+/**
+ * @brief Structure representing an UART driver.
+ */
+struct UARTDriver {
+ /**
+ * @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 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 DMA mode bit mask.
+ */
+ uint32_t dmamode;
+ /**
+ * @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
+
+#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);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_UART */
+
+#endif /* _UART_LLD_H_ */
+
+/** @} */
|