driver: esp32: add bluetooth support

Add support to BLE and BR/EDR feature.

Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
This commit is contained in:
Sylvio Alves 2021-04-01 00:51:49 -03:00 committed by Anas Nashif
commit a3c35c93ff
8 changed files with 389 additions and 6 deletions

View file

@ -16,3 +16,20 @@ config LOG_DETECT_MISSED_STRDUP
default n default n
endif endif
if BT
config HEAP_MEM_POOL_SIZE
default 16384
config ENTROPY_GENERATOR
default y
config DYNAMIC_INTERRUPTS
default y
choice BT_HCI_BUS_TYPE
default BT_ESP32
endchoice
endif # BT

View file

@ -7,3 +7,4 @@ zephyr_sources_ifdef(CONFIG_BT_RPMSG rpmsg.c)
zephyr_sources_ifdef(CONFIG_BT_RPMSG_NRF53 rpmsg_nrf53.c) zephyr_sources_ifdef(CONFIG_BT_RPMSG_NRF53 rpmsg_nrf53.c)
zephyr_sources_ifdef(CONFIG_BT_STM32_IPM ipm_stm32wb.c) zephyr_sources_ifdef(CONFIG_BT_STM32_IPM ipm_stm32wb.c)
zephyr_sources_ifdef(CONFIG_BT_USERCHAN userchan.c) zephyr_sources_ifdef(CONFIG_BT_USERCHAN userchan.c)
zephyr_sources_ifdef(CONFIG_BT_ESP32 hci_esp32.c)

View file

@ -63,6 +63,11 @@ config BT_USERCHAN
The Bluetooth adapter must be powered off in order for Zephyr to The Bluetooth adapter must be powered off in order for Zephyr to
be able to use it. be able to use it.
config BT_ESP32
bool "ESP32 HCI driver"
help
Espressif HCI bluetooth interface
config BT_NO_DRIVER config BT_NO_DRIVER
bool "No default HCI driver" bool "No default HCI driver"
help help
@ -128,7 +133,7 @@ endif # BT_RPMSG_NRF53
config BT_DRIVER_QUIRK_NO_AUTO_DLE config BT_DRIVER_QUIRK_NO_AUTO_DLE
bool "Host auto-initiated Data Length Update quirk" bool "Host auto-initiated Data Length Update quirk"
depends on BT_AUTO_DATA_LEN_UPDATE depends on BT_AUTO_DATA_LEN_UPDATE
default y if BT_RPMSG_NRF53 default y if BT_RPMSG_NRF53 || BT_ESP32
help help
Enable the quirk wherein BT Host stack will auto-initiate Data Length Enable the quirk wherein BT Host stack will auto-initiate Data Length
Update procedure for new connections for controllers that do not Update procedure for new connections for controllers that do not

View file

@ -0,0 +1,313 @@
/*
* Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#define LOG_MODULE_NAME bt_hci_driver_esp32
#include "common/log.h"
#include <init.h>
#include <sys/byteorder.h>
#include <drivers/bluetooth/hci_driver.h>
#include <esp_bt.h>
#define HCI_CMD 0x01
#define HCI_ACL 0x02
#define HCI_SCO 0x03
#define HCI_EVT 0x04
#define HCI_ISO 0x05
#define HCI_BT_ESP32_TIMEOUT K_MSEC(2000)
static K_SEM_DEFINE(hci_send_sem, 1, 1);
static bool is_hci_event_discardable(const uint8_t *evt_data)
{
uint8_t evt_type = evt_data[0];
switch (evt_type) {
#if defined(CONFIG_BT_BREDR)
case BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI:
case BT_HCI_EVT_EXTENDED_INQUIRY_RESULT:
return true;
#endif
case BT_HCI_EVT_LE_META_EVENT: {
uint8_t subevt_type = evt_data[sizeof(struct bt_hci_evt_hdr)];
switch (subevt_type) {
case BT_HCI_EVT_LE_ADVERTISING_REPORT:
return true;
case BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT:
return true;
default:
return false;
}
}
default:
return false;
}
}
static struct net_buf *bt_esp_evt_recv(uint8_t *data, size_t remaining)
{
bool discardable = false;
struct bt_hci_evt_hdr hdr;
struct net_buf *buf;
if (remaining < sizeof(hdr)) {
BT_ERR("Not enough data for event header");
return NULL;
}
discardable = is_hci_event_discardable(data);
memcpy((void *)&hdr, data, sizeof(hdr));
data += sizeof(hdr);
remaining -= sizeof(hdr);
if (remaining != hdr.len) {
BT_ERR("Event payload length is not correct");
return NULL;
}
BT_DBG("len %u", hdr.len);
buf = bt_buf_get_evt(hdr.evt, discardable, K_NO_WAIT);
if (!buf) {
if (discardable) {
BT_DBG("Discardable buffer pool full, ignoring event");
} else {
BT_ERR("No available event buffers!");
}
return buf;
}
net_buf_add_mem(buf, &hdr, sizeof(hdr));
net_buf_add_mem(buf, data, remaining);
return buf;
}
static struct net_buf *bt_esp_acl_recv(uint8_t *data, size_t remaining)
{
struct bt_hci_acl_hdr hdr;
struct net_buf *buf;
if (remaining < sizeof(hdr)) {
BT_ERR("Not enough data for ACL header");
return NULL;
}
buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_NO_WAIT);
if (buf) {
memcpy((void *)&hdr, data, sizeof(hdr));
data += sizeof(hdr);
remaining -= sizeof(hdr);
net_buf_add_mem(buf, &hdr, sizeof(hdr));
} else {
BT_ERR("No available ACL buffers!");
return NULL;
}
if (remaining != sys_le16_to_cpu(hdr.len)) {
BT_ERR("ACL payload length is not correct");
net_buf_unref(buf);
return NULL;
}
BT_DBG("len %u", remaining);
net_buf_add_mem(buf, data, remaining);
return buf;
}
static struct net_buf *bt_esp_iso_recv(uint8_t *data, size_t remaining)
{
struct bt_hci_iso_hdr hdr;
struct net_buf *buf;
if (remaining < sizeof(hdr)) {
BT_ERR("Not enough data for ISO header");
return NULL;
}
buf = bt_buf_get_rx(BT_BUF_ISO_IN, K_NO_WAIT);
if (buf) {
memcpy((void *)&hdr, data, sizeof(hdr));
data += sizeof(hdr);
remaining -= sizeof(hdr);
net_buf_add_mem(buf, &hdr, sizeof(hdr));
} else {
BT_ERR("No available ISO buffers!");
return NULL;
}
if (remaining != sys_le16_to_cpu(hdr.len)) {
BT_ERR("ISO payload length is not correct");
net_buf_unref(buf);
return NULL;
}
BT_DBG("len %zu", remaining);
net_buf_add_mem(buf, data, remaining);
return buf;
}
static int hci_esp_host_rcv_pkt(uint8_t *data, uint16_t len)
{
uint8_t pkt_indicator;
struct net_buf *buf = NULL;
size_t remaining = len;
BT_HEXDUMP_DBG(data, len, "host packet data:");
pkt_indicator = *data++;
remaining -= sizeof(pkt_indicator);
switch (pkt_indicator) {
case HCI_EVT:
buf = bt_esp_evt_recv(data, remaining);
break;
case HCI_ACL:
buf = bt_esp_acl_recv(data, remaining);
break;
case HCI_SCO:
buf = bt_esp_iso_recv(data, remaining);
break;
default:
BT_ERR("Unknown HCI type %u", pkt_indicator);
return -1;
}
if (buf) {
BT_DBG("Calling bt_recv(%p)", buf);
bt_recv(buf);
}
return 0;
}
static void hci_esp_controller_rcv_pkt_ready(void)
{
k_sem_give(&hci_send_sem);
}
static esp_vhci_host_callback_t vhci_host_cb = {
hci_esp_controller_rcv_pkt_ready,
hci_esp_host_rcv_pkt
};
static int bt_esp32_send(struct net_buf *buf)
{
int err = 0;
uint8_t pkt_indicator;
BT_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len);
switch (bt_buf_get_type(buf)) {
case BT_BUF_ACL_OUT:
pkt_indicator = HCI_ACL;
break;
case BT_BUF_CMD:
pkt_indicator = HCI_CMD;
break;
case BT_BUF_ISO_OUT:
pkt_indicator = HCI_ISO;
break;
default:
BT_ERR("Unknown type %u", bt_buf_get_type(buf));
goto done;
}
net_buf_push_u8(buf, pkt_indicator);
BT_HEXDUMP_DBG(buf->data, buf->len, "Final HCI buffer:");
if (!esp_vhci_host_check_send_available()) {
BT_WARN("Controller not ready to receive packets");
}
if (k_sem_take(&hci_send_sem, HCI_BT_ESP32_TIMEOUT) == 0) {
esp_vhci_host_send_packet(buf->data, buf->len);
} else {
BT_ERR("Send packet timeout error");
err = -ETIMEDOUT;
}
done:
net_buf_unref(buf);
k_sem_give(&hci_send_sem);
return err;
}
static int bt_esp32_ble_init(void)
{
int ret;
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
#ifdef CONFIG_BT_BREDR
esp_bt_mode_t mode = ESP_BT_MODE_BTDM;
#else
esp_bt_mode_t mode = ESP_BT_MODE_BLE;
#endif
ret = esp_bt_controller_init(&bt_cfg);
if (ret) {
BT_ERR("Bluetooth controller init failed %d", ret);
return ret;
}
ret = esp_bt_controller_enable(mode);
if (ret) {
BT_ERR("Bluetooth controller enable failed: %d", ret);
return ret;
}
esp_vhci_host_register_callback(&vhci_host_cb);
return 0;
}
static int bt_esp32_open(void)
{
int err;
err = bt_esp32_ble_init();
if (err) {
return err;
}
BT_DBG("ESP32 BT started");
return 0;
}
static const struct bt_hci_driver drv = {
.name = "BT ESP32",
.open = bt_esp32_open,
.send = bt_esp32_send,
.bus = BT_HCI_DRIVER_BUS_IPM,
#if defined(CONFIG_BT_DRIVER_QUIRK_NO_AUTO_DLE)
.quirks = BT_QUIRK_NO_AUTO_DLE,
#endif
};
static int bt_esp32_init(const struct device *unused)
{
ARG_UNUSED(unused);
bt_hci_driver_register(&drv);
return 0;
}
SYS_INIT(bt_esp32_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

View file

@ -7,12 +7,19 @@ config SOC_ESP32
select CLOCK_CONTROL select CLOCK_CONTROL
select CLOCK_CONTROL_ESP32 select CLOCK_CONTROL_ESP32
if SOC_ESP32
config IDF_TARGET_ESP32 config IDF_TARGET_ESP32
bool "ESP32 as target board" bool "ESP32 as target board"
default y default y
depends on SOC_ESP32
config ESPTOOLPY_FLASHFREQ_80M config ESPTOOLPY_FLASHFREQ_80M
bool bool
default y default y
depends on SOC_ESP32
config ESP32_BT_RESERVE_DRAM
hex "Bluetooth controller reserved RAM region"
default 0xdb5c if BT
default 0
endif # SOC_ESP32

View file

@ -39,9 +39,8 @@ MEMORY
* *
* FIXME: * FIXME:
* - Utilize available memory regions to full capacity * - Utilize available memory regions to full capacity
* - Reserve memory region for BT controller library from ROM
*/ */
dram0_0_seg(RW): org = 0x3FFB0000, len = 0x30000 dram0_0_seg(RW): org = 0x3FFB0000 + CONFIG_ESP32_BT_RESERVE_DRAM, len = 0x2c200 - CONFIG_ESP32_BT_RESERVE_DRAM
dram0_1_seg(RW): org = 0x3FFE4350, len = 0x1BCB0 dram0_1_seg(RW): org = 0x3FFE4350, len = 0x1BCB0
drom0_0_seg(R): org = 0x3F400020, len = 0x400000-0x20 drom0_0_seg(R): org = 0x3F400020, len = 0x400000-0x20
rtc_iram_seg(RWX): org = 0x400C0000, len = 0x2000 rtc_iram_seg(RWX): org = 0x400C0000, len = 0x2000
@ -206,6 +205,12 @@ _net_buf_pool_list = _esp_net_buf_pool_list;
.dram0.data : .dram0.data :
{ {
_data_start = ABSOLUTE(.); _data_start = ABSOLUTE(.);
_btdm_data_start = ABSOLUTE(.);
*libbtdm_app.a:(.data .data.*)
. = ALIGN (4);
_btdm_data_end = ABSOLUTE(.);
*(.data) *(.data)
*(.data.*) *(.data.*)
*(.gnu.linkonce.d.*) *(.gnu.linkonce.d.*)
@ -260,6 +265,26 @@ _net_buf_pool_list = _esp_net_buf_pool_list;
. = ALIGN(4); . = ALIGN(4);
#endif #endif
#if defined(CONFIG_BT_BREDR)
. = ALIGN(4);
Z_LINK_ITERABLE(bt_l2cap_br_fixed_chan);
. = ALIGN(4);
#endif
#if defined(CONFIG_BT_MESH)
Z_LINK_ITERABLE(bt_mesh_subnet_cb);
Z_LINK_ITERABLE(bt_mesh_app_key_cb);
Z_LINK_ITERABLE(bt_mesh_hb_cb);
#endif
. = ALIGN(4);
Z_LINK_ITERABLE(bt_gatt_service_static);
. = ALIGN(4);
. = ALIGN(4);
Z_LINK_ITERABLE(bt_l2cap_fixed_chan);
. = ALIGN(4);
. = ALIGN(4); . = ALIGN(4);
Z_LINK_ITERABLE(shell); Z_LINK_ITERABLE(shell);
. = ALIGN(4); . = ALIGN(4);
@ -363,6 +388,8 @@ __shell_root_cmds_end = __esp_shell_root_cmds_end;
#endif #endif
_iram_text_end = ABSOLUTE(.); _iram_text_end = ABSOLUTE(.);
. = ALIGN(4);
_iram_end = ABSOLUTE(.);
} GROUP_LINK_IN(IRAM_REGION) } GROUP_LINK_IN(IRAM_REGION)
.flash.text : .flash.text :
@ -396,6 +423,12 @@ __shell_root_cmds_end = __esp_shell_root_cmds_end;
{ {
. = ALIGN (8); . = ALIGN (8);
_bss_start = ABSOLUTE(.); _bss_start = ABSOLUTE(.);
_btdm_bss_start = ABSOLUTE(.);
*libbtdm_app.a:(.bss .bss.* COMMON)
. = ALIGN (4);
_btdm_bss_end = ABSOLUTE(.);
*(.dynsbss) *(.dynsbss)
*(.sbss) *(.sbss)
*(.sbss.*) *(.sbss.*)
@ -414,6 +447,9 @@ __shell_root_cmds_end = __esp_shell_root_cmds_end;
_bss_end = ABSOLUTE(.); _bss_end = ABSOLUTE(.);
} GROUP_LINK_IN(RAMABLE_REGION) } GROUP_LINK_IN(RAMABLE_REGION)
ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
"DRAM segment data does not fit.")
SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),) SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),)
{ {
. = ALIGN (8); . = ALIGN (8);
@ -435,3 +471,6 @@ __shell_root_cmds_end = __esp_shell_root_cmds_end;
} }
} }
ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
"IRAM0 segment data does not fit.")

View file

@ -190,7 +190,7 @@ if BT_CONN
config BT_HCI_ACL_FLOW_CONTROL config BT_HCI_ACL_FLOW_CONTROL
bool "Controller to Host ACL flow control support" bool "Controller to Host ACL flow control support"
# Enable if building a Host-only build # Enable if building a Host-only build
default y if !BT_CTLR && !BT_STM32_IPM default y if !BT_CTLR && !BT_STM32_IPM && !BT_ESP32
# Enable if building a Controller-only build # Enable if building a Controller-only build
default y if BT_HCI_RAW default y if BT_HCI_RAW
select POLL select POLL

View file

@ -119,6 +119,7 @@ config BT_HCI_RESERVE
default 1 if BT_SPI default 1 if BT_SPI
default 1 if BT_STM32_IPM default 1 if BT_STM32_IPM
default 1 if BT_USERCHAN default 1 if BT_USERCHAN
default 1 if BT_ESP32
# Even if no driver is selected the following default is still # Even if no driver is selected the following default is still
# needed e.g. for unit tests. # needed e.g. for unit tests.
default 0 default 0