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:
parent
abccc41db7
commit
56e59eb036
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
22
cpu/esp32/esp-ble-nimble/Kconfig
Normal file
22
cpu/esp32/esp-ble-nimble/Kconfig
Normal 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.
|
3
cpu/esp32/esp-ble-nimble/Makefile
Normal file
3
cpu/esp32/esp-ble-nimble/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE=esp_ble_nimble
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
17
cpu/esp32/esp-ble-nimble/doc.txt
Normal file
17
cpu/esp32/esp-ble-nimble/doc.txt
Normal 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>
|
||||
*/
|
204
cpu/esp32/esp-ble-nimble/esp_ble_nimble.c
Normal file
204
cpu/esp32/esp-ble-nimble/esp_ble_nimble.c
Normal 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);
|
||||
}
|
41
cpu/esp32/include/esp_ble_nimble/syscfg/syscfg.h
Normal file
41
cpu/esp32/include/esp_ble_nimble/syscfg/syscfg.h
Normal 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 */
|
||||
/** @} */
|
@ -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,
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user