You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2016/10/11 16:25:22 UTC

[03/45] incubator-mynewt-core git commit: mcu: MK64F12: add uart HAL

mcu: MK64F12: add uart HAL

- Console input needs work

Signed-off-by: Michael Scott <mi...@linaro.org>


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/920371ad
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/920371ad
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/920371ad

Branch: refs/heads/develop
Commit: 920371ad8c06a430234234a4818ae6f236167892
Parents: b8ee7f5
Author: Michael Scott <mi...@linaro.org>
Authored: Fri Oct 7 16:40:26 2016 -0700
Committer: Michael Scott <mi...@linaro.org>
Committed: Mon Oct 10 23:59:41 2016 -0700

----------------------------------------------------------------------
 hw/mcu/nxp/MK64F12/src/hal_uart.c     | 403 +++++++++++++++++++++++++++++
 hw/mcu/nxp/MK64F12/src/hal_uart_nxp.h |  80 ++++++
 2 files changed, 483 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/920371ad/hw/mcu/nxp/MK64F12/src/hal_uart.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nxp/MK64F12/src/hal_uart.c b/hw/mcu/nxp/MK64F12/src/hal_uart.c
new file mode 100644
index 0000000..8c04bf1
--- /dev/null
+++ b/hw/mcu/nxp/MK64F12/src/hal_uart.c
@@ -0,0 +1,403 @@
+/**
+ * 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 "syscfg/syscfg.h"
+#include "hal/hal_uart.h"
+#include "hal/hal_gpio.h"
+#include "hal/hal_system.h"
+#include "bsp/cmsis_nvic.h"
+#include "bsp/bsp.h"
+#include "os/os.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "mcu/frdm-k64f_hal.h"
+#include "MK64F12.h"
+#include "fsl_port.h"
+#include "fsl_uart.h"
+#include "fsl_debug_console.h"
+
+#include "hal_uart_nxp.h"
+
+/*! @brief Ring buffer size (Unit: Byte). */
+#define TX_BUF_SZ  32
+#define RX_BUF_SZ  128
+
+struct uart_ring {
+    uint16_t ur_head;
+    uint16_t ur_tail;
+    uint16_t ur_size;
+    uint8_t _pad;
+    uint8_t *ur_buf;
+};
+
+struct hal_uart {
+    UART_Type       *u_base;
+    clock_name_t     clk_src;
+    uint32_t         u_irq;
+    PORT_Type       *p_base;
+    clock_ip_name_t  p_clock;
+    int  u_pin_rx;
+    int  u_pin_tx;
+    /* TODO: support flow control pins */
+    hal_uart_rx_char u_rx_func;
+    hal_uart_tx_char u_tx_func;
+    hal_uart_tx_done u_tx_done;
+    void *u_func_arg;
+    uint8_t u_configured:1;
+    uint8_t u_open:1;
+    uint8_t u_tx_started:1;
+    struct uart_ring ur_tx;
+    uint8_t tx_buffer[TX_BUF_SZ];
+    struct uart_ring ur_rx;
+    uint8_t rx_buffer[RX_BUF_SZ];
+};
+
+/* UART configurations */
+static struct hal_uart uarts[FSL_FEATURE_SOC_UART_COUNT];
+
+static uint8_t const s_uartExists[] = NXP_UART_EXISTS;
+static uint8_t const s_uartEnabled[] = NXP_UART_ENABLED;
+static UART_Type *const s_uartBases[] = UART_BASE_PTRS;
+static clock_name_t s_uartClocks[] = NXP_UART_CLOCKS;
+static uint8_t const s_uartIRQ[] = UART_RX_TX_IRQS;
+static PORT_Type *const s_uartPort[] = NXP_UART_PORTS;
+static clock_ip_name_t const s_uartPortClocks[] = NXP_UART_PORT_CLOCKS;
+static uint8_t const s_uartPIN_RX[] = NXP_UART_PIN_RX;
+static uint8_t const s_uartPIN_TX[] = NXP_UART_PIN_TX;
+
+/*
+ * RING BUFFER FUNCTIONS
+ */
+
+static uint8_t ur_is_empty(struct uart_ring *ur)
+{
+    return (ur->ur_head == ur->ur_tail);;
+}
+
+static uint8_t ur_is_full(struct uart_ring *ur)
+{
+    return (((ur->ur_tail + 1) % ur->ur_size) == ur->ur_head);
+}
+
+static void ur_bump(struct uart_ring *ur)
+{
+    if (!ur_is_empty(ur)) {
+        ur->ur_head++;
+        ur->ur_head %= ur->ur_size;
+        return;
+    }
+}
+
+static uint8_t ur_read(struct uart_ring *ur)
+{
+    return ur->ur_buf[ur->ur_head];
+}
+
+static int ur_queue(struct uart_ring *ur, uint8_t data)
+{
+    if (!ur_is_full(ur)) {
+        ur->ur_buf[ur->ur_tail] = data;
+        ur->ur_tail++;
+        ur->ur_tail %= ur->ur_size;
+        return 0;
+    }
+    return -1;
+}
+
+/*
+ * END RING BUFFER FUNCTIONS
+ */
+
+int hal_uart_init_cbs(int port, hal_uart_tx_char tx_func,
+  hal_uart_tx_done tx_done, hal_uart_rx_char rx_func, void *arg)
+{
+    struct hal_uart *u;
+
+    if (port >= FSL_FEATURE_SOC_UART_COUNT) {
+        return -1;
+    }
+    u = &uarts[port];
+    u->u_rx_func = rx_func;
+    u->u_tx_func = tx_func;
+    u->u_tx_done = tx_done;
+    u->u_func_arg = arg;
+
+    return 0;
+}
+
+void hal_uart_blocking_tx(int port, uint8_t byte)
+{
+    struct hal_uart *u;
+
+    if (port >= FSL_FEATURE_SOC_UART_COUNT) {
+        return;
+    }
+    u = &uarts[port];
+    if (!u->u_configured || !u->u_open) {
+        return;
+    }
+
+    UART_WriteBlocking(u->u_base, &byte, 1);
+}
+
+static int
+hal_uart_tx_fill_buf(struct hal_uart *u)
+{
+    int data = 0;
+    int i = 0;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+    while (!ur_is_full(&u->ur_tx)) {
+        if (u->u_tx_func)
+            data = u->u_tx_func(u->u_func_arg);
+        if (data <= 0) {
+            break;
+        }
+        i++;
+        ur_queue(&u->ur_tx, data);
+    }
+    OS_EXIT_CRITICAL(sr);
+    return i;
+}
+
+void hal_uart_start_tx(int port)
+{
+    struct hal_uart *u;
+    int data = -1;
+    int rc;
+
+    if (port >= FSL_FEATURE_SOC_UART_COUNT) {
+        return;
+    }
+    u = &uarts[port];
+    if (!u->u_configured || !u->u_open) {
+        return;
+    }
+
+    /* main loop */
+    while (true)
+    {
+        /* add data to TX ring buffer */
+        if (u->u_tx_started == 0) {
+            rc = hal_uart_tx_fill_buf(u);
+            if (rc > 0)
+                u->u_tx_started = 1;
+        }
+
+        /* Send data only when UART TX register is empty and TX ring buffer has data to send out. */
+        while (!ur_is_empty(&u->ur_tx) &&
+               (kUART_TxDataRegEmptyFlag & UART_GetStatusFlags(u->u_base)))
+        {
+            data = ur_read(&u->ur_tx);
+            UART_WriteByte(u->u_base, data);
+            ur_bump(&u->ur_tx);
+        }
+
+        if (ur_is_empty(&u->ur_tx)) {
+            if (u->u_tx_done)
+                u->u_tx_done(u->u_func_arg);
+            u->u_tx_started = 0;
+            break;
+        }
+    }
+}
+
+void hal_uart_start_rx(int port)
+{
+    struct hal_uart *u;
+    os_sr_t sr;
+    int rc = 0;
+
+    if (port >= FSL_FEATURE_SOC_UART_COUNT) {
+        return;
+    }
+    u = &uarts[port];
+    if (!u->u_configured || !u->u_open) {
+        return;
+    }
+
+    /* Send back what's in the RX ring buffer until it's empty or we get an error */
+    while ((rc >= 0) && !ur_is_empty(&u->ur_rx))
+    {
+        OS_ENTER_CRITICAL(sr);
+        rc = u->u_rx_func(u->u_func_arg, ur_read(&u->ur_rx));
+        if (rc >= 0)
+            ur_bump(&u->ur_rx);
+        OS_EXIT_CRITICAL(sr);
+    }
+}
+
+void uart_irq_handler(void)
+{
+    struct hal_uart *u;
+    int port;
+    uint8_t data;
+
+    for (port = 0; port < FSL_FEATURE_SOC_UART_COUNT; port++) {
+        u = &uarts[port];
+        if (u->u_configured && u->u_open) {
+            /* Check for RX data */
+            if ((kUART_RxDataRegFullFlag | kUART_RxOverrunFlag) &
+                    UART_GetStatusFlags(u->u_base)) {
+                data = UART_ReadByte(u->u_base);
+                ur_queue(&u->ur_rx, data);
+            }
+            /* Check for TX complete */
+            if (kUART_TxDataRegEmptyFlag & UART_GetStatusFlags(u->u_base)) {
+                if (u->u_tx_started) {
+                    u->u_tx_started = 0;
+                    if (u->u_tx_done)
+                        u->u_tx_done(u->u_func_arg);
+                }
+            }
+        }
+    }
+}
+
+int hal_uart_config(int port, int32_t speed, uint8_t databits, uint8_t stopbits,
+                    enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl)
+{
+    struct hal_uart *u;
+    uart_config_t uconfig;
+
+    if (port >= FSL_FEATURE_SOC_UART_COUNT) {
+        return -1;
+    }
+    u = &uarts[port];
+    if (!u->u_configured || u->u_open) {
+        return -1;
+    }
+
+    /* PIN config (all UARTs use kPORT_MuxAlt3) */
+    CLOCK_EnableClock(u->p_clock);
+    PORT_SetPinMux(u->p_base, u->u_pin_rx, kPORT_MuxAlt3);
+    PORT_SetPinMux(u->p_base, u->u_pin_tx, kPORT_MuxAlt3);
+
+    /* UART CONFIG */
+    UART_GetDefaultConfig(&uconfig);
+    uconfig.baudRate_Bps = speed;
+
+    /* TODO: only handles 8 databits currently */
+
+    switch (stopbits) {
+    case 1:
+        uconfig.stopBitCount = kUART_OneStopBit;
+        break;
+    case 2:
+        uconfig.stopBitCount = kUART_TwoStopBit;
+        break;
+    default:
+        return -1;
+    }
+
+    switch (parity) {
+    case HAL_UART_PARITY_NONE:
+        uconfig.parityMode = kUART_ParityDisabled;
+        break;
+    case HAL_UART_PARITY_ODD:
+        uconfig.parityMode = kUART_ParityOdd;
+        break;
+    case HAL_UART_PARITY_EVEN:
+        uconfig.parityMode = kUART_ParityEven;
+        break;
+    }
+
+    /* TODO: HW flow control not supported */
+    assert(flow_ctl == HAL_UART_FLOW_CTL_NONE);
+
+    u->u_open = 1;
+    u->u_tx_started = 0;
+
+    NVIC_SetVector(u->u_irq, (uint32_t)uart_irq_handler);
+
+    /* Initialize UART device */
+    if (port != 0) {
+        UART_Init(u->u_base, &uconfig, CLOCK_GetFreq(u->clk_src));
+        UART_EnableTx(u->u_base, true);
+        UART_EnableRx(u->u_base, true);
+        UART_EnableInterrupts(u->u_base,
+                              kUART_RxDataRegFullInterruptEnable
+                              | kUART_RxOverrunInterruptEnable);
+        EnableIRQ(u->u_irq);
+    }
+
+    return 0;
+}
+
+int hal_uart_close(int port)
+{
+    struct hal_uart *u;
+
+    if (port >= FSL_FEATURE_SOC_UART_COUNT) {
+        return -1;
+    }
+    u = &uarts[port];
+    if (!u->u_open) {
+        return -1;
+    }
+
+    u->u_open = 0;
+    UART_DisableInterrupts(u->u_base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | kUART_TxDataRegEmptyInterruptEnable);
+    DisableIRQ(u->u_irq);
+    UART_EnableTx(u->u_base, false);
+    UART_EnableRx(u->u_base, false);
+
+    return 0;
+}
+
+int hal_uart_init(int port, void *cfg)
+{
+    if (s_uartExists[port]) {
+        if (s_uartEnabled[port]) {
+            uarts[port].u_base        = s_uartBases[port];
+            uarts[port].clk_src       = s_uartClocks[port];
+            uarts[port].u_irq         = s_uartIRQ[port];
+            uarts[port].p_base        = s_uartPort[port];
+            uarts[port].p_clock       = s_uartPortClocks[port];
+            uarts[port].u_pin_rx      = s_uartPIN_RX[port];
+            uarts[port].u_pin_tx      = s_uartPIN_TX[port];
+            uarts[port].ur_tx.ur_buf  = uarts[port].tx_buffer;
+            uarts[port].ur_tx.ur_size = TX_BUF_SZ;
+            uarts[port].ur_tx.ur_head = 0;
+            uarts[port].ur_tx.ur_tail = 0;
+            uarts[port].ur_rx.ur_buf  = uarts[port].rx_buffer;
+            uarts[port].ur_rx.ur_size = RX_BUF_SZ;
+            uarts[port].ur_rx.ur_head = 0;
+            uarts[port].ur_rx.ur_tail = 0;
+            uarts[port].u_configured  = 1;
+        }
+        else {
+            uarts[port].u_configured = 0;
+        }
+    }
+
+    if (port == 0) {
+        CLOCK_EnableClock(uarts[0].p_clock);
+        PORT_SetPinMux(uarts[0].p_base, uarts[0].u_pin_rx, kPORT_MuxAlt3);
+        PORT_SetPinMux(uarts[0].p_base, uarts[0].u_pin_tx, kPORT_MuxAlt3);
+        DbgConsole_Init((uint32_t)uarts[0].u_base, 115200,
+                        DEBUG_CONSOLE_DEVICE_TYPE_UART, CLOCK_GetFreq(uarts[0].clk_src));
+        PRINTF("UART%d CONFIGURED\r\n", port);
+    }
+
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/920371ad/hw/mcu/nxp/MK64F12/src/hal_uart_nxp.h
----------------------------------------------------------------------
diff --git a/hw/mcu/nxp/MK64F12/src/hal_uart_nxp.h b/hw/mcu/nxp/MK64F12/src/hal_uart_nxp.h
new file mode 100644
index 0000000..ccb6251
--- /dev/null
+++ b/hw/mcu/nxp/MK64F12/src/hal_uart_nxp.h
@@ -0,0 +1,80 @@
+/**
+ * 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.
+ */
+
+#ifndef __MCU_FRDMK64F_HAL_UART_H_
+#define __MCU_FRDMK64F_HAL_UART_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define NXP_UART_EXISTS      { 1, \
+                               1, \
+                               (FSL_FEATURE_SOC_UART_COUNT > 2U), \
+                               (FSL_FEATURE_SOC_UART_COUNT > 3U), \
+                               (FSL_FEATURE_SOC_UART_COUNT > 4U), \
+                               (FSL_FEATURE_SOC_UART_COUNT > 5U) }
+
+#define NXP_UART_ENABLED     { MYNEWT_VAL(UART_0), \
+                               MYNEWT_VAL(UART_1), \
+                               MYNEWT_VAL(UART_2), \
+                               MYNEWT_VAL(UART_3), \
+                               MYNEWT_VAL(UART_4), \
+                               MYNEWT_VAL(UART_5) }
+
+#define NXP_UART_CLOCKS      { UART0_CLK_SRC, \
+                               UART1_CLK_SRC, \
+                               UART2_CLK_SRC, \
+                               UART3_CLK_SRC, \
+                               UART4_CLK_SRC, \
+                               UART5_CLK_SRC }
+
+#define NXP_UART_PORTS       { MYNEWT_VAL(UART_0_PORT), \
+                               MYNEWT_VAL(UART_1_PORT), \
+                               MYNEWT_VAL(UART_2_PORT), \
+                               MYNEWT_VAL(UART_3_PORT), \
+                               MYNEWT_VAL(UART_4_PORT), \
+                               MYNEWT_VAL(UART_5_PORT) }
+
+#define NXP_UART_PORT_CLOCKS { MYNEWT_VAL(UART_0_PORT_CLOCK), \
+                               MYNEWT_VAL(UART_1_PORT_CLOCK), \
+                               MYNEWT_VAL(UART_2_PORT_CLOCK), \
+                               MYNEWT_VAL(UART_3_PORT_CLOCK), \
+                               MYNEWT_VAL(UART_4_PORT_CLOCK), \
+                               MYNEWT_VAL(UART_5_PORT_CLOCK) }
+
+#define NXP_UART_PIN_RX      { MYNEWT_VAL(UART_0_PIN_RX), \
+                               MYNEWT_VAL(UART_1_PIN_RX), \
+                               MYNEWT_VAL(UART_2_PIN_RX), \
+                               MYNEWT_VAL(UART_3_PIN_RX), \
+                               MYNEWT_VAL(UART_4_PIN_RX), \
+                               MYNEWT_VAL(UART_5_PIN_RX) }
+
+#define NXP_UART_PIN_TX      { MYNEWT_VAL(UART_0_PIN_TX), \
+                               MYNEWT_VAL(UART_1_PIN_TX), \
+                               MYNEWT_VAL(UART_2_PIN_TX), \
+                               MYNEWT_VAL(UART_3_PIN_TX), \
+                               MYNEWT_VAL(UART_4_PIN_TX), \
+                               MYNEWT_VAL(UART_5_PIN_TX) }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MCU_FRDMK64F_HAL_UART_H_ */