1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

cpu/esp32: add NimBLE support for ESP32

This commit is contained in:
Gunar Schorcht 2022-08-11 12:46:41 +02:00
parent abccc41db7
commit 56e59eb036
14 changed files with 332 additions and 2 deletions

View File

@ -31,6 +31,7 @@ config MODULE_ESP_SPI_RAM
Say y to use external SPI RAM connected through the SPI interface.
rsource "bootloader/Kconfig"
rsource "esp-ble-nimble/Kconfig"
rsource "esp-idf/Kconfig"
rsource "esp-idf-api/Kconfig"
rsource "periph/Kconfig"

View File

@ -18,6 +18,8 @@ config CPU_FAM_ESP32
select CPU_CORE_XTENSA_LX6
select HAS_ARCH_ESP32
select HAS_CPU_ESP32
select HAS_BLE_NIMBLE
select HAS_BLE_NIMBLE_NETIF
select HAS_ESP_BLE
select HAS_ESP_BLE_ESP32
select HAS_ESP_HW_COUNTER

View File

@ -13,6 +13,10 @@ ifneq (, $(filter esp_bootloader, $(USEMODULE)))
DIRS += bootloader
endif
ifneq (, $(filter esp_ble_nimble, $(USEMODULE)))
DIRS += esp-ble-nimble
endif
ifneq (, $(filter esp_eth, $(USEMODULE)))
DIRS += esp-eth
endif

View File

@ -131,6 +131,14 @@ ifneq (,$(filter mtd,$(USEMODULE)))
USEMODULE += esp_idf_spi_flash
endif
ifneq (,$(filter nimble,$(USEPKG)))
USEMODULE += esp_ble
USEMODULE += esp_ble_nimble
USEMODULE += nimble_host
USEMODULE += nimble_transport_hci_h4
USEMODULE += ztimer_msec
endif
ifneq (,$(filter periph_adc,$(USEMODULE)))
USEMODULE += esp_idf_adc
endif

View File

@ -25,6 +25,7 @@ endif
ifeq (esp32,$(CPU_FAM))
FEATURES_PROVIDED += ble_nimble
FEATURES_PROVIDED += ble_nimble_netif
FEATURES_PROVIDED += esp_ble
FEATURES_PROVIDED += esp_ble_esp32
endif

View File

@ -86,6 +86,7 @@ ifneq (,$(filter esp_ble,$(USEMODULE)))
endif
ifneq (,$(filter esp_ble_nimble,$(USEMODULE)))
INCLUDES += -I$(RIOTCPU)/$(CPU)/include/esp_ble_nimble
INCLUDES += $(NIMIBASE)/nimble/transport/common/hci_h4/include
endif

View File

@ -55,6 +55,7 @@ This document describes the RIOT implementation for supported variants
2. [WiFi Network Interface](#esp32_wifi_network_interface)
3. [WiFi SoftAP Network Interface](#esp32_wifi_ap_network_interface)
4. [ESP-NOW Network Interface](#esp32_esp_now_network_interface)
4. [Bluetooth Interface](#esp32_esp_bluetooth_interface)
5. [Other Network Devices](#esp32_other_network_devices)
10. [Application-Specific Configurations](#esp32_application_specific_configurations)
1. [Make Variable `CFLAGS`](#esp32_config_make_variable)
@ -204,7 +205,7 @@ The key features of ESP32 are:
| SPIs | 4 | yes (2) |
| UARTs | 3 | yes |
| WiFi | IEEE 802.11 b/g/n built in | yes |
| Bluetooth | v4.2 BR/EDR and BLE | no |
| Bluetooth | v4.2 BR/EDR and BLE | yes |
| Ethernet | MAC interface with dedicated DMA and IEEE 1588 support | yes |
| CAN | version 2.0 | yes |
| IR | up to 8 channels TX/RX | no |
@ -335,7 +336,6 @@ at the moment:
- Only **one core** (the PRO CPU) is used because RIOT does not support running
multiple threads simultaneously.
- **Bluetooth** cannot be used at the moment.
- **Flash encryption** is not yet supported.
[Back to table of contents](#esp32_toc)
@ -1691,6 +1691,21 @@ the channel of the AP asvalue for the parameter 'ESP_NOW_CHANNEL'.
[Back to table of contents](#esp32_toc)
## Bluetooth Network Interface {#esp32_esp_bluetooth_interface}
The following ESP32x SoC variants (families) integrate a Bluetooth Link
Controller and a Bluetooth baseband system:
- ESP32 supports Bluetooth v4.2 BR/EDR and Bluetooth LE
- ESP32-C3, ESP32-S3 support Bluetooth 5 and Bluetooth mesh
The Bluetooth interface can be used with the Bluetooth host implementation
of the NimBLE package. Use one of the `nimble_*` modules for different
applications to enable the Bluetooth interface and the NimBLE host
implementation. Please refer to the NimBle package documentation for details.
[Back to table of contents](#esp32_toc)
## Other Network Devices {#esp32_other_network_devices}
RIOT provides a number of driver modules for different types of network

View File

@ -0,0 +1,22 @@
# Copyright (c) 2022 HAW Hamburg
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
#
config MODULE_ESP_BLE_NIMBLE
bool "ESP32 Bluetooth LE HCI for NimBLE host"
depends on TEST_KCONFIG
depends on CPU_FAM_ESP32
depends on HAS_ESP_BLE
default y if TEST_KCONFIG && MODULE_NIMBLE
select MODULE_ESP_BLE
select MODULE_NIMBLE_HOST
select MODULE_NIMBLE_TRANSPORT_HCI_H4
select MODULE_ZTIMER_MSEC
config HAS_ESP_BLE
bool
help
Indicates that a ESP32 Buetooth LE controller.

View File

@ -0,0 +1,3 @@
MODULE=esp_ble_nimble
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,17 @@
/*
* Copyright (C) 2022 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup cpu_esp32_esp_ble_nimble ESP32 Bluetooth LE HCI for NimBLE host
* @ingroup cpu_esp32
* @brief ESP32 Bluetooth LE HCI implementation for NimBLE host
*
* This module realizes the HCI for NimBLE host using the ESP32 Bluetooth controller
*
* @author Gunar Schorcht <gunar@schorcht.net>
*/

View File

@ -0,0 +1,204 @@
/*
* Copyright (C) 2022 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp32_esp_ble_nimble
* @{
*
* @file
* @brief Implementation of the Bluetooth LE Host Controller Interface
*
* ESP32x SoC Bluetooth LE controller uses the uses UART H4 transport protocol.
*
* @author Gunar Schorcht <gunar@schorcht.net>
* @}
*/
#include "log.h"
#include "esp_bt.h"
#include "mutex.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"
/* The size of an HCI command packet is defined as POOL_CMD_SIZE
* in `./nimble/transport/src/transport.c.`. Since there is no defined
* symbol in the header files, we have to define it here. According to
* the BLE specification, controllers must accept HCI command packets
* with up to 255 bytes of data excluding the header. */
#define BLE_HCI_CMD_SIZE (255 + BLE_HCI_CMD_HDR_LEN)
#define BLE_HCI_CMD_HDR_LEN (3)
#define BLE_HCI_EVT_HDR_LEN (2)
#define BLE_VHCI_TIMEOUT_MS 2000
/* Definition of UART H4 packet types */
enum {
BLE_HCI_UART_H4_NONE = 0x00,
BLE_HCI_UART_H4_CMD = 0x01,
BLE_HCI_UART_H4_ACL = 0x02,
BLE_HCI_UART_H4_SCO = 0x03,
BLE_HCI_UART_H4_EVT = 0x04
};
static const char *LOG_TAG = "esp_nimble";
static mutex_t _esp_vhci_semaphore = MUTEX_INIT;
static struct hci_h4_sm _esp_h4sm;
static void _ble_vhci_controller_ready_cb(void)
{
mutex_unlock(&_esp_vhci_semaphore);
}
static int _ble_vhci_packet_received_cb(uint8_t *data, uint16_t len)
{
/* process the HCI H4 formatted packet and call ble_transport_to_hs_* */
len = hci_h4_sm_rx(&_esp_h4sm, data, len);
return 0;
}
static const esp_vhci_host_callback_t vhci_host_cb = {
.notify_host_send_available = _ble_vhci_controller_ready_cb,
.notify_host_recv = _ble_vhci_packet_received_cb,
};
static inline int _ble_transport_to_ll(uint8_t *packet, uint16_t len)
{
uint8_t rc = 0;
/* 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");
}
/* take the semaphore with timeout and send the packet to the controller */
if (ztimer_mutex_lock_timeout(ZTIMER_MSEC, &_esp_vhci_semaphore,
BLE_VHCI_TIMEOUT_MS) == 0) {
esp_vhci_host_send_packet(packet, len);
}
else {
rc = BLE_HS_ETIMEOUT_HCI;
}
return rc;
}
int ble_transport_to_ll_cmd_impl(void *buf)
{
uint16_t len;
uint8_t rc = 0;
uint8_t packet[BLE_HCI_CMD_SIZE + 1];
uint8_t* cmd = buf;
assert(cmd != NULL);
/* Prepare the HCI H4 formatted packet. HCI H4 uses one byte HCI packet
* indicator in front of the HCI command packet. */
len = BLE_HCI_CMD_HDR_LEN + cmd[2] + 1; /* overall length */
packet[0] = BLE_HCI_UART_H4_CMD; /* first byte is the packet indicator */
memcpy(packet + 1, cmd, len - 1);
/* send the packet */
rc = _ble_transport_to_ll(packet, len);
/* release the packet buffer */
ble_transport_free(buf);
return rc;
}
int ble_transport_to_ll_acl_impl(struct os_mbuf *om)
{
uint16_t len = 0;
uint8_t rc = 0;
uint8_t packet[MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE) + 1];
assert(om != NULL);
/* If this packet is zero length, just free it */
if (OS_MBUF_PKTLEN(om) == 0) {
os_mbuf_free_chain(om);
return 0;
}
/* Prepare the HCI H4 formatted packet. HCI H4 uses one byte HCI packet
indicator in front of the HCI command packet. */
packet[0] = BLE_HCI_UART_H4_ACL;
len++;
os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), &packet[1]);
len += OS_MBUF_PKTLEN(om);
/* send the packet */
rc = _ble_transport_to_ll(packet, len);
/* release the mbuf */
os_mbuf_free_chain(om);
return rc;
}
static int _esp_hci_h4_frame_cb(uint8_t pkt_type, void *data)
{
int rc = 0;
switch (pkt_type) {
case HCI_H4_ACL:
rc = ble_transport_to_hs_acl(data);
break;
case HCI_H4_EVT:
rc = ble_transport_to_hs_evt(data);
break;
default:
assert(0);
break;
}
return rc;
}
void esp_ble_nimble_init(void)
{
esp_err_t ret;
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
/* 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,
"Bluetooth controller release classic bt memory failed: %s",
esp_err_to_name(ret));
assert(0);
}
*/
/* 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);
}
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);
}
/* register callbacks from Bluetooth LE controller */
if ((ret = esp_vhci_host_register_callback(&vhci_host_cb)) != ESP_OK) {
assert(0);
}
/* init HCI H4 processing */
hci_h4_sm_init(&_esp_h4sm, &hci_h4_allocs_from_ll, _esp_hci_h4_frame_cb);
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2022 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp32_esp_ble_nimble
* @{
*
* @file
* @brief NimBLE configuration for ESP32x SoCs
*
* @author Gunar Schorcht <gunar@schorcht.net>
*/
#ifndef ESP_BLE_NIMBLE_SYSCFG_SYSCFG_H
#define ESP_BLE_NIMBLE_SYSCFG_SYSCFG_H
#if !DOXYGEN
/* disable native transport mechanism and enable the custom transport mechanism */
#define MYNEWT_VAL_BLE_TRANSPORT_LL__custom (1)
#define MYNEWT_VAL_BLE_TRANSPORT_LL__native (0)
#include_next "syscfg/syscfg.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* !DOXYGEN */
#endif /* ESP_BLE_NIMBLE_SYSCFG_SYSCFG_H */
/** @} */

View File

@ -195,6 +195,11 @@ extern void asymcute_handler_run(void);
AUTO_INIT(asymcute_handler_run,
AUTO_INIT_PRIO_MOD_ASYMCUTE);
#endif
#if IS_USED(MODULE_ESP_BLE_NIMBLE)
extern void esp_ble_nimble_init(void);
AUTO_INIT(esp_ble_nimble_init,
AUTO_INIT_PRIO_MOD_ESP_BLE_NIMBLE);
#endif
#if IS_USED(MODULE_NIMBLE)
extern void nimble_riot_init(void);
AUTO_INIT(nimble_riot_init,

View File

@ -209,6 +209,12 @@ extern "C" {
*/
#define AUTO_INIT_PRIO_MOD_ASYMCUTE 1310
#endif
#ifndef AUTO_INIT_PRIO_MOD_ESP_BLE_NIMBLE
/**
* @brief ESP BLE NimBLE priority
*/
#define AUTO_INIT_PRIO_MOD_ESP_BLE_NIMBLE 1319
#endif
#ifndef AUTO_INIT_PRIO_MOD_NIMBLE
/**
* @brief NimBLE priority