This is an automated email from the ASF dual-hosted git repository.

andk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git


The following commit(s) were added to refs/heads/master by this push:
     new 80ef459c nimble/transport: Add UART transport for external controller
80ef459c is described below

commit 80ef459c48dd2e938789013da1222438ffa2bf92
Author: Andrzej Kaczmarek <[email protected]>
AuthorDate: Fri Oct 14 18:48:51 2022 +0200

    nimble/transport: Add UART transport for external controller
    
    This is the same as standard "uart" transport except it's for LL side
    which means it can be used for NimBLE host to talk to external
    controller. Enable it by "BLE_TRANSPORT_LL: uart_ll".
---
 nimble/transport/pkg.yml                |   2 +
 nimble/transport/syscfg.yml             |   1 +
 nimble/transport/uart_ll/pkg.yml        |  32 +++++
 nimble/transport/uart_ll/src/hci_uart.c | 245 ++++++++++++++++++++++++++++++++
 nimble/transport/uart_ll/syscfg.yml     |  39 +++++
 5 files changed, 319 insertions(+)

diff --git a/nimble/transport/pkg.yml b/nimble/transport/pkg.yml
index 5070c728..30237f75 100644
--- a/nimble/transport/pkg.yml
+++ b/nimble/transport/pkg.yml
@@ -48,6 +48,8 @@ pkg.deps.'BLE_TRANSPORT_HS == "cdc"':
     - nimble/transport/cdc
 pkg.deps.'BLE_TRANSPORT_LL == "apollo3"':
     - nimble/transport/apollo3
+pkg.deps.'BLE_TRANSPORT_LL == "uart_ll"':
+    - nimble/transport/uart_ll
 
 pkg.deps.BLE_MONITOR_RTT:
     - "@apache-mynewt-core/hw/drivers/rtt"
diff --git a/nimble/transport/syscfg.yml b/nimble/transport/syscfg.yml
index 7f02f6cc..febe09d4 100644
--- a/nimble/transport/syscfg.yml
+++ b/nimble/transport/syscfg.yml
@@ -46,6 +46,7 @@ syscfg.defs:
             - nrf5340
             - socket
             - apollo3
+            - uart_ll
             - custom
 
     BLE_TRANSPORT_ACL_COUNT:
diff --git a/nimble/transport/uart_ll/pkg.yml b/nimble/transport/uart_ll/pkg.yml
new file mode 100644
index 00000000..efc97d54
--- /dev/null
+++ b/nimble/transport/uart_ll/pkg.yml
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+
+pkg.name: nimble/transport/uart_ll
+pkg.description: HCI H4 transport over UART to external controller
+pkg.author: "Apache Mynewt <[email protected]>"
+pkg.homepage: "https://mynewt.apache.org/";
+
+pkg.deps:
+    - "@apache-mynewt-core/hw/hal"
+    - "@apache-mynewt-core/kernel/os"
+    - nimble
+    - nimble/transport/common/hci_h4
+
+pkg.apis:
+    - ble_transport
diff --git a/nimble/transport/uart_ll/src/hci_uart.c 
b/nimble/transport/uart_ll/src/hci_uart.c
new file mode 100644
index 00000000..95eae3f4
--- /dev/null
+++ b/nimble/transport/uart_ll/src/hci_uart.c
@@ -0,0 +1,245 @@
+/*
+ * 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 <errno.h>
+#include <stdint.h>
+#include <sysinit/sysinit.h>
+#include <syscfg/syscfg.h>
+#include "os/os_mbuf.h"
+#include "os/os_mempool.h"
+#include "hal/hal_uart.h"
+#include "nimble/transport.h"
+#include "nimble/transport/hci_h4.h"
+
+#define TX_Q_SIZE   (MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_HS_COUNT) + 1)
+
+struct hci_uart_tx {
+    uint8_t type;
+    uint8_t sent_type;
+    uint16_t len;
+    uint16_t idx;
+
+    struct os_mbuf *om;
+    uint8_t *buf;
+
+    STAILQ_ENTRY(hci_uart_tx) tx_q_next;
+};
+
+static STAILQ_HEAD(, hci_uart_tx) tx_q;
+
+static struct os_mempool pool_tx_q;
+static uint8_t pool_tx_q_buf[ OS_MEMPOOL_BYTES(TX_Q_SIZE,
+                                               sizeof(struct hci_uart_tx)) ];
+
+struct hci_h4_sm hci_uart_h4sm;
+
+static int
+hci_uart_frame_cb(uint8_t pkt_type, void *data)
+{
+    switch (pkt_type) {
+    case HCI_H4_EVT:
+        return ble_transport_to_hs_evt(data);
+    case HCI_H4_ACL:
+        return ble_transport_to_hs_acl(data);
+    default:
+        assert(0);
+        break;
+    }
+
+    return -1;
+}
+
+static int
+hci_uart_rx_char(void *arg, uint8_t data)
+{
+    hci_h4_sm_rx(&hci_uart_h4sm, &data, 1);
+
+    return 0;
+}
+
+static int
+hci_uart_tx_char(void *arg)
+{
+    struct hci_uart_tx *tx;
+    uint8_t ch;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+    tx = STAILQ_FIRST(&tx_q);
+    OS_EXIT_CRITICAL(sr);
+    if (!tx) {
+        return -1;
+    }
+
+    if (!tx->sent_type) {
+        tx->sent_type = 1;
+        return tx->type;
+    }
+
+    switch (tx->type) {
+    case HCI_H4_CMD:
+        ch = tx->buf[tx->idx];
+        tx->idx++;
+        if (tx->idx == tx->len) {
+            ble_transport_free(tx->buf);
+            OS_ENTER_CRITICAL(sr);
+            STAILQ_REMOVE_HEAD(&tx_q, tx_q_next);
+            OS_EXIT_CRITICAL(sr);
+            os_memblock_put(&pool_tx_q, tx);
+        }
+        break;
+    case HCI_H4_ACL:
+        os_mbuf_copydata(tx->om, 0, 1, &ch);
+        os_mbuf_adj(tx->om, 1);
+        tx->len--;
+        if (tx->len == 0) {
+            os_mbuf_free_chain(tx->om);
+            OS_ENTER_CRITICAL(sr);
+            STAILQ_REMOVE_HEAD(&tx_q, tx_q_next);
+            OS_EXIT_CRITICAL(sr);
+            os_memblock_put(&pool_tx_q, tx);
+        }
+        break;
+    default:
+        assert(0);
+        OS_ENTER_CRITICAL(sr);
+        STAILQ_REMOVE_HEAD(&tx_q, tx_q_next);
+        OS_EXIT_CRITICAL(sr);
+        os_memblock_put(&pool_tx_q, tx);
+    }
+
+    return ch;
+}
+
+static int
+hci_uart_configure(void)
+{
+    enum hal_uart_parity parity;
+    enum hal_uart_flow_ctl flowctl;
+    int rc;
+
+    rc = hal_uart_init_cbs(MYNEWT_VAL(BLE_TRANSPORT_UART_PORT),
+                           hci_uart_tx_char, NULL,
+                           hci_uart_rx_char, NULL);
+    if (rc != 0) {
+        return -1;
+    }
+
+    if (MYNEWT_VAL_CHOICE(BLE_TRANSPORT_UART_PARITY, odd)) {
+        parity = HAL_UART_PARITY_ODD;
+    } else if (MYNEWT_VAL_CHOICE(BLE_TRANSPORT_UART_PARITY, even)) {
+        parity = HAL_UART_PARITY_EVEN;
+    } else {
+        parity = HAL_UART_PARITY_NONE;
+    }
+
+    if (MYNEWT_VAL_CHOICE(BLE_TRANSPORT_UART_FLOW_CONTROL, rtscts)) {
+        flowctl = HAL_UART_FLOW_CTL_RTS_CTS;
+    } else {
+        flowctl = HAL_UART_FLOW_CTL_NONE;
+    }
+
+    rc = hal_uart_config(MYNEWT_VAL(BLE_TRANSPORT_UART_PORT),
+                         MYNEWT_VAL(BLE_TRANSPORT_UART_BAUDRATE),
+                         MYNEWT_VAL(BLE_TRANSPORT_UART_DATA_BITS),
+                         MYNEWT_VAL(BLE_TRANSPORT_UART_STOP_BITS),
+                         parity, flowctl);
+    if (rc != 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+int
+ble_transport_to_ll_cmd_impl(void *buf)
+{
+    struct hci_uart_tx *txe;
+    os_sr_t sr;
+
+    txe = os_memblock_get(&pool_tx_q);
+    if (!txe) {
+        assert(0);
+        return -ENOMEM;
+    }
+
+    txe->type = HCI_H4_CMD;
+    txe->sent_type = 0;
+    txe->len = 3 + ((uint8_t *)buf)[2];
+    txe->buf = buf;
+    txe->idx = 0;
+    txe->om = NULL;
+
+    OS_ENTER_CRITICAL(sr);
+    STAILQ_INSERT_TAIL(&tx_q, txe, tx_q_next);
+    OS_EXIT_CRITICAL(sr);
+
+    hal_uart_start_tx(MYNEWT_VAL(BLE_TRANSPORT_UART_PORT));
+
+    return 0;
+}
+
+int
+ble_transport_to_ll_acl_impl(struct os_mbuf *om)
+{
+    struct hci_uart_tx *txe;
+    os_sr_t sr;
+
+    txe = os_memblock_get(&pool_tx_q);
+    if (!txe) {
+        assert(0);
+        return -ENOMEM;
+    }
+
+    txe->type = HCI_H4_ACL;
+    txe->sent_type = 0;
+    txe->len = OS_MBUF_PKTLEN(om);
+    txe->idx = 0;
+    txe->buf = NULL;
+    txe->om = om;
+
+    OS_ENTER_CRITICAL(sr);
+    STAILQ_INSERT_TAIL(&tx_q, txe, tx_q_next);
+    OS_EXIT_CRITICAL(sr);
+
+    hal_uart_start_tx(MYNEWT_VAL(BLE_TRANSPORT_UART_PORT));
+
+    return 0;
+}
+
+void
+ble_transport_ll_init(void)
+{
+    int rc;
+
+    SYSINIT_ASSERT_ACTIVE();
+
+    rc = hci_uart_configure();
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mempool_init(&pool_tx_q, TX_Q_SIZE, sizeof(struct hci_uart_tx),
+                         pool_tx_q_buf, "hci_uart_tx_q");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    hci_h4_sm_init(&hci_uart_h4sm, &hci_h4_allocs_from_ll, hci_uart_frame_cb);
+
+    STAILQ_INIT(&tx_q);
+}
diff --git a/nimble/transport/uart_ll/syscfg.yml 
b/nimble/transport/uart_ll/syscfg.yml
new file mode 100644
index 00000000..ccf38b61
--- /dev/null
+++ b/nimble/transport/uart_ll/syscfg.yml
@@ -0,0 +1,39 @@
+# 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.
+#
+
+syscfg.defs:
+    BLE_TRANSPORT_UART_LL_PORT:
+        description: UART index to use for HCI interface
+        value: 0
+    BLE_TRANSPORT_UART_LL_BAUDRATE:
+        description: Baudrate on UART
+        value: 1000000
+    BLE_TRANSPORT_UART_LL_DATA_BITS:
+        description: Number of data bits on UART
+        value: 8
+    BLE_TRANSPORT_UART_LL_STOP_BITS:
+        description: Number of stop bits on UART
+        value: 1
+    BLE_TRANSPORT_UART_LL_PARITY:
+        description: Parity on UART
+        value: none
+        choices: none,even,odd
+    BLE_TRANSPORT_UART_LL_FLOW_CONTROL:
+        description: Flow control on UART
+        choices: off,rtscts
+        value: rtscts

Reply via email to