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 31c2e74  Apollo 3 nimBLE support
31c2e74 is described below

commit 31c2e74807b0ad62ddb372046059bfceec89ad9c
Author: Tian Zeng <[email protected]>
AuthorDate: Tue Feb 15 14:34:08 2022 -0500

    Apollo 3 nimBLE support
---
 nimble/transport/apollo3/pkg.yml               |  46 ++++
 nimble/transport/apollo3/src/apollo3_ble_hci.c | 351 +++++++++++++++++++++++++
 nimble/transport/apollo3/syscfg.yml            |  37 +++
 nimble/transport/pkg.yml                       |   2 +
 nimble/transport/syscfg.yml                    |   1 +
 5 files changed, 437 insertions(+)

diff --git a/nimble/transport/apollo3/pkg.yml b/nimble/transport/apollo3/pkg.yml
new file mode 100644
index 0000000..6706344
--- /dev/null
+++ b/nimble/transport/apollo3/pkg.yml
@@ -0,0 +1,46 @@
+#
+# 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/apollo3
+pkg.description: >
+    HCI transport for Ambiq Apollo3
+    The BLE subsystem implemented on Apollo3 is a fully integrated system 
which is accessed
+    via the BLE interface block, and provides autonomous clock and power 
management.
+    The subsystem has a 32-bit core which runs from a 32 MHz oscillator, and 
is dedicated
+    to running the lower portion of the BLE stack with a standard Host 
Controller interface (HCI).
+    This core does not support user programming, as all user code runs on the 
main Cortex M4 processor.
+    Software leverages the fully HCI compliant interface for Bluetooth 
operation.
+    A series of proprietary HCI commands are also leveraged to provide 
additional performance and low power operation.
+    The BLE controller and host can be configured to support up to seven 
simultaneous connections on chip revision A1 (4 on chip revision B0).
+    Secure connections and extended packet length are also supported.
+    See the Apollo3 Datasheet for a full description of the BLE subsystem.
+pkg.author: "Apache Mynewt <[email protected]>"
+pkg.homepage: "http://mynewt.apache.org/";
+pkg.keywords:
+    - ble
+    - bluetooth
+    - apollo3
+
+pkg.deps:
+    - nimble
+    - nimble/transport/common/hci_h4
+    - "@apache-mynewt-core/kernel/os"
+
+pkg.apis:
+    - ble_transport
diff --git a/nimble/transport/apollo3/src/apollo3_ble_hci.c 
b/nimble/transport/apollo3/src/apollo3_ble_hci.c
new file mode 100644
index 0000000..34b6266
--- /dev/null
+++ b/nimble/transport/apollo3/src/apollo3_ble_hci.c
@@ -0,0 +1,351 @@
+/*
+ * 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 <os/mynewt.h>
+#include <nimble/hci_common.h>
+#include <nimble/transport.h>
+#include <nimble/transport/hci_h4.h>
+
+#include "am_mcu_apollo.h"
+
+#define HCI_CMD_HDR_LEN (3) /*!< \brief Command packet header length */
+
+/* Tx power level in dBm. */
+typedef enum {
+  TX_POWER_LEVEL_MINUS_10P0_dBm = 0x4,
+  TX_POWER_LEVEL_MINUS_5P0_dBm = 0x5,
+  TX_POWER_LEVEL_0P0_dBm = 0x8,
+  TX_POWER_LEVEL_PLUS_3P0_dBm = 0xF,
+  TX_POWER_LEVEL_INVALID = 0x10,
+} txPowerLevel_t;
+
+/* Structure for holding outgoing HCI packets. */
+typedef struct {
+    uint32_t len;
+    uint32_t data[MYNEWT_VAL(BLE_TRANSPORT_APOLLO3_MAX_TX_PACKET) / 
sizeof(uint32_t)];
+} hci_drv_write_t;
+
+uint32_t g_read_buf[MYNEWT_VAL(BLE_TRANSPORT_APOLLO3_MAX_RX_PACKET) / 
sizeof(uint32_t)];
+
+/* BLE module handle for Ambiq HAL functions */
+void *ble_handle;
+
+uint8_t g_ble_mac_address[6] = {0};
+
+static struct hci_h4_sm hci_apollo3_h4sm;
+
+static void
+apollo3_ble_hci_trans_rx_process(void)
+{
+    uint32_t len;
+    int rlen;
+    uint8_t *buf = (uint8_t *)g_read_buf;
+
+    am_hal_ble_blocking_hci_read(ble_handle, (uint32_t *)buf, &len);
+
+    /* NOTE: Ambiq Apollo3 controller does not have local supported lmp 
features implemented
+     * The command will always return 0 so we overwrite the buffer here
+     */
+    if(buf[4] == 0x03 && buf[5] == 0x10 && len == 15) {
+        memset(&buf[11], 0x60, sizeof(uint8_t));
+    }
+
+    rlen = hci_h4_sm_rx(&hci_apollo3_h4sm, buf, len);
+    assert(rlen >= 0);
+}
+
+/* Interrupt handler that looks for BLECIRQ. This gets set by BLE core when 
there is something to read */
+static void
+apollo3_hci_int(void)
+{
+    uint32_t int_status;
+
+    /* Read and clear the interrupt status. */
+    int_status = am_hal_ble_int_status(ble_handle, true);
+    am_hal_ble_int_clear(ble_handle, int_status);
+
+    /* Handle any DMA or Command Complete interrupts. */
+    am_hal_ble_int_service(ble_handle, int_status);
+
+    /* If this was a BLEIRQ interrupt, attempt to start a read operation. */
+    if (int_status & AM_HAL_BLE_INT_BLECIRQ)
+    {
+        /* Lower WAKE */
+        am_hal_ble_wakeup_set(ble_handle, 0);
+
+        /* Call read function to pull in data from controller */
+        apollo3_ble_hci_trans_rx_process();
+    }
+    else {
+        assert(0);
+    }
+}
+
+/* Boot the radio. */
+uint32_t
+apollo3_hci_radio_boot(bool is_cold_boot)
+{
+    uint32_t xtal_retry_cnt = 0;
+    uint32_t am_boot_status;
+    am_hal_mcuctrl_device_t device_info;
+    am_hal_ble_config_t ble_config =
+    {
+        /* Configure the HCI interface clock for 6 MHz */
+        .ui32SpiClkCfg = AM_HAL_BLE_HCI_CLK_DIV8,
+
+        /* Set HCI read and write thresholds to 32 bytes each. */
+        .ui32ReadThreshold = 32,
+        .ui32WriteThreshold = 32,
+
+        /* The MCU will supply the clock to the BLE core. */
+        .ui32BleClockConfig = AM_HAL_BLE_CORE_MCU_CLK,
+
+        /* Note: These settings only apply to Apollo3 A1/A2 silicon, not B0 
silicon.
+         * Default settings for expected BLE clock drift (measured in PPM).
+         */
+        .ui32ClockDrift = 0,
+        .ui32SleepClockDrift = 50,
+
+        /* Default setting - AGC Enabled */
+        .bAgcEnabled = true,
+
+        /* Default setting - Sleep Algo enabled */
+        .bSleepEnabled = true,
+
+        /* Apply the default patches when am_hal_ble_boot() is called. */
+        .bUseDefaultPatches = true,
+    };
+
+    /* Configure and enable the BLE interface. */
+    am_boot_status = AM_HAL_STATUS_FAIL;
+    while (am_boot_status != AM_HAL_STATUS_SUCCESS) {
+        am_hal_pwrctrl_low_power_init();
+        am_hal_ble_initialize(0, &ble_handle);
+        am_hal_ble_power_control(ble_handle, AM_HAL_BLE_POWER_ACTIVE);
+
+        am_hal_ble_config(ble_handle, &ble_config);
+
+        /*
+         * Delay 1s for 32768Hz clock stability. This isn't required unless 
this is
+         * our first run immediately after a power-up.
+         */
+        if (is_cold_boot) {
+            os_time_delay(OS_TICKS_PER_SEC);
+        }
+
+        /* Attempt to boot the radio. */
+        am_boot_status = am_hal_ble_boot(ble_handle);
+
+        /* Check our status, exit if radio is running */
+        if (am_boot_status == AM_HAL_STATUS_SUCCESS) {
+            break;
+        }
+        else if (am_boot_status == AM_HAL_BLE_32K_CLOCK_UNSTABLE) {
+            /* If the radio is running, but the clock looks bad, we can try to 
restart. */
+            am_hal_ble_power_control(ble_handle, AM_HAL_BLE_POWER_OFF);
+            am_hal_ble_deinitialize(ble_handle);
+
+            /* We won't restart forever. After we hit the maximum number of 
retries, we'll just return with failure. */
+            if (xtal_retry_cnt++ < 
MYNEWT_VAL(BLE_TRANSPORT_APOLLO3_MAX_XTAL_RETRIES)) {
+                os_time_delay(OS_TICKS_PER_SEC);
+            }
+            else {
+                return SYS_EUNKNOWN;
+            }
+        }
+        else {
+            am_hal_ble_power_control(ble_handle, AM_HAL_BLE_POWER_OFF);
+            am_hal_ble_deinitialize(ble_handle);
+            /*
+             * If the radio failed for some reason other than 32K Clock
+             * instability, we should just report the failure and return.
+             */
+            return SYS_EUNKNOWN;
+        }
+    }
+
+    /* Set the BLE TX Output power to 0dBm. */
+    am_hal_ble_tx_power_set(ble_handle, TX_POWER_LEVEL_0P0_dBm);
+
+    /* Enable interrupts for the BLE module. */
+    am_hal_ble_int_clear(ble_handle, (AM_HAL_BLE_INT_CMDCMP |
+                               AM_HAL_BLE_INT_DCMP |
+                               AM_HAL_BLE_INT_BLECIRQ));
+
+    am_hal_ble_int_enable(ble_handle, (AM_HAL_BLE_INT_CMDCMP |
+                                AM_HAL_BLE_INT_DCMP |
+                                AM_HAL_BLE_INT_BLECIRQ));
+
+    /* When it's is_cold_boot, it will use Apollo's Device ID to form 
Bluetooth address. */
+    if (is_cold_boot) {
+        am_hal_mcuctrl_info_get(AM_HAL_MCUCTRL_INFO_DEVICEID, &device_info);
+
+        /* Bluetooth address formed by ChipID1 (32 bits) and ChipID0 (8-23 
bits). */
+        memcpy(g_ble_mac_address, &device_info.ui32ChipID1, 
sizeof(device_info.ui32ChipID1));
+
+        /* ui32ChipID0 bit 8-31 is test time during chip manufacturing */
+        g_ble_mac_address[4] = (device_info.ui32ChipID0 >> 8) & 0xFF;
+        g_ble_mac_address[5] = (device_info.ui32ChipID0 >> 16) & 0xFF;
+    }
+
+    NVIC_EnableIRQ(BLE_IRQn);
+
+    return 0;
+}
+
+/* Wake update helper function */
+static void
+apollo3_update_wake(void)
+{
+    AM_CRITICAL_BEGIN;
+
+    /* Set WAKE if there's something in the write queue, but not if SPISTATUS 
or IRQ is high. */
+    if ((BLEIFn(0)->BSTATUS_b.SPISTATUS == 0) && (BLEIF->BSTATUS_b.BLEIRQ == 
false)) {
+        am_hal_ble_wakeup_set(ble_handle, 1);
+
+        /* If we've set wakeup, but IRQ came up at the same time, we should 
just lower WAKE again. */
+        if (BLEIF->BSTATUS_b.BLEIRQ == true) {
+            am_hal_ble_wakeup_set(ble_handle, 0);
+        }
+    }
+
+    AM_CRITICAL_END;
+}
+
+/*
+ * Function used by the BLE stack to send HCI messages to the BLE controller.
+ * The payload is placed into a queue and the controller is turned on. When it 
is ready
+ * an interrupt will fire to handle sending a message
+ */
+static uint8_t
+apollo3_hci_write(uint8_t type, uint16_t len, uint8_t *data)
+{
+    uint8_t *write_ptr;
+    hci_drv_write_t write_buf;
+
+    /* comparison compensates for the type byte at index 0. */
+    if (len > (MYNEWT_VAL(BLE_TRANSPORT_APOLLO3_MAX_TX_PACKET)-1)) {
+        return 0;
+    }
+
+    /* Set all of the fields in the hci write structure. */
+    write_buf.len = len + 1;
+
+    write_ptr = (uint8_t *) write_buf.data;
+
+    *write_ptr++ = type;
+
+    for (uint32_t i = 0; i < len; i++) {
+        write_ptr[i] = data[i];
+    }
+
+    /* Wake up the BLE controller. */
+    apollo3_update_wake();
+
+    /* Wait on SPI status before writing */
+    while (BLEIFn(0)->BSTATUS_b.SPISTATUS) {
+        os_time_delay(1);
+    }
+
+    am_hal_ble_blocking_hci_write(ble_handle, AM_HAL_BLE_RAW, write_buf.data, 
write_buf.len);
+
+    return 0;
+}
+
+static int
+apollo3_ble_hci_acl_tx(struct os_mbuf *om)
+{
+    struct os_mbuf *x;
+    int rc = 0;
+
+    x = om;
+    while (x) {
+        rc = apollo3_hci_write(HCI_H4_ACL, x->om_len, x->om_data);
+        if (rc < 0) {
+            break;
+        }
+        x = SLIST_NEXT(x, om_next);
+    }
+
+    os_mbuf_free_chain(om);
+
+    return (rc < 0) ? BLE_ERR_MEM_CAPACITY : 0;
+}
+
+static int
+apollo3_ble_hci_frame_cb(uint8_t pkt_type, void *data)
+{
+    int rc;
+
+    switch (pkt_type) {
+    case HCI_H4_ACL:
+        rc = ble_transport_to_hs_acl(data);
+        break;
+    case HCI_H4_EVT:
+        rc = ble_transport_to_hs_evt(data);
+        break;
+    default:
+        assert(0);
+        break;
+    }
+
+    return rc;
+}
+
+static void
+apollo3_ble_hci_init(void)
+{
+    SYSINIT_ASSERT_ACTIVE();
+
+    /* Enable interrupt to handle read based on BLECIRQ */
+    NVIC_SetVector(BLE_IRQn, (uint32_t)apollo3_hci_int);
+
+    /* Initial coldboot configuration */
+    apollo3_hci_radio_boot(1);
+}
+
+int
+ble_transport_to_ll_cmd_impl(void *buf)
+{
+    int rc;
+    uint8_t *cmd = buf;
+    int len = HCI_CMD_HDR_LEN + cmd[2];
+
+    rc = apollo3_hci_write(HCI_H4_CMD, len, cmd);
+
+    ble_transport_free(cmd);
+
+    return (rc < 0) ? BLE_ERR_MEM_CAPACITY :  0;
+}
+
+int
+ble_transport_to_ll_acl_impl(struct os_mbuf *om)
+{
+    return apollo3_ble_hci_acl_tx(om);
+}
+
+void
+ble_transport_ll_init(void)
+{
+    hci_h4_sm_init(&hci_apollo3_h4sm, &hci_h4_allocs_from_ll,
+                   apollo3_ble_hci_frame_cb);
+    apollo3_ble_hci_init();
+}
\ No newline at end of file
diff --git a/nimble/transport/apollo3/syscfg.yml 
b/nimble/transport/apollo3/syscfg.yml
new file mode 100644
index 0000000..82e9f54
--- /dev/null
+++ b/nimble/transport/apollo3/syscfg.yml
@@ -0,0 +1,37 @@
+# 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_APOLLO3_MAX_TX_PACKET:
+        description: >
+            Maximum TX packet size to controller in bytes.
+        value: 256
+
+    BLE_TRANSPORT_APOLLO3_MAX_RX_PACKET:
+        description: >
+            Maximum RX packet size from controller in bytes.
+        value: 256
+
+    BLE_TRANSPORT_APOLLO3_MAX_XTAL_RETRIES:
+        description: >
+            Maximum number of retries to boot radio when clock is found to be 
unstable.
+        value: 10
+
+syscfg.restrictions:
+    - '!BLE_CONTROLLER'
+    - '!BLE_HS_FLOW_CTRL'
diff --git a/nimble/transport/pkg.yml b/nimble/transport/pkg.yml
index 12b9f40..5fbcbd2 100644
--- a/nimble/transport/pkg.yml
+++ b/nimble/transport/pkg.yml
@@ -44,6 +44,8 @@ pkg.deps.'BLE_TRANSPORT_HS == "uart"':
     - nimble/transport/uart
 pkg.deps.'BLE_TRANSPORT_HS == "usb"':
     - nimble/transport/usb
+pkg.deps.'BLE_TRANSPORT_LL == "apollo3"':
+    - nimble/transport/apollo3
 
 pkg.deps.BLE_MONITOR_RTT:
     - "@apache-mynewt-core/hw/drivers/rtt"
diff --git a/nimble/transport/syscfg.yml b/nimble/transport/syscfg.yml
index 4985250..e69b0ef 100644
--- a/nimble/transport/syscfg.yml
+++ b/nimble/transport/syscfg.yml
@@ -44,6 +44,7 @@ syscfg.defs:
             - dialog_cmac
             - nrf5340
             - socket
+            - apollo3
             - custom
 
     BLE_TRANSPORT_ACL_COUNT:

Reply via email to