mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-25 22:43:50 +01:00
cpu/esp32: add BLE support for the ESP32-H2
This commit is contained in:
parent
62fd4805d9
commit
e528d3488d
@ -27,6 +27,9 @@ ifneq (,$(filter esp_ble,$(USEMODULE)))
|
||||
ifeq (esp32,$(CPU_FAM))
|
||||
FEATURES_REQUIRED += esp_ble_esp32
|
||||
USEPKG += esp32_sdk_lib_bt_esp32
|
||||
else ifeq (esp32h2,$(CPU_FAM))
|
||||
FEATURES_REQUIRED += esp_ble_esp32h2
|
||||
USEPKG += esp32_sdk_lib_bt_esp32h2
|
||||
else ifneq (,$(filter esp32c3 esp32s3,$(CPU_FAM)))
|
||||
FEATURES_REQUIRED += esp_ble_esp32c3
|
||||
USEPKG += esp32_sdk_lib_bt_esp32c3
|
||||
@ -161,9 +164,15 @@ endif
|
||||
ifneq (,$(filter nimble,$(USEPKG)))
|
||||
USEMODULE += esp_ble
|
||||
USEMODULE += esp_ble_nimble
|
||||
USEMODULE += esp_idf_nvs_flash
|
||||
USEMODULE += nimble_host
|
||||
USEMODULE += nimble_transport_hci_h4
|
||||
USEMODULE += ztimer_msec
|
||||
ifeq (esp32h2,$(CPU_FAM))
|
||||
# TODO for the moment, we use tinycrypt for encryption
|
||||
# USEPKG += esp32_sdk_mbedtls
|
||||
USEPKG += esp32_sdk_lib_coexist
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter periph_adc,$(USEMODULE)))
|
||||
|
||||
@ -45,17 +45,19 @@ ifneq (esp32h2,$(CPU_FAM))
|
||||
FEATURES_PROVIDED += esp_wifi_enterprise
|
||||
endif
|
||||
|
||||
ifeq (esp32,$(CPU_FAM))
|
||||
ifneq (,$(filter esp32 esp32c3 esp32h2 esp32s3,$(CPU_FAM)))
|
||||
FEATURES_PROVIDED += ble_nimble
|
||||
FEATURES_PROVIDED += ble_nimble_netif
|
||||
FEATURES_PROVIDED += esp_ble
|
||||
endif
|
||||
|
||||
ifeq (esp32,$(CPU_FAM))
|
||||
FEATURES_PROVIDED += esp_ble_esp32
|
||||
else ifeq (esp32h2,$(CPU_FAM))
|
||||
FEATURES_PROVIDED += esp_ble_esp32h2
|
||||
else ifneq (,$(filter esp32c3 esp32s3,$(CPU_FAM)))
|
||||
FEATURES_PROVIDED += ble_adv_ext
|
||||
FEATURES_PROVIDED += ble_nimble
|
||||
FEATURES_PROVIDED += ble_nimble_netif
|
||||
FEATURES_PROVIDED += ble_phy_2mbit
|
||||
FEATURES_PROVIDED += esp_ble
|
||||
FEATURES_PROVIDED += esp_ble_esp32c3
|
||||
endif
|
||||
|
||||
|
||||
@ -184,6 +184,9 @@ ifneq (,$(filter esp_ble,$(USEMODULE)))
|
||||
INCLUDES += -I$(ESP32_SDK_DIR)/components/bt/include/esp32c3/include
|
||||
endif
|
||||
ifeq (esp32h2,$(CPU_FAM))
|
||||
CFLAGS += -Ddefault_RNG_defined=0
|
||||
CFLAGS += -DNIMBLE_OS_MSYS_INIT_IN_CONTROLLER=1
|
||||
CFLAGS += -DNIMBLE_G_MSYS_POOL_LIST_IN_CONTROLLER=1
|
||||
INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_hw_support/port/$(CPU_FAM)/private_include
|
||||
endif
|
||||
endif
|
||||
@ -211,6 +214,7 @@ endif
|
||||
|
||||
ifneq (,$(filter esp_idf_nvs_flash,$(USEMODULE)))
|
||||
INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_partition/include
|
||||
INCLUDES += -I$(ESP32_SDK_DIR)/components/nvs_flash/include
|
||||
CFLAGS += -DMBEDTLS_CIPHER_MODE_XTS
|
||||
endif
|
||||
|
||||
@ -401,12 +405,18 @@ endif
|
||||
# Libraries needed when using esp_ble
|
||||
ifneq (,$(filter esp_ble,$(USEMODULE)))
|
||||
LINKFLAGS += -L$(ESP32_SDK_LIB_PHY_DIR)/$(CPU_FAM)
|
||||
LINKFLAGS += -L$(ESP32_SDK_LIB_BT_DIR)/$(CPU_FAM)
|
||||
ARCHIVES += -lbtdm_app
|
||||
ARCHIVES += -lphy -lstdc++
|
||||
ifneq (,$(filter esp32 esp32c3 esp32s3,$(CPU_FAM)))
|
||||
LINKFLAGS += -L$(ESP32_SDK_LIB_BT_DIR)/$(CPU_FAM)
|
||||
ARCHIVES += -lbtdm_app
|
||||
else ifeq (esp32h2,$(CPU_FAM))
|
||||
LINKFLAGS += -L$(ESP32_SDK_LIB_COEXIST_DIR)/$(CPU_FAM)
|
||||
LINKFLAGS += -L$(ESP32_SDK_LIB_BT_DIR)
|
||||
ARCHIVES += -lble_app -lcoexist
|
||||
endif
|
||||
ifeq (esp32,$(CPU_FAM))
|
||||
ARCHIVES += -lrtc
|
||||
else ifneq (,$(filter esp32c3 esp32s3,$(CPU_FAM)))
|
||||
else ifneq (,$(filter esp32c3 esp32h2 esp32s3,$(CPU_FAM)))
|
||||
ARCHIVES += -lbtbb
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -22,14 +22,16 @@
|
||||
#include "log.h"
|
||||
#include "esp_bt.h"
|
||||
#include "mutex.h"
|
||||
#include "nimble_riot.h"
|
||||
#include "od.h"
|
||||
|
||||
#include "host/ble_hs.h"
|
||||
#include "nimble/hci_common.h"
|
||||
#include "nimble/nimble_port.h"
|
||||
#include "nimble/transport/hci_h4.h"
|
||||
#include "sysinit/sysinit.h"
|
||||
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
@ -45,6 +47,23 @@
|
||||
|
||||
#define BLE_VHCI_TIMEOUT_MS 2000
|
||||
|
||||
#if CPU_FAM_ESP32 || CPU_FAM_ESP32S3 || CPU_FAM_ESP32C3
|
||||
/* On ESP32, ESP32-S3 and ESP32-C3, the BT Controller calls the
|
||||
* notify_host_send_available callback function when it becomes ready to
|
||||
* receive commands from the host. It can be used to unlock a mutex that
|
||||
* is used to synchronize the access to the BT Controller by different
|
||||
* threads. */
|
||||
# define BT_CTRL_SUPPORTS_READY_CB 1
|
||||
#elif CPU_FAM_ESP32C2 || CPU_FAM_ESP32C6 || CPU_FAM_ESP32H2
|
||||
/* On other ESP32x variants like ESP32-C2, ESP32-C6 and ESP32-H2,
|
||||
* this callback function is not used and we have to use another mechanism. */
|
||||
# define BT_CTRL_SUPPORTS_READY_CB 0
|
||||
# define BT_CTRL_WAIT_READY_CYCLES 10
|
||||
# define BT_CTRL_WAIT_READY_INTERVALL_MS 10
|
||||
#else
|
||||
# error "Platform implementation is missing"
|
||||
#endif
|
||||
|
||||
/* Definition of UART H4 packet types */
|
||||
enum {
|
||||
BLE_HCI_UART_H4_NONE = 0x00,
|
||||
@ -56,19 +75,30 @@ enum {
|
||||
|
||||
static const char *LOG_TAG = "esp_nimble";
|
||||
|
||||
#if BT_CTRL_SUPPORTS_READY_CB
|
||||
static mutex_t _esp_vhci_semaphore = MUTEX_INIT;
|
||||
#endif
|
||||
|
||||
static struct hci_h4_sm _esp_h4sm;
|
||||
|
||||
static void _ble_vhci_controller_ready_cb(void)
|
||||
{
|
||||
DEBUG("%s\n", __func__);
|
||||
|
||||
#if BT_CTRL_SUPPORTS_READY_CB
|
||||
mutex_unlock(&_esp_vhci_semaphore);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int _ble_vhci_packet_received_cb(uint8_t *data, uint16_t len)
|
||||
{
|
||||
DEBUG("%s: data=%p len=%u\n", __func__, data, len);
|
||||
|
||||
/* process the HCI H4 formatted packet and call ble_transport_to_hs_* */
|
||||
len = hci_h4_sm_rx(&_esp_h4sm, data, len);
|
||||
if (nimble_port_initialized) {
|
||||
len = hci_h4_sm_rx(&_esp_h4sm, data, len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -81,6 +111,9 @@ static inline int _ble_transport_to_ll(uint8_t *packet, uint16_t len)
|
||||
{
|
||||
uint8_t rc = 0;
|
||||
|
||||
DEBUG("%s: controller status=%d\n", __func__, esp_bt_controller_get_status());
|
||||
|
||||
#if BT_CTRL_SUPPORTS_READY_CB
|
||||
/* check whether the controller is ready to accept packets */
|
||||
if (!esp_vhci_host_check_send_available()) {
|
||||
LOG_TAG_DEBUG(LOG_TAG, "Controller not ready to accept packets");
|
||||
@ -94,6 +127,23 @@ static inline int _ble_transport_to_ll(uint8_t *packet, uint16_t len)
|
||||
else {
|
||||
rc = BLE_HS_ETIMEOUT_HCI;
|
||||
}
|
||||
#else
|
||||
unsigned i = 0;
|
||||
for (; i < BT_CTRL_WAIT_READY_CYCLES; i++) {
|
||||
if (esp_vhci_host_check_send_available()) {
|
||||
break;
|
||||
}
|
||||
ztimer_sleep(ZTIMER_MSEC, BT_CTRL_WAIT_READY_INTERVALL_MS);
|
||||
}
|
||||
if (i < BT_CTRL_WAIT_READY_CYCLES) {
|
||||
esp_vhci_host_send_packet(packet, len);
|
||||
}
|
||||
else {
|
||||
LOG_TAG_DEBUG(LOG_TAG, "Controller not ready to accept packets");
|
||||
rc = BLE_HS_ETIMEOUT_HCI;
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -113,8 +163,8 @@ int ble_transport_to_ll_cmd_impl(void *buf)
|
||||
packet[0] = BLE_HCI_UART_H4_CMD; /* first byte is the packet indicator */
|
||||
memcpy(packet + 1, cmd, len - 1);
|
||||
|
||||
DEBUG("%s: CMD host to ctrl\n", __func__);
|
||||
if (ENABLE_DEBUG && IS_USED(MODULE_OD)) {
|
||||
printf("CMD host to ctrl:\n");
|
||||
od_hex_dump(packet + 1, len - 1, OD_WIDTH_DEFAULT);
|
||||
}
|
||||
|
||||
@ -147,8 +197,8 @@ int ble_transport_to_ll_acl_impl(struct os_mbuf *om)
|
||||
packet[0] = BLE_HCI_UART_H4_ACL;
|
||||
len++;
|
||||
|
||||
DEBUG("%s: ACL host to ctrl\n", __func__);
|
||||
if (ENABLE_DEBUG && IS_USED(MODULE_OD)) {
|
||||
printf("ACL host to ctrl:\n");
|
||||
od_hex_dump(packet + 1,
|
||||
(om->om_len < 32) ? om->om_len : 32, OD_WIDTH_DEFAULT);
|
||||
}
|
||||
@ -169,17 +219,19 @@ static int _esp_hci_h4_frame_cb(uint8_t pkt_type, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
DEBUG("%s: pkt_type=%d data=%p\n", __func__, pkt_type, data);
|
||||
|
||||
switch (pkt_type) {
|
||||
case HCI_H4_ACL:
|
||||
DEBUG("%s: ACL ctrl to host\n", __func__);
|
||||
if (ENABLE_DEBUG && IS_USED(MODULE_OD)) {
|
||||
printf("ACL ctrl to host:\n");
|
||||
od_hex_dump((uint8_t *)data, 4, OD_WIDTH_DEFAULT);
|
||||
}
|
||||
rc = ble_transport_to_hs_acl(data);
|
||||
break;
|
||||
case HCI_H4_EVT:
|
||||
DEBUG("%s: EVT ctrl to host\n", __func__);
|
||||
if (ENABLE_DEBUG && IS_USED(MODULE_OD)) {
|
||||
printf("EVT ctrl to host:\n");
|
||||
od_hex_dump((uint8_t *)data, ((uint8_t *)data)[1] + 2, OD_WIDTH_DEFAULT);
|
||||
}
|
||||
rc = ble_transport_to_hs_evt(data);
|
||||
@ -197,6 +249,12 @@ void esp_ble_nimble_init(void)
|
||||
esp_err_t ret;
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
|
||||
if (IS_ACTIVE(CONFIG_ESP_WIFI_NVS_ENABLED) && !IS_USED(MODULE_ESP_WIFI_ANY)) {
|
||||
if (nvs_flash_init() != ESP_OK) {
|
||||
LOG_ERROR("nfs_flash_init failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: BLE mode only used, the memory for BT Classic could be released
|
||||
if ((ret = esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);) != ESP_OK) {
|
||||
LOG_TAG_ERROR(LOG_TAG,
|
||||
@ -206,17 +264,23 @@ void esp_ble_nimble_init(void)
|
||||
}
|
||||
*/
|
||||
|
||||
DEBUG("%s: ctrl status=%d\n", __func__, esp_bt_controller_get_status());
|
||||
|
||||
/* init and enable the Bluetooth LE controller */
|
||||
if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) {
|
||||
LOG_TAG_ERROR(LOG_TAG, "Bluetooth controller initialize failed: %d", ret);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
DEBUG("%s: ctrl status=%d\n", __func__, esp_bt_controller_get_status());
|
||||
|
||||
if ((ret = esp_bt_controller_enable(ESP_BT_MODE_BLE)) != ESP_OK) {
|
||||
LOG_TAG_ERROR(LOG_TAG, "Bluetooth controller enable failed: %d", ret);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
DEBUG("%s: ctrl status=%d\n", __func__, esp_bt_controller_get_status());
|
||||
|
||||
/* register callbacks from Bluetooth LE controller */
|
||||
if ((ret = esp_vhci_host_register_callback(&vhci_host_cb)) != ESP_OK) {
|
||||
assert(0);
|
||||
|
||||
@ -49,6 +49,7 @@ extern "C" {
|
||||
#endif
|
||||
#define CPU_INUM_GPIO 2 /**< Level interrupt with low priority 1 */
|
||||
#define CPU_INUM_BLE 5 /**< Level interrupt with low priority 1 */
|
||||
#define CPU_INUM_BT_MAC 8 /**< Level interrupt with low priority 1 */
|
||||
#define CPU_INUM_RTT 9 /**< Level interrupt with low priority 1 */
|
||||
#define CPU_INUM_SERIAL_JTAG 10 /**< Edge interrupt with low priority 1 */
|
||||
#define CPU_INUM_I2C 12 /**< Level interrupt with low priority 1 */
|
||||
|
||||
@ -45,7 +45,7 @@ typedef struct intr_handle_data_t {
|
||||
uint8_t level;
|
||||
} intr_handle_data_t;
|
||||
|
||||
/* TODO change to a clearer approach */
|
||||
/* TODO change to a clearer and more dynamic approach */
|
||||
static const struct intr_handle_data_t _irq_data_table[] = {
|
||||
#ifndef __XTENSA__
|
||||
{ ETS_FROM_CPU_INTR0_SOURCE, CPU_INUM_SOFTWARE, 1 },
|
||||
@ -81,8 +81,10 @@ static const struct intr_handle_data_t _irq_data_table[] = {
|
||||
#endif
|
||||
#if defined(SOC_BLE_SUPPORTED)
|
||||
# if defined(CPU_FAM_ESP32) || defined(CPU_FAM_ESP32S3) || defined(CPU_FAM_ESP32C3)
|
||||
{ ETS_RWBLE_INTR_SOURCE, CPU_INUM_BLE, 2 },
|
||||
{ ETS_RWBLE_INTR_SOURCE, CPU_INUM_BLE, 1 },
|
||||
# elif defined(CPU_FAM_ESP32H2)
|
||||
{ ETS_LP_BLE_TIMER_INTR_SOURCE, CPU_INUM_BLE, 1 },
|
||||
{ ETS_BT_MAC_INTR_SOURCE, CPU_INUM_BT_MAC, 1 },
|
||||
# else
|
||||
# error "Platform implementation is missing"
|
||||
# endif
|
||||
@ -193,12 +195,22 @@ esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler,
|
||||
#ifdef SOC_CPU_HAS_FLEXIBLE_INTC
|
||||
/* set interrupt level given by flags */
|
||||
esp_cpu_intr_set_priority(_irq_data_table[i].intr, esp_intr_flags_to_level(flags));
|
||||
esp_cpu_intr_set_type(_irq_data_table[i].intr,
|
||||
flags & ESP_INTR_FLAG_EDGE ? ESP_CPU_INTR_TYPE_EDGE
|
||||
: ESP_CPU_INTR_TYPE_LEVEL);
|
||||
#endif
|
||||
|
||||
#if SOC_INT_PLIC_SUPPORTED
|
||||
RV_CLEAR_CSR(mideleg, BIT(_irq_data_table[i].intr));
|
||||
#endif
|
||||
|
||||
/* enable the interrupt if ESP_INTR_FLAG_INTRDISABLED is not set */
|
||||
if ((flags & ESP_INTR_FLAG_INTRDISABLED) == 0) {
|
||||
esp_cpu_intr_enable(BIT(_irq_data_table[i].intr));
|
||||
}
|
||||
else {
|
||||
esp_cpu_intr_disable(BIT(_irq_data_table[i].intr));
|
||||
}
|
||||
|
||||
if (ret_handle) {
|
||||
*((intr_handle_t *)ret_handle) = (const intr_handle_t)&_irq_data_table[i];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user