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: