diff options
Diffstat (limited to 'os/halnew/platforms/STM32/USARTv1')
-rw-r--r-- | os/halnew/platforms/STM32/USARTv1/serial_lld.c | 531 | ||||
-rw-r--r-- | os/halnew/platforms/STM32/USARTv1/serial_lld.h | 303 | ||||
-rw-r--r-- | os/halnew/platforms/STM32/USARTv1/uart_lld.c | 838 | ||||
-rw-r--r-- | os/halnew/platforms/STM32/USARTv1/uart_lld.h | 680 |
4 files changed, 2352 insertions, 0 deletions
diff --git a/os/halnew/platforms/STM32/USARTv1/serial_lld.c b/os/halnew/platforms/STM32/USARTv1/serial_lld.c new file mode 100644 index 000000000..a8333bf77 --- /dev/null +++ b/os/halnew/platforms/STM32/USARTv1/serial_lld.c @@ -0,0 +1,531 @@ +/*
+ 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 "ch.h"
+#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) {
+ flagsmask_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;
+ chSysLockFromIsr();
+ chnAddFlagsI(sdp, sts);
+ chSysUnlockFromIsr();
+}
+
+/**
+ * @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; /* SR reset step 1.*/
+ uint16_t dr = u->DR; /* SR reset step 2.*/
+
+ /* Error condition detection.*/
+ if (sr & (USART_SR_ORE | USART_SR_NE | USART_SR_FE | USART_SR_PE))
+ set_error(sdp, sr);
+ /* Special case, LIN break detection.*/
+ if (sr & USART_SR_LBD) {
+ chSysLockFromIsr();
+ chnAddFlagsI(sdp, SD_BREAK_DETECTED);
+ chSysUnlockFromIsr();
+ u->SR &= ~USART_SR_LBD;
+ }
+ /* Data available.*/
+ if (sr & USART_SR_RXNE) {
+ chSysLockFromIsr();
+ sdIncomingDataI(sdp, (uint8_t)dr);
+ chSysUnlockFromIsr();
+ }
+ /* Transmission buffer empty.*/
+ if ((cr1 & USART_CR1_TXEIE) && (sr & USART_SR_TXE)) {
+ msg_t b;
+ chSysLockFromIsr();
+ b = chOQGetI(&sdp->oqueue);
+ if (b < Q_OK) {
+ chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
+ u->CR1 = (cr1 & ~USART_CR1_TXEIE) | USART_CR1_TCIE;
+ }
+ else
+ u->DR = b;
+ chSysUnlockFromIsr();
+ }
+ /* Physical transmission end.*/
+ if (sr & USART_SR_TC) {
+ chSysLockFromIsr();
+ chnAddFlagsI(sdp, CHN_TRANSMISSION_END);
+ chSysUnlockFromIsr();
+ u->CR1 = cr1 & ~USART_CR1_TCIE;
+ u->SR &= ~USART_SR_TC;
+ }
+}
+
+#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
+static void notify1(GenericQueue *qp) {
+
+ (void)qp;
+ USART1->CR1 |= USART_CR1_TXEIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__)
+static void notify2(GenericQueue *qp) {
+
+ (void)qp;
+ USART2->CR1 |= USART_CR1_TXEIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__)
+static void notify3(GenericQueue *qp) {
+
+ (void)qp;
+ USART3->CR1 |= USART_CR1_TXEIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__)
+static void notify4(GenericQueue *qp) {
+
+ (void)qp;
+ UART4->CR1 |= USART_CR1_TXEIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__)
+static void notify5(GenericQueue *qp) {
+
+ (void)qp;
+ UART5->CR1 |= USART_CR1_TXEIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__)
+static void notify6(GenericQueue *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
+ */
+CH_IRQ_HANDLER(STM32_USART1_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD1);
+
+ CH_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
+ */
+CH_IRQ_HANDLER(STM32_USART2_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD2);
+
+ CH_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
+ */
+CH_IRQ_HANDLER(STM32_USART3_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD3);
+
+ CH_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
+ */
+CH_IRQ_HANDLER(STM32_UART4_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD4);
+
+ CH_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
+ */
+CH_IRQ_HANDLER(STM32_UART5_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD5);
+
+ CH_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
+ */
+CH_IRQ_HANDLER(STM32_USART6_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD6);
+
+ CH_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,
+ CORTEX_PRIORITY_MASK(STM32_SERIAL_USART1_PRIORITY));
+ }
+#endif
+#if STM32_SERIAL_USE_USART2
+ if (&SD2 == sdp) {
+ rccEnableUSART2(FALSE);
+ nvicEnableVector(STM32_USART2_NUMBER,
+ CORTEX_PRIORITY_MASK(STM32_SERIAL_USART2_PRIORITY));
+ }
+#endif
+#if STM32_SERIAL_USE_USART3
+ if (&SD3 == sdp) {
+ rccEnableUSART3(FALSE);
+ nvicEnableVector(STM32_USART3_NUMBER,
+ CORTEX_PRIORITY_MASK(STM32_SERIAL_USART3_PRIORITY));
+ }
+#endif
+#if STM32_SERIAL_USE_UART4
+ if (&SD4 == sdp) {
+ rccEnableUART4(FALSE);
+ nvicEnableVector(STM32_UART4_NUMBER,
+ CORTEX_PRIORITY_MASK(STM32_SERIAL_UART4_PRIORITY));
+ }
+#endif
+#if STM32_SERIAL_USE_UART5
+ if (&SD5 == sdp) {
+ rccEnableUART5(FALSE);
+ nvicEnableVector(STM32_UART5_NUMBER,
+ CORTEX_PRIORITY_MASK(STM32_SERIAL_UART5_PRIORITY));
+ }
+#endif
+#if STM32_SERIAL_USE_USART6
+ if (&SD6 == sdp) {
+ rccEnableUSART6(FALSE);
+ nvicEnableVector(STM32_USART6_NUMBER,
+ CORTEX_PRIORITY_MASK(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/halnew/platforms/STM32/USARTv1/serial_lld.h b/os/halnew/platforms/STM32/USARTv1/serial_lld.h new file mode 100644 index 000000000..7242537d7 --- /dev/null +++ b/os/halnew/platforms/STM32/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.*/ \
+ InputQueue iqueue; \
+ /* Output queue.*/ \
+ OutputQueue 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/halnew/platforms/STM32/USARTv1/uart_lld.c b/os/halnew/platforms/STM32/USARTv1/uart_lld.c new file mode 100644 index 000000000..cad1cf084 --- /dev/null +++ b/os/halnew/platforms/STM32/USARTv1/uart_lld.c @@ -0,0 +1,838 @@ +/*
+ 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 "ch.h"
+#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)
+
+#if (STM32_UART_USE_UART4 || STM32_UART_USE_UART5)
+ #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)
+#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
+
+/*===========================================================================*/
+/* 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 Check CR2 and CR3 values for compatibility with UART4, UART5.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+#if (STM32_UART_USE_UART4 || STM32_UART_USE_UART5)
+static void uart_check_config(const UARTDriver *uartp) {
+
+ uint16_t cr;
+
+ cr = uartp->config->cr2;
+ chDbgCheck((cr & STM32_UART45_CR2_CHECK_MASK) == 0,
+ "Some flags from CR2 unavailable for this UART");
+
+ cr = uartp->config->cr3;
+ chDbgCheck((cr & STM32_UART45_CR3_CHECK_MASK) == 0,
+ "Some flags from CR3 unavailable for this UART");
+}
+#endif /* (STM32_UART_USE_UART4 || STM32_UART_USE_UART5) */
+
+/**
+ * @brief Configures and activates the UART peripheral.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+void uart_lld_start(UARTDriver *uartp) {
+
+#if STM32_UART_USE_UART4
+ if (uartp == &UARTD4)
+ uart_check_config(uartp);
+#elif STM32_UART_USE_UART5
+ else if (uartp == &UARTD5)
+ uart_check_config(uartp);
+#endif
+
+ if (uartp->state == UART_STOP) {
+#if STM32_UART_USE_USART1
+ if (&UARTD1 == uartp) {
+ bool_t b;
+ b = dmaStreamAllocate(uartp->dmarx,
+ STM32_UART_USART1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ chDbgAssert(!b, "uart_lld_start(), #1", "stream already allocated");
+ b = dmaStreamAllocate(uartp->dmatx,
+ STM32_UART_USART1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ chDbgAssert(!b, "uart_lld_start(), #2", "stream already allocated");
+ rccEnableUSART1(FALSE);
+ nvicEnableVector(STM32_USART1_NUMBER,
+ CORTEX_PRIORITY_MASK(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_t b;
+ b = dmaStreamAllocate(uartp->dmarx,
+ STM32_UART_USART2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ chDbgAssert(!b, "uart_lld_start(), #3", "stream already allocated");
+ b = dmaStreamAllocate(uartp->dmatx,
+ STM32_UART_USART2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ chDbgAssert(!b, "uart_lld_start(), #4", "stream already allocated");
+ rccEnableUSART2(FALSE);
+ nvicEnableVector(STM32_USART2_NUMBER,
+ CORTEX_PRIORITY_MASK(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_t b;
+ b = dmaStreamAllocate(uartp->dmarx,
+ STM32_UART_USART3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ chDbgAssert(!b, "uart_lld_start(), #5", "stream already allocated");
+ b = dmaStreamAllocate(uartp->dmatx,
+ STM32_UART_USART3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ chDbgAssert(!b, "uart_lld_start(), #6", "stream already allocated");
+ rccEnableUSART3(FALSE);
+ nvicEnableVector(STM32_USART3_NUMBER,
+ CORTEX_PRIORITY_MASK(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_t b;
+ b = dmaStreamAllocate(uartp->dmarx,
+ STM32_UART_UART4_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ chDbgAssert(!b, "uart_lld_start(), #7", "stream already allocated");
+ b = dmaStreamAllocate(uartp->dmatx,
+ STM32_UART_UART4_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ chDbgAssert(!b, "uart_lld_start(), #8", "stream already allocated");
+ rccEnableUART4(FALSE);
+ nvicEnableVector(STM32_UART4_NUMBER,
+ CORTEX_PRIORITY_MASK(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_t b;
+ b = dmaStreamAllocate(uartp->dmarx,
+ STM32_UART_UART5_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ chDbgAssert(!b, "uart_lld_start(), #9", "stream already allocated");
+ b = dmaStreamAllocate(uartp->dmatx,
+ STM32_UART_UART5_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ chDbgAssert(!b, "uart_lld_start(), #10", "stream already allocated");
+ rccEnableUART5(FALSE);
+ nvicEnableVector(STM32_UART5_NUMBER,
+ CORTEX_PRIORITY_MASK(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_t b;
+ b = dmaStreamAllocate(uartp->dmarx,
+ STM32_UART_USART6_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ chDbgAssert(!b, "uart_lld_start(), #11", "stream already allocated");
+ b = dmaStreamAllocate(uartp->dmatx,
+ STM32_UART_USART6_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ chDbgAssert(!b, "uart_lld_start(), #12", "stream already allocated");
+ rccEnableUSART6(FALSE);
+ nvicEnableVector(STM32_USART6_NUMBER,
+ CORTEX_PRIORITY_MASK(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/halnew/platforms/STM32/USARTv1/uart_lld.h b/os/halnew/platforms/STM32/USARTv1/uart_lld.h new file mode 100644 index 000000000..ba8f00f1e --- /dev/null +++ b/os/halnew/platforms/STM32/USARTv1/uart_lld.h @@ -0,0 +1,680 @@ +/*
+ 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_UART4) || 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) chSysHalt()
+#endif
+
+#if STM32_ADVANCED_DMA || defined(__DOXYGEN__)
+
+/**
+ * @brief DMA stream used for USART1 RX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_UART_USART1_RX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5)
+#endif
+
+/**
+ * @brief DMA stream used for USART1 TX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_UART_USART1_TX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
+#endif
+
+/**
+ * @brief DMA stream used for USART2 RX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_UART_USART2_RX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
+#endif
+
+/**
+ * @brief DMA stream used for USART2 TX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_UART_USART2_TX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
+#endif
+
+/**
+ * @brief DMA stream used for USART3 RX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_UART_USART3_RX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1)
+#endif
+
+/**
+ * @brief DMA stream used for USART3 TX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_UART_USART3_TX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3)
+#endif
+
+/**
+ * @brief DMA stream used for UART4 RX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_UART_UART4_RX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
+#endif
+
+/**
+ * @brief DMA stream used for UART4 TX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_UART_UART4_TX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
+#endif
+
+/**
+ * @brief DMA stream used for UART5 RX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_UART_UART5_RX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
+#endif
+
+/**
+ * @brief DMA stream used for UART5 TX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_UART_UART5_TX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
+#endif
+
+/**
+ * @brief DMA stream used for USART6 RX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_UART_USART6_RX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
+#endif
+
+/**
+ * @brief DMA stream used for USART6 TX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_UART_USART6_TX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
+#endif
+
+#else /* !STM32_ADVANCED_DMA */
+
+/* Fixed streams for platforms using the old DMA peripheral, the values are
+ valid for both STM32F1xx and STM32L1xx.*/
+#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
+#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
+#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
+#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
+#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3)
+#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
+#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3)
+#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5)
+
+#endif /* !STM32_ADVANCED_DMA*/
+/** @} */
+
+/*===========================================================================*/
+/* 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(STM32F4XX) || !defined(STM32F4XX)
+ #error "UART4 DMA access not supported in this platform"
+ #endif
+#endif
+
+#if STM32_UART_USE_UART5
+ #if !STM32_HAS_UART5
+ #error "UART5 not present in the selected device"
+ #endif
+
+ #if !defined(STM32F4XX) || !defined(STM32F4XX)
+ #error "UART5 DMA access not supported in this platform"
+ #endif
+#endif
+
+#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
+
+#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 !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_ */
+
+/** @} */
|