mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
Merge branch 'feat/nimble_logs_compression' into 'master'
feat(nimble): Support NimBLE log compression and decompression over SPI See merge request espressif/esp-idf!46967
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
# list(APPEND sdkconfig_defaults)
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
|
||||
# idf_build_set_property(MINIMAL_BUILD ON)
|
||||
project(ble_spi_slave)
|
||||
@@ -0,0 +1,111 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- |
|
||||
|
||||
# NimBLE SPI Slave Receiver Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
## Overview
|
||||
|
||||
This example configures the device as an **SPI slave receiver** and prints received data to UART in hexadecimal format.
|
||||
|
||||
It is intended to work with a peer device acting as an SPI master (for example, a NimBLE BLE Log sender). Data is received on SPI and projected to the serial monitor, which makes this example useful for bring-up and transport validation.
|
||||
|
||||
### What this example does
|
||||
|
||||
- Initializes SPI slave mode (`SPI2_HOST`)
|
||||
- Uses MOSI/SCLK/CS lines to receive data in half-duplex style
|
||||
- Keeps MISO disabled (`-1`)
|
||||
- Receives transactions in 1024-byte DMA buffers
|
||||
- Prints received bytes to UART in 32-byte lines (`%02X` format)
|
||||
|
||||
## Hardware behavior
|
||||
|
||||
The receive pins are configured from Kconfig symbols used by this example:
|
||||
|
||||
- `CONFIG_BT_BLE_LOG_SPI_OUT_MOSI_IO_NUM`
|
||||
- `CONFIG_BT_BLE_LOG_SPI_OUT_SCLK_IO_NUM`
|
||||
- `CONFIG_BT_BLE_LOG_SPI_OUT_CS_IO_NUM`
|
||||
|
||||
Defined in [main/ble_spi_slave.h](main/ble_spi_slave.h).
|
||||
|
||||
The example enables pull-ups on MOSI/SCLK/CS to reduce false activity when no master is connected.
|
||||
|
||||
## Hardware connection
|
||||
|
||||
Connect your SPI master device to the example target:
|
||||
|
||||
- Master MOSI -> Slave MOSI
|
||||
- Master SCLK -> Slave SCLK
|
||||
- Master CS -> Slave CS
|
||||
- GND <-> GND
|
||||
|
||||
Notes:
|
||||
|
||||
- MISO is not used by this example.
|
||||
- SPI mode is fixed to mode 0 in current code.
|
||||
- Ensure both devices share a common ground.
|
||||
|
||||
## How to Use Example
|
||||
|
||||
Before project configuration and build, set the target:
|
||||
|
||||
```bash
|
||||
idf.py set-target <chip_name>
|
||||
```
|
||||
|
||||
### Configure the project
|
||||
|
||||
Open configuration menu:
|
||||
|
||||
```bash
|
||||
idf.py menuconfig
|
||||
```
|
||||
|
||||
Configure SPI pin assignments used by this example via Bluetooth/BLE Log SPI output configuration (MOSI/SCLK/CS), so they match your wiring.
|
||||
|
||||
### Build and flash
|
||||
|
||||
```bash
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
(To exit the serial monitor, type `Ctrl-]`.)
|
||||
|
||||
## Expected output
|
||||
|
||||
When the SPI master sends data, this example prints the received bytes as hexadecimal text, for example:
|
||||
|
||||
```text
|
||||
08 00 07 4F 01 00 CC CA 18 00 ...
|
||||
```
|
||||
|
||||
Output is line-broken every 32 bytes for readability in the monitor.
|
||||
|
||||
## Typical use with BLE Log pipelines
|
||||
|
||||
This receiver can be used as the SPI-side capture endpoint in BLE Log transport testing:
|
||||
|
||||
1. Master device sends BLE Log frame bytes over SPI.
|
||||
2. This example receives and prints them on UART.
|
||||
3. Host tools can capture UART hex and decode with BLE log decompression scripts.
|
||||
|
||||
## Limitations
|
||||
|
||||
- This example does not decode BLE payloads; it only receives and prints raw bytes.
|
||||
- Transaction buffer size is fixed at 1024 bytes in current source.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **No data printed**
|
||||
- Verify wiring and shared ground.
|
||||
- Verify pin configuration in menuconfig matches your board wiring.
|
||||
- Verify SPI master is actively transmitting and uses mode 0.
|
||||
|
||||
- **Corrupted or unstable output**
|
||||
- Check signal integrity and clock speed.
|
||||
- Confirm pull-ups and board-level electrical compatibility.
|
||||
|
||||
- **Build errors related to drivers**
|
||||
- Ensure SPI/GPIO driver components are enabled (already declared in this example component dependencies).
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
idf_component_register(SRCS "main.c"
|
||||
REQUIRES esp_driver_spi esp_driver_gpio
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
// Please update the following configuration according to your HardWare spec
|
||||
#define RCV_HOST SPI2_HOST
|
||||
|
||||
#define GPIO_MOSI CONFIG_BT_BLE_LOG_SPI_OUT_MOSI_IO_NUM
|
||||
#define GPIO_MISO -1
|
||||
#define GPIO_SCLK CONFIG_BT_BLE_LOG_SPI_OUT_SCLK_IO_NUM
|
||||
#define GPIO_CS CONFIG_BT_BLE_LOG_SPI_OUT_CS_IO_NUM
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "driver/spi_slave.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "ble_spi_slave.h"
|
||||
|
||||
/*
|
||||
SPI receiver (slave) example.
|
||||
|
||||
This example is supposed to work together with a NimBLE module acting as SPI master.
|
||||
It uses the standard SPI pins (MISO, MOSI, SCLK, CS) to transmit logs over in a
|
||||
half-duplex fashion, that is, the master puts data on the MOSI pin, while the MISO pins
|
||||
remain inactive.
|
||||
*/
|
||||
|
||||
//Dummy callback called after a transaction is queued and ready for pickup by master.
|
||||
static void my_post_setup_cb(spi_slave_transaction_t *trans)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Dummy callback called after transaction is sent/received.
|
||||
static void my_post_trans_cb(spi_slave_transaction_t *trans)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Main application
|
||||
void app_main(void)
|
||||
{
|
||||
int n = 0;
|
||||
esp_err_t ret;
|
||||
spi_slave_transaction_t t = {0};
|
||||
|
||||
//Configuration for the SPI bus
|
||||
spi_bus_config_t buscfg = {
|
||||
.mosi_io_num = GPIO_MOSI,
|
||||
.miso_io_num = -1,
|
||||
.sclk_io_num = GPIO_SCLK,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
};
|
||||
|
||||
//Configuration for the SPI slave interface
|
||||
spi_slave_interface_config_t slvcfg = {
|
||||
.mode = 0,
|
||||
.spics_io_num = GPIO_CS,
|
||||
.queue_size = 3,
|
||||
.flags = 0,
|
||||
.post_setup_cb = my_post_setup_cb,
|
||||
.post_trans_cb = my_post_trans_cb
|
||||
};
|
||||
|
||||
//Enable pull-ups on SPI lines so we don't detect rogue pulses when no master is connected.
|
||||
gpio_set_pull_mode(GPIO_MOSI, GPIO_PULLUP_ONLY);
|
||||
gpio_set_pull_mode(GPIO_SCLK, GPIO_PULLUP_ONLY);
|
||||
gpio_set_pull_mode(GPIO_CS, GPIO_PULLUP_ONLY);
|
||||
|
||||
/**
|
||||
* The default drive capability on esp32 is GPIO_DRIVE_CAP_2 (~20 mA).
|
||||
* When connecting master devices that uses a source/sink current lower or higher than GPIO_DRIVER_CAP_DEFAULT.
|
||||
* Using a drive strength that does not match the requirements of the connected device can cause issues
|
||||
* such as unreliable switching, or damage to the GPIO pin or external device.
|
||||
*
|
||||
* - GPIO_DRIVE_CAP_0: ~5 mA
|
||||
* - GPIO_DRIVE_CAP_1: ~10 mA
|
||||
* - GPIO_DRIVE_CAP_2: ~20 mA
|
||||
* - GPIO_DRIVE_CAP_3: ~40 mA
|
||||
|
||||
gpio_set_drive_capability(GPIO_MOSI, GPIO_DRIVE_CAP_3);
|
||||
gpio_set_drive_capability(GPIO_SCLK, GPIO_DRIVE_CAP_3);
|
||||
gpio_set_drive_capability(GPIO_CS, GPIO_DRIVE_CAP_3);
|
||||
|
||||
**/
|
||||
|
||||
//Initialize SPI slave interface
|
||||
ret = spi_slave_initialize(RCV_HOST, &buscfg, &slvcfg, SPI_DMA_CH_AUTO);
|
||||
assert(ret == ESP_OK);
|
||||
|
||||
// For SPI DMA, buffers should be word-aligned.
|
||||
WORD_ALIGNED_ATTR uint8_t recvbuf[1024];
|
||||
|
||||
while (1) {
|
||||
//Clear receive buffer, set send buffer to something sane
|
||||
memset(recvbuf, 0x00, 1024);
|
||||
|
||||
//Set up a transaction of 1024 bytes to receive
|
||||
t.length = 1024 * 8;
|
||||
t.tx_buffer = NULL;
|
||||
t.rx_buffer = recvbuf;
|
||||
|
||||
/* This call enables the SPI slave interface to receive to the recvbuf. The transaction is
|
||||
* initialized by the SPI master, however, so it will not actually happen until the master starts a hardware transaction
|
||||
* by pulling CS low and pulsing the clock etc.
|
||||
*/
|
||||
ret = spi_slave_transmit(RCV_HOST, &t, portMAX_DELAY);
|
||||
|
||||
/* Get the actual number of bytes received */
|
||||
int rcv_bytes = t.trans_len / 8;
|
||||
if (rcv_bytes == 0) {
|
||||
rcv_bytes = 1024; // Fallback if hardware didn't report exact length
|
||||
}
|
||||
|
||||
/* Print the binary buffer in safe 32-byte chunks */
|
||||
for (int i = 0; i < rcv_bytes; i++) {
|
||||
// Print the raw byte (ignoring null-terminators)
|
||||
printf("%02X ", recvbuf[i]);
|
||||
|
||||
// Break the line to prevent ESP-IDF terminal truncation
|
||||
if ((i + 1) % 32 == 0 || i == rcv_bytes - 1) {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
|
||||
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
|
||||
CONFIG_BTDM_CTRL_MODE_BTDM=n
|
||||
CONFIG_BT_BLUEDROID_ENABLED=n
|
||||
CONFIG_BT_NIMBLE_ENABLED=y
|
||||
CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED=y
|
||||
Reference in New Issue
Block a user