This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 82ad4b0e080a4ba3e17506c6504114540c78db8e Author: Sergey Nikitenko <[email protected]> AuthorDate: Wed Jul 27 16:19:20 2022 +0300 stm32wb: adding BLE support --- arch/arm/src/stm32wb/Kconfig | 232 ++++++ arch/arm/src/stm32wb/Make.defs | 16 +- arch/arm/src/stm32wb/hardware/stm32wb_ipcc.h | 2 +- arch/arm/src/stm32wb/stm32wb_blehci.c | 348 +++++++++ .../stm32wb/{stm32wb_ipcc.h => stm32wb_blehci.h} | 34 +- arch/arm/src/stm32wb/stm32wb_ipcc.h | 104 +++ arch/arm/src/stm32wb/stm32wb_mbox.c | 813 +++++++++++++++++++++ arch/arm/src/stm32wb/stm32wb_mbox.h | 174 +++++ arch/arm/src/stm32wb/stm32wb_mbox_list.h | 144 ++++ arch/arm/src/stm32wb/stm32wb_mbox_shci.h | 186 +++++ arch/arm/src/stm32wb/stm32wb_rcc.c | 11 + boards/arm/stm32wb/nucleo-wb55rg/README.txt | 7 + .../stm32wb/nucleo-wb55rg/configs/ble/defconfig | 55 ++ .../stm32wb/nucleo-wb55rg/include/nucleo-wb55rg.h | 6 + .../arm/stm32wb/nucleo-wb55rg/src/stm32_appinit.c | 26 + 15 files changed, 2130 insertions(+), 28 deletions(-) diff --git a/arch/arm/src/stm32wb/Kconfig b/arch/arm/src/stm32wb/Kconfig index 9396f76881..d13bcc0b03 100644 --- a/arch/arm/src/stm32wb/Kconfig +++ b/arch/arm/src/stm32wb/Kconfig @@ -941,4 +941,236 @@ config STM32WB_SPI_DMA endmenu +config STM32WB_MBOX + bool + default n + select STM32WB_IPCC + +menuconfig STM32WB_BLE + bool "BLE" + default n + select STM32WB_MBOX + ---help--- + Enable BLE support. + +if STM32WB_BLE + +config STM32WB_BLE_C2HOST + bool "Enable CPU2 HOST stack" + default y + +config STM32WB_BLE_MAX_CONN + int "Maximum BLE simultaneous connections" + range 1 8 + default 2 + +config STM32WB_BLE_GATT_MAX_ATTR_NUM + int "GATT attributes max count" + range 9 255 + default 64 + +config STM32WB_BLE_GATT_MAX_SVC_NUM + int "GATT services max count" + range 2 64 + default 8 + +config STM32WB_BLE_GATT_ATTR_BUF_SIZE + int "GATT attributes storage buf size" + default 1344 + ---help--- + Size of the storage area for attribute values. Hardcoded in CPU2 firmware. + +config STM32WB_BLE_DLE + bool "Support Data Length Extension (DLE)" + default y + +config STM32WB_BLE_MAX_ATT_MTU + int "Maximum supported attribute MTU" + range 23 512 + default 156 + +config STM32WB_BLE_SLAVE_SCA + int "Sleep clock accuracy in slave mode [PPM]" + default 500 + ---help--- + Sleep clock accuracy (ppm value) in slave mode. + +choice + prompt "Sleep clock accuracy in master mode" + default STM32WB_BLE_MASTER_SCA_0 + ---help--- + Sleep clock accuracy in master mode. + +config STM32WB_BLE_MASTER_SCA_0 + bool "251-500 ppm" + +config STM32WB_BLE_MASTER_SCA_1 + bool "151-250 ppm" + +config STM32WB_BLE_MASTER_SCA_2 + bool "101-150 ppm" + +config STM32WB_BLE_MASTER_SCA_3 + bool "76-100 ppm" + +config STM32WB_BLE_MASTER_SCA_4 + bool "51-75 ppm" + +config STM32WB_BLE_MASTER_SCA_5 + bool "31-50 ppm" + +config STM32WB_BLE_MASTER_SCA_6 + bool "21-30 ppm" + +config STM32WB_BLE_MASTER_SCA_7 + bool "0-20 ppm" + +endchoice # Sleep clock accuracy in master mode + +config STM32WB_BLE_MASTER_SCA + int + default 7 if STM32WB_BLE_MASTER_SCA_7 + default 6 if STM32WB_BLE_MASTER_SCA_6 + default 5 if STM32WB_BLE_MASTER_SCA_5 + default 4 if STM32WB_BLE_MASTER_SCA_4 + default 3 if STM32WB_BLE_MASTER_SCA_3 + default 2 if STM32WB_BLE_MASTER_SCA_2 + default 1 if STM32WB_BLE_MASTER_SCA_1 + default 0 + +choice + prompt "Low speed clock source" + default STM32WB_BLE_LS_CLK_SRC_LSE + ---help--- + Low speed 32 kHz clock source. + +config STM32WB_BLE_LS_CLK_SRC_LSE + bool "LSE" + +config STM32WB_BLE_LS_CLK_SRC_HSE + bool "HSE" + +endchoice # Low speed clock source + +config STM32WB_BLE_LS_CLK_SRC + int + default 1 if STM32WB_BLE_LS_CLKSRC_HSE + default 0 + +config STM32WB_BLE_MAX_CONN_EVT_LENGTH + hex "Max connection event length" + default 0xffffffff + ---help--- + Maximum duration of a slave connection event in units of 625/256us (~2.44us). + +config STM32WB_BLE_HSE_STARTUP + hex "HSE startup time" + default 0x148 + ---help--- + HSE startup time in units of 625/256us (~2.44us). + +config STM32WB_BLE_VITERBI + bool "Enable Viterbi algorithm" + default y + ---help--- + Enable Viterbi algorithm implementation + +config STM32WB_BLE_MAX_INITOR_COC_NUM + int "Max number of connection-oriented channels" + range 0 64 + default 32 + ---help--- + Maximum number of connection-oriented channels in initiator mode. + +config STM32WB_BLE_SVC_CHANGED_CHAR + bool "Enable service changed characteristic" + default n + +config STM32WB_BLE_WRITABLE_DEVICE_NAME + bool "Writable device name" + default y + +config STM32WB_BLE_CHAN_SEL_ALG2 + bool "Enable channel selection algorithm 2" + default n + +choice + prompt "Power class" + default STM32WB_BLE_POWER_CLASS_2_3 + +config STM32WB_BLE_POWER_CLASS_2_3 + bool "Power Class 2-3" + +config STM32WB_BLE_POWER_CLASS_1 + bool "Power Class 1" + +endchoice # Power class + +config STM32WB_BLE_MIN_TX_POWER + int "Minimum transmit power [dBm]" + range -127 20 + default 0 + +config STM32WB_BLE_MAX_TX_POWER + int "Maximum transmit power [dBm]" + range -127 20 + default 0 + +choice + prompt "AGC RSSI model" + default STM32WB_BLE_AGC_RSSI_LEGACY + +config STM32WB_BLE_AGC_RSSI_LEGACY + bool "AGC RSSI Legacy" + +config STM32WB_BLE_AGC_RSSI_IMPROVED + bool "AGC RSSI Improved" + +endchoice # AGC RSSI model + +config STM32WB_BLE_ADVERTISING + bool "Support advertising" + default y + +config STM32WB_BLE_SCANNING + bool "Support scanning" + default y + +config STM32WB_BLE_LE_2M_PHY + bool "Support LE 2M PHY" + default y + +config STM32WB_BLE_LE_CODED_PHY + bool "Support LE Coded PHY" + default y if STM32WB_STM32WB15 || STM32WB_STM32WB35 || STM32WB_STM32WB55 + default n + depends on STM32WB_STM32WB15 || STM32WB_STM32WB35 || STM32WB_STM32WB55 + +config STM32WB_BLE_TTY_NAME + string "BLE TTY device name" + default "/dev/ttyHCI0" + depends on UART_BTH4 + +config STM32WB_BLE_FICR_STATIC_ADDR + bool "Configure factory generated static random address" + default n + +config STM32WB_BLE_PUB_ADDR + hex "Configure BT public address" + default 0x0000000000 + +endif # STM32WB_BLE + +if STM32WB_MBOX + +config STM32WB_MBOX_TX_CMD_QUEUE_LEN + int "Mailbox TX command queue length" + default 2 + +config STM32WB_MBOX_RX_EVT_QUEUE_LEN + int "Mailbox RX event queue length" + default 5 + +endif # STM32WB_MBOX + endif # ARCH_CHIP_STM32WB diff --git a/arch/arm/src/stm32wb/Make.defs b/arch/arm/src/stm32wb/Make.defs index a0c9611422..886776d368 100644 --- a/arch/arm/src/stm32wb/Make.defs +++ b/arch/arm/src/stm32wb/Make.defs @@ -81,10 +81,6 @@ ifeq ($(CONFIG_STM32WB_PWR),y) CHIP_CSRCS += stm32wb_exti_pwr.c endif -ifeq ($(CONFIG_STM32WB_IPCC),y) -CHIP_CSRCS += stm32wb_ipcc.c -endif - ifeq ($(CONFIG_STM32WB_RTC),y) ifeq ($(CONFIG_RTC_ALARM),y) CHIP_CSRCS += stm32wb_exti_alarm.c @@ -97,6 +93,18 @@ CHIP_CSRCS += stm32wb_rtc.c stm32wb_rtc_lowerhalf.c endif endif +ifeq ($(CONFIG_STM32WB_IPCC),y) +CHIP_CSRCS += stm32wb_ipcc.c +endif + +ifeq ($(CONFIG_STM32WB_MBOX),y) +CHIP_CSRCS += stm32wb_mbox.c +endif + +ifeq ($(CONFIG_STM32WB_BLE),y) +CHIP_CSRCS += stm32wb_blehci.c +endif + ifeq ($(CONFIG_DEBUG_FEATURES),y) CHIP_CSRCS += stm32wb_dumpgpio.c endif diff --git a/arch/arm/src/stm32wb/hardware/stm32wb_ipcc.h b/arch/arm/src/stm32wb/hardware/stm32wb_ipcc.h index 740f408849..178ccd90a6 100644 --- a/arch/arm/src/stm32wb/hardware/stm32wb_ipcc.h +++ b/arch/arm/src/stm32wb/hardware/stm32wb_ipcc.h @@ -34,7 +34,7 @@ #define STM32WB_IPCC_C2CR_OFFSET 0x0010 /* CPU2 control register */ #define STM32WB_IPCC_C2MR_OFFSET 0x0014 /* CPU2 mask register */ #define STM32WB_IPCC_C2SCR_OFFSET 0x0018 /* CPU2 status set/clear register */ -#define STM32WB_IPCC_C2TOC1SR_OFFSET 0x001c /* CPU2 to CPU2 status register */ +#define STM32WB_IPCC_C2TOC1SR_OFFSET 0x001c /* CPU2 to CPU1 status register */ /* Register Addresses *******************************************************/ diff --git a/arch/arm/src/stm32wb/stm32wb_blehci.c b/arch/arm/src/stm32wb/stm32wb_blehci.c new file mode 100644 index 0000000000..560a03dc1e --- /dev/null +++ b/arch/arm/src/stm32wb/stm32wb_blehci.c @@ -0,0 +1,348 @@ +/**************************************************************************** + * arch/arm/src/stm32wb/stm32wb_blehci.c + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <assert.h> +#include <debug.h> + +#include <nuttx/wireless/bluetooth/bt_hci.h> +#include <nuttx/wireless/bluetooth/bt_driver.h> +#include <nuttx/arch.h> +#include <nuttx/wqueue.h> + +#if defined(CONFIG_UART_BTH4) +# include <nuttx/serial/uart_bth4.h> +#endif + +#include "stm32wb_ipcc.h" +#include "stm32wb_mbox.h" +#include "stm32wb_mbox_shci.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define STM32WB_BLE_PREP_WRITE_NUM \ + STM32WB_MBOX_DEFAULT_BLE_PREP_WRITE_NUM(CONFIG_STM32WB_BLE_MAX_ATT_MTU) + +#define STM32WB_C2_MEM_BLOCK_NUM \ + STM32WB_MBOX_DEFAULT_C2_MEM_BLOCK_NUM(CONFIG_STM32WB_BLE_MAX_ATT_MTU, \ + CONFIG_STM32WB_BLE_MAX_CONN, \ + STM32WB_BLE_PREP_WRITE_NUM) + +#ifdef CONFIG_STM32WB_BLE_C2HOST +# define STM32WB_BLE_C2HOST STM32WB_SHCI_BLE_INIT_OPT_STACK_LL_HOST +#else +# define STM32WB_BLE_C2HOST STM32WB_SHCI_BLE_INIT_OPT_STACK_LL +#endif + +#ifdef CONFIG_STM32WB_BLE_SVC_CHANGED_CHAR +# define STM32WB_BLE_SVC_CHANGED_CHAR STM32WB_SHCI_BLE_INIT_OPT_SVC_CHCHAR_ENABLED +#else +# define STM32WB_BLE_SVC_CHANGED_CHAR STM32WB_SHCI_BLE_INIT_OPT_SVC_CHCHAR_DISABLED +#endif + +#ifdef CONFIG_STM32WB_BLE_WRITABLE_DEVICE_NAME +# define STM32WB_BLE_DEVICE_NAME_MODE STM32WB_SHCI_BLE_INIT_OPT_DEVICE_NAME_MODE_RW +#else +# define STM32WB_BLE_DEVICE_NAME_MODE STM32WB_SHCI_BLE_INIT_OPT_DEVICE_NAME_MODE_RO +#endif + +#ifdef CONFIG_STM32WB_BLE_CHAN_SEL_ALG2 +# define STM32WB_BLE_CS_ALG2 STM32WB_SHCI_BLE_INIT_OPT_CS_ALG2_ENABLED +#else +# define STM32WB_BLE_CS_ALG2 STM32WB_SHCI_BLE_INIT_OPT_CS_ALG2_DISABLED +#endif + +#ifdef CONFIG_STM32WB_BLE_POWER_CLASS_1 +# define STM32WB_BLE_POWER_CLASS STM32WB_SHCI_BLE_INIT_OPT_POWER_CLASS_1 +#else +# define STM32WB_BLE_POWER_CLASS STM32WB_SHCI_BLE_INIT_OPT_POWER_CLASS_2_3 +#endif + +#define STM32WB_BLE_INIT_OPTIONS \ + (STM32WB_BLE_C2HOST | STM32WB_BLE_SVC_CHANGED_CHAR | \ + STM32WB_BLE_DEVICE_NAME_MODE | STM32WB_BLE_CS_ALG2 | \ + STM32WB_BLE_POWER_CLASS) + +#ifdef CONFIG_STM32WB_BLE_AGC_RSSI_IMPROVED +# define STM32WB_BLE_RXMOD_AGC_RSSI STM32WB_SHCI_BLE_INIT_RXMOD_AGC_RSSI_IMPROVED +#else +# define STM32WB_BLE_RXMOD_AGC_RSSI STM32WB_SHCI_BLE_INIT_RXMOD_AGC_RSSI_LEGACY +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int stm32wb_blehci_driveropen(struct bt_driver_s *btdev); +static int stm32wb_blehci_driversend(struct bt_driver_s *btdev, + enum bt_buf_type_e type, + void *data, size_t len); +static int stm32wb_blehci_rxevt(struct stm32wb_mbox_evt_s *evt); +static void stm32wb_blehci_bleinit(void); +static int stm32wb_blehci_driverinitialize(void); +static void stm32wb_blehci_drvinitworker(void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct bt_driver_s g_blehci_driver = +{ + .head_reserve = 0, + .open = stm32wb_blehci_driveropen, + .send = stm32wb_blehci_driversend +}; + +static sem_t g_excl_sem = SEM_INITIALIZER(1); +struct work_s g_drv_init_work; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wb_blehci_driveropen + ****************************************************************************/ + +static int stm32wb_blehci_driveropen(struct bt_driver_s *btdev) +{ + return 0; +} + +/**************************************************************************** + * Name: stm32wb_blehci_driversend + ****************************************************************************/ + +static int stm32wb_blehci_driversend(struct bt_driver_s *btdev, + enum bt_buf_type_e type, + void *data, size_t len) +{ + int ret = -EIO; + + if (type == BT_CMD || type == BT_ACL_OUT) + { + wlinfo("passing type %s to mailbox driver\n", + (type == BT_CMD) ? "CMD" : "ACL"); + + /* Ensure non-concurrent access */ + + ret = nxsem_wait_uninterruptible(&g_excl_sem); + if (ret < 0) + { + return ret; + } + + if (type == BT_CMD) + { + ret = stm32wb_mbox_blecmd(data, len); + } + else + { + ret = stm32wb_mbox_bleacl(data, len); + } + + nxsem_post(&g_excl_sem); + } + + return ret < 0 ? ret : (int)len; +} + +/**************************************************************************** + * Name: stm32wb_blehci_rxevt + ****************************************************************************/ + +static int stm32wb_blehci_rxevt(struct stm32wb_mbox_evt_s *evt) +{ + size_t len; + + switch (evt->type) + { + case STM32WB_MBOX_HCIEVT: + len = sizeof(evt->evt_hdr) + evt->evt_hdr.len; + if (evt->evt_hdr.evt == BT_HCI_EVT_CMD_COMPLETE) + { + wlinfo("received CMD_COMPLETE from mailbox " + "(opcode: 0x%x, status: 0x%x)\n", + *(uint16_t *)((uint8_t *)&evt->evt_hdr + 3), + *((uint8_t *)&evt->evt_hdr + 5)); + } + else + { + wlinfo("received HCI EVT from mailbox " + "(evt: %d, len: %zu)\n", evt->evt_hdr.evt, len); + } + + bt_netdev_receive(&g_blehci_driver, BT_EVT, &evt->evt_hdr, len); + break; + + case STM32WB_MBOX_HCIACL: + wlinfo("received HCI ACL from mailbox (handle: %d)\n", + evt->acl_hdr.handle); + len = sizeof(evt->acl_hdr) + evt->acl_hdr.len; + + bt_netdev_receive(&g_blehci_driver, BT_ACL_IN, &evt->acl_hdr, len); + break; + + case STM32WB_MBOX_SYSEVT: + wlinfo("received SYS event from mailbox (evt: %d)\n", + evt->evt_hdr.evt); + if (evt->evt_hdr.evt == STM32WB_SHCI_ASYNC_EVT && + *(uint16_t *)(&evt->evt_hdr + 1) == STM32WB_SHCI_ASYNC_EVT_C2RDY) + { + stm32wb_blehci_bleinit(); + } + break; + + case STM32WB_MBOX_SYSACK: + + /* CPU2 Ready is the only expected response */ + + DEBUGASSERT(evt->evt_hdr.evt == STM32WB_SHCI_ACK_EVT_C2RDY); + + if (evt->evt_hdr.evt == STM32WB_SHCI_ACK_EVT_C2RDY) + { + wlinfo("system command ACK response"); + + /* Make driver initialisation in low priority work queue */ + + work_queue(LPWORK, &g_drv_init_work, + stm32wb_blehci_drvinitworker, NULL, 0); + } + break; + + default: + break; + } + + return 0; +} + +/**************************************************************************** + * Name: stm32wb_blehci_bleinit + ****************************************************************************/ + +static void stm32wb_blehci_bleinit(void) +{ + /* Prepare BLE configuration */ + + struct stm32wb_shci_ble_init_cfg_s params = + { + .ble_buf = NULL, + .ble_buf_size = 0, + .gatt_attr_num = CONFIG_STM32WB_BLE_GATT_MAX_ATTR_NUM, + .gatt_srv_num = CONFIG_STM32WB_BLE_GATT_MAX_SVC_NUM, + .gatt_attr_buf_size = CONFIG_STM32WB_BLE_GATT_ATTR_BUF_SIZE, + .max_conn = CONFIG_STM32WB_BLE_MAX_CONN, + .dle_enable = CONFIG_STM32WB_BLE_DLE, + .prep_write_op_num = STM32WB_BLE_PREP_WRITE_NUM, + .mem_block_num = STM32WB_C2_MEM_BLOCK_NUM, + .att_max_mtu_size = CONFIG_STM32WB_BLE_MAX_ATT_MTU, + .slave_sca = CONFIG_STM32WB_BLE_SLAVE_SCA, + .master_sca_range = CONFIG_STM32WB_BLE_MASTER_SCA, + .ls_clock_source = CONFIG_STM32WB_BLE_LS_CLK_SRC, + .conn_event_length = CONFIG_STM32WB_BLE_MAX_CONN_EVT_LENGTH, + .hse_startup = CONFIG_STM32WB_BLE_HSE_STARTUP, + .viterbi_enable = CONFIG_STM32WB_BLE_VITERBI, + .options = STM32WB_BLE_INIT_OPTIONS, + .hw_version = 0, + .max_initor_coc_num = CONFIG_STM32WB_BLE_MAX_INITOR_COC_NUM, + .tx_power_min = CONFIG_STM32WB_BLE_MIN_TX_POWER, + .tx_power_max = CONFIG_STM32WB_BLE_MAX_TX_POWER, + .rx_model_config = STM32WB_BLE_RXMOD_AGC_RSSI + }; + + /* Initialise BLE */ + + stm32wb_mbox_bleinit(¶ms); +} + +/**************************************************************************** + * Name: stm32wb_blehci_driverinitialize + ****************************************************************************/ + +static int stm32wb_blehci_driverinitialize(void) +{ + int ret = 0; + +#ifdef CONFIG_UART_BTH4 + /* Register UART BT H4 device */ + + ret = uart_bth4_register(CONFIG_STM32WB_BLE_TTY_NAME, &g_blehci_driver); + if (ret < 0) + { + wlerr("bt_bth4_register error: %d\n", ret); + return ret; + } +#elif defined(CONFIG_NET_BLUETOOTH) + /* Register network device */ + + ret = bt_netdev_register(&g_blehci_driver); + if (ret < 0) + { + wlerr("bt_netdev_register error: %d\n", ret); + return ret; + } +#endif + + return ret; +} + +/**************************************************************************** + * Name: stm32wb_blehci_drvinitworker + ****************************************************************************/ + +static void stm32wb_blehci_drvinitworker(void *arg) +{ + stm32wb_blehci_driverinitialize(); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wb_blehci_initialize + * + * Description: + * Initialize and register BLE HCI driver which interfaces a BLE host + * stack to a BLE controller running on CPU2 via HCI protocol. Driver + * registration occurs later when CPU2 notifies its ready status. + * + ****************************************************************************/ + +void stm32wb_blehci_initialize(void) +{ + /* Initialize mbox internal data structures and set + * event receive handler. + */ + + stm32wb_mboxinitialize(stm32wb_blehci_rxevt); + + /* Enable communication hardware and bootup CPU2 */ + + stm32wb_mboxenable(); +} diff --git a/arch/arm/src/stm32wb/stm32wb_ipcc.h b/arch/arm/src/stm32wb/stm32wb_blehci.h similarity index 74% copy from arch/arm/src/stm32wb/stm32wb_ipcc.h copy to arch/arm/src/stm32wb/stm32wb_blehci.h index 5183c77d7b..84a679ab80 100644 --- a/arch/arm/src/stm32wb/stm32wb_ipcc.h +++ b/arch/arm/src/stm32wb/stm32wb_blehci.h @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/arm/src/stm32wb/stm32wb_ipcc.h + * arch/arm/src/stm32wb/stm32wb_blehci.h * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -18,22 +18,18 @@ * ****************************************************************************/ -#ifndef __ARCH_ARM_SRC_STM32WB_STM32WB_IPCC_H -#define __ARCH_ARM_SRC_STM32WB_STM32WB_IPCC_H +#ifndef __ARCH_ARM_SRC_STM32WB_STM32WB_BLEHCI_H +#define __ARCH_ARM_SRC_STM32WB_STM32WB_BLEHCI_H /**************************************************************************** * Included Files ****************************************************************************/ #include <nuttx/config.h> - -#include <stdbool.h> - -#include "chip.h" -#include "hardware/stm32wb_ipcc.h" +#include <sys/types.h> /**************************************************************************** - * Pre-processor Definitions + * Public Data ****************************************************************************/ #ifndef __ASSEMBLY__ @@ -52,24 +48,16 @@ extern "C" ****************************************************************************/ /**************************************************************************** - * Name: stm32wb_ipccreset - * - * Description: - * Reset the IPCC registers to default state - * - ****************************************************************************/ - -void stm32wb_ipccreset(void); - -/**************************************************************************** - * Name: stm32wb_ipccenable + * Name: stm32wb_blehci_initialize * * Description: - * Enable the IPCC and start CPU2 + * Initialize and register BLE HCI driver which interfaces a BLE host + * stack to a BLE controller running on CPU2 via HCI protocol. Driver + * registration occurs later when CPU2 notifies its ready status. * ****************************************************************************/ -void stm32wb_ipccenable(void); +void stm32wb_blehci_initialize(void); #undef EXTERN #if defined(__cplusplus) @@ -77,4 +65,4 @@ void stm32wb_ipccenable(void); #endif #endif /* __ASSEMBLY__ */ -#endif /* __ARCH_ARM_SRC_STM32WB_STM32WB_IPCC_H */ +#endif /* __ARCH_ARM_SRC_STM32WB_STM32WB_BLEHCI_H */ diff --git a/arch/arm/src/stm32wb/stm32wb_ipcc.h b/arch/arm/src/stm32wb/stm32wb_ipcc.h index 5183c77d7b..8f92e3f5e9 100644 --- a/arch/arm/src/stm32wb/stm32wb_ipcc.h +++ b/arch/arm/src/stm32wb/stm32wb_ipcc.h @@ -30,6 +30,7 @@ #include <stdbool.h> #include "chip.h" +#include "arm_internal.h" #include "hardware/stm32wb_ipcc.h" /**************************************************************************** @@ -71,6 +72,109 @@ void stm32wb_ipccreset(void); void stm32wb_ipccenable(void); +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wb_ipcc_rxactive + * + * Description: + * Check channel receive active flag. + * + ****************************************************************************/ + +static inline bool stm32wb_ipcc_rxactive(uint8_t chan) +{ + return (getreg32(STM32WB_IPCC_C2TOC1SR) & IPCC_C2TOC1SR_BIT(chan)) != 0; +} + +/**************************************************************************** + * Name: stm32wb_ipcc_txactive + * + * Description: + * Check channel transmit active flag. + * + ****************************************************************************/ + +static inline bool stm32wb_ipcc_txactive(uint8_t chan) +{ + return (getreg32(STM32WB_IPCC_C1TOC2SR) & IPCC_C1TOC2SR_BIT(chan)) != 0; +} + +/**************************************************************************** + * Name: stm32wb_ipcc_settxactive + * + * Description: + * Set channel transmit active flag. + * + ****************************************************************************/ + +static inline void stm32wb_ipcc_settxactive(uint8_t chan) +{ + putreg32(IPCC_C1SCR_SET_BIT(chan), STM32WB_IPCC_C1SCR); +} + +/**************************************************************************** + * Name: stm32wb_ipcc_masktxf + * + * Description: + * Mask channel transmit free interrupt. + * + ****************************************************************************/ + +static inline void stm32wb_ipcc_masktxf(uint8_t chan) +{ + uint32_t regval = getreg32(STM32WB_IPCC_C1MR); + regval |= IPCC_C1MR_FM_BIT(chan); + putreg32(regval, STM32WB_IPCC_C1MR); +} + +/**************************************************************************** + * Name: stm32wb_ipcc_unmasktxf + * + * Description: + * Unmask channel transmit free interrupt. + * + ****************************************************************************/ + +static inline void stm32wb_ipcc_unmasktxf(uint8_t chan) +{ + uint32_t regval = getreg32(STM32WB_IPCC_C1MR); + regval &= ~IPCC_C1MR_FM_BIT(chan); + putreg32(regval, STM32WB_IPCC_C1MR); +} + +/**************************************************************************** + * Name: stm32wb_ipcc_maskrxo + * + * Description: + * Mask channel receive occupied interrupt. + * + ****************************************************************************/ + +static inline void stm32wb_ipcc_maskrxo(uint8_t chan) +{ + uint32_t regval = getreg32(STM32WB_IPCC_C1MR); + regval |= IPCC_C1MR_OM_BIT(chan); + putreg32(regval, STM32WB_IPCC_C1MR); +} + +/**************************************************************************** + * Name: stm32wb_ipcc_maskrxo + * + * Description: + * Unmask channel receive occupied interrupt. + * + ****************************************************************************/ + +static inline void stm32wb_ipcc_unmaskrxo(uint8_t chan) +{ + uint32_t regval = getreg32(STM32WB_IPCC_C1MR); + regval &= ~IPCC_C1MR_OM_BIT(chan); + putreg32(regval, STM32WB_IPCC_C1MR); +} + #undef EXTERN #if defined(__cplusplus) } diff --git a/arch/arm/src/stm32wb/stm32wb_mbox.c b/arch/arm/src/stm32wb/stm32wb_mbox.c new file mode 100644 index 0000000000..f3bed170a4 --- /dev/null +++ b/arch/arm/src/stm32wb/stm32wb_mbox.c @@ -0,0 +1,813 @@ +/**************************************************************************** + * arch/arm/src/stm32wb/stm32wb_mbox.c + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <assert.h> +#include <debug.h> + +#include <nuttx/arch.h> +#include <nuttx/wqueue.h> + +#include "arm_internal.h" +#include "stm32wb_ipcc.h" +#include "stm32wb_mbox.h" +#include "hardware/stm32wb_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Mailbox shared buffer base address. Normally it is located at + * the beginning of SRAM2a. + */ + +#define STM32WB_MBOX_SHARED_BASE STM32WB_SRAM2A_BASE + +/* Mailbox shared buffer fields */ + +#define stm32wb_mbox_shared \ + (*(struct stm32wb_mbox_shared_buffer_s *)STM32WB_MBOX_SHARED_BASE) + +#define stm32wb_mbox_ref_table (stm32wb_mbox_shared.ref_table) +#define stm32wb_mbox_di_table (stm32wb_mbox_shared.dev_info_table) +#define stm32wb_mbox_sys_table (stm32wb_mbox_shared.sys_table) +#define stm32wb_mbox_mm_table (stm32wb_mbox_shared.mm_table) +#define stm32wb_mbox_ble_table (stm32wb_mbox_shared.ble_table) + +/* Mailbox buffer sizes */ + +#define STM32WB_MBOX_CS_BUF_SIZE 16 +#define STM32WB_MBOX_CMDPKT_BUF_SIZE 268 +#define STM32WB_MBOX_ACLPKT_BUF_SIZE 264 + +#define STM32WB_MBOX_RX_BUF_SIZE \ + (CONFIG_STM32WB_MBOX_RX_EVT_QUEUE_LEN * STM32WB_MBOX_CMDPKT_BUF_SIZE) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Mailbox shared buffer structures */ + +begin_packed_struct struct stm32wb_mbox_safe_boot_info_table_s +{ + uint32_t version; +} end_packed_struct; + +begin_packed_struct struct stm32wb_mbox_fus_info_table_s +{ + uint32_t version; + uint32_t memory_size; + uint32_t fus_info; +} end_packed_struct; + +begin_packed_struct struct stm32wb_mbox_wireless_fw_info_table_s +{ + uint32_t version; + uint32_t memory_size; + uint32_t info_stack; + uint32_t reserved; +} end_packed_struct; + +begin_packed_struct struct stm32wb_mbox_device_info_table_s +{ + struct stm32wb_mbox_safe_boot_info_table_s safe_boot_info_table; + struct stm32wb_mbox_fus_info_table_s fus_info_table; + struct stm32wb_mbox_wireless_fw_info_table_s wireless_fw_info_table; +} end_packed_struct; + +begin_packed_struct struct stm32wb_mbox_ble_table_s +{ + void *cmd_buffer; + void *cs_buffer; + void *evt_queue; + void *acl_buffer; +} end_packed_struct; + +begin_packed_struct struct stm32wb_mbox_sys_table_s +{ + void *cmd_buffer; + void *evt_queue; +} end_packed_struct; + +begin_packed_struct struct stm32wb_mbox_mem_manager_table_s +{ + void *ble_spare_buffer; + void *sys_spare_buffer; + void *evtpool_buffer; + uint32_t evtpool_size; + void *evtfree_buffer; + void *traces_evtpool_buffer; + uint32_t traces_evtpool_size; +} end_packed_struct; + +begin_packed_struct struct stm32wb_mbox_ref_table_s +{ + struct stm32wb_mbox_device_info_table_s *dev_info_table; + struct stm32wb_mbox_ble_table_s *ble_table; + void *thread_table; + struct stm32wb_mbox_sys_table_s *sys_table; + struct stm32wb_mbox_mem_manager_table_s *mm_table; + void *traces_table; + void *mac_802_15_4_table; + void *zigbee_table; + void *ble_lld_test_table; + void *ble_lld_table; +} end_packed_struct; + +/* Mailbox shared buffer memory layout structure */ + +struct stm32wb_mbox_shared_buffer_s +{ + aligned_data(4) struct stm32wb_mbox_ref_table_s ref_table; + + aligned_data(4) struct stm32wb_mbox_device_info_table_s dev_info_table; + aligned_data(4) struct stm32wb_mbox_ble_table_s ble_table; + aligned_data(4) struct stm32wb_mbox_sys_table_s sys_table; + aligned_data(4) struct stm32wb_mbox_mem_manager_table_s mm_table; + + aligned_data(4) stm32wb_mbox_list_t evtfree_buffer; +#ifdef CONFIG_STM32WB_BLE + aligned_data(4) stm32wb_mbox_list_t ble_evt_queue; +#endif + aligned_data(4) stm32wb_mbox_list_t sys_evt_queue; + +#ifdef CONFIG_STM32WB_BLE + aligned_data(4) uint8_t ble_cs_buffer[STM32WB_MBOX_CS_BUF_SIZE]; +#endif + aligned_data(4) uint8_t evtpool_buffer[STM32WB_MBOX_RX_BUF_SIZE]; + aligned_data(4) uint8_t sys_cmd_buffer[STM32WB_MBOX_CMDPKT_BUF_SIZE]; + aligned_data(4) uint8_t sys_spare_buffer[STM32WB_MBOX_CMDPKT_BUF_SIZE]; +#ifdef CONFIG_STM32WB_BLE + aligned_data(4) uint8_t ble_spare_buffer[STM32WB_MBOX_CMDPKT_BUF_SIZE]; + aligned_data(4) uint8_t ble_cmd_buffer[STM32WB_MBOX_CMDPKT_BUF_SIZE]; + aligned_data(4) uint8_t ble_acl_buffer[STM32WB_MBOX_ACLPKT_BUF_SIZE]; +#endif +}; + +/* Mailbox channel data type */ + +struct stm32wb_mbox_channel_s +{ + uint8_t ch_num; + stm32wb_mbox_list_t msg_buf_queue; + struct stm32wb_mbox_cmd_s *msg_buf; + bool ack_ready; +}; + +/**************************************************************************** + * Private Function prototypes + ****************************************************************************/ + +static void stm32wb_ipcc_rxoisr(int irq, uint32_t *regs, void *arg); +static void stm32wb_ipcc_txfisr(int irq, uint32_t *regs, void *arg); + +static void stm32wb_mbox_rxworker(void *arg); +static void stm32wb_mbox_txworker(void *arg); + +static void stm32wb_mbox_eventfree(stm32wb_mbox_list_t *evt); +static void stm32wb_mbox_acksyscmd(void); + +static int stm32wb_mbox_txdata(struct stm32wb_mbox_channel_s *chan, + uint8_t type, void *data, size_t len); +static bool stm32wb_mbox_txnext(struct stm32wb_mbox_channel_s *chan); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct work_s g_rx_evt_work; +static struct work_s g_tx_cmd_work; + +static stm32wb_mbox_list_t g_rx_evt_queue; +static stm32wb_mbox_list_t g_tx_evtfree_queue; +static uint8_t g_free_buffers[CONFIG_STM32WB_MBOX_TX_CMD_QUEUE_LEN] + [STM32WB_MBOX_CMDPKT_BUF_SIZE]; +static stm32wb_mbox_list_t g_free_buffers_pool; + +static struct stm32wb_mbox_channel_s g_syscmd_channel; +#ifdef CONFIG_STM32WB_BLE +static struct stm32wb_mbox_channel_s g_blecmd_channel; +static struct stm32wb_mbox_channel_s g_bleacl_channel; +#endif + +static stm32wb_mbox_evt_handler_t receive_evt_handler; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wb_ipcc_rxoisr + * + * Description: + * RX channel occupied interrupt handler (communication data posted + * by sending processor). + * + ****************************************************************************/ + +static void stm32wb_ipcc_rxoisr(int irq, uint32_t *regs, void *arg) +{ + uint32_t clrmask = 0; + + /* Pull events from system channel into processing queue */ + + if (stm32wb_ipcc_rxactive(STM32WB_MBOX_SYSEVT_CHANNEL)) + { + stm32wb_mbox_list_moveall(&stm32wb_mbox_shared.sys_evt_queue, + &g_rx_evt_queue); + + clrmask |= IPCC_C1SCR_CLR_BIT(STM32WB_MBOX_SYSEVT_CHANNEL); + } + +#ifdef CONFIG_STM32WB_BLE + + /* Pull events from BLE channel into processing queue */ + + if (stm32wb_ipcc_rxactive(STM32WB_MBOX_BLEEVT_CHANNEL)) + { + stm32wb_mbox_list_moveall(&stm32wb_mbox_shared.ble_evt_queue, + &g_rx_evt_queue); + + clrmask |= IPCC_C1SCR_CLR_BIT(STM32WB_MBOX_BLEEVT_CHANNEL); + } +#endif + + /* Process collected events in the work queue */ + + if (work_available(&g_rx_evt_work)) + { + work_queue(HPWORK, &g_rx_evt_work, stm32wb_mbox_rxworker, NULL, 0); + } + + /* Clear active statuses */ + + putreg32(clrmask, STM32WB_IPCC_C1SCR); +} + +/**************************************************************************** + * Name: stm32wb_ipcc_txfisr + * + * Description: + * TX channel free interrupt handler (communication data retrieved + * by receiving processor). + * + ****************************************************************************/ + +static void stm32wb_ipcc_txfisr(int irq, uint32_t *regs, void *arg) +{ + uint32_t c1mr = getreg32(STM32WB_IPCC_C1MR); + uint32_t txfsrc; + + /* TXF interrupt can be triggered by not masked channels and active status + * of the source channel is cleared by CPU2. So we ignore masked and active + * channels and rise other C1MR bits to highlight needed channels. + */ + + txfsrc = ~(c1mr | (getreg32(STM32WB_IPCC_C1TOC2SR) << IPCC_C1MR_FM_SHIFT)) + & IPCC_C1MR_FM_MASK; + + /* Check if the release channel triggered the interrupt */ + + if (txfsrc & IPCC_C1MR_FM_BIT(STM32WB_MBOX_EVT_RELEASE_CHANNEL)) + { + /* Move all released events (if any) into transmission mailbox */ + + if (!stm32wb_mbox_list_is_empty(&g_tx_evtfree_queue)) + { + stm32wb_mbox_list_moveall(&g_tx_evtfree_queue, + &stm32wb_mbox_shared.evtfree_buffer); + + /* Start release channel transmission */ + + stm32wb_ipcc_settxactive(STM32WB_MBOX_EVT_RELEASE_CHANNEL); + } + } + + /* Check other channels, except the release channel */ + + if (txfsrc & ~IPCC_C1MR_FM_BIT(STM32WB_MBOX_EVT_RELEASE_CHANNEL)) + { + /* Check if the system channel triggered the interrupt */ + + if (txfsrc & IPCC_C1MR_FM_BIT(STM32WB_MBOX_SYSCMD_CHANNEL)) + { + /* System channel works in 'half-duplex' mode and acks + * immediately on each command before TXF, so it needs + * to process ack response before sending next command. + */ + + g_syscmd_channel.ack_ready = true; + } + + /* Continue command processing in a work queue */ + + if (work_available(&g_tx_cmd_work)) + { + work_queue(HPWORK, &g_tx_cmd_work, stm32wb_mbox_txworker, NULL, 0); + } + } + + /* Mask triggered channels */ + + putreg32(c1mr | txfsrc, STM32WB_IPCC_C1MR); +} + +/**************************************************************************** + * Name: stm32wb_mbox_txworker + ****************************************************************************/ + +static void stm32wb_mbox_txworker(void *arg) +{ + bool handled; + + /* Process all queued commands if a dedicated channel is free */ + + do + { + handled = false; + + if (!stm32wb_ipcc_txactive(STM32WB_MBOX_SYSCMD_CHANNEL)) + { + /* Process ack response before send new command */ + + if (g_syscmd_channel.ack_ready) + { + stm32wb_mbox_acksyscmd(); + g_syscmd_channel.ack_ready = false; + } + + handled = stm32wb_mbox_txnext(&g_syscmd_channel); + } + +#ifdef CONFIG_STM32WB_BLE + if (!stm32wb_ipcc_txactive(STM32WB_MBOX_BLECMD_CHANNEL)) + { + handled |= stm32wb_mbox_txnext(&g_blecmd_channel); + } + + if (!stm32wb_ipcc_txactive(STM32WB_MBOX_BLEACL_CHANNEL)) + { + handled |= stm32wb_mbox_txnext(&g_bleacl_channel); + } +#endif + } + while (handled); +} + +/**************************************************************************** + * Name: stm32wb_mbox_rxworker + ****************************************************************************/ + +static void stm32wb_mbox_rxworker(void *arg) +{ + stm32wb_mbox_list_t *evt; + irqstate_t flags; + + while (1) + { + flags = enter_critical_section(); + + /* Pull an event from the queue */ + + evt = stm32wb_mbox_list_remove_head(&g_rx_evt_queue); + + leave_critical_section(flags); + + if (evt == NULL) + { + break; + } + + /* Pass event to a callback function without a list header */ + + receive_evt_handler((struct stm32wb_mbox_evt_s *)(evt + 1)); + + /* Free completed event. Released event needs to return to CPU2 + * via release channel. + */ + + stm32wb_mbox_eventfree((stm32wb_mbox_list_t *)evt); + } +} + +/**************************************************************************** + * Name: stm32wb_mbox_txdata + * + * Description: + * Send data over specified mailbox channel if possible. If the + * channel is busy then add a prepared packet into awaiting queue. + * + ****************************************************************************/ + +static int stm32wb_mbox_txdata(struct stm32wb_mbox_channel_s *chan, + uint8_t type, void *data, size_t len) +{ + irqstate_t flags; + struct stm32wb_mbox_cmd_s *pkt_buf; + + flags = enter_critical_section(); + + /* To start transmission the channel needs to be free, there should be + * none of other waiting commands and none of unprocessed ack responses. + */ + + if (stm32wb_mbox_list_is_empty(&chan->msg_buf_queue) && + !stm32wb_ipcc_txactive(chan->ch_num) && !chan->ack_ready) + { + /* Channel is ready, copy command into transmission buffer */ + + pkt_buf = chan->msg_buf; + } + else + { + /* Otherwise get temp buffer for command */ + + pkt_buf = (struct stm32wb_mbox_cmd_s *) + stm32wb_mbox_list_remove_head(&g_free_buffers_pool); + } + + leave_critical_section(flags); + + if (pkt_buf == NULL) + { + return -ENOBUFS; + } + + pkt_buf->type = type; + memcpy(&pkt_buf->cmd_hdr, data, len); + + if (pkt_buf == chan->msg_buf) + { + /* Command is ready in mailbox buffer, start transmission now */ + + stm32wb_ipcc_settxactive(chan->ch_num); + + if (!stm32wb_mbox_list_is_empty(&chan->msg_buf_queue) || + chan->ch_num == STM32WB_MBOX_SYSCMD_CHANNEL) + { + /* There are more commands awaiting, so unmask interrupt to get + * notified when channel gets ready to process a next one. + * And the system channel needs to check ack on completion. + */ + + stm32wb_ipcc_unmasktxf(chan->ch_num); + } + } + else + { + /* Command is in temp buffer, push it into queue */ + + flags = enter_critical_section(); + stm32wb_mbox_list_add_tail(&chan->msg_buf_queue, &pkt_buf->list_hdr); + leave_critical_section(flags); + + /* Unmask interrupt to get notified when channel gets free */ + + stm32wb_ipcc_unmasktxf(chan->ch_num); + } + + return OK; +} + +/**************************************************************************** + * Name: stm32wb_mbox_txnext + * + * Description: + * Send next command from the queue. + * + ****************************************************************************/ + +static bool stm32wb_mbox_txnext(struct stm32wb_mbox_channel_s *chan) +{ + struct stm32wb_mbox_cmd_s *pkt_buf; + + pkt_buf = (struct stm32wb_mbox_cmd_s *) + stm32wb_mbox_list_remove_head(&chan->msg_buf_queue); + + if (pkt_buf != NULL) + { + chan->msg_buf->type = pkt_buf->type; + + if (chan->ch_num == STM32WB_MBOX_BLEACL_CHANNEL) + { + memcpy(chan->msg_buf, &pkt_buf->acl_hdr, + pkt_buf->acl_hdr.len); + } + else + { + memcpy(chan->msg_buf, &pkt_buf->cmd_hdr, + pkt_buf->cmd_hdr.param_len); + } + + /* Start transmission */ + + stm32wb_ipcc_settxactive(chan->ch_num); + + if (!stm32wb_mbox_list_is_empty(&chan->msg_buf_queue)) + { + /* Unmask TXF interrupt to get notified when completed */ + + stm32wb_ipcc_unmasktxf(chan->ch_num); + } + + /* Put back to pool the freed command buffer */ + + stm32wb_mbox_list_add_tail(&g_free_buffers_pool, &pkt_buf->list_hdr); + } + + return pkt_buf != NULL; +} + +/**************************************************************************** + * Name: stm32wb_mbox_eventfree + * + * Description: + * Free handled mailbox event. + * + ****************************************************************************/ + +static void stm32wb_mbox_eventfree(stm32wb_mbox_list_t *evt) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + /* Collect releasing events in the global list */ + + stm32wb_mbox_list_add_tail(&g_tx_evtfree_queue, evt); + + /* Check if release channel is ready to process now */ + + if (!stm32wb_ipcc_txactive(STM32WB_MBOX_EVT_RELEASE_CHANNEL)) + { + /* Move all collected events into transmission queue */ + + stm32wb_mbox_list_moveall(&g_tx_evtfree_queue, + &stm32wb_mbox_shared.evtfree_buffer); + + /* Start transmission */ + + stm32wb_ipcc_settxactive(STM32WB_MBOX_EVT_RELEASE_CHANNEL); + } + else + { + /* Unmask interrupt to get notified when channel gets free */ + + stm32wb_ipcc_unmasktxf(STM32WB_MBOX_EVT_RELEASE_CHANNEL); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: stm32wb_mbox_acksyscmd + * + * Description: + * Send ACK response event for completed system command. + * + ****************************************************************************/ + +static void stm32wb_mbox_acksyscmd(void) +{ + struct stm32wb_mbox_evt_s *evt; + + /* System command ACK response is placed at the same address as the + * processed command but without a list header. + */ + + evt = (struct stm32wb_mbox_evt_s *)(&g_syscmd_channel.msg_buf); + evt->type = STM32WB_MBOX_SYSACK; + + receive_evt_handler(evt); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wb_mboxinitialize + * + * Description: + * Initialize mailbox driver memory. + * + * Input Parameters: + * evt_handler - the function to call on event receive + * + ****************************************************************************/ + +void stm32wb_mboxinitialize(stm32wb_mbox_evt_handler_t evt_handler) +{ + int i; + + /* Init mailbox shared data */ + + stm32wb_mbox_list_initialize(&stm32wb_mbox_shared.sys_evt_queue); + stm32wb_mbox_list_initialize(&stm32wb_mbox_shared.evtfree_buffer); +#ifdef CONFIG_STM32WB_BLE + stm32wb_mbox_list_initialize(&stm32wb_mbox_shared.ble_evt_queue); +#endif + + stm32wb_mbox_ref_table.dev_info_table = &stm32wb_mbox_di_table; + stm32wb_mbox_ref_table.ble_table = &stm32wb_mbox_ble_table; + stm32wb_mbox_ref_table.sys_table = &stm32wb_mbox_sys_table; + stm32wb_mbox_ref_table.mm_table = &stm32wb_mbox_mm_table; + + stm32wb_mbox_sys_table.cmd_buffer = &stm32wb_mbox_shared.sys_cmd_buffer; + stm32wb_mbox_sys_table.evt_queue = &stm32wb_mbox_shared.sys_evt_queue; + + stm32wb_mbox_mm_table.evtpool_buffer = &stm32wb_mbox_shared + .evtpool_buffer; + stm32wb_mbox_mm_table.evtpool_size = sizeof(stm32wb_mbox_shared + .evtpool_buffer); + stm32wb_mbox_mm_table.evtfree_buffer = &stm32wb_mbox_shared + .evtfree_buffer; + stm32wb_mbox_mm_table.sys_spare_buffer = &stm32wb_mbox_shared + .sys_spare_buffer; +#ifdef CONFIG_STM32WB_BLE + stm32wb_mbox_mm_table.ble_spare_buffer = &stm32wb_mbox_shared + .ble_spare_buffer; +#endif + +#ifdef CONFIG_STM32WB_BLE + stm32wb_mbox_ble_table.cmd_buffer = &stm32wb_mbox_shared.ble_cmd_buffer; + stm32wb_mbox_ble_table.acl_buffer = &stm32wb_mbox_shared.ble_acl_buffer; + stm32wb_mbox_ble_table.cs_buffer = &stm32wb_mbox_shared.ble_cs_buffer; + stm32wb_mbox_ble_table.evt_queue = &stm32wb_mbox_shared.ble_evt_queue; +#endif + + /* Init system channel data */ + + g_syscmd_channel.ch_num = STM32WB_MBOX_SYSCMD_CHANNEL; + g_syscmd_channel.msg_buf = (struct stm32wb_mbox_cmd_s *) + stm32wb_mbox_shared.sys_cmd_buffer; + stm32wb_mbox_list_initialize(&g_syscmd_channel.msg_buf_queue); + +#ifdef CONFIG_STM32WB_BLE + /* Init BLE command channel data */ + + g_blecmd_channel.ch_num = STM32WB_MBOX_BLECMD_CHANNEL; + g_blecmd_channel.msg_buf = (struct stm32wb_mbox_cmd_s *) + stm32wb_mbox_shared.ble_cmd_buffer; + stm32wb_mbox_list_initialize(&g_blecmd_channel.msg_buf_queue); + + /* Init BLE ACL channel data */ + + g_bleacl_channel.ch_num = STM32WB_MBOX_BLEACL_CHANNEL; + g_bleacl_channel.msg_buf = (struct stm32wb_mbox_cmd_s *) + stm32wb_mbox_shared.ble_cmd_buffer; + stm32wb_mbox_list_initialize(&g_bleacl_channel.msg_buf_queue); +#endif + + /* Init local (not shared) queues */ + + stm32wb_mbox_list_initialize(&g_rx_evt_queue); + stm32wb_mbox_list_initialize(&g_tx_evtfree_queue); + + stm32wb_mbox_list_initialize(&g_free_buffers_pool); + for (i = 0; i < CONFIG_STM32WB_MBOX_TX_CMD_QUEUE_LEN; i++) + { + stm32wb_mbox_list_add_tail(&g_free_buffers_pool, + (stm32wb_mbox_list_t *)g_free_buffers[i]); + } + + /* Set event receive function */ + + receive_evt_handler = evt_handler; +} + +/**************************************************************************** + * Name: stm32wb_mboxenable + * + * Description: + * Enable mailbox hardware and start communication. The CPU2 responses + * with C2Ready event on success. + * + ****************************************************************************/ + +void stm32wb_mboxenable(void) +{ + uint32_t regval; + + /* Setup RXO and TXF interrupts */ + + irq_attach(STM32WB_IRQ_IPCCRX, (xcpt_t)stm32wb_ipcc_rxoisr, NULL); + up_enable_irq(STM32WB_IRQ_IPCCRX); + + irq_attach(STM32WB_IRQ_IPCCTX, (xcpt_t)stm32wb_ipcc_txfisr, NULL); + up_enable_irq(STM32WB_IRQ_IPCCTX); + + regval = getreg32(STM32WB_IPCC_C1CR); + regval |= IPCC_C1CR_RXOIE | IPCC_C1CR_TXFIE; + putreg32(regval, STM32WB_IPCC_C1CR); + + /* Unmask system channel RXO interrupt. Once CPU2 started we expect + * to receive C2READY event via system channel. + */ + + stm32wb_ipcc_unmaskrxo(STM32WB_MBOX_SYSEVT_CHANNEL); + + /* Enable IPCC hardware and bootup CPU2 */ + + stm32wb_ipccenable(); +} + +/**************************************************************************** + * Name: stm32wb_mbox_syscmd + * + * Description: + * Send command over mailbox system channel. Command data must be + * prepended with HCI header. + * + ****************************************************************************/ + +int stm32wb_mbox_syscmd(void *data, size_t len) +{ + return stm32wb_mbox_txdata(&g_syscmd_channel, STM32WB_MBOX_SYSCMD, + data, len); +} + +#ifdef CONFIG_STM32WB_BLE +/**************************************************************************** + * Name: stm32wb_mbox_blecmd + * + * Description: + * Send command over mailbox BLE channel. Command data must be + * prepended with HCI header. + * + ****************************************************************************/ + +int stm32wb_mbox_blecmd(void *data, size_t len) +{ + return stm32wb_mbox_txdata(&g_blecmd_channel, STM32WB_MBOX_HCICMD, + data, len); +} + +/**************************************************************************** + * Name: stm32wb_mbox_bleacl + * + * Description: + * Send BLE ACL data over mailbox BLE ACL channel. Data must be + * prepended with HCI ACL header. + * + ****************************************************************************/ + +int stm32wb_mbox_bleacl(void *data, size_t len) +{ + return stm32wb_mbox_txdata(&g_bleacl_channel, STM32WB_MBOX_HCIACL, + data, len); +} + +/**************************************************************************** + * Name: stm32wb_mbox_bleinit + * + * Description: + * Initialize and start BLE subsystem with provided configuration params. + * + ****************************************************************************/ + +void stm32wb_mbox_bleinit(struct stm32wb_shci_ble_init_cfg_s *params) +{ + struct bt_hci_cmd_hdr_s *cmd; + + /* Just borrow a temporary free buffer for command data */ + + cmd = (struct bt_hci_cmd_hdr_s *)stm32wb_mbox_shared.sys_spare_buffer; + + /* Prepare command data */ + + cmd->opcode = STM32WB_SHCI_BLE_INIT; + cmd->param_len = sizeof(*cmd); + memcpy(cmd + 1, params, sizeof(*params)); + + /* Send BLE init command to CPU2 */ + + stm32wb_mbox_syscmd(cmd, sizeof(*cmd) + sizeof(*params)); + + /* Unmask BLE event channel RXO interrupt */ + + stm32wb_ipcc_unmaskrxo(STM32WB_MBOX_BLEEVT_CHANNEL); +} +#endif /* CONFIG_STM32WB_BLE */ diff --git a/arch/arm/src/stm32wb/stm32wb_mbox.h b/arch/arm/src/stm32wb/stm32wb_mbox.h new file mode 100644 index 0000000000..210bf1c6b0 --- /dev/null +++ b/arch/arm/src/stm32wb/stm32wb_mbox.h @@ -0,0 +1,174 @@ +/**************************************************************************** + * arch/arm/src/stm32wb/stm32wb_mbox.h + * + * 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 __ARCH_ARM_SRC_STM32WB_STM32WB_MBOX_H +#define __ARCH_ARM_SRC_STM32WB_STM32WB_MBOX_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> + +#include <nuttx/wireless/bluetooth/bt_hci.h> + +#include "stm32wb_mbox_list.h" +#include "stm32wb_mbox_shci.h" + +/**************************************************************************** + * Pre-Processor Declarations + ****************************************************************************/ + +/* Mailbox channels */ + +#define STM32WB_MBOX_BLEEVT_CHANNEL 1 +#define STM32WB_MBOX_BLECMD_CHANNEL 1 +#define STM32WB_MBOX_SYSEVT_CHANNEL 2 +#define STM32WB_MBOX_SYSCMD_CHANNEL 2 +#define STM32WB_MBOX_EVT_RELEASE_CHANNEL 4 +#define STM32WB_MBOX_BLEACL_CHANNEL 6 + +/* Mailbox packet types */ + +#define STM32WB_MBOX_HCICMD 0x01 +#define STM32WB_MBOX_HCIACL 0x02 +#define STM32WB_MBOX_HCIEVT 0x04 +#define STM32WB_MBOX_SYSCMD 0x10 +#define STM32WB_MBOX_SYSEVT 0x12 +#define STM32WB_MBOX_SYSACK 0xe0 + +/* Mailbox configuration helpers */ + +#define STM32WB_MBOX_BLE_ATT_DEFAULT_MTU 23 +#define STM32WB_MBOX_C2_MEM_BLOCK_SZ 32 + +#define DIV_UP(a, b) (((a) + (b) - 1) / (b)) + +#define STM32WB_MBOX_DEFAULT_BLE_PREP_WRITE_NUM(max_mtu) \ + (DIV_UP((max_mtu), STM32WB_MBOX_BLE_ATT_DEFAULT_MTU - 5) * 2) + +#define STM32WB_MBOX_DEFAULT_C2_MEM_BLOCK_NUM(max_mtu, max_conn, pw) \ + ((pw) + ((max_conn) + 1) * (DIV_UP((max_mtu) + 4, STM32WB_MBOX_C2_MEM_BLOCK_SZ) + 2)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Mailbox data transfer packets */ + +begin_packed_struct struct stm32wb_mbox_evt_s +{ + uint8_t type; + union + { + struct bt_hci_evt_hdr_s evt_hdr; + struct bt_hci_acl_hdr_s acl_hdr; + }; +} end_packed_struct; + +begin_packed_struct struct stm32wb_mbox_cmd_s +{ + stm32wb_mbox_list_t list_hdr; + uint8_t type; + union + { + struct bt_hci_cmd_hdr_s cmd_hdr; + struct bt_hci_acl_hdr_s acl_hdr; + }; +} end_packed_struct; + +/* Mailbox receive event handler type */ + +typedef int (*stm32wb_mbox_evt_handler_t)(struct stm32wb_mbox_evt_s *); + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wb_mboxinitialize + * + * Description: + * Initialize mailbox driver memory. + * + * Input Parameters: + * evt_handler - the function to call on event receive + * + ****************************************************************************/ + +void stm32wb_mboxinitialize(stm32wb_mbox_evt_handler_t evt_handler); + +/**************************************************************************** + * Name: stm32wb_mboxenable + * + * Description: + * Enable mailbox hardware and start communication. The CPU2 responses + * with C2Ready event on success. + * + ****************************************************************************/ + +void stm32wb_mboxenable(void); + +/**************************************************************************** + * Name: stm32wb_mbox_syscmd + * + * Description: + * Send command over mailbox system channel. Command data must be + * prepended with HCI header. + * + ****************************************************************************/ + +int stm32wb_mbox_syscmd(void *data, size_t len); + +/**************************************************************************** + * Name: stm32wb_mbox_blecmd + * + * Description: + * Send command over mailbox BLE channel. Command data must be + * prepended with HCI header. + * + ****************************************************************************/ + +int stm32wb_mbox_blecmd(void *data, size_t len); + +/**************************************************************************** + * Name: stm32wb_mbox_bleacl + * + * Description: + * Send BLE ACL data over mailbox BLE ACL channel. Data must be + * prepended with HCI ACL header. + * + ****************************************************************************/ + +int stm32wb_mbox_bleacl(void *data, size_t len); + +/**************************************************************************** + * Name: stm32wb_mbox_bleinit + * + * Description: + * Initialize and start BLE subsystem with provided configuration params. + * + ****************************************************************************/ + +void stm32wb_mbox_bleinit(struct stm32wb_shci_ble_init_cfg_s *params); + +#endif /* __ARCH_ARM_SRC_STM32WB_STM32WB_MBOX_H */ diff --git a/arch/arm/src/stm32wb/stm32wb_mbox_list.h b/arch/arm/src/stm32wb/stm32wb_mbox_list.h new file mode 100644 index 0000000000..6081476022 --- /dev/null +++ b/arch/arm/src/stm32wb/stm32wb_mbox_list.h @@ -0,0 +1,144 @@ +/**************************************************************************** + * arch/arm/src/stm32wb/stm32wb_mbox_list.h + * + * 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 __ARCH_ARM_SRC_STM32WB_STM32WB_MBOX_LIST_H +#define __ARCH_ARM_SRC_STM32WB_STM32WB_MBOX_LIST_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This list implementation is similar to list_node, but prev and next + * fields are at opposite places and the struct is packed. Also there is + * a new list_moveall function. + */ + +begin_packed_struct struct stm32wb_mbox_list_s +{ + struct stm32wb_mbox_list_s *next; + struct stm32wb_mbox_list_s *prev; +} end_packed_struct; + +typedef struct stm32wb_mbox_list_s stm32wb_mbox_list_t; + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wb_mbox_list_initialize + * + * Description: + * Initialize internal fields. + * + ****************************************************************************/ + +static inline void stm32wb_mbox_list_initialize(stm32wb_mbox_list_t *list) +{ + list->prev = list; + list->next = list; +} + +/**************************************************************************** + * Name: stm32wb_mbox_list_add_tail + * + * Description: + * Add new node at the end of the list. + * + ****************************************************************************/ + +static inline void stm32wb_mbox_list_add_tail(stm32wb_mbox_list_t *list, + stm32wb_mbox_list_t *item) +{ + item->prev = list->prev; + item->next = list; + list->prev->next = item; + list->prev = item; +} + +/**************************************************************************** + * Name: stm32wb_mbox_list_remove_head + * + * Description: + * Remove and return first node from the list head (if any). + * + ****************************************************************************/ + +static inline stm32wb_mbox_list_t * +stm32wb_mbox_list_remove_head(stm32wb_mbox_list_t *list) +{ + if (list->next != list) + { + stm32wb_mbox_list_t *item = list->next; + item->next->prev = item->prev; + item->prev->next = item->next; + item->prev = NULL; + item->next = NULL; + return item; + } + else + { + return NULL; + } +} + +/**************************************************************************** + * Name: stm32wb_mbox_list_is_empty + * + * Description: + * Check if the list is empty. + * + ****************************************************************************/ + +static inline bool stm32wb_mbox_list_is_empty(stm32wb_mbox_list_t *list) +{ + return (list->next == list); +} + +/**************************************************************************** + * Name: stm32wb_mbox_list_moveall + * + * Description: + * Remove all nodes from source list and add them to the end of the + * destination list. + * + ****************************************************************************/ + +static inline void stm32wb_mbox_list_moveall(stm32wb_mbox_list_t *src, + stm32wb_mbox_list_t *dst) +{ + if (src->next != src) + { + src->next->prev = dst->prev; + src->prev->next = dst; + dst->prev->next = src->next; + dst->prev = src->prev; + src->prev = src; + src->next = src; + } +} + +#endif /* __ARCH_ARM_SRC_STM32WB_STM32WB_MBOX_LIST_H */ diff --git a/arch/arm/src/stm32wb/stm32wb_mbox_shci.h b/arch/arm/src/stm32wb/stm32wb_mbox_shci.h new file mode 100644 index 0000000000..7ca109fda5 --- /dev/null +++ b/arch/arm/src/stm32wb/stm32wb_mbox_shci.h @@ -0,0 +1,186 @@ +/**************************************************************************** + * arch/arm/src/stm32wb/stm32wb_mbox_shci.h + * + * 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 __ARCH_ARM_SRC_STM32WB_STM32WB_MBOX_SHCI_H +#define __ARCH_ARM_SRC_STM32WB_STM32WB_MBOX_SHCI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <nuttx/compiler.h> + +/**************************************************************************** + * Pre-Processor Declarations + ****************************************************************************/ + +/* SHCI event types *********************************************************/ + +#define STM32WB_SHCI_ASYNC_EVT 0xff + +/* SHCI async event subtypes */ + +#define STM32WB_SHCI_ASYNC_EVT_C2RDY 0x9200 + +/* SHCI system command acknowledgement events */ + +#define STM32WB_SHCI_ACK_EVT_C2RDY 0x05 + +/* SHCI command opcodes *****************************************************/ + +#define STM32WB_SHCI_OGF 0x3f +#define STM32WB_SHCI_OP(ogf, ocf) (((ogf) << 10) | (ocf)) + +#define STM32WB_SHCI_FUS_GET_STATE STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x52) +#define STM32WB_SHCI_FUS_FW_UPGRADE STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x54) +#define STM32WB_SHCI_FUS_FW_DELETE STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x55) +#define STM32WB_SHCI_FUS_UPDATE_AUTH_KEY STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x56) +#define STM32WB_SHCI_FUS_LOCK_AUTH_KEY STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x57) +#define STM32WB_SHCI_FUS_STORE_USR_KEY STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x58) +#define STM32WB_SHCI_FUS_LOAD_USR_KEY STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x59) +#define STM32WB_SHCI_FUS_START_WS STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x5a) +#define STM32WB_SHCI_FUS_LOCK_USR_KEY STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x5d) +#define STM32WB_SHCI_FUS_UNLOAD_USR_KEY STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x5e) +#define STM32WB_SHCI_FUS_ANTIROLLBACK STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x5f) +#define STM32WB_SHCI_BLE_INIT STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x66) +#define STM32WB_SHCI_THREAD_INIT STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x67) +#define STM32WB_SHCI_DEBUG_INIT STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x68) +#define STM32WB_SHCI_FLASH_ERASE_ACTIVITY STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x69) +#define STM32WB_SHCI_CONCURRENT_SET_MODE STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x6a) +#define STM32WB_SHCI_FLASH_STORE_DATA STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x6b) +#define STM32WB_SHCI_FLASH_ERASE_DATA STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x6c) +#define STM32WB_SHCI_RADIO_ALLOW_LOW_POWER STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x6d) +#define STM32WB_SHCI_MAC_802154_INIT STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x6e) +#define STM32WB_SHCI_REINIT STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x6f) +#define STM32WB_SHCI_ZIGBEE_INIT STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x70) +#define STM32WB_SHCI_LLD_TESTS_INIT STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x71) +#define STM32WB_SHCI_EXTPA_CONFIG STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x72) +#define STM32WB_SHCI_SET_FLASH_CONTROL STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x73) +#define STM32WB_SHCI_BLE_LLD_INIT STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x74) +#define STM32WB_SHCI_CONFIG STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x75) +#define STM32WB_SHCI_GET_NEXT_BLE_EVT_TIME STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x76) +#define STM32WB_SHCI_ENABLE_NEXT_802154_NF STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x77) +#define STM32WB_SHCI_802_15_4_DEINIT STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x78) + +/* Command params bitfield definitions **************************************/ + +/* BLE init command option flags */ + +#define STM32WB_SHCI_BLE_INIT_OPT_STACK_MASK (1 << 0) /* Bit 0: BLE stack select */ +# define STM32WB_SHCI_BLE_INIT_OPT_STACK_LL_HOST (0 << 0) /* 0x0: Link Layer and Host */ +# define STM32WB_SHCI_BLE_INIT_OPT_STACK_LL (1 << 0) /* 0x1: Link Layer only */ + +#define STM32WB_SHCI_BLE_INIT_OPT_SVC_CHCHAR_MASK (1 << 1) /* Bit 1: Service Changed characteristic */ +# define STM32WB_SHCI_BLE_INIT_OPT_SVC_CHCHAR_ENABLED (0 << 1) /* 0x0: Characteristic enabled */ +# define STM32WB_SHCI_BLE_INIT_OPT_SVC_CHCHAR_DISABLED (1 << 1) /* 0x1: Characteristic disabled */ + +#define STM32WB_SHCI_BLE_INIT_OPT_DEVICE_NAME_MODE_MASK (1 << 2) /* Bit 2: Device Name mode */ +# define STM32WB_SHCI_BLE_INIT_OPT_DEVICE_NAME_MODE_RW (0 << 2) /* 0x0: Read-Write mode */ +# define STM32WB_SHCI_BLE_INIT_OPT_DEVICE_NAME_MODE_RO (1 << 2) /* 0x1: Read-Only mode */ + +#define STM32WB_SHCI_BLE_INIT_OPT_CS_ALG2_MASK (1 << 4) /* Bit 4: Channel selection algorithm 2 enabled */ +# define STM32WB_SHCI_BLE_INIT_OPT_CS_ALG2_DISABLED (0 << 4) /* 0x0: Algorithm 2 disabled */ +# define STM32WB_SHCI_BLE_INIT_OPT_CS_ALG2_ENABLED (1 << 4) /* 0x1: Algorithm 2 enabled */ + +#define STM32WB_SHCI_BLE_INIT_OPT_POWER_CLASS_MASK (1 << 7) /* Bit 7: Power class */ +# define STM32WB_SHCI_BLE_INIT_OPT_POWER_CLASS_2_3 (0 << 7) /* 0x0: Power Class 2-3 */ +# define STM32WB_SHCI_BLE_INIT_OPT_POWER_CLASS_1 (1 << 7) /* 0x1: Power Class 1 */ + +/* BLE init command rx_model_config flags */ + +#define STM32WB_SHCI_BLE_INIT_RXMOD_AGC_RSSI_MASK (1 << 0) /* Bit 0: AGC RSSI model */ +# define STM32WB_SHCI_BLE_INIT_RXMOD_AGC_RSSI_LEGACY (0 << 0) /* 0x0: AGC RSSI Legacy */ +# define STM32WB_SHCI_BLE_INIT_RXMOD_AGC_RSSI_IMPROVED (1 << 0) /* 0x1: AGC RSSI Improved */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* STM32WB_SHCI_BLE_INIT command params */ + +begin_packed_struct struct stm32wb_shci_ble_init_cfg_s +{ + void *ble_buf; /* Not used, must be NULL. */ + uint32_t ble_buf_size; /* Not used, must be 0. */ + + uint16_t gatt_attr_num; /* Maximum number of GATT attributes. */ + uint16_t gatt_srv_num; /* Maximum number of GATT services. */ + uint16_t gatt_attr_buf_size; /* GATT attributes storage buf size. */ + + uint8_t max_conn; /* Maximum number of simultaneous + * connections, up to 8 is supported. */ + + uint8_t dle_enable; /* Data Length Extension enable. */ + + uint8_t prep_write_op_num; /* Maximum number of Prepare Write + * operations. */ + + uint8_t mem_block_num; /* Number of allocated memory blocks, + * throughput performance / memory usage + * tuning. */ + + uint16_t att_max_mtu_size; /* Maximum attribute MTU size. */ + + uint16_t slave_sca; /* Sleep clock accuracy (ppm value) in + * slave mode. */ + + uint8_t master_sca_range; /* Sleep clock accuracy in master mode: + * 0x00: 251 ppm to 500 ppm + * 0x01: 151 ppm to 250 ppm + * 0x02: 101 ppm to 150 ppm + * 0x03: 76 ppm to 100 ppm + * 0x04: 51 ppm to 75 ppm + * 0x05: 31 ppm to 50 ppm + * 0x06: 21 ppm to 30 ppm + * 0x07: 0 ppm to 20 ppm */ + + uint8_t ls_clock_source; /* Low speed 32 kHz clock source: + * 0x00: use LSE + * 0x01: use HSE */ + + uint32_t conn_event_length; /* Maximum duration of a slave connection + * event in units of 625/256us + * (~2.44us). */ + + uint16_t hse_startup; /* HSE startup time in units of 625/256us + * (~2.44us). */ + + uint8_t viterbi_enable; /* Enable Viterbi algorithm + * implementation. */ + + uint8_t options; /* BLE init option flags. */ + + uint8_t hw_version; /* Not used, must be 0. */ + + uint8_t max_initor_coc_num; /* Maximum number of connection-oriented + * channels in initiator mode. */ + + int8_t tx_power_min; /* Minimum transmit power in dBm. + * Range: -127 .. 20 */ + + int8_t tx_power_max; /* Maximum transmit power in dBm. + * Range: -127 .. 20 */ + + uint8_t rx_model_config; /* RX model config flags */ +} end_packed_struct; + +#endif /* __ARCH_ARM_SRC_STM32WB_STM32WB_MBOX_SHCI_H */ diff --git a/arch/arm/src/stm32wb/stm32wb_rcc.c b/arch/arm/src/stm32wb/stm32wb_rcc.c index d268009732..44b3fe4e10 100644 --- a/arch/arm/src/stm32wb/stm32wb_rcc.c +++ b/arch/arm/src/stm32wb/stm32wb_rcc.c @@ -810,6 +810,17 @@ static void stm32wb_stdclockconfig(void) putreg32(regval, STM32WB_RCC_CR); # endif #endif /* STM32WB_USE_LSE */ + + /* Select CPU2 RF wakeup clock source, no clock if not set */ + + regval = getreg32(STM32WB_RCC_CSR); + regval &= ~RCC_CSR_RFWKPSEL_MASK; +#if defined(STM32WB_BOARD_RFWKP_USELSE) + regval |= RCC_CSR_RFWKPSEL_LSE; +#elif defined(STM32WB_BOARD_RFWKP_USEHSE) + regval |= RCC_CSR_RFWKPSEL_HSE; +#endif + putreg32(regval, STM32WB_RCC_CSR); } } #endif diff --git a/boards/arm/stm32wb/nucleo-wb55rg/README.txt b/boards/arm/stm32wb/nucleo-wb55rg/README.txt index d0228bb114..f9fc90530e 100644 --- a/boards/arm/stm32wb/nucleo-wb55rg/README.txt +++ b/boards/arm/stm32wb/nucleo-wb55rg/README.txt @@ -26,6 +26,8 @@ Status supported - GPIO, EXTI, DMA, timers, flash, PWR, RTC, USART/LPUART, SPI, IPCC. SRAM2 heap allocation works. Builtin apps work and ostest passed. + July 2022: Added BLE support with mailbox IPC driver. + LEDs ==== @@ -60,3 +62,8 @@ Configurations Configures the NuttShell (nsh) located at examples/nsh. This configuration is focused on low level, command-line driver testing. + + ble: + + Besides the NuttShell this configuration also enables BLE support. + It includes btsak application for testing BLE applications. diff --git a/boards/arm/stm32wb/nucleo-wb55rg/configs/ble/defconfig b/boards/arm/stm32wb/nucleo-wb55rg/configs/ble/defconfig new file mode 100644 index 0000000000..dca33bff35 --- /dev/null +++ b/boards/arm/stm32wb/nucleo-wb55rg/configs/ble/defconfig @@ -0,0 +1,55 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NET_IPv4 is not set +CONFIG_ALLOW_BSD_COMPONENTS=y +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nucleo-wb55rg" +CONFIG_ARCH_BOARD_NUCLEO_WB55RG=y +CONFIG_ARCH_CHIP="stm32wb" +CONFIG_ARCH_CHIP_STM32WB55RG=y +CONFIG_ARCH_CHIP_STM32WB=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=6500 +CONFIG_BTSAK=y +CONFIG_BUILTIN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DRIVERS_BLUETOOTH=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_FS_PROCFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_NET=y +CONFIG_NET_BLUETOOTH=y +CONFIG_NET_STATISTICS=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_MQ_MSGS=32 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=196608 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_STM32WB_BLE=y +CONFIG_STM32WB_DISABLE_IDLE_SLEEP_DURING_DEBUG=y +CONFIG_STM32WB_DMA1=y +CONFIG_STM32WB_PWR=y +CONFIG_STM32WB_USART1=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_TESTING_OSTEST=y +CONFIG_USART1_SERIAL_CONSOLE=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_BLUETOOTH=y diff --git a/boards/arm/stm32wb/nucleo-wb55rg/include/nucleo-wb55rg.h b/boards/arm/stm32wb/nucleo-wb55rg/include/nucleo-wb55rg.h index c2fc3aacf9..79ae8bb8c4 100644 --- a/boards/arm/stm32wb/nucleo-wb55rg/include/nucleo-wb55rg.h +++ b/boards/arm/stm32wb/nucleo-wb55rg/include/nucleo-wb55rg.h @@ -69,6 +69,12 @@ # define MSI_CLOCK_CONFIG 1 /* MSI @ 4MHz autotrimmed via LSE */ #endif +#if 0 +# define STM32WB_BOARD_RFWKP_USEHSE 1 /* CPU2 use HSE/1024 on RF wakeup */ +#elif 1 +# define STM32WB_BOARD_RFWKP_USELSE 1 /* CPU2 use LSE on RF wakeup */ +#endif + #if defined(HSI_CLOCK_CONFIG) #define STM32WB_BOARD_USEHSI 1 diff --git a/boards/arm/stm32wb/nucleo-wb55rg/src/stm32_appinit.c b/boards/arm/stm32wb/nucleo-wb55rg/src/stm32_appinit.c index d505e8b887..497284720e 100644 --- a/boards/arm/stm32wb/nucleo-wb55rg/src/stm32_appinit.c +++ b/boards/arm/stm32wb/nucleo-wb55rg/src/stm32_appinit.c @@ -43,6 +43,12 @@ # include "stm32wb_rtc.h" #endif +#ifdef CONFIG_STM32WB_BLE +# include "stm32wb_blehci.h" +#endif + +#include "nucleo-wb55rg.h" + /**************************************************************************** * Private Data ****************************************************************************/ @@ -51,6 +57,20 @@ * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: arm_netinitialize + * + * Description: + * Dummy function expected to start-up logic. + * + ****************************************************************************/ + +#if defined(CONFIG_NET) && !defined(CONFIG_NETDEV_LATEINIT) +void arm_netinitialize(void) +{ +} +#endif + /**************************************************************************** * Name: board_app_initialize * @@ -135,6 +155,12 @@ int board_app_initialize(uintptr_t arg) } #endif +#ifdef CONFIG_STM32WB_BLE + /* Initialize and register BLE HCI driver */ + + stm32wb_blehci_initialize(); +#endif + return ret; } #endif /* CONFIG_BOARDCTL */
