You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2021/02/01 07:45:30 UTC

[GitHub] [mynewt-core] kasjer commented on a change in pull request #2436: Add da1469x uart driver

kasjer commented on a change in pull request #2436:
URL: https://github.com/apache/mynewt-core/pull/2436#discussion_r567616137



##########
File path: hw/drivers/uart/uart_da1469x/src/uart_da1469x.c
##########
@@ -0,0 +1,563 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <bsp.h>
+#include "uart/uart.h"
+#include "mcu/da1469x_pd.h"
+#include "mcu/da1469x_hal.h"
+#include "hal/hal_gpio.h"
+#include "uart_da1469x/uart_da1469x.h"
+
+static void da1469x_uart_uart_isr(void);
+static void da1469x_uart_uart2_isr(void);
+static void da1469x_uart_uart3_isr(void);
+
+struct da1469x_uart_hw_data {
+    UART2_Type *regs;
+    IRQn_Type irqn;
+    mcu_gpio_func rx_pin_func;
+    mcu_gpio_func tx_pin_func;
+    mcu_gpio_func rts_pin_func;
+    mcu_gpio_func cts_pin_func;
+    /* Mask for (RE)SET_CLK_COM_REG */
+    uint8_t clk_com_mask;
+    void (*isr)(void);
+};
+
+static const struct da1469x_uart_hw_data da1469x_uart0_hw = {
+    .regs = (UART2_Type *)UART,
+    .irqn = UART_IRQn,
+    .rx_pin_func = MCU_GPIO_FUNC_UART_RX,
+    .tx_pin_func = MCU_GPIO_FUNC_UART_TX,
+    .rts_pin_func = MCU_GPIO_FUNC_GPIO,
+    .cts_pin_func = MCU_GPIO_FUNC_GPIO,
+    .clk_com_mask = CRG_COM_RESET_CLK_COM_REG_UART_ENABLE_Msk,
+    .isr = da1469x_uart_uart_isr,
+};
+
+static const struct da1469x_uart_hw_data da1469x_uart1_hw = {
+    .regs = (UART2_Type *)UART2,
+    .irqn = UART2_IRQn,
+    .rx_pin_func = MCU_GPIO_FUNC_UART2_RX,
+    .tx_pin_func = MCU_GPIO_FUNC_UART2_TX,
+    .rts_pin_func = MCU_GPIO_FUNC_UART2_RTSN,
+    .cts_pin_func = MCU_GPIO_FUNC_UART2_CTSN,
+    .clk_com_mask = CRG_COM_RESET_CLK_COM_REG_UART2_ENABLE_Msk,
+    .isr = da1469x_uart_uart2_isr,
+};
+
+static const struct da1469x_uart_hw_data da1469x_uart2_hw = {
+    .regs = (UART2_Type *)UART3,
+    .irqn = UART3_IRQn,
+    .rx_pin_func = MCU_GPIO_FUNC_UART3_RX,
+    .tx_pin_func = MCU_GPIO_FUNC_UART3_TX,
+    .rts_pin_func = MCU_GPIO_FUNC_UART3_RTSN,
+    .cts_pin_func = MCU_GPIO_FUNC_UART3_CTSN,
+    .clk_com_mask = CRG_COM_RESET_CLK_COM_REG_UART3_ENABLE_Msk,
+    .isr = da1469x_uart_uart3_isr,
+};
+
+static struct da1469x_uart_dev *da1469x_dev0;
+static struct da1469x_uart_dev *da1469x_dev1;
+static struct da1469x_uart_dev *da1469x_dev2;
+
+static void da1469x_uart_uart_configure(struct da1469x_uart_dev *dev);
+static void da1469x_uart_uart_shutdown(struct da1469x_uart_dev *dev);
+
+static void
+da1469x_uart_on_wakeup_callout_cb(struct os_event *ev)
+{
+    struct da1469x_uart_dev *dev = ev->ev_arg;
+
+    da1469x_uart_uart_configure(dev);
+}
+
+static void
+da1469x_uart_on_wakeup_gpio_cb(void *arg)
+{
+    struct da1469x_uart_dev *dev = arg;
+
+    hal_gpio_irq_disable(dev->da1469x_cfg.pin_rx);
+    hal_gpio_irq_release(dev->da1469x_cfg.pin_rx);
+
+    os_callout_reset(&dev->wakeup_callout,
+                     os_time_ms_to_ticks32(MYNEWT_VAL(UART_DA1469X_WAKEUP_DELAY_MS)));
+}
+
+static void
+da1469x_uart_on_setup_wakeup_cb(struct os_event *ev)
+{
+    struct da1469x_uart_dev *dev = ev->ev_arg;
+
+    hal_gpio_irq_init(dev->da1469x_cfg.pin_rx, da1469x_uart_on_wakeup_gpio_cb, dev,
+                      HAL_GPIO_TRIG_RISING, HAL_GPIO_PULL_NONE);
+    hal_gpio_irq_enable(dev->da1469x_cfg.pin_rx);
+}
+
+static void
+da1469x_uart_setup_wakeup(struct da1469x_uart_dev *dev)
+{
+    os_eventq_put(os_eventq_dflt_get(), &dev->setup_wakeup_event);
+}
+
+static inline void
+da1469x_uart_tx_intr_enable(struct da1469x_uart_dev *dev)
+{
+    dev->hw->regs->UART2_IER_DLH_REG |= UART2_UART2_IER_DLH_REG_PTIME_DLH7_Msk |
+                                        UART2_UART2_IER_DLH_REG_ETBEI_DLH1_Msk;
+}
+
+static inline void
+da1469x_uart_tx_intr_disable(struct da1469x_uart_dev *dev)
+{
+    dev->hw->regs->UART2_IER_DLH_REG &= ~(UART2_UART2_IER_DLH_REG_PTIME_DLH7_Msk |
+                                          UART2_UART2_IER_DLH_REG_ETBEI_DLH1_Msk);
+}
+
+static inline void
+da1469x_uart_lsr_intr_enable(struct da1469x_uart_dev *dev)
+{
+    dev->hw->regs->UART2_IER_DLH_REG |= UART2_UART2_IER_DLH_REG_ELSI_DLH2_Msk;
+}
+
+static inline void
+da1469x_uart_rx_intr_enable(struct da1469x_uart_dev *dev)
+{
+    dev->hw->regs->UART2_IER_DLH_REG |= UART2_UART2_IER_DLH_REG_ERBFI_DLH0_Msk;
+}
+
+static inline void
+da1469x_uart_rx_intr_disable(struct da1469x_uart_dev *dev)
+{
+    dev->hw->regs->UART2_IER_DLH_REG &= ~UART2_UART2_IER_DLH_REG_ERBFI_DLH0_Msk;
+}
+
+static void
+da1469x_uart_isr_thr_empty(struct da1469x_uart_dev *dev)
+{
+    struct uart_conf *uc = &dev->uc;
+    int ch;
+
+    while (dev->hw->regs->UART2_USR_REG & UART2_UART2_USR_REG_UART_TFNF_Msk) {
+        ch = uc->uc_tx_char(uc->uc_cb_arg);
+        if (ch < 0) {
+            da1469x_uart_tx_intr_disable(dev);
+            dev->tx_started = 0;
+            if (uc->uc_tx_done) {
+                uc->uc_tx_done(uc->uc_cb_arg);
+            }
+            break;
+        }
+
+        dev->hw->regs->UART2_RBR_THR_DLL_REG = ch;
+    }
+}
+
+static void
+da1469x_uart_isr_recv_data(struct da1469x_uart_dev *dev)
+{
+    int ch;
+
+    dev->rx_data = dev->hw->regs->UART2_RBR_THR_DLL_REG;
+
+    ch = dev->uc.uc_rx_char(dev->uc.uc_cb_arg, dev->rx_data);
+    if (ch < 0) {
+        da1469x_uart_rx_intr_disable(dev);
+        dev->rx_stalled = 1;
+    }
+}
+
+static void
+da1469x_uart_isr(struct da1469x_uart_dev *dev)
+{
+    UART2_Type *uart = dev->hw->regs;
+    bool no_intr = false;
+
+    os_trace_isr_enter();
+
+    while (!no_intr) {
+        /*
+         * NOTE: should be UART2_UART2_IIR_FCR_REG_IIR_FCR_Msk below but this is
+         *     defined (incorrectly) as 0xFF so incorrect value is read.
+         */
+        switch (uart->UART2_IIR_FCR_REG & 0x0F) {
+        case 0x01: /* no interrupt pending */
+            no_intr = true;
+            break;
+        case 0x02: /* THR empty */
+            da1469x_uart_isr_thr_empty(dev);
+            break;
+        case 0x04: /* received data available */
+            da1469x_uart_isr_recv_data(dev);
+            break;
+        case 0x06: /* receiver line status */
+            if (uart->UART2_LSR_REG & UART2_UART2_LSR_REG_UART_BI_Msk) {
+                da1469x_uart_uart_shutdown(dev);
+                da1469x_uart_setup_wakeup(dev);
+                no_intr = true;
+            }
+            break;
+        case 0x07: /* busy detect */
+            (void)uart->UART2_USR_REG;
+            da1469x_uart_uart_shutdown(dev);
+            da1469x_uart_setup_wakeup(dev);
+            no_intr = true;
+            break;
+        case 0x0c: /* character timeout */
+            break;
+        default:
+            assert(0);
+            break;
+        }
+    }
+
+    os_trace_isr_exit();
+}
+
+static void
+da1469x_uart_uart_isr(void)
+{
+    da1469x_uart_isr(da1469x_dev0);
+}
+
+static void
+da1469x_uart_uart2_isr(void)
+{
+    da1469x_uart_isr(da1469x_dev1);
+}
+
+static void
+da1469x_uart_uart3_isr(void)
+{
+    da1469x_uart_isr(da1469x_dev2);
+}
+
+static void
+da1469x_uart_uart_configure(struct da1469x_uart_dev *dev)
+{
+    struct uart_conf *uc = &dev->uc;
+    uint32_t baudrate_cfg;
+    uint32_t reg;
+    UART2_Type *uart = dev->hw->regs;
+    IRQn_Type irqn = dev->hw->irqn;
+
+    da1469x_pd_acquire(MCU_PD_DOMAIN_COM);
+
+    NVIC_DisableIRQ(irqn);
+
+    if (dev->da1469x_cfg.pin_rx >= 0) {
+        /* Turn RX pin to GPIO input during configuration to avoid busy state */
+        mcu_gpio_set_pin_function(dev->da1469x_cfg.pin_rx, MCU_GPIO_MODE_INPUT,
+                                  MCU_GPIO_FUNC_GPIO);
+    }
+
+    /* Reset UART */
+    CRG_COM->RESET_CLK_COM_REG = dev->hw->clk_com_mask;
+    CRG_COM->SET_CLK_COM_REG = dev->hw->clk_com_mask;
+    uart->UART2_SRR_REG = UART2_UART2_SRR_REG_UART_UR_Msk |
+                          UART2_UART2_SRR_REG_UART_RFR_Msk |
+                          UART2_UART2_SRR_REG_UART_XFR_Msk;
+
+    /* Configure baudrate */
+    baudrate_cfg = (32000000 - 1 + (uc->uc_speed / 2)) / uc->uc_speed;

Review comment:
       There is DivN block after system clock so for 96MHz PLL 32MHz is source for UART clock, same for no PPL and XTAL32M.
   Maybe if system clock is set to LP_CLK, value should be different.
   I can apply 32MHz limit to expression if you think UART is likely to be used with LP clock.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org