initial commit
@@ -0,0 +1,574 @@
|
||||
# Bluetooth Implementation in ESP-Hosted
|
||||
|
||||
**Table of Contents**
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Table of Contents</summary>
|
||||
|
||||
- [1. Introduction](#1-introduction)
|
||||
- [1.1 Prerequisites](#11-prerequisites)
|
||||
- [1.2 Choosing a Bluetooth Host stack](#12-choosing-a-bluetooth-host-stack)
|
||||
- [2. Bluetooth Controller](#2-bluetooth-controller)
|
||||
- [3. Bluetooth Interface](#3-bluetooth-interface)
|
||||
- [3.1 Initializing the Bluetooth Controller](#31-initializing-the-bluetooth-controller)
|
||||
- [4. NimBLE Host Stack](#4-nimble-host-stack)
|
||||
- [4.1. Transporting HCI data using Hosted HCI in NimBLE](#41-transporting-hci-data-using-hosted-hci-in-nimble)
|
||||
- [4.1.1. Bluetooth Host Hosted HCI Initialization](#411-bluetooth-host-hosted-hci-initialization)
|
||||
- [4.1.2. Bluetooth Host Sending Data through Hosted HCI in NimBLE](#412-bluetooth-host-sending-data-through-hosted-hci-in-nimble)
|
||||
- [4.1.3. Bluetooth Host Receiving Data from Hosted HCI in NimBLE](#413-bluetooth-host-receiving-data-from-hosted-hci-in-nimble)
|
||||
- [4.2. Transporting HCI data using UART](#42-transporting-hci-data-using-uart)
|
||||
- [4.2.1. Bluetooth Host HCI Initialization](#421-bluetooth-host-hci-initialization)
|
||||
- [4.2.2. Bluetooth Host Sending Data using HCI](#422-bluetooth-host-sending-data-using-hci)
|
||||
- [4.2.3. Bluetooth Host Receiving Data using HCI](#423-bluetooth-host-receiving-data-using-hci)
|
||||
- [5. BlueDroid Host Stack](#5-bluedroid-host-stack)
|
||||
- [5.1. Transporting HCI data using Hosted HCI in BlueDroid](#51-transporting-hci-data-using-hosted-hci-in-bluedroid)
|
||||
- [5.1.1. Bluetooth Host Hosted HCI Initialization](#511-bluetooth-host-hosted-hci-initialization)
|
||||
- [5.1.2. Bluetooth Host Sending Data through Hosted HCI in BlueDroid](#512-bluetooth-host-sending-data-through-hosted-hci-in-bluedroid)
|
||||
- [5.1.3. Bluetooth Host Receiving Data from Hosted HCI in BlueDroid](#513-bluetooth-host-receiving-data-from-hosted-hci-in-bluedroid)
|
||||
- [5.2. Transporting HCI data using UART](#52-transporting-hci-data-using-uart)
|
||||
- [5.2.1. Bluetooth Host HCI Initialization](#521-bluetooth-host-hci-initialization)
|
||||
- [5.2.2. Bluetooth Host Sending Data using HCI](#522-bluetooth-host-sending-data-using-hci)
|
||||
- [5.2.3. Bluetooth Host Receiving Data using HCI](#523-bluetooth-host-receiving-data-using-hci)
|
||||
- [6. Configuring the Co-processor for Standard HCI over UART](#6-configuring-the-co-processor-for-standard-hci-over-uart)
|
||||
- [7. References](#7-references)
|
||||
|
||||
</details>
|
||||
|
||||
## 1. Introduction
|
||||
|
||||
ESP-Hosted can transport Bluetooth HCI packets between the Bluetooth
|
||||
Host on the Hosted Master and the Bluetooth Controller on the Hosted
|
||||
Co-processor. The Host MCU implement the Bluetooth app and Bluetooth
|
||||
Host Stack and the co-processor runs the Bluetooth controller and
|
||||
hardware.
|
||||
|
||||
ESP-Hosted is Bluetooth stack agnostic. To showcase ESP-Hosted's
|
||||
Bluetooth support, both `esp-nimble` and `esp-bluedroid` are used
|
||||
here. Users can use their own preferred Bluetooth stack with some
|
||||
porting effort.
|
||||
|
||||
`esp-nimble` is a fork of Apache NimBLE and available from
|
||||
ESP-IDF. The NimBLE Bluetooth stack provides Bluetooth Low Energy (BLE)
|
||||
only functionality.
|
||||
|
||||
`esp-bluedroid` is a fork of the Bluedroid based stack and available
|
||||
from ESP-IDF. The BlueDroid stack supports classic Bluetooth as well
|
||||
as Bluetooth Low Energy.
|
||||
|
||||
See [References](#7-references) for links with more information.
|
||||
|
||||
### 1.1 Prerequisites
|
||||
|
||||
- check that the memory requirement for your preferred Bluetooth host stack can be satisfied on the Host.
|
||||
- the ESP32 only supports Bluetooth v4.2. If you are using a ESP32 as the co-processor, the host Bluetooth stack must also be v4.2.
|
||||
|
||||
### 1.2 Choosing a Bluetooth Host stack
|
||||
|
||||
For usecases involving classic Bluetooth as well as Bluetooth Low
|
||||
Energy, BlueDroid should be used.
|
||||
|
||||
For Bluetooth Low Energy-only usecases, using NimBLE is
|
||||
recommended. It is less demanding in terms of code footprint and
|
||||
runtime memory, making it suitable for such scenarios.
|
||||
|
||||
## 2. Bluetooth Controller
|
||||
|
||||
ESP-Hosted uses the Bluetooth controller running on the co-processor.
|
||||
|
||||
As ESP-Hosted is just the communication medium, it supports both
|
||||
Classic BT and BLE controllers. The controller available depends upon
|
||||
the ESP chipset chosen. As of today, ESP32 supports Classic-BT+BLE,
|
||||
whereas, the other ESP chipsets support BLE only.
|
||||
|
||||
## 3. Bluetooth Interface
|
||||
|
||||
Hosted provides two ways to let the Bluetooth stack running on the
|
||||
Host to communicate with the Bluetooth controller on the co-processor:
|
||||
Standard HCI and Hosted HCI.
|
||||
|
||||
**Standard HCI**
|
||||
|
||||
Standard HCI works in dedicated mode. Bluetooth traffic cannot be
|
||||
multiplexed with other traffic, so a dedicated transport is
|
||||
needed. Bluetooth HCI frames are transferred over the dedicated
|
||||
transport.
|
||||
|
||||
- standard HCI is a transparent way of handling HCI messages
|
||||
- HCI messages originating from the Bluetooth stack on the Host are
|
||||
sent through an interface (like UART) directly to the Bluetooth
|
||||
controller on the co-processor.
|
||||
- requires extra GPIOs for the standard HCI interface, independent of
|
||||
the GPIOs used for the ESP-Hosted interface
|
||||
|
||||
Use this option if you want:
|
||||
|
||||
- transparency: no extra data added to the HCI messages
|
||||
- portability: because it is standard HCI, you can replace the
|
||||
co-processor with any other co-processor (ESP or otherwise) that has
|
||||
a Bluetooth controller
|
||||
|
||||
**Hosted HCI**
|
||||
|
||||
Hosted HCI is Standard HCI encapsulated for transport over
|
||||
ESP-Hosted. Bluetooth traffic is multiplexed with other traffic types
|
||||
on the same transport, each with different Interface types. See the [traffic
|
||||
types](../README.md#72-interface-types) support by ESP-Hosted message
|
||||
headers.
|
||||
|
||||
- Hosted HCI is standard HCI with extra headers or metadata added
|
||||
- Hosted HCI embeds the ESP-Hosted header and re-uses the underlying
|
||||
ESP-Hosted transport, such as SPI/SDIO
|
||||
- this option is easier to set up. Once the existing ESP-Hosted
|
||||
Transport (SPI or SDIO, for example) has been set up, Bluetooth
|
||||
just works
|
||||
|
||||
Use this option if you want:
|
||||
|
||||
- complete control of Bluetooth messages
|
||||
- extra flexibility of debugging
|
||||
- no extra GPIOs (required for Standard HCI)
|
||||
|
||||
> [!NOTE]
|
||||
> If Hosted HCI is configured as the Bluetooth transport, then your
|
||||
> Bluetooth over Standard HCI configuration must be disabled, and vice
|
||||
> versa.
|
||||
|
||||
### 3.1 Initializing the Bluetooth Controller
|
||||
|
||||
> [!NOTE]
|
||||
> Before ESP-Hosted-MCU v2.5.2, the Bluetooth Controller on the
|
||||
> co-processor was **enabled** by default. This section on
|
||||
> initializing the Bluetooth Controller applies to ESP-Hosted-MCU
|
||||
> v2.5.2 and after.
|
||||
|
||||
The Bluetooth Controller on the co-processor is disabled by
|
||||
default. This allows the BT Mac Address to be set, which must be done
|
||||
before the controller is enabled. The BT Controller should be enabled
|
||||
before initialzing the BT Host Stack.
|
||||
|
||||
To get and set the BT Controller MAC address:
|
||||
|
||||
1. Call `esp_hosted_connect_to_slave()` to intialise the transport
|
||||
2. (Optional) Call `esp_hosted_iface_mac_addr_len_get` to get the length of the BT MAC address
|
||||
3. (Optional) Call `esp_hosted_iface_mac_addr_get` to get the current BT MAC address
|
||||
4. Call `esp_hosted_iface_mac_addr_set` to set the current BT MAC address
|
||||
|
||||
After setting the BT Controller MAC address, you can now enable the BT Controller.
|
||||
|
||||
> [!NOTE]
|
||||
> This MAC address setting is temporary and will revert after device
|
||||
> reset. For permanent MAC address change, modify during hardware
|
||||
> provisioning or burn directly into eFuse using appropriate commands
|
||||
|
||||
To enable the BT Controller:
|
||||
|
||||
1. Call `esp_hosted_connect_to_slave()` to intialise the transport. (Skip this if already called while seting the BT MAC Address above.)
|
||||
2. (Optional) Call `esp_hosted_iface_mac_addr_get()` and
|
||||
`esp_hosted_iface_mac_addr_set()` to get and set the BT Mac Address
|
||||
3. Call `esp_hosted_bt_controller_init()` to initialise the BT Controller
|
||||
4. Call `esp_hosted_bt_controller_enable()` to enable the BT Controller
|
||||
5. Initialise the BT Host stack
|
||||
|
||||
To disable the Controller:
|
||||
|
||||
1. Deinitialise the BT Host stack
|
||||
2. Call `esp_hosted_bt_controller_disable()` to disable the BT Controller
|
||||
3. Call `esp_hosted_bt_controller_deinit()` to deinit the BT Controller
|
||||
|
||||
## 4. NimBLE Host Stack
|
||||
|
||||
The ESP-Hosted Master implements the set of API calls required by the
|
||||
NimBLE Bluetooth stack to initialize, send and receive Bluetooth data:
|
||||
|
||||
- `hci_drv_init`
|
||||
- `ble_transport_ll_init`
|
||||
- `ble_transport_to_ll_acl_impl`
|
||||
- `ble_transport_to_ll_cmd_impl`
|
||||
- `ble_transport_to_hs_evt`
|
||||
- `ble_transport_to_hs_acl`
|
||||
|
||||
The following sequence diagrams show how to send and receive Bluetooth
|
||||
on both the Hosted Master and co-processor.
|
||||
|
||||
### 4.1. Transporting HCI data using Hosted HCI in NimBLE
|
||||
|
||||
#### 4.1.1. Bluetooth Host Hosted HCI Initialization
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box rgb(128, 128, 128) Hosted Master
|
||||
participant ble as NimBLE Host Bluetooth Stack
|
||||
participant hhci as Hosted HCI Driver
|
||||
participant master as SPI/SDIO Interface
|
||||
end
|
||||
|
||||
box rgb(128, 128, 128) Hosted Co-processor
|
||||
participant sinterface as SPI/SDIO Interface
|
||||
participant slave as Bluetooth Controller
|
||||
end
|
||||
|
||||
ble ->> +hhci : hci_drv_init()
|
||||
Note over hhci: do any init required
|
||||
hhci -->> -ble :
|
||||
|
||||
ble ->> +hhci : ble_transport_ll_init()
|
||||
Note over hhci : do any transport init required
|
||||
hhci -->> -ble :
|
||||
```
|
||||
|
||||
**Bluetooth Host Initialization**
|
||||
|
||||
#### 4.1.2. Bluetooth Host Sending Data through Hosted HCI in NimBLE
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box rgb(128, 128, 128) Hosted Master
|
||||
participant ble as NimBLE Host Bluetooth Stack
|
||||
participant hhci as Hosted HCI Driver
|
||||
participant master as SPI/SDIO Interface
|
||||
end
|
||||
|
||||
box rgb(128, 128, 128) Hosted Co-processor
|
||||
participant sinterface as SPI/SDIO Interface
|
||||
participant slave as Bluetooth Controller
|
||||
end
|
||||
|
||||
ble ->> +hhci : ble_transport_to_ll_acl_impl()
|
||||
Note over hhci : convert ACL data to HCI
|
||||
hhci ->> +master : esp_hosted_tx()
|
||||
Note over master : add Hosted header
|
||||
master ->> +sinterface: SPI/SDIO
|
||||
Note over master,sinterface : (Hosted HCI data)
|
||||
master -->> -hhci :
|
||||
hhci -->> -ble :
|
||||
|
||||
Note over sinterface : remove Hosted header
|
||||
sinterface ->> -slave : HCI data
|
||||
```
|
||||
|
||||
**Bluetooth Host Sending Data**
|
||||
|
||||
#### 4.1.3. Bluetooth Host Receiving Data from Hosted HCI in NimBLE
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box rgb(128, 128, 128) Hosted Master
|
||||
participant ble as NimBLE Host Bluetooth Stack
|
||||
participant hhci as Hosted HCI Driver
|
||||
participant master as SPI/SDIO Interface
|
||||
end
|
||||
|
||||
box rgb(128, 128, 128) Hosted Co-processor
|
||||
participant sinterface as SPI/SDIO Interface
|
||||
participant slave as Bluetooth Controller
|
||||
end
|
||||
|
||||
slave ->> +sinterface : HCI data
|
||||
Note over sinterface : Add Hosted header
|
||||
sinterface ->> -master : SPI/SDIO
|
||||
Note over sinterface,master : (Hosted HCI data)
|
||||
Note over master : Remove Hosted header
|
||||
|
||||
master ->> +hhci : hci_rx_handler()
|
||||
|
||||
alt Receive Event Data
|
||||
Note over hhci: convert HCI data to Event
|
||||
hhci ->> ble : ble_transport_to_hs_evt()
|
||||
ble -->> hhci :
|
||||
else Receive ACL Data
|
||||
Note over hhci: convert HCI data to ACL
|
||||
hhci ->> ble : ble_transport_to_hs_acl()
|
||||
ble -->> hhci :
|
||||
end
|
||||
|
||||
hhci -->> -master :
|
||||
```
|
||||
|
||||
**Bluetooth Host Receiving Data**
|
||||
|
||||
### 4.2. Transporting HCI data using UART
|
||||
|
||||
#### 4.2.1. Bluetooth Host HCI Initialization
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box rgb(128, 128, 128) Master
|
||||
participant ble as NimBLE Host Bluetooth Stack
|
||||
participant huart as UART Driver
|
||||
end
|
||||
|
||||
box rgb(128, 128, 128) Co-processor
|
||||
participant slave as Bluetooth Controller with UART Interface
|
||||
end
|
||||
|
||||
ble ->> huart : hci_drv_init()
|
||||
Note over huart : do any init required
|
||||
huart -->> ble :
|
||||
|
||||
ble ->> huart : ble_transport_ll_init()
|
||||
Note over huart : do any transport init required
|
||||
huart --> ble :
|
||||
```
|
||||
|
||||
**Bluetooth Host Initialization**
|
||||
|
||||
#### 4.2.2. Bluetooth Host Sending Data using HCI
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box rgb(128, 128, 128) Master
|
||||
participant ble as NimBLE Host Bluetooth Stack
|
||||
participant huart as UART Driver
|
||||
end
|
||||
|
||||
box rgb(128, 128, 128) Co-processor
|
||||
participant slave as Bluetooth Controller with UART Interface
|
||||
end
|
||||
|
||||
ble ->> huart : ble_transport_to_ll_acl_impl()
|
||||
Note over huart : convert ACL data to HCI
|
||||
huart ->> slave : UART TX
|
||||
Note over huart,slave : (standard HCI)
|
||||
huart -->> ble :
|
||||
```
|
||||
|
||||
**Bluetooth Host Sending Data**
|
||||
|
||||
#### 4.2.3. Bluetooth Host Receiving Data using HCI
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box rgb(128, 128, 128) Master
|
||||
participant ble as NimBLE Host Bluetooth Stack
|
||||
participant huart as UART Driver
|
||||
end
|
||||
|
||||
box rgb(128, 128, 128) Co-processor
|
||||
participant slave as Bluetooth Controller with UART Interface
|
||||
end
|
||||
|
||||
slave ->> huart : UART RX
|
||||
Note over slave,huart: (standard HCI)
|
||||
|
||||
alt Receive Event Data
|
||||
Note over huart : convert HCI data to Event
|
||||
huart ->> ble : ble_transport_to_hs_evt()
|
||||
ble -->> huart :
|
||||
else Receive ACL Data
|
||||
Note over huart : convert HCI data to ACL
|
||||
huart ->> ble : ble_transport_to_hs_acl()
|
||||
ble -->> huart :
|
||||
end
|
||||
```
|
||||
|
||||
**Bluetooth Host Receiving Data**
|
||||
|
||||
## 5. BlueDroid Host Stack
|
||||
|
||||
ESP-Hosted implements the set of API calls required by the BlueDroid
|
||||
Bluetooth stack to initialise, send and receive Bluetooth data.
|
||||
|
||||
- `hosted_hci_bluedroid_open`
|
||||
- `hosted_hci_bluedroid_close`
|
||||
- `hosted_hci_bluedroid_send`
|
||||
- `hosted_hci_bluedroid_check_send_available`
|
||||
- `hosted_hci_bluedroid_register_host_callback`
|
||||
|
||||
`hosted_hci_bluedroid_open` must be called by the application before
|
||||
attaching the transport APIs to BlueDroid and starting BlueDroid. This
|
||||
initializes the underlying transport.
|
||||
|
||||
`hosted_hci_bluedroid_register_host_callback` records the callback
|
||||
provided by BlueDroid that is use to notify the Bluetooth stack of
|
||||
incoming HCI data (as `notify_host_recv`).
|
||||
|
||||
The following sequence diagrams show how to send and receive Bluetooth
|
||||
on both the Hosted Master and Co-processor.
|
||||
|
||||
### 5.1. Transporting HCI data using Hosted HCI in BlueDroid
|
||||
|
||||
#### 5.1.1. Bluetooth Host Hosted HCI Initialization
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box rgb(128, 128, 128) Hosted Master
|
||||
participant bt as Host Application
|
||||
participant hhci as Hosted HCI Driver
|
||||
participant master as SPI/SDIO Interface
|
||||
end
|
||||
|
||||
box rgb(128, 128, 128) Hosted Co-processor
|
||||
participant sinterface as SPI/SDIO Interface
|
||||
participant slave as Bluetooth Controller
|
||||
end
|
||||
|
||||
bt ->> +hhci : hosted_hci_bluedroid_open()
|
||||
Note over hhci: do any init required
|
||||
hhci -->> -bt :
|
||||
```
|
||||
|
||||
**Bluetooth Host Initialization**
|
||||
|
||||
#### 5.1.2. Bluetooth Host Sending Data through Hosted HCI in BlueDroid
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box rgb(128, 128, 128) Hosted Master
|
||||
participant bt as BlueDroid Host Bluetooth Stack
|
||||
participant hhci as Hosted HCI Driver
|
||||
participant master as SPI/SDIO Interface
|
||||
end
|
||||
|
||||
box rgb(128, 128, 128) Hosted Co-processor
|
||||
participant sinterface as SPI/SDIO Interface
|
||||
participant slave as Bluetooth Controller
|
||||
end
|
||||
|
||||
bt ->> +hhci : hosted_hci_bluedroid_send()
|
||||
Note over hhci : HCI data
|
||||
hhci ->> +master : esp_hosted_tx()
|
||||
Note over master : add Hosted header
|
||||
master ->> +sinterface: SPI/SDIO
|
||||
Note over master,sinterface : (Hosted HCI data)
|
||||
master -->> -hhci :
|
||||
hhci -->> -bt :
|
||||
|
||||
Note over sinterface : remove Hosted header
|
||||
sinterface ->> -slave : HCI data
|
||||
```
|
||||
|
||||
**Bluetooth Host Sending Data**
|
||||
|
||||
#### 5.1.3. Bluetooth Host Receiving Data from Hosted HCI in BlueDroid
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box rgb(128, 128, 128) Hosted Master
|
||||
participant bt as BlueDroid Host Bluetooth Stack
|
||||
participant hhci as Hosted HCI Driver
|
||||
participant master as SPI/SDIO Interface
|
||||
end
|
||||
|
||||
box rgb(128, 128, 128) Hosted Co-processor
|
||||
participant sinterface as SPI/SDIO Interface
|
||||
participant slave as Bluetooth Controller
|
||||
end
|
||||
|
||||
slave ->> +sinterface : HCI data
|
||||
Note over sinterface : Add Hosted header
|
||||
sinterface ->> -master : SPI/SDIO
|
||||
Note over sinterface,master : (Hosted HCI data)
|
||||
Note over master : Remove Hosted header
|
||||
|
||||
master ->> +hhci : hci_rx_handler()
|
||||
|
||||
hhci ->> bt : notify_host_recv()
|
||||
Note over hhci, bt: HCI data
|
||||
|
||||
hhci -->> -master :
|
||||
```
|
||||
|
||||
**Bluetooth Host Receiving Data**
|
||||
|
||||
### 5.2. Transporting HCI data using UART
|
||||
|
||||
When using BlueDroid Host Bluetooth Stack with UART, UART functions
|
||||
that do the following are required:
|
||||
|
||||
- `uart_open` to open the UART driver and initialise the UART (set GPIOs, Baud Rate, etc.)
|
||||
- `uart_tx` to transmit data over UART
|
||||
- `UART RX` is a thread that waits for incoming UART data
|
||||
- `notify_host_recv` is a BlueDroid callback registered with `UART RX` to receive UART data
|
||||
|
||||
`uart_open` is called before starting BlueDroid, while `uart_tx` and
|
||||
`notify_host_recv` are registered by BlueDroid with the UART Driver. See this [ESP-IDF BlueDroid Example using UART](https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart) for an example implementation.
|
||||
|
||||
#### 5.2.1. Bluetooth Host HCI Initialization
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box rgb(128, 128, 128) Master
|
||||
participant bt as Host Application
|
||||
participant huart as UART Driver
|
||||
end
|
||||
|
||||
box rgb(128, 128, 128) Co-processor
|
||||
participant slave as Bluetooth Controller with UART Interface
|
||||
end
|
||||
|
||||
bt ->> +huart : uart_open()
|
||||
Note over huart: do any uart init required
|
||||
huart -->> -bt :
|
||||
```
|
||||
|
||||
**Bluetooth Host Initialization**
|
||||
|
||||
#### 5.2.2. Bluetooth Host Sending Data using HCI
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box rgb(128, 128, 128) Master
|
||||
participant bt as BlueDroid Host Bluetooth Stack
|
||||
participant huart as UART Driver
|
||||
end
|
||||
|
||||
box rgb(128, 128, 128) Co-processor
|
||||
participant slave as Bluetooth Controller with UART Interface
|
||||
end
|
||||
|
||||
bt ->> huart : uart_tx()
|
||||
huart ->> slave : UART TX
|
||||
Note over huart,slave : (standard HCI)
|
||||
huart -->> bt :
|
||||
```
|
||||
|
||||
**Bluetooth Host Sending Data**
|
||||
|
||||
#### 5.2.3. Bluetooth Host Receiving Data using HCI
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box rgb(128, 128, 128) Master
|
||||
participant bt as BlueDroid Host Bluetooth Stack
|
||||
participant huart as UART Driver
|
||||
end
|
||||
|
||||
box rgb(128, 128, 128) Co-processor
|
||||
participant slave as Bluetooth Controller with UART Interface
|
||||
end
|
||||
|
||||
slave ->> huart : UART RX
|
||||
Note over slave,huart: (standard HCI)
|
||||
huart ->> bt : notify_host_recv()
|
||||
Note over huart, bt: HCI data
|
||||
|
||||
bt -->> huart:
|
||||
```
|
||||
|
||||
**Bluetooth Host Receiving Data**
|
||||
|
||||
## 6. Configuring the Co-processor for Standard HCI over UART
|
||||
|
||||
Standard HCI over UART setup is done through the Bluetooth Component
|
||||
kconfig settings. In menuconfig, select `Component config` ->
|
||||
`Bluetooth` -> `Controller Options` -> `HCI mode` or `HCI Config` and
|
||||
set it to `UART(H4)`.
|
||||
|
||||
Depending on the selected co-processor, you can configure various UART
|
||||
parameters (Tx, Rx pins, hardware flow control, RTS, CTS pins,
|
||||
baudrate) through the Bluetooth Component. Other UART parameters not
|
||||
handled by the Bluetooth Component are configured by ESP-Hosted
|
||||
through `Example Configuration` -> `HCI UART Settings`.
|
||||
|
||||
> [!NOTE]
|
||||
> Make sure the Standard HCI UART GPIO pins selected do not conflict
|
||||
> with the GPIO pins used for the selected ESP-Hosted transport.
|
||||
|
||||
## 7. References
|
||||
|
||||
- esp-nimble: https://github.com/espressif/esp-nimble
|
||||
- ESP-IDF NimBLE-based Host APIs: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/bluetooth/nimble/index.html
|
||||
- Bluetooth API: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/bluetooth/index.html
|
||||
- ESP-IDF example using NimBLE on Host to send HCI through UART to co-processor: https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/nimble/bleprph_host_only
|
||||
- ESP-IDF example using BlueDroid on Host to send HCI through UART to co-processor: https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart
|
||||
@@ -0,0 +1,195 @@
|
||||
# Design Considerations and Debugging ESP-Hosted
|
||||
|
||||
**Table of Contents**
|
||||
|
||||
- [1. Choosing the Correct ESP chip as Slave](#1-choosing-the-correct-esp-chip-as-slave)
|
||||
- [1.1. Using ESP chip as Hosted Master](#11-using-esp-chip-as-hosted-master)
|
||||
- [2. General Hardware Considerations](#2-general-hardware-considerations)
|
||||
- [2.1. GPIOs used for interface](#21-gpios-used-for-interface)
|
||||
- [2.2. Using SPI insted of SDIO](#22-using-spi-insted-of-sdio)
|
||||
- [2.3. Whenever possible, Use `IO_MUX` GPIOs.](#23-whenever-possible-use-io_mux-gpios)
|
||||
- [2.4. Signal Length and Noise Reduction](#24-signal-length-and-noise-reduction)
|
||||
- [3. General Debugging Guidelines](#3-general-debugging-guidelines)
|
||||
- [3.1. Add tapping points to your PCB prototype](#31-add-tapping-points-to-your-pcb-prototype)
|
||||
- [3.2. Tap out additional GPIO signals as testing points and future expansion](#32-tap-out-additional-gpio-signals-as-testing-points-and-future-expansion)
|
||||
- [3.3. Verifying Hosted Interface with Raw Throughput](#33-verifying-hosted-interface-with-raw-throughput)
|
||||
- [4. Others](#4-others)
|
||||
- [5. References](#5-references)
|
||||
|
||||
There are several considerations that need to be taken into account
|
||||
when implementing ESP-Hosted for your system.
|
||||
|
||||
## 1 Choosing the Correct ESP chip as Slave
|
||||
|
||||
For prototyping, any ESP32 chip can be used as the slave, provided it
|
||||
has the required interface (SPI, SDIO). But when creating an actual
|
||||
product, it is important to select the proper ESP32 chip as a Hosted
|
||||
Slave.
|
||||
|
||||
There are many ESP32 chips, each with difference features and
|
||||
performance capabilities. Based on your product requirements
|
||||
(interface to use, CPU, memory, power requirements, etc.), choose the
|
||||
ESP32 chip(s) that can meet your requirements.
|
||||
|
||||
Use the ESP Product Selector guide to help you decide which ESP32
|
||||
chips and/or modules are suitable for your product.
|
||||
|
||||
> [!NOTE]
|
||||
> See [References](#5-references) for links to the Selector Guide
|
||||
> and other links.
|
||||
|
||||
## 1.1 Using ESP chip as Hosted Master
|
||||
|
||||
The project defaults to using an ESP chip as the Hosted Master. This
|
||||
is to act as a reference platform and make it easier to evaluate and
|
||||
test Hosted before porting it to your MCU of choice.
|
||||
|
||||
## 2 General Hardware Considerations
|
||||
|
||||
### 2.1 GPIOs used for interface
|
||||
|
||||
Make sure the correct GPIOs pins on the Hosted Slave and Master are
|
||||
connected together. Verify that the correct GPIOs are set-up in
|
||||
`Menuconfig` for both the Slave and Master.
|
||||
|
||||
> [!NOTE]
|
||||
> In general most ESP GPIOs can be used for input and output. But on
|
||||
> the ESP32, some GPIOs can only be used for input and are not usable
|
||||
> under Hosted. Check the ESP datasheet to verify the GPIOs you select
|
||||
> can be used as a Hosted interface.
|
||||
|
||||
### 2.2 Evaluate with jumpers first
|
||||
|
||||
It is flexible to evaluate with jumper cables or bread board than full-fledged PCB.
|
||||
In general, SPI (Standard & Dual SPI) imposes fewer hardware requirements compared to
|
||||
SDIO. SPI is easier to prototype, and available on more ESP chips and
|
||||
MCUs compared to SDIO.
|
||||
Before going to SDIO 4 bit mode PCB, it's better to evaluate SDIO 1-Bit mode.
|
||||
|
||||
Once you evaluate the solution on jumper cables, you can move to PCB solutions with same or high performance transport.
|
||||
|
||||
###### Jumper cable considerations
|
||||
- Use high quality jumper cables
|
||||
- Use jumper cables as small as possible. you can cut and solder the joints if need be.
|
||||
- Use equal length jumper cables for all the connections
|
||||
- Grounds: Connect as many grounds as possible, this lowers the interference.
|
||||
- Jumper cable lengths
|
||||
- Standard SPI: At max 10cm, lower the better
|
||||
- Dual SPI: At max 10cm, lower the better
|
||||
- SDIO 1 Bit: At max 5cm, lower the better
|
||||
- Quad SPI : jumpers not supported, only PCB
|
||||
- SDIO 4 Bit: Jumpers not supported, only PCB
|
||||
|
||||
### 2.3 Whenever possible, Use `IO_MUX` GPIOs.
|
||||
|
||||
In general, ESP peripheral interfaces can be assigned to any available
|
||||
GPIO through a multiplexer. But some ESPs have dedicated GPIOs for
|
||||
peripherals (`IO_MUX`). These `IO_MUX` GPIOs have better timing
|
||||
characteristics and support higher frequencies. They should be use
|
||||
when possible to minimise timing and skew issues when using the
|
||||
interface for Hosted.
|
||||
|
||||
> [!NOTE]
|
||||
> The SDIO interface on the ESP32 and ESP32-C6 have fixed GPIO
|
||||
> assignments and cannot be changed.
|
||||
|
||||
### 2.4 Signal Length and Noise Reduction
|
||||
|
||||
For best performance, a PCB with traces should be used to connect the
|
||||
Hosted Slave and Master. For prototyping, jumper cables can be used,
|
||||
but may only work at a lower `CLK` frequency.
|
||||
|
||||
In general, keep the cable and PCB traces short and of the same
|
||||
length, to minimise propogation delay and clock skew:
|
||||
|
||||
- for SPI, keep them to 10 cm or less
|
||||
- for SDIO, keep them to 5 cm or less
|
||||
|
||||
Isolate the interface signals, expecially the `CLK` signal, from other
|
||||
signals. For PCBs, surround the signal swith a ground plane, and keep
|
||||
the `CLK` signal clean by not routing it close to other high frequency
|
||||
signals.
|
||||
|
||||
For jumper cables, you can try surrounding the signals, especially the
|
||||
`CLK` signal, with grounded wires to shield them from interference.
|
||||
|
||||
> [!NOTE]
|
||||
> For SDIO, external pull-up resistors (recommended value: 51 kOhms)
|
||||
> are required. Using jumper cable are **not** recommended for SDIO. You
|
||||
> may be able to get SDIO working with jumper cables by using a lower
|
||||
> `CLK` frequency and using 1-bit SDIO mode.
|
||||
|
||||
> [!NOTE]
|
||||
> Also check the Hosted documentation for SPI and SDIO for more
|
||||
> information and guidelines on the interfaces.
|
||||
|
||||
## 3 General Debugging Guidelines
|
||||
|
||||
### 3.1 Add tapping points to your prototype
|
||||
|
||||
Adding tapping points or headers to the Hosted interface signals on
|
||||
your prototype will make it easier to check whether the Hosted
|
||||
interface is working as expected.
|
||||
|
||||
### 3.2 Tap out additional GPIO signals as testing points and future expansion
|
||||
|
||||
Add tapping points to some unused GPIOs on both the Hosted Slave and
|
||||
Host on your prototype PCB. This can later be use for debugging or
|
||||
enhancing your own Hosted code.
|
||||
|
||||
For example, add your own debugging code to the Hosted Slave and
|
||||
Master code to set a GPIO value when a condition is met. This GPIO can
|
||||
be used to light a LED or trigger a capture on an oscilloscope or
|
||||
logic analyzer, for example. This is useful for capturing rare or
|
||||
intermittent conditions while testing Hosted.
|
||||
|
||||
In the future, Hosted may also offer newer transport options or more features, like controlling
|
||||
power modes on the Host and Slave. These may require additional GPIOs
|
||||
for control, so it would be good to keep some additional GPIOs
|
||||
available and accesable for future use.
|
||||
|
||||
### 3.3 Verifying Hosted Interface with Raw Throughput
|
||||
|
||||
ESP-Hosted has a Raw Throughput Option to test sending of data between
|
||||
the Host and Slave. This can be used to verify the hardware for signal
|
||||
errors and to check the achievable throughput of Hosted.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Use this option to verify that Hosted hardware and software are
|
||||
> working as expected before involving other software layers like
|
||||
> networking.
|
||||
|
||||
To enable the Raw Throughput Option on Slave, enter `Menuconfig` and
|
||||
enable **Example Configuration** ---> **Hosted Debugging** --->
|
||||
**RawTP**.
|
||||
|
||||
To enable the Raw Throughput Option and set Raw Throughput direction
|
||||
on Host, enter `Menuconfig` and enable **Component config** --->
|
||||
**ESP-Hosted config** ---> **Debug Settings** ---> **RawTP**. Set
|
||||
the data transfer direction: **Host to Slave**, **Slave to Host** or
|
||||
**Bidirectional**.
|
||||
|
||||
## 4 Others
|
||||
|
||||
Check the References below for links to the Product Selector, and more
|
||||
detailed information on the interfaces used in Hosted. If you have
|
||||
other issues with Hosted, you can check the Troubleshooting Guide.
|
||||
|
||||
You can also raise an Issue on the ESP-Hosted Github repository. Check
|
||||
that the issue has not already been raised before submitting. The
|
||||
solution to your problem may have already been provided.
|
||||
|
||||
## 5 References
|
||||
|
||||
**External Links**
|
||||
|
||||
- ESP Product Selector: https://products.espressif.com/
|
||||
- ESP-Hosted Github Issues: https://github.com/espressif/esp-hosted-mcu/issues
|
||||
|
||||
**ESP-Hosted Documentation Links**
|
||||
|
||||
- SPI Full Duplex interface documentation: [spi_full_duplex.md](spi_full_duplex.md)
|
||||
- SDIO interface documentation: [sdio.md](sdio.md)
|
||||
- SPI Half Duplex interface documentation: [spi_half_duplex.md](spi_half_duplex.md)
|
||||
- UART documentation: [uart.md](uart.md)
|
||||
- Troubleshooting Guide: [troubleshooting.md](troubleshooting.md)
|
||||
@@ -0,0 +1,335 @@
|
||||
# ESP-Hosted on the ESP32-P4-Function-EV-Board DevKit
|
||||
|
||||
<details>
|
||||
<summary>Table of Contents</summary>
|
||||
|
||||
- [1. Introduction](#1-introduction)
|
||||
- [2. Set-Up ESP-IDF](#2-set-up-esp-idf)
|
||||
- [3. Building Host for the P4](#3-building-host-for-the-p4)
|
||||
- [Adding Components](#31-adding-components)
|
||||
- [Configuring Defaults](#32-configuring-defaults)
|
||||
- [Building Firmware](#33-building-firmware)
|
||||
- [4. Checking ESP-Hosted](#4-checking-esp-hosted)
|
||||
- [5. Flashing ESP32-C6](#5-flashing-esp32-c6)
|
||||
- [Using ESP-Prog](#51-serial-flashing-using-esp-prog-initial-setup)
|
||||
- [OTA Updates](#52-esp-hosted-slave-ota-updates-recommended)
|
||||
- [6. Troubleshooting](#6-troubleshooting)
|
||||
- [7. Flashing the On-board ESP32-P4 through the ESP-Prog](#7-flashing-esp32-p4)
|
||||
- [8. Testing ESP-Hosted with SPI-FD with other MCUs](#8-testing-esp-hosted-with-spi-fd-with-other-mcus)
|
||||
- [9. References](#10-references)
|
||||
</details>
|
||||
|
||||
## 1. Introduction
|
||||
|
||||
This guide covers using ESP-Hosted-MCU on the ESP32-P4-Function-EV-Board. The board includes an on-board ESP32-C6 module that comes pre-flashed with ESP-Hosted-MCU slave firmware (v0.0.6). This provides Wi-Fi/Bluetooth connectivity to the on-board ESP32-P4, which acts as the host.
|
||||
|
||||
The image below shows the board.
|
||||
|
||||
<img src="images/esp32-p4-function-ev-board.jpg" alt="ESP32-P4-Function-EV-Board" width="800" />
|
||||
|
||||
*ESP32-P4-Function-EV-Board*
|
||||
|
||||
The ESP32-P4 communicates with the ESP32-C6 module using SDIO.
|
||||
|
||||
## 2. Set-Up ESP-IDF
|
||||
|
||||
If you haven't already set up ESP-IDF, choose one of the following options:
|
||||
|
||||
#### Option 1: Installer Way (Recommended)
|
||||
|
||||
- **Windows**
|
||||
- Follow the [Standard Setup of Toolchain for Windows](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup.html)
|
||||
- Use the ESP-IDF [Powershell Command Prompt](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup.html#using-the-command-prompt) for all commands
|
||||
|
||||
- **Linux or MacOS**
|
||||
- For bash:
|
||||
```bash
|
||||
bash docs/setup_esp_idf__latest_stable__linux_macos.sh
|
||||
```
|
||||
- For fish:
|
||||
```fish
|
||||
fish docs/setup_esp_idf__latest_stable__linux_macos.fish
|
||||
```
|
||||
|
||||
#### Option 2: Manual Way
|
||||
|
||||
Follow the [ESP-IDF Get Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html) for manual installation.
|
||||
|
||||
## 3. Building Host for the P4
|
||||
|
||||
### 3.1. Adding Components
|
||||
|
||||
Add the required components to your project:
|
||||
|
||||
```bash
|
||||
idf.py add-dependency "espressif/esp_wifi_remote"
|
||||
idf.py add-dependency "espressif/esp_hosted"
|
||||
```
|
||||
|
||||
**Important:** Remove `esp-extconn` if present, as it conflicts with `esp-hosted`.
|
||||
|
||||
Open `main/idf_component.yml` and remove or comment out this block if it exists:
|
||||
|
||||
```yaml
|
||||
# ------- Delete or comment this block ---------
|
||||
espressif/esp-extconn:
|
||||
version: "~0.1.0"
|
||||
rules:
|
||||
- if: "target in [esp32p4]"
|
||||
# -----------------------------------
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The co-processor is selected through `esp_wifi_remote`. Make sure to select the correct slave target in:
|
||||
> `Component config` → `Wi-Fi Remote` → `choose slave target`
|
||||
>
|
||||
> This selection determines the ESP-Hosted transport options and default GPIOs.
|
||||
|
||||
### 3.2. Configuring Defaults
|
||||
|
||||
Edit `sdkconfig.defaults.esp32p4` to include the following configuration:
|
||||
|
||||
```
|
||||
### sdkconfig for ESP32-P4 + C6 Dev board
|
||||
CONFIG_SLAVE_IDF_TARGET_ESP32C6=y
|
||||
CONFIG_ESP_HOSTED_P4_DEV_BOARD_FUNC_BOARD=y
|
||||
|
||||
CONFIG_WIFI_RMT_STATIC_RX_BUFFER_NUM=16
|
||||
CONFIG_WIFI_RMT_DYNAMIC_RX_BUFFER_NUM=64
|
||||
CONFIG_WIFI_RMT_DYNAMIC_TX_BUFFER_NUM=64
|
||||
CONFIG_WIFI_RMT_AMPDU_TX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_TX_BA_WIN=32
|
||||
CONFIG_WIFI_RMT_AMPDU_RX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_RX_BA_WIN=32
|
||||
|
||||
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=65534
|
||||
CONFIG_LWIP_TCP_WND_DEFAULT=65534
|
||||
CONFIG_LWIP_TCP_RECVMBOX_SIZE=64
|
||||
CONFIG_LWIP_UDP_RECVMBOX_SIZE=64
|
||||
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=64
|
||||
|
||||
CONFIG_LWIP_TCP_SACK_OUT=y
|
||||
```
|
||||
|
||||
For optimized parameters when using other co-processors, see the [Performance Optimization Guide](performance_optimization.md).
|
||||
|
||||
### 3.3. Building Firmware
|
||||
|
||||
Build and flash the firmware:
|
||||
|
||||
```sh
|
||||
idf.py set-target esp32p4
|
||||
idf.py build
|
||||
idf.py -p <P4 Serial Port> flash monitor
|
||||
```
|
||||
|
||||
Replace `<P4 Serial Port>` with your actual serial port (e.g., `COM3` on Windows or `/dev/ttyUSB0` on Linux).
|
||||
|
||||
## 4. Checking ESP-Hosted
|
||||
|
||||
After flashing, you should see output similar to this on the console:
|
||||
|
||||
```
|
||||
I (498) H_API: esp_wifi_remote_init
|
||||
I (498) transport: Attempt connection with slave: retry[0]
|
||||
I (498) transport: Reset slave using GPIO[54]
|
||||
I (498) os_wrapper_esp: GPIO [54] configured
|
||||
I (508) gpio: GPIO[54]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
|
||||
I (1678) sdio_wrapper: SDIO master: Data-Lines: 4-bit Freq(KHz)[40000 KHz]
|
||||
I (1678) sdio_wrapper: GPIOs: CLK[18] CMD[19] D0[14] D1[15] D2[16] D3[17] Slave_Reset[54]
|
||||
I (1678) H_SDIO_DRV: Starting SDIO process rx task
|
||||
I (1678) sdio_wrapper: Queues: Tx[20] Rx[20] SDIO-Rx-Mode[3]
|
||||
I (1718) gpio: GPIO[15]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
|
||||
I (1718) gpio: GPIO[17]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
|
||||
Name:
|
||||
Type: SDIO
|
||||
Speed: 40.00 MHz (limit: 40.00 MHz)
|
||||
Size: 0MB
|
||||
CSD: ver=1, sector_size=0, capacity=0 read_bl_len=0
|
||||
SCR: sd_spec=0, bus_width=0
|
||||
TUPLE: DEVICE, size: 3: D9 01 FF
|
||||
TUPLE: MANFID, size: 4
|
||||
MANF: 0092, CARD: 6666
|
||||
TUPLE: FUNCID, size: 2: 0C 00
|
||||
TUPLE: FUNCE, size: 4: 00 00 02 32
|
||||
TUPLE: CONFIG, size: 5: 01 01 00 02 07
|
||||
TUPLE: CFTABLE_ENTRY, size: 8
|
||||
INDX: C1, Intface: 1, Default: 1, Conf-Entry-Num: 1
|
||||
IF: 41
|
||||
FS: 30, misc: 0, mem_space: 1, irq: 1, io_space: 0, timing: 0, power: 0
|
||||
IR: 30, mask: 1, IRQ: FF FF
|
||||
LEN: FFFF
|
||||
TUPLE: END
|
||||
I (1768) sdio_wrapper: Function 0 Blocksize: 512
|
||||
I (1778) sdio_wrapper: Function 1 Blocksize: 512
|
||||
I (1778) H_SDIO_DRV: SDIO Host operating in PACKET MODE
|
||||
I (1788) H_SDIO_DRV: generate slave intr
|
||||
I (1798) transport: Received INIT event from ESP32 peripheral
|
||||
I (1798) transport: EVENT: 12
|
||||
I (1798) transport: EVENT: 11
|
||||
I (1808) transport: capabilities: 0xd
|
||||
I (1808) transport: Features supported are:
|
||||
I (1818) transport: * WLAN
|
||||
I (1818) transport: - HCI over SDIO
|
||||
I (1818) transport: - BLE only
|
||||
I (1828) transport: EVENT: 13
|
||||
I (1828) transport: ESP board type is : 13
|
||||
|
||||
I (1838) transport: Base transport is set-up
|
||||
|
||||
I (1838) transport: Slave chip Id[12]
|
||||
I (1848) hci_stub_drv: Host BT Support: Disabled
|
||||
I (1848) H_SDIO_DRV: Received INIT event
|
||||
I (1868) rpc_wrap: Received Slave ESP Init
|
||||
```
|
||||
|
||||
This confirms that ESP-Hosted is running correctly.
|
||||
|
||||
## 5. Flashing ESP32-C6
|
||||
|
||||
Note: The ESP32-C6 comes pre-flashed with ESP-Hosted slave firmware v0.0.6, so this step is optional unless you need to update the firmware. However, it is **recommended** to upgrade to the latest slave firmware to get updated features and performance optimizations.
|
||||
|
||||
### 5.1 Serial Flashing Using ESP-Prog (Initial Setup)
|
||||
|
||||
> [!TIP]
|
||||
> For firmware updates after initial setup, use the OTA method described in section 5.2
|
||||
|
||||
You'll need an ESP-Prog or similar UART adapter for serial flashing.
|
||||
|
||||
<img src="images/esp32-p4-function-ev-board-esp-prog.jpg" alt="ESP32-P4-Function-EV-Board with ESP-Prog Connected to ESP32-C6" width="800" />
|
||||
|
||||
*ESP32-P4-Function-EV-Board with ESP-Prog Connected to ESP32-C6*
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Get the ESP-Hosted slave example:
|
||||
|
||||
```bash
|
||||
idf.py create-project-from-example "espressif/esp_hosted:slave"
|
||||
```
|
||||
|
||||
2. Configure the project:
|
||||
|
||||
```sh
|
||||
idf.py set-target esp32c6
|
||||
idf.py menuconfig
|
||||
```
|
||||
|
||||
3. Verify SDIO is enabled (it should be by default):
|
||||
```
|
||||
Example Configuration
|
||||
└── Bus Config in between Host and Co-processor
|
||||
└── Transport layer
|
||||
└── Select "SDIO"
|
||||
```
|
||||
|
||||
4. Build the firmware:
|
||||
|
||||
```sh
|
||||
idf.py build
|
||||
```
|
||||
|
||||
5. Connect ESP-Prog to the `PROG_C6` header:
|
||||
|
||||
| ESP-Prog | PROG_C6 | Notes |
|
||||
| --- | --- | --- |
|
||||
| ESP\_EN | EN | |
|
||||
| ESP\_TXD | TXD | |
|
||||
| ESP\_RXD | RXD | |
|
||||
| VDD | - | **Do not connect** |
|
||||
| GND | GND | |
|
||||
| ESP\_IO0 | IO0 | |
|
||||
|
||||
6. Put the ESP32-P4 into bootloader mode to prevent interference:
|
||||
|
||||
**Manual method:**
|
||||
- Hold down the `BOOT` button
|
||||
- Press and release the `RST` button
|
||||
- Release the `BOOT` button
|
||||
|
||||
**Script method:**
|
||||
```sh
|
||||
esptool.py -p <host_serial_port> --before default_reset --after no_reset run
|
||||
```
|
||||
|
||||
7. Flash the C6:
|
||||
|
||||
```sh
|
||||
idf.py -p <Serial Port> flash monitor
|
||||
```
|
||||
|
||||
### 5.2 ESP-Hosted Slave OTA Updates (Recommended)
|
||||
|
||||
The ESP-Hosted link comes pre-configured and ready to use on first boot. You can update the slave firmware remotely from the host MCU using OTA (Over-The-Air) updates: **No** ESP-Prog, serial cable, or extra GPIO connections are required.
|
||||
|
||||
For step-by-step instructions, see the [Host Performs Slave OTA Example](../examples/host_performs_slave_ota/README.md).
|
||||
|
||||
## 6. Troubleshooting
|
||||
|
||||
If you encounter any issues, refer to the [Troubleshooting Guide](troubleshooting.md).
|
||||
|
||||
<details>
|
||||
<summary>7. Flashing the On-board ESP32-P4 through the ESP-Prog</summary>
|
||||
|
||||
The standard way to flash the P4 is through the **USB connector with Type-C cable** inserted into USB-UART port on ESP32-P4. However, you can also use an ESP-Prog connected to the serial interface.
|
||||
|
||||
<img src="images/esp32-p4-esp-prog.jpg" alt="ESP32-P4 Serial Connection with ESP-Prog" width="600" />
|
||||
|
||||
*ESP32-P4 Serial Connection with ESP-Prog*
|
||||
|
||||
**Connections:**
|
||||
|
||||
| ESP-Prog | P4 Header |
|
||||
| --- | --- |
|
||||
| ESP\_TXD | U0TXD (GPIO 37) |
|
||||
| ESP\_RXD | U0RXD (GPIO 38) |
|
||||
| GND | GND |
|
||||
|
||||
Leave other ESP-Prog pins disconnected.
|
||||
|
||||
**Flashing steps:**
|
||||
|
||||
1. Hold down the `BOOT` button
|
||||
2. Press and release the `RST` button
|
||||
3. Release the `BOOT` button
|
||||
|
||||
4. Flash the firmware:
|
||||
|
||||
```sh
|
||||
idf.py -p <Serial Port> flash monitor
|
||||
```
|
||||
|
||||
5. Press the `RST` button to restart the P4 after flashing.
|
||||
|
||||
</details>
|
||||
|
||||
## 8. Testing ESP-Hosted with SPI-FD with other MCUs
|
||||
|
||||
You can test ESP-Hosted using SPI Full Duplex (SPI-FD) by connecting another ESP-Dev-Kit or ESP Chipset to the P4 through the J1 GPIO header.
|
||||
|
||||
**Important:** Use GPIO 36 or lower to avoid LDO power issues with higher-numbered GPIOs.
|
||||
|
||||
**Recommended GPIO configuration:**
|
||||
|
||||
| Function | GPIO |
|
||||
|------------|------|
|
||||
| MOSI | 4 |
|
||||
| MISO | 5 |
|
||||
| CLK | 26 |
|
||||
| CS | 6 |
|
||||
| Handshake | 20 |
|
||||
| Data Ready | 32 |
|
||||
| Reset | 2 |
|
||||
|
||||
> [!NOTE]
|
||||
> Avoid using GPIO 35 and 36, as they affect bootloader mode. See [ESP32-P4 Boot Mode Selection](https://docs.espressif.com/projects/esptool/en/latest/esp32p4/advanced-topics/boot-mode-selection.html#select-bootloader-mode) for details.
|
||||
|
||||
> [!TIP]
|
||||
> For optimal performance testing, check out the [Shield Box Test Setup](shield-box-test-setup.md).
|
||||
|
||||
## 9. References
|
||||
|
||||
- [ESP32-P4-Function-EV-Board Documentation](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32p4/esp32-p4-function-ev-board/)
|
||||
- [ESP-Prog Guide](https://docs.espressif.com/projects/esp-iot-solution/en/latest/hw-reference/ESP-Prog_guide.html)
|
||||
- [`esp_wifi_remote` component](https://components.espressif.com/components/espressif/esp_wifi_remote/)
|
||||
- [`esp_hosted` component](https://components.espressif.com/components/espressif/esp_hosted/)
|
||||
@@ -0,0 +1,388 @@
|
||||
# Host Power Save (ESP-Hosted MCU)
|
||||
|
||||
## Overview
|
||||
|
||||
The **Host Power Save** feature allows the host MCU to enter low-power states while the ESP slave maintains network connectivity. This enables efficient power usage in battery-operated devices.
|
||||
|
||||
**Host Power Save Modes:**
|
||||
- **Deep Sleep at Host**: Ultra-low power consumption with GPIO wake-up
|
||||
- **Light Sleep at Host**: *(Coming Soon)* Faster wake-up with reduced power savings
|
||||
|
||||
Key features include:
|
||||
- Host enters power save mode, network stays online
|
||||
- Slave intelligently wakes host when needed
|
||||
- Power state synchronization between host and slave
|
||||
- Seamless network handover during power save
|
||||
- Integration with Network Split
|
||||
|
||||
---
|
||||
## Configuration
|
||||
|
||||
### Host Configuration
|
||||
|
||||
In host example project, run `idf.py menuconfig` and Enable `Allow host to power save`
|
||||
```
|
||||
# Host side kconfig
|
||||
Component config
|
||||
└── ESP-Hosted config
|
||||
└── [*] Allow host to power save <== Enable This
|
||||
└── [*] Allow host to enter deep sleep. ─┐
|
||||
├── (<gpio_num>) Host in: Host Wakeup GPIO │
|
||||
└── Host Wakeup GPIO Level ├── Default config (No change)
|
||||
└── (X) High ─┘
|
||||
```
|
||||
> [!NOTE]
|
||||
> 1. The wakeup GPIO number must be an RTC-capable GPIO.
|
||||
> 2. Ensure the wake up GPIO is unused
|
||||
|
||||
### Slave Configuration
|
||||
|
||||
In slave project, run `idf.py menuconfig` and Enable `Allow host to power save`
|
||||
|
||||
```
|
||||
# Slave side kconfig
|
||||
Example Configuration
|
||||
└── [*] Allow host to power save <== Enable This
|
||||
└── [*] Allow host to enter deep sleep. ─┐
|
||||
├── (<gpio_num>) Slave out: Host wakeup GPIO │
|
||||
└── Host Wakeup GPIO Level ├── Default config (No change)
|
||||
└── (X) High ─┘
|
||||
```
|
||||
|
||||
---
|
||||
## High Level Overview
|
||||
|
||||
The power management system coordinates between the host MCU and ESP slave to ensure smooth transitions between active and power save states.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Host as Host MCU
|
||||
participant Slave as ESP Slave
|
||||
participant Network as Network/WiFi
|
||||
|
||||
Host->>Slave: Power Save Start Signal
|
||||
Note over Slave: Slave takes over network operations
|
||||
Host->>Host: Enter Power Save Mode
|
||||
|
||||
Network->>Slave: Incoming packets
|
||||
Slave->>Slave: Packet needs host
|
||||
Slave->>Host: Trigger Wake-up GPIO
|
||||
Host->>Host: Exit Power Save Mode
|
||||
Host->>Slave: Power Save Stop Signal
|
||||
Slave->>Slave: Resume packet delivery
|
||||
```
|
||||
|
||||
### Wake-up Mechanisms
|
||||
|
||||
The slave initiates a wake-up by toggling a dedicated GPIO line to the host when one of the following triggers occurs:
|
||||
|
||||
* Periodic Timer-based Wake-up
|
||||
* CLI-based Wake-up
|
||||
* Network-triggered Wake-up
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[💤 Host in Power Save Mode] --> B{⏱️ Trigger on Slave?}
|
||||
B -->|🕒 Timer Expired| C[🔔 Send Wake-up GPIO]
|
||||
B -->|🧑💻 CLI Command| C
|
||||
B -->|🌐 Network Packet| C
|
||||
C --> D[⚡ Host Wakes Up]
|
||||
D --> E[▶️ Resume Operations]
|
||||
|
||||
classDef sleep fill:#f5f5f5,stroke:#888,font-size:14px;
|
||||
classDef event fill:#e3f2fd,stroke:#2196f3,font-size:14px;
|
||||
classDef action fill:#e0f7e9,stroke:#4caf50,font-size:14px;
|
||||
|
||||
class A sleep
|
||||
class B,C event
|
||||
class D,E action
|
||||
```
|
||||
|
||||
### State transitions
|
||||
|
||||
- Active → Preparing: Host prepares (notifies slave, configures GPIO)
|
||||
- Preparing → PowerSave: Host enters power save mode; slave handles network
|
||||
- PowerSave → Waking: Slave triggers wakeup on event (timer/packet/CLI)
|
||||
- Waking → Active: Host re-inits system, syncs with slave
|
||||
|
||||
```mermaid
|
||||
stateDiagram
|
||||
[*] --> Active
|
||||
Active --> Preparing: 🥱 start_host_power_save()
|
||||
Preparing --> PowerSave: 😴 Power Save Entry
|
||||
PowerSave --> Waking: 😳 Wake Event
|
||||
Waking --> Active: 😊 Slave sync-up complete
|
||||
|
||||
```
|
||||
---
|
||||
## Deep Dive
|
||||
|
||||
### 💤 Host Enters Power Save Mode
|
||||
|
||||
When the host application initiates power save mode, the following function sequence occurs to safely coordinate with the slave.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant App as Host Application (or CLI)
|
||||
participant PowerSaveDrv as power_save_drv.c
|
||||
participant TransportDrv as transport_drv.c
|
||||
participant Slave as Slave MCU
|
||||
|
||||
App->>PowerSaveDrv: start_host_power_save()
|
||||
PowerSaveDrv->>TransportDrv: notify_slave_host_power_save_start()
|
||||
TransportDrv->>Slave: bus_inform_slave_host_power_save_start()
|
||||
Slave-->>TransportDrv: Ack
|
||||
TransportDrv-->>PowerSaveDrv: Ack
|
||||
Note right of TransportDrv: Slave is now aware<br/>host is entering power save.
|
||||
PowerSaveDrv->>PowerSaveDrv: hold_slave_reset_gpio_pre_power_save()
|
||||
Note right of PowerSaveDrv: Prevents slave from resetting.
|
||||
PowerSaveDrv->>PowerSaveDrv: _h_config_host_power_save_hal_impl()
|
||||
Note right of PowerSaveDrv: Configures wakeup GPIO.
|
||||
PowerSaveDrv->>PowerSaveDrv: _h_start_host_power_save_hal_impl()
|
||||
Note right of PowerSaveDrv: Host enters power save mode.
|
||||
```
|
||||
|
||||
### Host Wake-up and Synchronization Sequence
|
||||
|
||||
The slave wakes the host using a GPIO signal. Upon rebooting, the host detects the wake-up reason and synchronizes with the slave through a handshake mechanism, after which normal operation resumes.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant SlaveApp as Slave<br/>(App/CLI)
|
||||
participant SlavePS as Slave<br/>(host_power_save.c)
|
||||
participant HostHW as Host MCU<br/>(Hardware)
|
||||
participant HostTransport as Host<br/>(transport_drv.c)
|
||||
participant HostPS as Host<br/>(power_save_drv.c)
|
||||
|
||||
SlaveApp->>SlavePS: wakeup_host()
|
||||
SlavePS->>SlavePS: wakeup_host_mandate()
|
||||
SlavePS->>HostHW: Toggles Wake-up GPIO
|
||||
Note over SlavePS: Now blocks, waiting<br/>for wakeup_sem.
|
||||
|
||||
HostHW-->>HostTransport: Host wakes from power save
|
||||
Note over HostTransport: esp_hosted_init() is called,<br/>which calls transport_drv_reconfigure().
|
||||
|
||||
HostTransport->>HostPS: esp_hosted_woke_from_power_save()
|
||||
HostPS-->>HostTransport: Returns true
|
||||
|
||||
HostTransport->>HostPS: stop_host_power_save()
|
||||
HostPS->>HostTransport: notify_slave_host_power_save_stop()
|
||||
HostTransport-->>SlavePS: Sends "Power Save Off" event<br/>via transport layer.
|
||||
|
||||
Note over SlavePS: host_power_save_alert() handles the event.
|
||||
SlavePS->>SlavePS: Gives wakeup_sem.
|
||||
Note over SlavePS: Handshake complete.
|
||||
SlavePS-->>SlaveApp: wakeup_host_mandate() returns,<br/> unblocking the application.
|
||||
|
||||
Note over HostTransport, SlavePS: System is now fully active.
|
||||
SlavePS->>HostTransport: Resume packet delivery for Network Packet Wake-up case
|
||||
```
|
||||
---
|
||||
## APIs
|
||||
|
||||
### Sources
|
||||
|
||||
#### Host Files
|
||||
|
||||
- `host/api/include/esp_hosted_power_save.h`: enums and APIs
|
||||
- `host/drivers/power_save/power_save_drv.c`: power save logic
|
||||
- `host/drivers/transport/transport_drv.c`: slave communication
|
||||
- `host/drivers/transport/{sdio,spi}/...`: bus specific power save hooks
|
||||
|
||||
#### Slave Files
|
||||
|
||||
- `slave/main/host_power_save.h`: slave enums and APIs
|
||||
- `slave/main/host_power_save.c`: wake-up management
|
||||
- `slave/main/lwip_filter.c`: packet inspection (for wake-up)
|
||||
|
||||
### Functions
|
||||
|
||||
#### Host APIs
|
||||
|
||||
```c
|
||||
/* Power save driver APIs (host side) */
|
||||
int esp_hosted_power_save_enabled(void);
|
||||
int esp_hosted_power_save_init(void);
|
||||
int esp_hosted_woke_from_power_save(void);
|
||||
int esp_hosted_power_saving(void);
|
||||
int esp_hosted_power_save_start(esp_hosted_power_save_type_t power_save_type);
|
||||
int esp_hosted_power_save_timer_start(uint32_t time_ms, int timer_type);
|
||||
int esp_hosted_power_save_timer_stop(void);
|
||||
|
||||
/* Retain GPIO during power save */
|
||||
int hold_slave_reset_gpio_pre_power_save(void);
|
||||
int release_slave_reset_gpio_post_wakeup(void);
|
||||
```
|
||||
|
||||
#### Slave APIs
|
||||
|
||||
|
||||
```c
|
||||
/* Slave-side power save APIs */
|
||||
int host_power_save_init(void (*host_wakeup_callback)(void));
|
||||
int is_host_power_saving(void);
|
||||
int is_host_wakeup_needed(interface_buffer_handle_t *buf_handle);
|
||||
int wakeup_host_mandate(uint32_t timeout_ms);
|
||||
int wakeup_host(uint32_t timeout_ms);
|
||||
int host_power_save_alert(uint32_t ps_evt);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CLI Demo
|
||||
|
||||
### Enter Power Save Mode
|
||||
|
||||
1. **Enable CLI**: Ensure `ESP_HOSTED_CLI_ENABLED` is enabled in the host's `menuconfig`.
|
||||
2. **Start the CLI**: The CLI starts automatically when `esp_hosted_init()` is called.
|
||||
3. **Enter the command**: At the `host>` prompt, type the `power_save` command.
|
||||
|
||||
```sh
|
||||
host> host-power-save
|
||||
I (11147) esp_cli: Putting ESP32-P4 into power save mode...
|
||||
I (11147) H_power_save: Inform slave: Host PS start
|
||||
I (11148) H_SDIO_DRV: Inform slave, host power save is started
|
||||
ESP-ROM:esp32p4...
|
||||
...
|
||||
```
|
||||
This command calls `esp_hosted_power_save_start()`, which signals the slave and puts the host into the configured power save mode. If it is deep sleep power save, The host would not be able to execute any further code until it is woken up.
|
||||
|
||||
### Wake-up from Slave
|
||||
|
||||
The host can be woken up by the slave under several conditions, such as receiving a specific network packet. On the slave, a CLI command `wake-up` is available for demonstration.
|
||||
|
||||
1. **Network Packet Wake-up**: By default, the slave is configured to wake the host upon receiving certain network traffic (e.g., on priority ports like SSH, or MQTT messages containing a "wakeup-host" payload).
|
||||
2. **Manual Wake-up (Demo)**: Use the `wake-up` command in the slave's terminal.
|
||||
|
||||
**Slave Log:**
|
||||
```sh
|
||||
coprocessor> wake-up-host
|
||||
I (13730) esp_cli: Asking P4 to wake-up...
|
||||
I (13730) host_ps: WAKE UP Host!!!!!
|
||||
I (13741) host_ps: Cleared wakeup gpio, IO2
|
||||
...
|
||||
I (15543) host_ps: Wakeup semaphore given
|
||||
I (15543) host_ps: host woke up
|
||||
```
|
||||
|
||||
**Host Log (After Wake-up):**
|
||||
```sh
|
||||
...
|
||||
I (430) H_power_save: Wakeup from power save
|
||||
I (432) transport: Waiting for power save to be off
|
||||
I (1137) H_SDIO_DRV: Host woke up from power save
|
||||
...
|
||||
```
|
||||
When the host wakes up, checks wake-up reason, and re-establishes slave connectivity automatically.
|
||||
|
||||
---
|
||||
|
||||
## Coding Example
|
||||
|
||||
While the CLI provides an easy demo, most applications would trigger power save modes using the power save APIs.
|
||||
|
||||
### Host example
|
||||
|
||||
The example below shows how to check wake-up reason and enter power save mode programmatically:
|
||||
|
||||
```c
|
||||
#include "esp_hosted.h"
|
||||
#include "esp_hosted_power_save.h"
|
||||
|
||||
static const char* TAG = "HOST_APP";
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
/* First, check the reason of host bootup. is it deep sleep? */
|
||||
if (esp_hosted_woke_from_power_save()) {
|
||||
ESP_LOGI(TAG, "Host woke up from power save mode.");
|
||||
}
|
||||
|
||||
esp_hosted_init();
|
||||
esp_hosted_power_save_init();
|
||||
|
||||
/*
|
||||
* The call to esp_hosted_init() automatically handles informing the
|
||||
* slave that the host has woken up. No explicit call to
|
||||
* stop_host_power_save() is needed here.
|
||||
*/
|
||||
|
||||
ESP_LOGI(TAG, "Application running. Entering power save in 15 seconds.");
|
||||
vTaskDelay(pdMS_TO_TICKS(15000));
|
||||
|
||||
ESP_LOGI(TAG, "Initiating power save now.");
|
||||
/* This function does not return. The host will enter power save mode
|
||||
* and wake up from app_main upon wake-up event. */
|
||||
esp_hosted_power_save_start(HOSTED_POWER_SAVE_TYPE_DEEP_SLEEP);
|
||||
}
|
||||
```
|
||||
|
||||
### Slave Example
|
||||
|
||||
The slave wakes the host automatically for host destined network packets.
|
||||
The example below demonstrates manual wake-up using timer
|
||||
|
||||
```c
|
||||
#include "host_power_save.h"
|
||||
|
||||
static const char* TAG = "SLAVE_APP";
|
||||
|
||||
void wake_host_task(void *pvParameters)
|
||||
{
|
||||
/* Wait for a while before attempting to wake the host */
|
||||
vTaskDelay(pdMS_TO_TICKS(30000));
|
||||
|
||||
ESP_LOGI(TAG, "Checking host power state.");
|
||||
|
||||
/* Check if the host is actually sleeping */
|
||||
if (is_host_power_saving()) {
|
||||
ESP_LOGI(TAG, "Host is in power save mode. Sending wake-up signal.");
|
||||
|
||||
/*
|
||||
* Attempt to wake the host. The timeout (in ms) is for the
|
||||
* handshake to complete after the host wakes up.
|
||||
*/
|
||||
int ret = wakeup_host(5000);
|
||||
if (ret == 0) {
|
||||
ESP_LOGI(TAG, "Host wake-up process initiated successfully.");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to wake up host. Error: %d", ret);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Host is already awake.");
|
||||
}
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
/*
|
||||
* Initialize slave-side components...
|
||||
* host_power_save_init() is called internally by the ESP-Hosted component.
|
||||
*/
|
||||
|
||||
/* Create a task to wake up the host */
|
||||
xTaskCreate(wake_host_task, "wake_host_task", 2048, NULL, 5, NULL);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
1. **Wake-up Failures**
|
||||
- Check GPIO configuration and physical connections.
|
||||
- Verify `CONFIG_ESP_HOSTED_HOST_WAKEUP_GPIO` is set correctly on both host and slave.
|
||||
- Check that the GPIO level configuration (High/Low) matches on both devices.
|
||||
|
||||
2. **Conflicting GPIOs**
|
||||
- Ensure you use Host Wakeup GPIO different from the GPIOs used in communication bus underlying
|
||||
|
||||
3. **Network Connectivity Loss**
|
||||
- Verify the slave maintains its WiFi connection while the host is asleep.
|
||||
- Check the Network Split configuration if enabled.
|
||||
|
||||
4. **Transport Synchronization Issues**
|
||||
- Ensure the correct power state signals are being sent. After wake-up, the host should log that it is informing the slave it has woken up.
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
# Network Split Feature for ESP-Hosted MCU
|
||||
|
||||
|
||||
| Supported Slave Targets | ESP32-C5 | ESP32-C6 | ESP32-S2 | ESP32-S3 |
|
||||
|------------------------|:--------:|:--------:|:--------:|:--------:|
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
**Network Split** allows the **Host MCU** and **ESP32 Slave** to share one IP address and split traffic between them.
|
||||
|
||||
It is especially useful when the host sleeps — the ESP continues handling selected network activity (e.g., MQTT, DNS).
|
||||
|
||||
**Highlights:**
|
||||
|
||||
* Port-based traffic routing
|
||||
* Shared IP address
|
||||
* Packet filtering and DPI
|
||||
* Wake-on-packet support (e.g., MQTT)
|
||||
* Power management integration
|
||||
* **Supported Slave Targets:** ESP32-C5/C6/S2/S3 only
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
### On the Slave
|
||||
|
||||
1. Run:
|
||||
|
||||
```bash
|
||||
idf.py menuconfig
|
||||
```
|
||||
2. Enable:
|
||||
|
||||
```
|
||||
Example Configuration
|
||||
└── [*] Enable Network Split
|
||||
```
|
||||
3. (Optional) Customize under `Network Split Configuration`:
|
||||
|
||||
```
|
||||
├── Host Static Port Forwarding
|
||||
│ ├── TCP dst: 22,80,443,8080,8554
|
||||
│ └── UDP dst: 53,123
|
||||
├── Port Ranges
|
||||
│ ├── Host: 49152–61439
|
||||
│ └── Slave: 61440–65535
|
||||
└── Default Destination: slave / host / both
|
||||
```
|
||||
|
||||
### On the Host
|
||||
|
||||
1. Run:
|
||||
|
||||
```bash
|
||||
idf.py menuconfig
|
||||
```
|
||||
2. Enable:
|
||||
|
||||
```
|
||||
Component config
|
||||
└── ESP-Hosted config
|
||||
└── [*] Enable Network Split
|
||||
```
|
||||
3. Match **port ranges** with the slave:
|
||||
|
||||
```
|
||||
└── LWIP port config
|
||||
├── Host LWIP: 49152–61439
|
||||
└── Slave LWIP: 61440–65535
|
||||
```
|
||||
4. Integrate into your app:
|
||||
```c
|
||||
#include "esp_hosted.h"
|
||||
|
||||
void app_main(void) {
|
||||
esp_hosted_init();
|
||||
// Host now shares IP and splits traffic with slave
|
||||
}
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> The port ranges on the host and slave must match perfectly to avoid routing issues.
|
||||
|
||||
---
|
||||
|
||||
## Packet Routing Decisions
|
||||
|
||||
All incoming network packets arriving at the slave device are evaluated by the logic in `lwip_filter.c`. For each packet received from the WiFi router, the slave determines whether it should be processed locally, forwarded to the host, or handled by both network stacks, according to defined routing rules.
|
||||
|
||||
| Packet Type | Destination Port Condition | Routed To |
|
||||
|--------------------------------------- |--------------------------------------------|------------------------------------|
|
||||
| Broadcast, ARP Request, ICMP Request | N/A | Slave Network Stack |
|
||||
| ARP Response, ICMP Response | N/A | Both Network Stacks |
|
||||
| DHCP | Any | Both Network Stacks |
|
||||
| TCP/UDP | Listed in Static Port Forwarding | Host Network Stack |
|
||||
| TCP/UDP | Within Host Port Range | Host Network Stack |
|
||||
| TCP/UDP | Within Slave Port Range | Slave Network Stack |
|
||||
| TCP/UDP | Port 5001 (iperf) | Both Network Stacks |
|
||||
| MQTT (Port 1883) | Payload contains `"wakeup-host"` | Host Network Stack (Wake-up) |
|
||||
| Others | Not matched by any rule | Default Destination (as configured)|
|
||||
| Packet destined for Host Network Stack | Host is in deep sleep | Dropped (unless wake-up packet) |
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> The packet routing logic is fully customizable within the `lwip_filter.c` file, allowing users to adapt the network management behavior to their specific requirements.
|
||||
|
||||
The following diagrams illustrate the decision-making process for packet routing in the Network Split feature.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[New Packet] --> B{MAC Broadcast?}
|
||||
B -->|Yes| C[Send to<br/>Slave Network Stack]
|
||||
B -->|No| D{IP Packet?}
|
||||
D -->|Yes| E[Protocol Processing]
|
||||
D -->|No| F[ARP Processing]
|
||||
|
||||
E --> G{TCP?}
|
||||
E --> H{UDP?}
|
||||
E --> I{ICMP?}
|
||||
|
||||
classDef slaveNode fill:#d9f7be,stroke:#389e0d
|
||||
classDef hostNode fill:#d6e4ff,stroke:#1d39c4
|
||||
classDef invalidNode fill:#ffccc7,stroke:#cf1322
|
||||
classDef bothNode fill:#fff1b8,stroke:#d4b106
|
||||
|
||||
class C slaveNode
|
||||
```
|
||||
|
||||
#### TCP/UDP Packet Processing
|
||||
|
||||
Specific case of UDP/TCP packet processing is illustrated below
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
G[TCP/UDP Packet] --> G1{Port config in <br/>Host Static Forwarding List?<br/>}
|
||||
G1 -->|Yes| K[Send to<br/>Host Network Stack]
|
||||
|
||||
G1 -->|No| G2{Dest Port in<br/>Slave Range?}
|
||||
G2 -->|Yes| C[Send to<br/>Slave Network Stack]
|
||||
|
||||
G2 -->|No| G3{Dest Port in<br/>Host Range?}
|
||||
G3 -->|Yes| G4{Host Awake?}
|
||||
G4 -->|Yes| K
|
||||
G4 -->|No| G5{MQTT with<br/>wakeup signal?}
|
||||
G5 -->|Yes| K
|
||||
G5 -->|No| L[Drop Packet]
|
||||
|
||||
G3 -->|No| D[Send to<br/>Default Network Stack<br/>from config]
|
||||
|
||||
classDef slaveNode fill:#d9f7be,stroke:#389e0d
|
||||
classDef hostNode fill:#d6e4ff,stroke:#1d39c4
|
||||
classDef invalidNode fill:#ffccc7,stroke:#cf1322
|
||||
classDef defaultNode fill:#fff,stroke:#333
|
||||
|
||||
class K hostNode
|
||||
class C slaveNode
|
||||
class L invalidNode
|
||||
class D defaultNode
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Internals
|
||||
|
||||
### Core Routing API
|
||||
|
||||
```c
|
||||
// lwip_filter.c
|
||||
hosted_l2_bridge filter_and_route_packet(void *frame_data, uint16_t frame_length);
|
||||
|
||||
typedef enum {
|
||||
SLAVE_LWIP_BRIDGE = 0,
|
||||
HOST_LWIP_BRIDGE = 1,
|
||||
BOTH_LWIP_BRIDGE = 2,
|
||||
INVALID_BRIDGE = 3
|
||||
} hosted_l2_bridge;
|
||||
```
|
||||
|
||||
### Wake-Up on MQTT
|
||||
|
||||
```c
|
||||
static bool host_mqtt_wakeup_triggered(const void *payload, uint16_t length) {
|
||||
return memcmp(payload, "wakeup-host", strlen("wakeup-host")) == 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Extras
|
||||
|
||||
### Use Same Port on Both Sides?
|
||||
|
||||
Yes — port 5001 (iperf) is a working example. Others can be added similarly in `lwip_filter.c`.
|
||||
|
||||
---
|
||||
|
||||
## Files of Interest
|
||||
|
||||
| Purpose | File |
|
||||
| ---------------- | -------------------------------------- |
|
||||
| Routing logic | `slave/main/lwip_filter.c` |
|
||||
| Host-side config | `host/api/include/esp_hosted_config.h` |
|
||||
| Slave control | `slave/main/interface.h` |
|
||||
| API entry point | `esp_hosted_init()` |
|
||||
|
||||
|
||||
## Debugging & Tips
|
||||
|
||||
### Checklist
|
||||
|
||||
- Port ranges must not overlap
|
||||
- Logs from `lwip_filter.c` help debug routing
|
||||
- Static forwarding can override port ranges
|
||||
- Only supported on ESP32-C5/C6/S2/S3
|
||||
|
||||
### Debug Logging
|
||||
|
||||
Enable verbose logs in `lwip_filter.c`:
|
||||
|
||||
```c
|
||||
esp_log_level_set("lwip_filter", ESP_LOG_VERBOSE);
|
||||
```
|
||||
|
||||
Wi-Fi sniffer to inspect raw traffic (if really needed)
|
||||
|
||||
---
|
||||
29
managed_components/espressif__esp_hosted/docs/features.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Features Implmented in ESP-Hosted-MCU
|
||||
|
||||
This page documents the features implemented by ESP-Hosted-MCU.
|
||||
|
||||
## Wi-Fi
|
||||
|
||||
1. **Station** (scan, connect to an AP)
|
||||
2. **SoftAP** (configure, start, stop)
|
||||
3. **SoftAP+Station**
|
||||
4. (Optional) [**Network Split**](feature_network_split.md) for splitting network traffic support between the co-processor and the host
|
||||
5. (Optional) **iTWT** (individual Target Wake Time) Wi-Fi 6 (802.11ax) feature that lets a station negotiate its own wake/sleep schedule with an iTWT supporting AP to reduce power consumption
|
||||
- only works with co-processors that support iTWT like the ESP32-C6 and ESP32-C5
|
||||
6. (Optional) **Wi-Fi Enterprise** security mode for enhanced security in business environments
|
||||
7. (Optional) **Wi-Fi Easy Connect (DPP)** to securely onboard devices by scanning a QR code (displayed by the host) without entering a Wi-Fi password
|
||||
- requires a smartphone that supports Wi-Fi Easy Connect to scan the QR code and start the onboarding operation
|
||||
- APIs added:
|
||||
- `esp_supp_dpp_init`
|
||||
- `esp_supp_dpp_deinit`
|
||||
- `esp_supp_dpp_bootstrap_gen`
|
||||
- `esp_supp_dpp_start_listen`
|
||||
- `esp_supp_dpp_stop_listen`
|
||||
|
||||
## Bluetooth
|
||||
|
||||
1. **ESP-Hosted / UART HCI** support for ESP-Nimble and ESP-Bluedroid. See [Bluetooth Design](bluetooth_design.md) for more information
|
||||
|
||||
## Miscelaneous
|
||||
|
||||
1. (Optional) [**Host Power Save**](feature_host_power_save.md) to allow Host to go to sleep and be waken by co-processor
|
||||
|
After Width: | Height: | Size: 178 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 2.7 MiB |
|
After Width: | Height: | Size: 2.4 MiB |
|
After Width: | Height: | Size: 2.7 MiB |
@@ -0,0 +1,53 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
|
||||
<svg
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
width='630'
|
||||
height='728'
|
||||
shape-rendering='geometricPrecision'
|
||||
version='1.0'>
|
||||
<defs>
|
||||
<filter id='f2' x='0' y='0' width='200%' height='200%'>
|
||||
<feOffset result='offOut' in='SourceGraphic' dx='5' dy='5' />
|
||||
<feGaussianBlur result='blurOut' in='offOut' stdDeviation='3' />
|
||||
<feBlend in='SourceGraphic' in2='blurOut' mode='normal' />
|
||||
</filter>
|
||||
</defs>
|
||||
<g stroke-width='1' stroke-linecap='square' stroke-linejoin='round'>
|
||||
<rect x='0' y='0' width='630' height='728' style='fill: #ffffff'/>
|
||||
<path stroke='#000000' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='white' d='M85.0 294.0 Q85.0 301.0 90.0 301.0 L490.0 301.0 Q495.0 301.0 495.0 294.0 L495.0 42.0 L495.0 42.0 Q495.0 35.0 490.0 35.0 L90.0 35.0 L90.0 35.0 Q85.0 35.0 85.0 42.0 L85.0 294.0 z' />
|
||||
<path stroke='#000000' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='white' d='M90.0 385.0 Q85.0 385.0 85.0 392.0 L85.0 588.0 Q85.0 595.0 90.0 595.0 L490.0 595.0 L490.0 595.0 Q495.0 595.0 495.0 588.0 L495.0 392.0 L495.0 392.0 Q495.0 385.0 490.0 385.0 L90.0 385.0 z' />
|
||||
<path stroke='#000000' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='white' d='M115.0 84.0 Q115.0 77.0 120.0 77.0 L460.0 77.0 Q465.0 77.0 465.0 84.0 L465.0 238.0 L465.0 238.0 Q465.0 245.0 460.0 245.0 L120.0 245.0 L120.0 245.0 Q115.0 245.0 115.0 238.0 L115.0 84.0 z' />
|
||||
<path stroke='#000000' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='white' d='M120.0 441.0 Q115.0 441.0 115.0 448.0 L115.0 546.0 Q115.0 553.0 120.0 553.0 L460.0 553.0 L460.0 553.0 Q465.0 553.0 465.0 546.0 L465.0 448.0 L465.0 448.0 Q465.0 441.0 460.0 441.0 L120.0 441.0 z' />
|
||||
<path stroke='#000000' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='#eeeeee' d='M115.0 133.0 L115.0 84.0 Q115.0 77.0 120.0 77.0 L460.0 77.0 L460.0 77.0 Q465.0 77.0 465.0 84.0 L465.0 133.0 L465.0 133.0 z' />
|
||||
<path stroke='#000000' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='#aaffff' d='M115.0 189.0 L115.0 238.0 Q115.0 245.0 120.0 245.0 L460.0 245.0 L460.0 245.0 Q465.0 245.0 465.0 238.0 L465.0 189.0 L465.0 189.0 z' />
|
||||
<path stroke='#000000' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='#aaffff' d='M120.0 441.0 Q115.0 441.0 115.0 448.0 L115.0 497.0 L465.0 497.0 L465.0 448.0 Q465.0 441.0 460.0 441.0 L120.0 441.0 z' />
|
||||
<path stroke='#000000' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='#eeeeee' d='M285.0 189.0 L465.0 189.0 L465.0 133.0 L285.0 133.0 z' />
|
||||
<path stroke='#000000' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='#5555bb' d='M115.0 497.0 L115.0 546.0 Q115.0 553.0 120.0 553.0 L295.0 553.0 L295.0 553.0 L295.0 497.0 z' />
|
||||
<path stroke='#000000' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='#eeeeee' d='M115.0 133.0 L285.0 133.0 L285.0 189.0 L115.0 189.0 z' />
|
||||
<path stroke='#000000' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='#5555bb' d='M295.0 497.0 L295.0 553.0 L460.0 553.0 Q465.0 553.0 465.0 546.0 L465.0 497.0 L465.0 497.0 z' />
|
||||
<path stroke='#000000' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='#5555bb' d='M435.0 672.0 Q435.0 665.0 430.0 665.0 L390.0 665.0 Q385.0 665.0 385.0 672.0 L385.0 686.0 L385.0 686.0 Q385.0 693.0 390.0 693.0 L430.0 693.0 L430.0 693.0 Q435.0 693.0 435.0 686.0 L435.0 672.0 z' />
|
||||
<path stroke='#000000' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='#eeeeee' d='M70.0 665.0 Q75.0 665.0 75.0 672.0 L75.0 686.0 Q75.0 693.0 70.0 693.0 L30.0 693.0 L30.0 693.0 Q25.0 693.0 25.0 686.0 L25.0 672.0 L25.0 672.0 Q25.0 665.0 30.0 665.0 L70.0 665.0 z' />
|
||||
<path stroke='#000000' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='#aaffff' d='M205.0 686.0 Q205.0 693.0 210.0 693.0 L250.0 693.0 Q255.0 693.0 255.0 686.0 L255.0 672.0 L255.0 672.0 Q255.0 665.0 250.0 665.0 L210.0 665.0 L210.0 665.0 Q205.0 665.0 205.0 672.0 L205.0 686.0 z' />
|
||||
<path stroke='none' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='#000000' d='M285.0 308.0 L280.0 322.0 L290.0 322.0 z' />
|
||||
<path stroke='none' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='#000000' d='M280.0 364.0 L285.0 378.0 L290.0 364.0 z' />
|
||||
<path stroke='#000000' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='none' d='M595.0 623.0 L25.0 623.0 ' />
|
||||
<path stroke='#000000' stroke-width='1.000000' stroke-linecap='round' stroke-linejoin='round' fill='none' d='M285.0 371.0 L285.0 315.0 ' />
|
||||
<text x='223' y='418' font-family='Courier' font-size='14' stroke='none' fill='#000000' ><![CDATA[ESP (Hosted Slave)]]></text>
|
||||
<text x='242' y='474' font-family='Courier' font-size='14' stroke='none' fill='#000000' ><![CDATA[ESP Firmware]]></text>
|
||||
<text x='319' y='530' font-family='Courier' font-size='14' stroke='none' fill='#ffffff' ><![CDATA[ESP HCI Driver]]></text>
|
||||
<text x='450' y='684' font-family='Courier' font-size='14' stroke='none' fill='#000000' ><![CDATA[Standard ESP IDF]]></text>
|
||||
<text x='450' y='698' font-family='Courier' font-size='14' stroke='none' fill='#000000' ><![CDATA[components]]></text>
|
||||
<text x='147' y='166' font-family='Courier' font-size='14' stroke='none' fill='#000000' ><![CDATA[TCP/IP Stack]]></text>
|
||||
<text x='238' y='278' font-family='Courier' font-size='14' stroke='none' fill='#000000' ><![CDATA[Host MCU/MPU]]></text>
|
||||
<text x='305' y='348' font-family='Courier' font-size='14' stroke='none' fill='#000000' ><![CDATA[SPI/SDIO/UART]]></text>
|
||||
<text x='246' y='110' font-family='Courier' font-size='14' stroke='none' fill='#000000' ><![CDATA[Application]]></text>
|
||||
<text x='230' y='222' font-family='Courier' font-size='14' stroke='none' fill='#000000' ><![CDATA[ESP Host Driver]]></text>
|
||||
<text x='270' y='684' font-family='Courier' font-size='14' stroke='none' fill='#000000' ><![CDATA[ESP Hosted]]></text>
|
||||
<text x='267' y='698' font-family='Courier' font-size='14' stroke='none' fill='#000000' ><![CDATA[components]]></text>
|
||||
<text x='310' y='166' font-family='Courier' font-size='14' stroke='none' fill='#000000' ><![CDATA[Bluetooth Stack]]></text>
|
||||
<text x='94' y='684' font-family='Courier' font-size='14' stroke='none' fill='#000000' ><![CDATA[3rd Party]]></text>
|
||||
<text x='97' y='698' font-family='Courier' font-size='14' stroke='none' fill='#000000' ><![CDATA[components]]></text>
|
||||
<text x='143' y='530' font-family='Courier' font-size='14' stroke='none' fill='#ffffff' ><![CDATA[ESP Wifi Driver]]></text>
|
||||
<text x='24' y='642' font-family='Courier' font-size='14' stroke='none' fill='#000000' ><![CDATA[Legend]]></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.8 KiB |
@@ -0,0 +1,48 @@
|
||||
/----------------------------------------\
|
||||
| |
|
||||
| |
|
||||
| /----------------------------------\ |
|
||||
| | cEEE | |
|
||||
| | Application | |
|
||||
| | | |
|
||||
| +----------------+-----------------+ |
|
||||
| | cEEE |cEEE | |
|
||||
| | TCP/IP Stack |Bluetooth Stack | |
|
||||
| | | | |
|
||||
| +----------------+-----------------+ |
|
||||
| | | |
|
||||
| | cAFF ESP Host Driver | |
|
||||
| | | |
|
||||
| \----------------------------------/ |
|
||||
| |
|
||||
| Host MCU/MPU |
|
||||
| |
|
||||
\----------------------------------------/
|
||||
^
|
||||
|
|
||||
|SPI/SDIO/UART
|
||||
|
|
||||
v
|
||||
/----------------------------------------\
|
||||
| |
|
||||
| ESP (Hosted Slave) |
|
||||
| |
|
||||
| /----------------------------------\ |
|
||||
| | | |
|
||||
| | cAFF ESP Firmware | |
|
||||
| | | |
|
||||
| +-----------------+----------------+ |
|
||||
| |cBLU |cBLU | |
|
||||
| |ESP Wifi Driver |ESP HCI Driver | |
|
||||
| | | | |
|
||||
| \-----------------+----------------/ |
|
||||
| |
|
||||
| |
|
||||
\----------------------------------------/
|
||||
|
||||
----------------------------------------------------------
|
||||
Legend
|
||||
|
||||
/----\ /----\ /----\
|
||||
|cEEE|3rd Party |cAFF|ESP Hosted |cBLU| Standard ESP IDF
|
||||
\----/ components \----/components \----/ components
|
||||
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,49 @@
|
||||
@startuml
|
||||
|
||||
skinparam BoxPadding 20
|
||||
|
||||
box "Host with ESP-Hosted" #LightBlue
|
||||
participant Application as app
|
||||
participant "Wi-Fi Remote" as remote
|
||||
participant "ESP Hosted" as hostedh
|
||||
participant "Host Transport" as transporth
|
||||
end box
|
||||
|
||||
box "Slave ESP-Hosted" #LightGrey
|
||||
participant "Slave Transport" as transports
|
||||
participant "Slave Hosted" as hosteds
|
||||
participant "ESP-IDF Wi-Fi Library" as api
|
||||
participant "Wi-Fi Hardware" as wifi
|
||||
end box
|
||||
|
||||
skinparam ArrowThickness 1
|
||||
|
||||
app -> remote : esp_wifi_xxx()
|
||||
remote -> hostedh : esp_wifi_remote_xxx()
|
||||
hostedh -> transporth
|
||||
|
||||
skinparam ArrowThickness 5
|
||||
|
||||
transporth -> transports : SPI/SDIO
|
||||
|
||||
skinparam ArrowThickness 1
|
||||
|
||||
transports -> hosteds
|
||||
hosteds -> api : esp_wifi_xxx()
|
||||
api -> wifi
|
||||
wifi -> wifi : Wi-Fi action
|
||||
wifi --> api : response
|
||||
api --> hosteds : return value +\ndata (if any)
|
||||
hosteds --> transports
|
||||
|
||||
skinparam ArrowThickness 5
|
||||
|
||||
transports --> transporth : SPI/SDIO
|
||||
|
||||
skinparam ArrowThickness 1
|
||||
|
||||
transporth --> hostedh
|
||||
hostedh --> remote
|
||||
remote --> app : return value +\ndata (if any)
|
||||
|
||||
@enduml
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="258px" preserveAspectRatio="none" style="width:398px;height:258px;background:#FFFFFF;" version="1.1" viewBox="0 0 398 258" width="398px" zoomAndPan="magnify"><defs/><g><line style="stroke:#181818;stroke-width:0.5;stroke-dasharray:5.0,5.0;" x1="46" x2="46" y1="37.6094" y2="222.3672"/><line style="stroke:#181818;stroke-width:0.5;stroke-dasharray:5.0,5.0;" x1="173.4893" x2="173.4893" y1="37.6094" y2="222.3672"/><line style="stroke:#181818;stroke-width:0.5;stroke-dasharray:5.0,5.0;" x1="314.9375" x2="314.9375" y1="37.6094" y2="222.3672"/><rect fill="#E2E2F0" height="31.6094" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="82.4893" x="5" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="68.4893" x="12" y="26.5332">Application</text><rect fill="#E2E2F0" height="31.6094" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="82.4893" x="5" y="221.3672"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="68.4893" x="12" y="242.9004">Application</text><rect fill="#E2E2F0" height="31.6094" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="152.4482" x="97.4893" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="138.4482" x="104.4893" y="26.5332">ESP-IDF Wi-Fi Library</text><rect fill="#E2E2F0" height="31.6094" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="152.4482" x="97.4893" y="221.3672"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="138.4482" x="104.4893" y="242.9004">ESP-IDF Wi-Fi Library</text><rect fill="#E2E2F0" height="31.6094" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="111.2275" x="259.9375" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="97.2275" x="266.9375" y="26.5332">Wi-Fi Hardware</text><rect fill="#E2E2F0" height="31.6094" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="111.2275" x="259.9375" y="221.3672"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="97.2275" x="266.9375" y="242.9004">Wi-Fi Hardware</text><polygon fill="#181818" points="161.7134,65.9609,171.7134,69.9609,161.7134,73.9609,165.7134,69.9609" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="46.2446" x2="167.7134" y1="69.9609" y2="69.9609"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="82.3545" x="53.2446" y="65.1045">esp_wifi_xxx()</text><polygon fill="#181818" points="303.5513,79.9609,313.5513,83.9609,303.5513,87.9609,307.5513,83.9609" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="173.7134" x2="309.5513" y1="83.9609" y2="83.9609"/><line style="stroke:#181818;stroke-width:1.0;" x1="315.5513" x2="357.5513" y1="114.3125" y2="114.3125"/><line style="stroke:#181818;stroke-width:1.0;" x1="357.5513" x2="357.5513" y1="114.3125" y2="127.3125"/><line style="stroke:#181818;stroke-width:1.0;" x1="316.5513" x2="357.5513" y1="127.3125" y2="127.3125"/><polygon fill="#181818" points="326.5513,123.3125,316.5513,127.3125,326.5513,131.3125,322.5513,127.3125" style="stroke:#181818;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="68.6182" x="322.5513" y="109.4561">Wi-Fi action</text><polygon fill="#181818" points="184.7134,153.6641,174.7134,157.6641,184.7134,161.6641,180.7134,157.6641" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;stroke-dasharray:2.0,2.0;" x1="178.7134" x2="314.5513" y1="157.6641" y2="157.6641"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="53.479" x="190.7134" y="152.8076">response</text><polygon fill="#181818" points="57.2446,200.3672,47.2446,204.3672,57.2446,208.3672,53.2446,204.3672" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;stroke-dasharray:2.0,2.0;" x1="51.2446" x2="172.7134" y1="204.3672" y2="204.3672"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="79.8535" x="63.2446" y="183.1592">return value +</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="68.6436" x="63.2446" y="199.5107">data (if any)</text><!--SRC=[LOwz2eD03CVtUuhWf1HVmA5GQAK5XqA7BWL9zOI0d25tLdtx6XLfbq1-_u-4KG9LnEW2d9XRgZ1Gvm0z8BFX7pcwFExfxPp3azASeA2te4pHQgL_wsgvejG3Ybqy0pLap5mAwL43a87rN2eknt6C4wDmrfHaHkU-RIUnqjysQM-HkQPptgxv1RFIq8k33xQzXSFBrHWGOce0tPIOBm00]--></g></svg>
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
@@ -0,0 +1,13 @@
|
||||
@startuml
|
||||
|
||||
participant Application as app
|
||||
participant "ESP-IDF Wi-Fi Library" as api
|
||||
participant "Wi-Fi Hardware" as wifi
|
||||
|
||||
app -> api : esp_wifi_xxx()
|
||||
api -> wifi
|
||||
wifi -> wifi : Wi-Fi action
|
||||
wifi --> api : response
|
||||
api --> app : return value +\ndata (if any)
|
||||
|
||||
@enduml
|
||||
|
After Width: | Height: | Size: 7.9 KiB |
@@ -0,0 +1,34 @@
|
||||
@startuml
|
||||
|
||||
Title SPI HD Host and Slave Initialization
|
||||
|
||||
participant Slave
|
||||
participant Host
|
||||
|
||||
note across: Init
|
||||
|
||||
Host -> Slave: Read SLAVE_READY reg
|
||||
Slave -> Host: Not Ready (!0xEE)
|
||||
|
||||
...(loop)...
|
||||
|
||||
note over Slave: Now Ready: Set\nSLAVE_READY = 0xEE
|
||||
|
||||
Host -> Slave: Read SLAVE_READY reg
|
||||
Slave -> Host: Ready (0xEE)
|
||||
|
||||
Host -> Slave: Set SLAVE_CONTROL = 1
|
||||
|
||||
note over Slave: Open Data Path
|
||||
|
||||
note over Slave: Prepare Capability data
|
||||
|
||||
Slave -> Host: Assert Data_Ready
|
||||
|
||||
Host -> Slave: Read Data
|
||||
|
||||
Slave -> Host: Capability
|
||||
|
||||
note over Host: Configure based\non slave capabilities
|
||||
|
||||
@enduml
|
||||
|
After Width: | Height: | Size: 6.1 KiB |
@@ -0,0 +1,27 @@
|
||||
@startuml
|
||||
|
||||
Title SPI HD Host Read
|
||||
|
||||
participant Slave
|
||||
participant Host
|
||||
|
||||
note over Slave: Prepare data to send
|
||||
|
||||
Slave -> Host: Assert Data_Ready
|
||||
|
||||
Host -> Slave: Read TX_BUF_LEN
|
||||
note over Host: Bytes to transfer =\nTX_BUF_LEN - (cached)TX_BUF_LEN
|
||||
|
||||
Host -> Slave: Send CMD9
|
||||
|
||||
note over Slave: De-Assert Data_Ready
|
||||
|
||||
Host -> Slave: Send RDDMA
|
||||
|
||||
Slave -> Host: Transfer Data
|
||||
|
||||
Host -> Slave: CMD8\n(at end of transfer)
|
||||
|
||||
note over Host: update (cached)TX_BUF_LEN
|
||||
|
||||
@enduml
|
||||
|
After Width: | Height: | Size: 5.5 KiB |
@@ -0,0 +1,24 @@
|
||||
@startuml
|
||||
|
||||
Title SPI HD Host Write
|
||||
|
||||
participant Slave
|
||||
participant Host
|
||||
|
||||
note over Host: Prepare data to send
|
||||
|
||||
Host -> Slave: Read RX_BUF_LEN
|
||||
|
||||
note over Host: available buffers =\nRX_BUF_LEN - (cached)RX_BUF_LEN
|
||||
|
||||
note over Host: loop reading RX_BUF_LEN until\nbuffers available
|
||||
|
||||
Host -> Slave: Send WRDMA
|
||||
|
||||
Host -> Slave: Tranfer Data
|
||||
|
||||
Host -> Slave: Send WR_DONE\n(at end of transfer)
|
||||
|
||||
note over Host: update (cached)RX_BUF_LEN
|
||||
|
||||
@enduml
|
||||
|
After Width: | Height: | Size: 22 KiB |
@@ -0,0 +1,42 @@
|
||||
@startuml
|
||||
hide time-axis
|
||||
|
||||
binary "Chip Select" as cs
|
||||
clock "Clock" as clk with period 1
|
||||
concise "Data0-1" as data
|
||||
|
||||
Title SPI HD Transaction Using Two Data Lines
|
||||
|
||||
@0
|
||||
cs is high
|
||||
data is {-}
|
||||
|
||||
@+1
|
||||
cs is low
|
||||
data is "Command (D0 only)"
|
||||
|
||||
@+8
|
||||
data is "Address (D0-1)"
|
||||
|
||||
@+4
|
||||
data is "Dummy"
|
||||
|
||||
@+8
|
||||
data is "Data (D0-1)"
|
||||
|
||||
@+4
|
||||
data is "..."
|
||||
|
||||
@+4
|
||||
cs is high
|
||||
data is {-}
|
||||
|
||||
@1 <-> @9 : 8 clk
|
||||
@9 <-> @13 : 4 clk
|
||||
@13 <-> @21 : 8 clk
|
||||
@21 <-> @25 : 4 clk
|
||||
@25 <-> @29 : 4 clk
|
||||
|
||||
highlight 21 to 29 : Optional for SPI Transactions\nwithout data
|
||||
|
||||
@enduml
|
||||
|
After Width: | Height: | Size: 19 KiB |
@@ -0,0 +1,42 @@
|
||||
@startuml
|
||||
hide time-axis
|
||||
|
||||
binary "Chip Select" as cs
|
||||
clock "Clock" as clk with period 1
|
||||
concise "Data0-3" as data
|
||||
|
||||
Title SPI HD Transaction Using Four Data Lines
|
||||
|
||||
@0
|
||||
cs is high
|
||||
data is {-}
|
||||
|
||||
@+1
|
||||
cs is low
|
||||
data is "Command (D0 only)"
|
||||
|
||||
@+8
|
||||
data is "Address (D0-3)"
|
||||
|
||||
@+2
|
||||
data is "Dummy"
|
||||
|
||||
@+8
|
||||
data is "Data (D0-3)"
|
||||
|
||||
@+2
|
||||
data is "..."
|
||||
|
||||
@+2
|
||||
cs is high
|
||||
data is {-}
|
||||
|
||||
@1 <-> @9 : 8 clk
|
||||
@9 <-> @11 : 2 clk
|
||||
@11 <-> @19 : 8 clk
|
||||
@19 <-> @21 : 2 clk
|
||||
@21 <-> @23 : 2 clk
|
||||
|
||||
highlight 19 to 23 : Optional for SPI Transactions\nwithout data
|
||||
|
||||
@enduml
|
||||
@@ -0,0 +1,133 @@
|
||||
# List of RPC Commands implmenented in ESP-Hosted
|
||||
|
||||
A list of RPC Commands implemented in ESP-Hosted based on release version.
|
||||
|
||||
The RPC IDs listed here are for requests and events. Each request will have a corresponding response.
|
||||
|
||||
## List of RPC Requests
|
||||
|
||||
| No. | RPC ID | RPC Command | Added in Release |
|
||||
|----:|-------:|------------------------------------|-----------------:|
|
||||
| 1 | 257 | GetMacAddress | 0.0.6 |
|
||||
| 2 | 258 | SetMacAddress | 0.0.6 |
|
||||
| 3 | 259 | GetMode | 0.0.6 |
|
||||
| 4 | 260 | SetMode | 0.0.6 |
|
||||
| 5 | 261 | SuppDppInit | 2.4.3 |
|
||||
| 6 | 262 | SuppDppDeinit | 2.4.3 |
|
||||
| 7 | 263 | SuppDppBootstrapGen | 2.4.3 |
|
||||
| 8 | 264 | SuppDppStartListen | 2.4.3 |
|
||||
| 9 | 265 | SuppDppStopListen | 2.4.3 |
|
||||
| 10 | 270 | SetPs | 0.0.6 |
|
||||
| 11 | 271 | GetPs | 0.0.6 |
|
||||
| 12 | 272 | OTABegin | 0.0.6 |
|
||||
| 13 | 273 | OTAWrite | 0.0.6 |
|
||||
| 14 | 274 | OTAEnd | 0.0.6 |
|
||||
| 15 | 275 | WifiSetMaxTxPower | 0.0.6 |
|
||||
| 16 | 276 | WifiGetMaxTxPower | 0.0.6 |
|
||||
| 17 | 277 | ConfigHeartbeat | 0.0.6 |
|
||||
| 18 | 278 | WifiInit | 0.0.6 |
|
||||
| 19 | 279 | WifiDeinit | 0.0.6 |
|
||||
| 20 | 280 | WifiStart | 0.0.6 |
|
||||
| 21 | 281 | WifiStop | 0.0.6 |
|
||||
| 22 | 282 | WifiConnect | 0.0.6 |
|
||||
| 23 | 283 | WifiDisconnect | 0.0.6 |
|
||||
| 24 | 284 | WifiSetConfig | 0.0.6 |
|
||||
| 25 | 285 | WifiGetConfig | 0.0.6 |
|
||||
| 26 | 286 | WifiScanStart | 0.0.6 |
|
||||
| 27 | 287 | WifiScanStop | 0.0.6 |
|
||||
| 28 | 288 | WifiScanGetApNum | 0.0.6 |
|
||||
| 29 | 289 | WifiScanGetApRecords | 0.0.6 |
|
||||
| 30 | 290 | WifiClearApList | 0.0.6 |
|
||||
| 31 | 291 | WifiRestore | 0.0.6 |
|
||||
| 32 | 292 | WifiClearFastConnect | 0.0.6 |
|
||||
| 33 | 293 | WifiDeauthSta | 0.0.6 |
|
||||
| 34 | 294 | WifiStaGetApInfo | 0.0.6 |
|
||||
| 35 | 297 | WifiSetProtocol | 0.0.6 |
|
||||
| 36 | 298 | WifiGetProtocol | 0.0.6 |
|
||||
| 37 | 299 | WifiSetBandwidth | 0.0.6 |
|
||||
| 38 | 300 | WifiGetBandwidth | 0.0.6 |
|
||||
| 39 | 301 | WifiSetChannel | 0.0.6 |
|
||||
| 40 | 302 | WifiGetChannel | 0.0.6 |
|
||||
| 41 | 303 | WifiSetCountry | 0.0.6 |
|
||||
| 42 | 304 | WifiGetCountry | 0.0.6 |
|
||||
| 43 | 311 | WifiApGetStaList | 0.0.6 |
|
||||
| 44 | 312 | WifiApGetStaAid | 0.0.6 |
|
||||
| 45 | 313 | WifiSetStorage | 0.0.6 |
|
||||
| 46 | 325 | WifiSetInactiveTime | 2.2.2 |
|
||||
| 47 | 326 | WifiGetInactiveTime | 2.2.2 |
|
||||
| 48 | 334 | WifiSetCountryCode | 0.0.6 |
|
||||
| 49 | 335 | WifiGetCountryCode | 0.0.6 |
|
||||
| 50 | 338 | WifiStaGetAid | 0.0.10 |
|
||||
| 51 | 339 | WifiStaGetNegotiatedPhymode | 1.1.3 |
|
||||
| 52 | 341 | WifiStaGetRssi | 0.0.6 |
|
||||
| 53 | 342 | WifiSetProtocols | 0.0.10 |
|
||||
| 54 | 343 | WifiGetProtocols | 0.0.10 |
|
||||
| 55 | 344 | WifiSetBandwidths | 0.0.10 |
|
||||
| 56 | 345 | WifiGetBandwidths | 0.0.10 |
|
||||
| 57 | 346 | WifiSetBand | 0.0.10 |
|
||||
| 58 | 347 | WifiGetBand | 0.0.10 |
|
||||
| 59 | 348 | WifiSetBandMode | 0.0.10 |
|
||||
| 60 | 349 | WifiGetBandMode | 0.0.10 |
|
||||
| 61 | 350 | GetCoprocessorFwVersion | 1.0.0 |
|
||||
| 62 | 351 | WifiScanGetApRecord | 1.1.3 |
|
||||
| 63 | 352 | SetDhcpDnsStatus | 2.1.0 |
|
||||
| 64 | 353 | GetDhcpDnsStatus | 2.1.0 |
|
||||
| 65 | 354 | WifiStaTwtConfig | 2.2.2 |
|
||||
| 66 | 355 | WifiStaItwtSetup | 2.2.2 |
|
||||
| 67 | 356 | WifiStaItwtTeardown | 2.2.2 |
|
||||
| 68 | 357 | WifiStaItwtSuspend | 2.2.2 |
|
||||
| 69 | 358 | WifiStaItwtGetFlowIdStatus | 2.2.2 |
|
||||
| 70 | 359 | WifiStaItwtSendProbeReq | 2.2.2 |
|
||||
| 71 | 360 | WifiStaItwtSetTargetWakeTimeOffset | 2.2.2 |
|
||||
| 72 | 361 | WifiStaEnterpriseEnable | 2.4.0 |
|
||||
| 73 | 362 | WifiStaEnterpriseDisable | 2.4.0 |
|
||||
| 74 | 363 | EapSetIdentity | 2.4.0 |
|
||||
| 75 | 364 | EapClearIdentity | 2.4.0 |
|
||||
| 76 | 365 | EapSetUsername | 2.4.0 |
|
||||
| 77 | 366 | EapClearUsername | 2.4.0 |
|
||||
| 78 | 367 | EapSetPassword | 2.4.0 |
|
||||
| 79 | 368 | EapClearPassword | 2.4.0 |
|
||||
| 80 | 369 | EapSetNewPassword | 2.4.0 |
|
||||
| 81 | 370 | EapClearNewPassword | 2.4.0 |
|
||||
| 82 | 371 | EapSetCaCert | 2.4.0 |
|
||||
| 83 | 372 | EapClearCaCert | 2.4.0 |
|
||||
| 84 | 373 | EapSetCertificateAndKey | 2.4.0 |
|
||||
| 85 | 374 | EapClearCertificateAndKey | 2.4.0 |
|
||||
| 86 | 375 | EapGetDisableTimeCheck | 2.4.0 |
|
||||
| 87 | 376 | EapSetTtlsPhase2Method | 2.4.0 |
|
||||
| 88 | 377 | EapSetSuiteb192bitCertification | 2.4.0 |
|
||||
| 89 | 378 | EapSetPacFile | 2.4.0 |
|
||||
| 90 | 379 | EapSetFastParams | 2.4.0 |
|
||||
| 91 | 380 | EapUseDefaultCertBundle | 2.4.0 |
|
||||
| 92 | 381 | WifiSetOkcSupport | 2.4.0 |
|
||||
| 93 | 382 | EapSetDomainName | 2.4.0 |
|
||||
| 94 | 383 | EapSetDisableTimeCheck | 2.4.0 |
|
||||
| 95 | 384 | EapSetEapMethods | 2.4.0 |
|
||||
| 96 | 385 | IfaceMacAddrSetGet | 2.5.2 |
|
||||
| 97 | 386 | IfaceMacAddrLenGet | 2.5.2 |
|
||||
| 98 | 387 | FeatureControl | 2.5.2 |
|
||||
| 99 | 266 | OTAActivate | 2.6.0 |
|
||||
|
||||
## List of RPC Events
|
||||
|
||||
| No. | RPC ID | RPC Event | Added in Release |
|
||||
|----:|-------:|--------------------|-----------------:|
|
||||
| 1 | 769 | ESPInit | 0.0.6 |
|
||||
| 2 | 770 | Heartbeat | 0.0.6 |
|
||||
| 3 | 771 | AP_StaConnected | 0.0.6 |
|
||||
| 4 | 772 | AP_StaDisconnected | 0.0.6 |
|
||||
| 5 | 773 | WifiEventNoArgs | 0.0.6 |
|
||||
| 6 | 774 | StaScanDone | 0.0.6 |
|
||||
| 7 | 775 | StaConnected | 0.0.6 |
|
||||
| 8 | 776 | StaDisconnected | 0.0.6 |
|
||||
| 9 | 777 | DhcpDnsStatus | 2.0.17 |
|
||||
| 10 | 778 | StaItwtSetup | 2.2.2 |
|
||||
| 11 | 779 | StaItwtTeardown | 2.2.2 |
|
||||
| 12 | 780 | StaItwtSuspend | 2.2.2 |
|
||||
| 13 | 781 | StaItwtProbe | 2.2.2 |
|
||||
| 14 | 782 | SuppDppUriReady | 2.4.3 |
|
||||
| 15 | 783 | SuppDppCfgRecvd | 2.4.3 |
|
||||
| 16 | 784 | SuppDppFail | 2.4.3 |
|
||||
| 17 | 785 | WifiDppUriReady | 2.4.3 |
|
||||
| 18 | 786 | WifiDppCfgRecvd | 2.4.3 |
|
||||
| 19 | 787 | WifiDppFail | 2.4.3 |
|
||||
226
managed_components/espressif__esp_hosted/docs/migration_guide.md
Normal file
@@ -0,0 +1,226 @@
|
||||
This migration guide documents key changes in ESP-Hosted that users must be aware of when migrating from older versions.
|
||||
|
||||
#### Index
|
||||
1. [2.6.0 - ESP-Hosted Slave OTA](#coloryellow-text2512---esp-hosted-slave-ota)
|
||||
2. [2.5.2 - Bluetooth Controller on Co-Processor Disabled by Default](#coloryellow-text252---bluetooth-controller-on-co-processor-disabled-by-default)
|
||||
|
||||
|
||||
# $${\color{yellow} \text{2.6.0 - ESP-Hosted Slave OTA}}$$
|
||||
|
||||
|
||||
## Migration needed from versions
|
||||
|
||||
| Slave version | Host version |
|
||||
| ------------- | ------------ |
|
||||
| > 2.5.X | > 2.5.X |
|
||||
|
||||
## Reason for change
|
||||
|
||||
1. The existing `esp_hosted_slave_ota()` API was restrictive, supporting only HTTP-based OTA updates.
|
||||
The OTA APIs are now exposed so developers can implement their own OTA mechanisms.
|
||||
2. The port layer previously contained OTA logic, which forced inclusion of the HTTP client in the host codebase even when not required.
|
||||
|
||||
## Changes required on host
|
||||
|
||||
If you are migrating from the old `esp_hosted_slave_ota()` function, update your code as follows.
|
||||
|
||||
### Old API (deprecated)
|
||||
|
||||
```c
|
||||
#include "esp_hosted.h"
|
||||
|
||||
const char *image_url = "http://example.com/network_adapter.bin";
|
||||
esp_err_t ret = esp_hosted_slave_ota(image_url);
|
||||
if (ret == ESP_OK) {
|
||||
printf("OTA update failed[%d]\n", ret);
|
||||
}
|
||||
```
|
||||
|
||||
## New APIs
|
||||
|
||||
The slave OTA process is now performed using the following APIs.
|
||||
|
||||
### `esp_hosted_slave_ota_begin()`
|
||||
|
||||
```c
|
||||
esp_err_t esp_hosted_slave_ota_begin(void);
|
||||
```
|
||||
|
||||
Initializes the OTA process on the slave.
|
||||
|
||||
* Arguments: None
|
||||
* Returns: `ESP_OK` on success, or an error code on failure
|
||||
* What it does:
|
||||
|
||||
* Prepares the slave for firmware reception
|
||||
* Allocates OTA buffers
|
||||
* Sets up the OTA partition on the slave
|
||||
|
||||
### `esp_hosted_slave_ota_write()`
|
||||
|
||||
```c
|
||||
esp_err_t esp_hosted_slave_ota_write(const void *data, size_t size);
|
||||
```
|
||||
|
||||
Sends firmware data chunks to the slave.
|
||||
|
||||
* Arguments:
|
||||
|
||||
* `data`: Pointer to firmware data chunk
|
||||
* `size`: Size of the data chunk (typically 1400–1500 bytes)
|
||||
* Returns: `ESP_OK` on success, or an error code on failure
|
||||
* What it does:
|
||||
|
||||
* Transmits firmware data over ESP-Hosted transport (SDIO/SPI/UART)
|
||||
* The slave writes data to its OTA partition
|
||||
* Can be called multiple times for large firmware images
|
||||
|
||||
### `esp_hosted_slave_ota_end()`
|
||||
|
||||
```c
|
||||
esp_err_t esp_hosted_slave_ota_end(void);
|
||||
```
|
||||
|
||||
Finalizes the OTA process.
|
||||
|
||||
* Arguments: None
|
||||
* Returns: `ESP_OK` on success, or an error code on failure
|
||||
* What it does:
|
||||
|
||||
* Validates the complete firmware image on the slave
|
||||
* Calculates and verifies checksums
|
||||
* Marks the new firmware as valid but not yet active
|
||||
|
||||
### `esp_hosted_slave_ota_activate()`
|
||||
|
||||
```c
|
||||
esp_err_t esp_hosted_slave_ota_activate(void);
|
||||
```
|
||||
|
||||
Activates the newly flashed firmware.
|
||||
|
||||
* Arguments: None
|
||||
* Returns: `ESP_OK` on success, or an error code on failure
|
||||
* What it does:
|
||||
|
||||
* Switches the slave’s boot partition to the new firmware
|
||||
* Triggers slave reboot with the new firmware
|
||||
* Note: After this call, the slave restarts with the new firmware
|
||||
|
||||
## How to use the new APIs
|
||||
|
||||
A dedicated example demonstrates the usage of the new OTA APIs:
|
||||
[Slave OTA using ESP-Hosted transport](../examples/host_performs_slave_ota/README.md)
|
||||
|
||||
> [!TIP]
|
||||
> The example uses the new ESP-Hosted-MCU Slave OTA APIs.
|
||||
> You can reuse or customize it for your own OTA workflow.
|
||||
|
||||
Example methods supported:
|
||||
|
||||
| Method | Description |
|
||||
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Partition method | Slave firmware binary stored in Host’s partition table (`slave_fw` partition). Requires an extra host partition, but no Wi-Fi connectivity. |
|
||||
| LittleFS method | Host partition formatted as LittleFS and stores the slave firmware. Requires an extra host partition, but no Wi-Fi connectivity. |
|
||||
| HTTPS method | Slave firmware binary hosted on an HTTPS server. No extra host partition needed, but requires Wi-Fi connectivity. |
|
||||
|
||||
# $${\color{yellow} \text{2.5.2 - Bluetooth Controller on Co-Processor Disabled by Default}}$$
|
||||
|
||||
## Migration needed from versions
|
||||
|
||||
| Slave version | Host version |
|
||||
| ------------- | ------------ |
|
||||
| > 2.5.1 | > 2.5.1 |
|
||||
|
||||
Before v2.5.2, the Bluetooth controller on the co-processor was initialized and enabled by default.
|
||||
From v2.5.2 onwards, it starts in a disabled state.
|
||||
|
||||
## Reason for change
|
||||
|
||||
This allows users to modify the Bluetooth MAC address before the controller is initialized, as it can only be changed prior to enabling the controller.
|
||||
|
||||
## New APIs
|
||||
|
||||
### `esp_hosted_bt_controller_init()`
|
||||
|
||||
```c
|
||||
esp_err_t esp_hosted_bt_controller_init(void);
|
||||
```
|
||||
|
||||
Initializes the Bluetooth controller on the co-processor.
|
||||
|
||||
* Arguments: None
|
||||
* Returns: `ESP_OK` on success, or an error code on failure
|
||||
* What it does:
|
||||
|
||||
* Allocates and initializes controller resources
|
||||
* Prepares the controller for activation
|
||||
|
||||
### `esp_hosted_bt_controller_deinit()`
|
||||
|
||||
```c
|
||||
esp_err_t esp_hosted_bt_controller_deinit(bool mem_release);
|
||||
```
|
||||
|
||||
Deinitializes the Bluetooth controller on the co-processor.
|
||||
|
||||
* Arguments:
|
||||
|
||||
* `mem_release`: If true, releases controller memory (cannot be reused)
|
||||
* Returns: `ESP_OK` on success, or an error code on failure
|
||||
* What it does:
|
||||
|
||||
* Stops the Bluetooth controller
|
||||
* Optionally releases memory used by the controller
|
||||
* Once released, the controller cannot be reinitialized without reboot
|
||||
|
||||
### `esp_hosted_bt_controller_enable()`
|
||||
|
||||
```c
|
||||
esp_err_t esp_hosted_bt_controller_enable(void);
|
||||
```
|
||||
|
||||
Enables the Bluetooth controller on the co-processor.
|
||||
|
||||
* Arguments: None
|
||||
* Returns: `ESP_OK` on success, or an error code on failure
|
||||
* What it does:
|
||||
|
||||
* Starts the Bluetooth controller task
|
||||
* Enables radio and HCI interfaces for Bluetooth operation
|
||||
|
||||
### `esp_hosted_bt_controller_disable()`
|
||||
|
||||
```c
|
||||
esp_err_t esp_hosted_bt_controller_disable(void);
|
||||
```
|
||||
|
||||
Disables the Bluetooth controller on the co-processor.
|
||||
|
||||
* Arguments: None
|
||||
* Returns: `ESP_OK` on success, or an error code on failure
|
||||
* What it does:
|
||||
|
||||
* Gracefully stops the controller
|
||||
* Disables the Bluetooth radio
|
||||
* Must be called before deinitializing the controller
|
||||
|
||||
## Changes required on host
|
||||
|
||||
Before starting the Bluetooth stack on the host:
|
||||
|
||||
1. Call `esp_hosted_connect_to_slave()` to establish a connection with the slave.
|
||||
2. (Optional) Set the Bluetooth MAC address using `esp_hosted_iface_mac_addr_set()`.
|
||||
3. Initialize the Bluetooth controller using `esp_hosted_bt_controller_init()`.
|
||||
4. Enable the Bluetooth controller using `esp_hosted_bt_controller_enable()`.
|
||||
|
||||
See [Initializing the Bluetooth Controller](bluetooth_design.md#31-initializing-the-bluetooth-controller) for more details.
|
||||
|
||||
## How to use the new APIs
|
||||
|
||||
You can now start the host Bluetooth stack and use Bluetooth as usual.
|
||||
All ESP-Hosted Bluetooth host examples (NimBLE and BlueDroid) have been updated accordingly.
|
||||
|
||||
For an example showing how to change the BT MAC address before starting the controller, refer to:
|
||||
[BT Controller Example](../examples/host_bt_controller_mac_addr/)
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
# ESP-Hosted Performance Optimization Guide
|
||||
|
||||
Quick reference for optimizing ESP-Hosted performance across co-processors and different transport interfaces.
|
||||
|
||||
<details>
|
||||
<summary>Table of Contents</summary>
|
||||
|
||||
1. [Quick Start - High Performance Config](#1-quick-start---high-performance-config)
|
||||
|
||||
1.1 [ESP32-C6 as Co-Procesor](#11-esp32-c6-as-co-procesor)
|
||||
|
||||
1.2 [ESP32-C5 as Co-Processor](#12-esp32-c5-as-co-processor)
|
||||
|
||||
1.3 [ESP32-C61 as Co-Processor](#13-esp32-c61-as-co-processor)
|
||||
|
||||
1.4 [ESP32-C2 as Co-Processor](#14-esp32-c2-as-co-processor)
|
||||
|
||||
2. [Transport Optimization](#2-transport-optimization)
|
||||
|
||||
2.1 [SDIO (Highest Performance)](#21-sdio-highest-performance)
|
||||
|
||||
2.2 [SPI Full-Duplex](#22-spi-full-duplex)
|
||||
|
||||
2.3 [2.3 SPI Half-Duplex](#23-spi-half-duplex)
|
||||
|
||||
2.4 [UART (Lowest Performance)](#24-uart-lowest-performance)
|
||||
|
||||
3. [Memory Optimization](#3-memory-optimization)
|
||||
|
||||
4. [Hardware Guidelines](#4-hardware-guidelines)
|
||||
|
||||
4.1 [Critical Requirements](#41-critical-requirements)
|
||||
|
||||
4.2 [PCB Design Checklist](#42-pcb-design-checklist)
|
||||
|
||||
4.3 [Development Workflow](#43-development-workflow)
|
||||
|
||||
</details>
|
||||
|
||||
## 1 Quick Start - High Performance Config
|
||||
|
||||
For immediate performance gains, add these to your host's `sdkconfig.defaults.esp32XX` file based on the co-processor you are using.
|
||||
|
||||
> [!NOTE]
|
||||
> Adjust the values based on your MCU host's and co-processor memory capacity. These values may change when more testing shows better performance figures.
|
||||
|
||||
Test conditions for throughput numbers using the performance settings:
|
||||
|
||||
- raw: data transferred from sender to receiver over transport
|
||||
- iPerf used to measure TCP and UDP throughput
|
||||
|
||||
A diagram showing the setup used to get the throughput numbers.
|
||||
|
||||
<img src="images/PerformanceSetup-ShieldBox.png" alt="Shield box testing setup" width="800" />
|
||||
|
||||
> [!NOTE]
|
||||
> The diagram shows the router and ESP board in a shield box. The performance numbers here were obtained from an 'Open Air' configuration, without using a shield box.
|
||||
|
||||
### 1.1 ESP32-C6 as Co-Procesor
|
||||
|
||||
```
|
||||
### sdkconfig for ESP32-P4 + C6 as co-processor
|
||||
# Wi-Fi Performance
|
||||
CONFIG_WIFI_RMT_STATIC_RX_BUFFER_NUM=16
|
||||
CONFIG_WIFI_RMT_DYNAMIC_RX_BUFFER_NUM=64
|
||||
CONFIG_WIFI_RMT_DYNAMIC_TX_BUFFER_NUM=64
|
||||
CONFIG_WIFI_RMT_AMPDU_TX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_TX_BA_WIN=32
|
||||
CONFIG_WIFI_RMT_AMPDU_RX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_RX_BA_WIN=32
|
||||
|
||||
# TCP/IP Performance
|
||||
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=65534
|
||||
CONFIG_LWIP_TCP_WND_DEFAULT=65534
|
||||
CONFIG_LWIP_TCP_RECVMBOX_SIZE=64
|
||||
CONFIG_LWIP_UDP_RECVMBOX_SIZE=64
|
||||
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=64
|
||||
CONFIG_LWIP_TCP_SACK_OUT=y
|
||||
```
|
||||
|
||||
**Throughput using the settings.**
|
||||
|
||||
Using SDIO Transport, 4-bits, running at 40MHz, connected to a 2.4GHz network over the air
|
||||
|
||||
| Type | Direction | MBits/s |
|
||||
|------------|---------------|--------:|
|
||||
| Raw | P4 to C6 | 72 |
|
||||
| Raw | C6 to P4 | 80 |
|
||||
| iPerf, TCP | P4 to Test PC | 32 |
|
||||
| iPerf, UDP | P4 to Test PC | 50 |
|
||||
| iPerf, TCP | Test PC to P4 | 30 |
|
||||
| iPerf, UDP | Test PC to P4 | 49 |
|
||||
|
||||
### 1.2 ESP32-C5 as Co-Processor
|
||||
|
||||
```
|
||||
### sdkconfig for ESP32-P4 + C5 as co-processor
|
||||
# Wi-Fi Performance
|
||||
CONFIG_WIFI_RMT_STATIC_RX_BUFFER_NUM=10
|
||||
CONFIG_WIFI_RMT_DYNAMIC_RX_BUFFER_NUM=32
|
||||
CONFIG_WIFI_RMT_DYNAMIC_TX_BUFFER_NUM=32
|
||||
CONFIG_WIFI_RMT_AMPDU_TX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_TX_BA_WIN=32
|
||||
CONFIG_WIFI_RMT_AMPDU_RX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_RX_BA_WIN=16
|
||||
|
||||
# TCP/IP Performance
|
||||
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=11520
|
||||
CONFIG_LWIP_TCP_WND_DEFAULT=32768
|
||||
CONFIG_LWIP_TCP_RECVMBOX_SIZE=48
|
||||
CONFIG_LWIP_UDP_RECVMBOX_SIZE=48
|
||||
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=48
|
||||
|
||||
CONFIG_LWIP_TCP_SACK_OUT=y
|
||||
```
|
||||
|
||||
**Throughput using the settings.**
|
||||
|
||||
Using SDIO Transport, 4-bits, running at 40MHz, connected to a 5GHz network over the air
|
||||
|
||||
| Type | Direction | MBits/s |
|
||||
|------------|---------------|--------:|
|
||||
| Raw | P4 to C5 | 72 |
|
||||
| Raw | C5 to P4 | 81 |
|
||||
| iPerf, TCP | P4 to Test PC | 23 |
|
||||
| iPerf, UDP | P4 to Test PC | 67 |
|
||||
| iPerf, TCP | Test PC to P4 | 32 |
|
||||
| iPerf, UDP | Test PC to P4 | 68 |
|
||||
|
||||
### 1.3 ESP32-C61 as Co-Processor
|
||||
|
||||
```
|
||||
### sdkconfig for ESP32-P4 + C61 as co-processor
|
||||
# Wi-Fi Performance
|
||||
CONFIG_WIFI_RMT_STATIC_RX_BUFFER_NUM=10
|
||||
CONFIG_WIFI_RMT_DYNAMIC_RX_BUFFER_NUM=16
|
||||
CONFIG_WIFI_RMT_DYNAMIC_TX_BUFFER_NUM=16
|
||||
CONFIG_WIFI_RMT_AMPDU_TX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_TX_BA_WIN=16
|
||||
CONFIG_WIFI_RMT_AMPDU_RX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_RX_BA_WIN=16
|
||||
|
||||
# TCP/IP Performance
|
||||
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=20480
|
||||
CONFIG_LWIP_TCP_WND_DEFAULT=20480
|
||||
CONFIG_LWIP_TCP_RECVMBOX_SIZE=48
|
||||
CONFIG_LWIP_UDP_RECVMBOX_SIZE=64
|
||||
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=48
|
||||
|
||||
CONFIG_LWIP_TCP_SACK_OUT=y
|
||||
```
|
||||
|
||||
**Throughput using the settings.**
|
||||
|
||||
Using SPI-FD Transport, running at 40MHz, connected to a 2.4GHz network over the air
|
||||
|
||||
| Type | Direction | MBits/s |
|
||||
|------------|---------------|--------:|
|
||||
| Raw | P4 to C61 | 25 |
|
||||
| Raw | C61 to P4 | 26 |
|
||||
| iPerf, TCP | P4 to Test PC | 12 |
|
||||
| iPerf, UDP | P4 to Test PC | 18 |
|
||||
| iPerf, TCP | Test PC to P4 | 15 |
|
||||
| iPerf, UDP | Test PC to P4 | 23 |
|
||||
|
||||
### 1.4 ESP32-C2 as Co-Processor
|
||||
|
||||
```
|
||||
### sdkconfig for ESP32-P4 + C2 as co-processor
|
||||
# Wi-Fi Performance
|
||||
CONFIG_WIFI_RMT_STATIC_RX_BUFFER_NUM=10
|
||||
CONFIG_WIFI_RMT_DYNAMIC_RX_BUFFER_NUM=32
|
||||
CONFIG_WIFI_RMT_DYNAMIC_TX_BUFFER_NUM=32
|
||||
CONFIG_WIFI_RMT_AMPDU_TX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_TX_BA_WIN=6
|
||||
CONFIG_WIFI_RMT_AMPDU_RX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_RX_BA_WIN=6
|
||||
|
||||
# TCP/IP Performance
|
||||
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=16384
|
||||
CONFIG_LWIP_TCP_WND_DEFAULT=32768
|
||||
CONFIG_LWIP_TCP_RECVMBOX_SIZE=20
|
||||
CONFIG_LWIP_UDP_RECVMBOX_SIZE=20
|
||||
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=20
|
||||
|
||||
CONFIG_LWIP_TCP_SACK_OUT=y
|
||||
```
|
||||
|
||||
**Throughput using the settings.**
|
||||
|
||||
Using SPI-FD Transport, running at 40MHz, connected to a 2.4GHz network over the air
|
||||
|
||||
| Type | Direction | MBits/s |
|
||||
|------------|---------------|--------:|
|
||||
| Raw | P4 to C2 | 25 |
|
||||
| Raw | C2 to P4 | 26 |
|
||||
| iPerf, TCP | P4 to Test PC | 12 |
|
||||
| iPerf, UDP | P4 to Test PC | 18 |
|
||||
| iPerf, TCP | Test PC to P4 | 13 |
|
||||
| iPerf, UDP | Test PC to P4 | 15 |
|
||||
|
||||
## 2 Transport Optimization
|
||||
|
||||
### 2.1 SDIO (Highest Performance)
|
||||
- **Clock Speed**: Start at 20 MHz, optimize up to 50 MHz
|
||||
- **Bus Width**: Use 4-bit mode
|
||||
- **Hardware**: Use PCB with controlled impedance, external pull-ups (51kΩ)
|
||||
- **Checksum**: Optional (SDIO hardware handles verification)
|
||||
|
||||
```
|
||||
CONFIG_ESP_HOSTED_SDIO_CLOCK_FREQ_KHZ=40000
|
||||
CONFIG_ESP_HOSTED_SDIO_BUS_WIDTH=4
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> See [Performance and Memory Usage](sdio.md#9-performance-and-memory-usage) on the trade-off between SDIO Performance and Memory Use
|
||||
|
||||
### 2.2 SPI Full-Duplex
|
||||
- **Clock Speed**: ESP32: ≤10 MHz, Others: ≤40 MHz
|
||||
- **Hardware**: Use IO_MUX pins, short traces (≤10cm for jumpers)
|
||||
- **Checksum**: Mandatory (SPI hardware lacks error detection)
|
||||
|
||||
```
|
||||
CONFIG_ESP_HOSTED_SPI_CLK_FREQ=40
|
||||
```
|
||||
|
||||
### 2.3 SPI Half-Duplex
|
||||
- **Data Lines**: Use 4-line (Quad SPI) mode
|
||||
- **Similar optimizations as SPI Full-Duplex**
|
||||
|
||||
### 2.4 UART (Lowest Performance)
|
||||
- **Baud Rate**: Use 921600 (highest stable rate)
|
||||
- **Best for**: Low-throughput applications, debugging
|
||||
|
||||
## 3 Memory Optimization
|
||||
|
||||
- Reduce memory footprint for resource-constrained applications:
|
||||
|
||||
```
|
||||
# Reduce queue sizes
|
||||
CONFIG_ESP_HOSTED_SDIO_TX_Q_SIZE=10 # Default: 20
|
||||
CONFIG_ESP_HOSTED_SDIO_RX_Q_SIZE=10 # Default: 20
|
||||
|
||||
# Enable memory pooling
|
||||
CONFIG_ESP_HOSTED_USE_MEMPOOL=y
|
||||
```
|
||||
|
||||
- Disable the not-in-use features
|
||||
- For example, disable bluetooth if not needed
|
||||
- Use external RAM, for higher memory (PSRAM is supported)
|
||||
- Optimise internal RAM using [ESP-IDF iram optimization tricks](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/performance/ram-usage.html)
|
||||
## 4 Hardware Guidelines
|
||||
|
||||
### 4.1 Critical Requirements
|
||||
1. **Signal Integrity**: Use PCB designs for production, jumpers only for prototyping
|
||||
2. **Power Supply**: Stable 3.3V, proper decoupling capacitors
|
||||
3. **Trace Length**: Match lengths, especially clock vs data lines
|
||||
4. **Pull-ups**: Required for SDIO (51kΩ) on CMD, D0-D3 lines
|
||||
|
||||
### 4.2 PCB Design Checklist
|
||||
- [ ] Equal trace lengths for communication signals
|
||||
- [ ] Ground plane for signal stability
|
||||
- [ ] Controlled impedance traces (50Ω typical)
|
||||
- [ ] Series termination resistors for high-speed signals
|
||||
- [ ] Extra GPIOs reserved for future features (deep sleep, etc.)
|
||||
|
||||
### 4.3 Development Workflow
|
||||
1. **Proof of Concept**: Start with jumper wires, low clock speeds
|
||||
2. **Incremental Optimization**: Increase transport clock step by step
|
||||
3. **Hardware Validation**: Move to PCB for final validation
|
||||
4. **Performance Tuning**: Optimize buffers and configurations
|
||||
5. **Disable features**: Any unsued components from ESP-IDF or
|
||||
|
||||
ESP-Hosted-MCU features could be disabled for more memory
|
||||
availability.
|
||||
638
managed_components/espressif__esp_hosted/docs/sdio.md
Normal file
@@ -0,0 +1,638 @@
|
||||
# ESP-Hosted SDIO Operation
|
||||
|
||||
Sections 3 below covers the hardware requirements like external pull-up requirement, possible efuse burning for co-processor and other hardware aspects to consider for SDIO.
|
||||
|
||||
Section 4 to 8 covers the complete step-wise setup co-processor and host with SDIO, for 1-bit and 4-bit SDIO.
|
||||
|
||||
If you wish to skip the theory, you can refer the [Quick Start Guide](#1-quick-start-guide) below. For quick navigation, please unfold the Table of Contents below.
|
||||
|
||||
<details>
|
||||
<summary>Table of Contents</summary>
|
||||
|
||||
1. [Quick Start Guide](#1-quick-start-guide)
|
||||
|
||||
2. [Introduction](#2-introduction)
|
||||
|
||||
3. [Hardware Considerations](#3-hardware-considerations) || [3.1 General Considerations](#31-general-considerations) || [3.2 Pull-up Resistors](#32-pull-up-resistors) || [3.3 Voltage Levels & eFuse burning](#33-voltage-levels--efuse-burning) || [3.4 Jumper Wires](#34-jumper-wires) || [3.5 PCB Design](#35-pcb-design) || [3.6 Advanced Considerations](#36-advanced-considerations) || [3.7 Testing Connections](#37-testing-connections)
|
||||
|
||||
4. [Hardware Setup](#4-hardware-setup)
|
||||
|
||||
5. [Set-Up ESP-IDF](#5-set-up-esp-idf)
|
||||
|
||||
6. [Flashing the Co-processor](#6-flashing-the-co-processor) || [6.1 Create Co-processor Project](#61-create-co-processor-project) || [6.2 Co-processor Config](#62-co-processor-config) || [6.3 Co-processor Build](#63-co-processor-build) || [6.4 Co-processor Flashing](#64-co-processor-flashing)
|
||||
|
||||
7. [Flashing the Host](#7-flashing-the-host) || [7.1 Select Example to Run in Hosted Mode](#71-select-example-to-run-in-hosted-mode) || [7.2 Host Project Component Configuration](#72-host-project-component-configuration) || [7.3 Menuconfig, Build and Flash Host](#73-menuconfig-build-and-flash-host)
|
||||
|
||||
8. [Testing and Troubleshooting](#8-testing-and-troubleshooting)
|
||||
|
||||
9. [Performance and Memory Usage](#9-performance-and-memory-usage) || [9.1 Stream and Packet Mode](#91-stream-and-packet-mode) || [9.2 Double Buffering on the Host](#92-double-buffering-on-the-host) || [9.3 Reducing Memory Usage](#93-reducing-memory-usage) || [9.4 Switching to Packet Mode](#94-switching-to-packet-mode)
|
||||
|
||||
10. [References](#10-references)
|
||||
|
||||
</details>
|
||||
|
||||
## 1 Quick Start Guide
|
||||
|
||||
This section provides a brief overview of how to get started with ESP-Hosted using SDIO mode. For detailed instructions on each step, please refer to the following sections:
|
||||
|
||||
- [4. Hardware Setup](#4-hardware-setup)
|
||||
- [5. Set-Up ESP-IDF](#5-set-up-esp-idf)
|
||||
- [6. Flashing the Co-processor](#6-flashing-the-co-processor)
|
||||
- [7. Flashing the Host](#7-flashing-the-host)
|
||||
- [8. Testing and Troubleshooting](#8-testing-and-troubleshooting)
|
||||
- [9. Performance and Memory Usage](#9-performance-and-memory-usage)
|
||||
|
||||
These sections will guide you through the process of flashing both the co-processor and host devices, setting up the hardware connections, and verifying successful communication.
|
||||
|
||||
## 2 Introduction
|
||||
|
||||
SDIO is a high-speed bus that uses the same SDMMC hardware protocol used for SD Cards, but with its own set of commands for communicating with SDIO aware peripherals.
|
||||
|
||||
> [!NOTE]
|
||||
> Only some ESP32 chips support the SDIO Protocol:
|
||||
>
|
||||
> A. SDIO as Slave (Co-processor): ESP32, ESP32-C6 \
|
||||
> B. SDIO as Master: ESP32, ESP32-S3, ESP32-P4
|
||||
|
||||
|
||||
## 3 Hardware Considerations
|
||||
|
||||
### 3.1 GPIO Configuration for SDIO
|
||||
|
||||
The SDIO interface can use almost any GPIO pins. For maximum speed and minimal delays, it is recommended to select the SDIO pin configuration that uses the dedicated `IO_MUX` pins. Hardware connections in later sections use `IO_MUX` pins, as much as possible.
|
||||
ESP32 only supports `IO_MUX` pins for SDIO. other chips may support other flexible pins using GPIO_Matrix, with small performance penalty.
|
||||
|
||||
### 3.2 Extra GPIO Signals Required
|
||||
|
||||
Extra GPIO signals are required for SDIO on Hosted and can be assigned to any free GPIO pins:
|
||||
|
||||
- `Reset` signal: an output signal from the host to the co-processor. When asserted, the host resets the co-processor. This is done when ESP-Hosted is started on the host, to synchronise the state of the host and co-processor.
|
||||
|
||||
> [!NOTE]
|
||||
> The `Reset` signal suggested to connect to the `EN` or `RST` pin on the co-processor, It is however configurable to use another GPIO pin.
|
||||
>
|
||||
> To configure this, use `idf.py menuconfig` on the co-processor: **Example configuration** ---> **SDIO Configuration** ---> **Host SDIO GPIOs** and set **Slave GPIO pin to reset itself**.
|
||||
|
||||
|
||||
### 3.3 General Hardware Considerations
|
||||
|
||||
- For SDIO, signal integrity is crucial, hence jumper wires are not recommended.
|
||||
- Jumper wires are only suitable for initial testing and prototyping.
|
||||
- If you wish, you can test SDIO 1-Bit mode using jumper cables, only for initial testing and prototyping. Pull-Ups are still mandatory for all, [CMD, DAT0, DAT1, DAT2, DAT3] irrespective how do you connect, using jumpers or PCB.
|
||||
- Ensure equal trace lengths for all SDIO connections, whether using jumper wires or PCB traces.
|
||||
- Very strict requirement, to keep wires as short as possible, under 5 cm. Smaller the better.
|
||||
- Use the lower clock frequency like 5 MHz for evaluation. Once solution verified, optimise the clock frequency in increasing steps to max possible value. Max SDIO host clock frequency that all SDIO co-processors can work is upto 50 MHz.
|
||||
- Provide proper power supply for both host and co-processor devices. Lower or incorrect power supplies can cause communication issues & suboptimal performance.
|
||||
|
||||
### 3.4 Pull-up Resistors
|
||||
- SDIO requires external pull-up resistor (51 kOhm recommended) and clean signals for proper operation.
|
||||
- For this reason, it is not recommended to use jumper cables. Use PCB traces to connect between a Hosted Master and Co-processor.
|
||||
- For full requirements, refer to ESP-IDF SDIO pull-up resistor requirements at [Pull-Up Requirements](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/sd_pullup_requirements.html).
|
||||
|
||||
### 3.5 Voltage Levels & eFuse burning
|
||||
- SDIO expects all signals to be at 3.3V level. If you are using level shifter, ensure that the level shifter output is set to 3.3V.
|
||||
- If you use classic ESP32, there is good chance that you would need to burn the eFuse.
|
||||
- eFuse burning is one time and **non reversible process**. You may brick your device, if burn the eFuse incorrectly.
|
||||
- Please check full documentation at [eFuse burning](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/sd_pullup_requirements.html) If your chip is listed explicitly, not to burn eFuse, you can ignore this.
|
||||
- This document covers below issues and their solutions:
|
||||
- External pull-ups to be used on: CMD, DAT0, DAT1, DAT2, DAT3, with 51K Ohm recommended, irrespective of jumpers or PCB.
|
||||
- Bootstrapping pin and DAT2 voltage issues and solution of eFuse burning, with complete procedure.
|
||||
|
||||
|
||||
### 3.6 Jumper Wires (only for SDIO 1-Bit mode)
|
||||
|
||||
- External Pull-ups mandatory for CMD, DAT0, DAT1, DAT2, DAT3 of 51 kOhm.
|
||||
- Smaller the better, strictly under 5 cm. All equal length.
|
||||
- Use high-quality, low-capacitance jumper wires.
|
||||
- Arrange wires to minimize crosstalk, especially for clock and data lines.
|
||||
- Possibly, use twisted pairs for clock and data lines to reduce electromagnetic interference.
|
||||
- If possible, use a ground wire between every signal wire to improve signal integrity.
|
||||
- Connect as many grounds as possible to improve common ground reference and reduce ground noise.
|
||||
|
||||
### 3.7 PCB Design
|
||||
|
||||
For optimal performance and reliability in production designs:
|
||||
|
||||
- Ensure equal trace lengths for all SDIO signals (CLK, CMD, DAT0, DAT1, DAT2, DAT3) as much as possible. This practice, known as length matching, is crucial for maintaining signal integrity and reducing timing skew, especially at higher frequencies.
|
||||
- If perfect length matching is not possible, prioritize matching the clock (CLK) trace length with the data lines.
|
||||
- Use controlled impedance traces for high-speed signals.
|
||||
- Place bypass capacitors close to the power pins of both the host and co-processor devices.
|
||||
- Consider using series termination resistors on the clock and data lines to reduce reflections.
|
||||
- For high-speed designs, use a 4-layer PCB with dedicated power and ground planes.
|
||||
|
||||
### 3.8 Advanced Considerations
|
||||
|
||||
- Calculate the maximum allowed trace length based on your clock frequency and PCB material.
|
||||
- Consider the capacitive load on the SDIO bus, especially for longer traces
|
||||
- For very high-speed designs, consider using differential signaling techniques.
|
||||
- Implement proper EMI/EMC design techniques to minimize electromagnetic interference.
|
||||
|
||||
## 4 Hardware Setup
|
||||
|
||||
Setting up the hardware involves connecting the master and co-processor devices via the SDIO pins and ensuring all extra GPIO signals are properly connected. Below is the table of connections for the SDIO setup between a host ESP chipset and another ESP chipset as co-processor:
|
||||
|
||||
### Host Connections
|
||||
|
||||
SDIO-capable host microcontrollers (MCUs) can connect their GPIO lines to the co-processor as detailed in the table below.
|
||||
|
||||
#### GPIO Flexibility
|
||||
|
||||
- The ESP32 supports SDIO host on fixed GPIOs.
|
||||
- The ESP32-S3 supports SDIO host on flexible GPIOs.
|
||||
- For the ESP32-P4, Slot 0 supports fixed GPIOs, while Slot 1 supports flexible GPIOs.
|
||||
|
||||
By default, Slot 1 is used on the ESP32-P4 to take advantage of its flexible pin mapping; however, Slot 0 is also supported. Parallel access to both Slot 0 and Slot 1 is supported for all hosts.
|
||||
|
||||
|
||||
| Signal | ESP32 | ESP32-S3 |
|
||||
|-----------|-------|----------|
|
||||
| CLK | 14 | 19 |
|
||||
| CMD | 15+[ext-pull-up](#34-pull-up-resistors) | 47+[ext-pull-up](#34-pull-up-resistors) |
|
||||
| D0 | 2+[ext-pull-up](#34-pull-up-resistors) | 13+[ext-pull-up](#34-pull-up-resistors) |
|
||||
| D1 | 4+[ext-pull-up](#34-pull-up-resistors) | 35+[ext-pull-up](#34-pull-up-resistors) |
|
||||
| D2 | 12+[ext-pull-up](#34-pull-up-resistors) | 20+[ext-pull-up](#34-pull-up-resistors) |
|
||||
| D3 | 13+[ext-pull-up](#34-pull-up-resistors) | 9+[ext-pull-up](#34-pull-up-resistors) |
|
||||
| Reset Out | 5 | 42 |
|
||||
|
||||
### ESP32-P4-Function-EV-Board Host Pin Mapping
|
||||
|
||||
| Signal | ESP32-P4 with ESP32-C6 Co-processor | ESP32-P4 with ESP32-C5 Co-processor |
|
||||
|-----------|-------------------------------------|-------------------------------------|
|
||||
| CLK | 18 | 33 |
|
||||
| CMD | 19+[ext-pull-up](#34-pull-up-resistors) | 4+[ext-pull-up](#34-pull-up-resistors) |
|
||||
| D0 | 14+[ext-pull-up](#34-pull-up-resistors) | 20+[ext-pull-up](#34-pull-up-resistors) |
|
||||
| D1 | 15+[ext-pull-up](#34-pull-up-resistors) | 23+[ext-pull-up](#34-pull-up-resistors) |
|
||||
| D2 | 16+[ext-pull-up](#34-pull-up-resistors) | 21+[ext-pull-up](#34-pull-up-resistors) |
|
||||
| D3 | 17+[ext-pull-up](#34-pull-up-resistors) | 22+[ext-pull-up](#34-pull-up-resistors) |
|
||||
| Reset Out | 54 | 53 |
|
||||
|
||||
>
|
||||
|
||||
### Co-processor connections
|
||||
|
||||
SDIO slave provider ESP chips are : ESP32, ESP32-C5, ESP32-C6.\
|
||||
All these chips have fixed GPIOs SDIO support.
|
||||
|
||||
| Signal | ESP32 | ESP32-C6 | ESP32-C5 |
|
||||
|----------|-------|----------|----------|
|
||||
| CLK | 14 | 19 | 9 |
|
||||
| CMD | 15 | 18 | 10 |
|
||||
| D0 | 2 | 20 | 8 |
|
||||
| D1 | 4 | 21 | 7 |
|
||||
| D2 | 12 | 22 | 14 |
|
||||
| D3 | 13 | 23 | 13 |
|
||||
| Reset In | EN | EN/RST | RST |
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> - External pull-ups are mandatory
|
||||
|
||||
## 5 Set-Up ESP-IDF
|
||||
|
||||
Before setting up the ESP-Hosted co-processor & host for SDIO mode, ensure that ESP-IDF is properly installed and set up on your system.
|
||||
|
||||
### 5.1 Installer Way
|
||||
|
||||
- **Windows**
|
||||
- Install and setup ESP-IDF on Windows as documented in the [Standard Setup of Toolchain for Windows](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup.html).
|
||||
- Use the ESP-IDF [Powershell Command Prompt](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup.html#using-the-command-prompt) for subsequent commands.
|
||||
|
||||
- **Linux or MacOS**
|
||||
- For bash:
|
||||
```bash
|
||||
bash docs/setup_esp_idf__latest_stable__linux_macos.sh
|
||||
```
|
||||
- For fish:
|
||||
```fish
|
||||
fish docs/setup_esp_idf__latest_stable__linux_macos.fish
|
||||
```
|
||||
|
||||
### 5.2 Manual Way
|
||||
|
||||
Please follow the [ESP-IDF Get Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html) for manual installation.
|
||||
|
||||
## 6. Flashing the Co-processor
|
||||
|
||||
| Supported Co-processor Targets | ESP32 | ESP32-C6 | ESP32-C5 |
|
||||
| ------------------------------ | ----- | -------- | -------- |
|
||||
|
||||
There are four steps to flash the ESP-Hosted co-processor firmware:
|
||||
|
||||
### 6.1 Create Co-processor Project
|
||||
|
||||
1. Navigate to the directory where you want to create the co-processor project.
|
||||
2. Use the following command to create a new project:
|
||||
```bash
|
||||
idf.py create-project <project_name>
|
||||
```
|
||||
Replace `<project_name>` with your desired project name.
|
||||
|
||||
### 6.2 Co-processor Config
|
||||
|
||||
1. Navigate to the project directory:
|
||||
```bash
|
||||
cd <project_name>
|
||||
```
|
||||
2. Configure the project:
|
||||
```bash
|
||||
idf.py menuconfig
|
||||
```
|
||||
|
||||
#### 6.2.1 Transport config
|
||||
- Navigate to "Example configuration" -> "Bus Config in between Host and Co-processor"
|
||||
- In "Transport layer", select "SDIO"
|
||||
|
||||
#### 6.2.2 Any other config
|
||||
- Optionally, Configure any additional SDIO-specific settings in the "SDIO Configuration" menu, like co-processor GPIOs, SDIO Mode, SDIO timing,etc.
|
||||
|
||||
###### Generated files
|
||||
- Generated config files are (1) `sdkconfig` file and (2) internal `sdkconfig.h` file.
|
||||
- Please note, any manually changes done to these generated files, would not take effect.
|
||||
|
||||
###### Defaulting specific config (Optional)
|
||||
- This is advanced option, so please be careful.
|
||||
- To mark some config options as default, you can add specific config line in file, `sdkconfig.defaults.<target>`. So whenever next time building, you do not need to re-configure.
|
||||
|
||||
### 6.3 Co-processor Build
|
||||
|
||||
1. Build the project:
|
||||
```bash
|
||||
idf.py build
|
||||
```
|
||||
|
||||
### 6.4 Co-processor Flashing
|
||||
|
||||
It is **recommended** to periodically upgrade the slave firmware to leverage new features, bug fixes, and performance improvements.
|
||||
|
||||
| Method | Description | Recommended Use |
|
||||
| -------------------------- | -------------------------------------------------- | ----------------------------------------------------- |
|
||||
| **Direct Serial Flashing** | Uses UART pins for direct firmware installation | First-time setup to install ESP-Hosted slave firmware |
|
||||
| **Slave OTA Update** | Performs slave firmware updates directly from Host | All subsequent updates after initial installation |
|
||||
|
||||
|
||||
#### 6.4.1 Serial Flashing (Initial Setup)
|
||||
|
||||
For the initial setup or when OTA is not available, use serial flashing.
|
||||
|
||||
Flash the co-processor firmware using
|
||||
```
|
||||
idf.py -p <co-processor_serial_port> flash
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> If you are not able to flash the co-processor, there might be a chance that host is not allowing to to do so.
|
||||
>
|
||||
> Put host in bootloader mode using following command and then retry flashing the co-processor
|
||||
>
|
||||
> `esptool.py -p **<host_serial_port>** --before default_reset --after no_reset run`
|
||||
>
|
||||
> Flash the co-processor and log the output:
|
||||
>
|
||||
> `idf.py -p <co-processor_serial_port> flash monitor`
|
||||
|
||||
##### 6.4.2 Co-processor OTA Flashing (Subsequent Updates)
|
||||
|
||||
The ESP-Hosted link comes pre-configured and ready to use on first boot. You can update the slave firmware remotely from the host MCU using OTA (Over-The-Air) updates: **No** ESP-Prog, serial cable, or extra GPIO connections are required.
|
||||
|
||||
For step-by-step instructions, see the [Host Performs Slave OTA Example](../examples/host_performs_slave_ota/README.md).
|
||||
|
||||
|
||||
|
||||
## 7 Flashing the Host
|
||||
|
||||
| Supported Host Targets | Any ESP chipset | Any Non-ESP chipset |
|
||||
| ----------------------- | --------------- | ------------------- |
|
||||
|
||||
Any host having SDIO master can be used as host. Please make sure the hardware configurations, like external pull-ups are installed correctly. Tthe voltage at SDIO pins is expected to be 3v3 volts.
|
||||
- ESP chipsets as SDIO master
|
||||
- ESP as host could be one of ESP32, ESP32-S3, ESP32-P4.
|
||||
- For ESP32 as host, may need additional **eFuse burning** for voltage correction on one of data pin. ESP32-S3 and ESP32-P4 does **not** need this.
|
||||
- Non ESP SDIO Master
|
||||
- Any other host having SDIO master can be used as host. Please make sure the hardware configurations, like ([external Pull-up Resistors](#42-pull-up-resistors)) are installed correctly. Tthe voltage at SDIO pins is expected to be 3v3 volts.
|
||||
- Pull-ups required for CMD, DAT0, DAT1, DAT2, DAT3 lines (for both 1-Bit and 4-Bit SDIO)
|
||||
- eFuse burning may be required for classic ESP32.
|
||||
- Pull-Up and eFuse burning is detailed in [(3) Hardware Considerations](#3-hardware-considerations)
|
||||
|
||||
### 7.1 Select Example to Run in Hosted Mode
|
||||
|
||||
Select an example from the [ESP-IDF examples directory](https://github.com/espressif/esp-idf/tree/master/examples) that you wish to run in ESP-Hosted mode. All Wi-Fi and Bluetooth examples are supported. For simplicity and demonstration purposes, we will use the [ESP-IDF iperf example](https://github.com/espressif/esp-idf/tree/master/examples/wifi/iperf).
|
||||
|
||||
### 7.2 Host Project Component Configuration
|
||||
|
||||
Now that ESP-IDF is set up, follow these steps to prepare the host:
|
||||
|
||||
###### 1. Navigate to the iperf example in your ESP-IDF directory:
|
||||
```
|
||||
cd $IDF_PATH/examples/wifi/iperf
|
||||
```
|
||||
|
||||
###### 2. Dependency components
|
||||
Add the required components to the project's `idf_component.yml` file:
|
||||
```
|
||||
idf.py add-dependency "espressif/esp_wifi_remote"
|
||||
idf.py add-dependency "espressif/esp_hosted"
|
||||
```
|
||||
|
||||
###### 3. Remove conflicting configuration
|
||||
Open the `main/idf_component.yml` file and remove/comment the following block if present:
|
||||
```
|
||||
# ------- Delete or comment this block ---------
|
||||
espressif/esp-extconn:
|
||||
version: "~0.1.0"
|
||||
rules:
|
||||
- if: "target in [esp32p4]"
|
||||
# -----------------------------------
|
||||
```
|
||||
This step is necessary because esp-extconn and esp-hosted cannot work together.
|
||||
|
||||
###### 4. Disable native Wi-Fi if available
|
||||
If your host ESP chip already has native Wi-Fi support, disable it by editing the `components/soc/<soc>/include/soc/Kconfig.soc_caps.in` file and changing all `WIFI` related configs to `n`.
|
||||
|
||||
If you happen to have both, host and co-processor as same ESP chipset type (for example two ESP32-C2), note an [additional step](docs/troubleshooting/#1-esp-host-to-evaluate-already-has-native-wi-fi)
|
||||
|
||||
|
||||
### 7.3 Menuconfig, Build and Flash Host
|
||||
|
||||
##### 1. High performance configurations
|
||||
This is optional step, suggested for high performance applications.
|
||||
|
||||
If using ESP32-P4 as host and the ESP32-C6 as the co-processor:
|
||||
|
||||
- Remove all `CONFIG_ESP_WIFI_` settings. They do not apply to ESP-Hosted.
|
||||
- Add the following settings to your `sdkconfig.defaults.esp32p4` file:
|
||||
```
|
||||
### sdkconfig for ESP32-P4 + C6 Dev board
|
||||
CONFIG_WIFI_RMT_STATIC_RX_BUFFER_NUM=16
|
||||
CONFIG_WIFI_RMT_DYNAMIC_RX_BUFFER_NUM=64
|
||||
CONFIG_WIFI_RMT_DYNAMIC_TX_BUFFER_NUM=64
|
||||
CONFIG_WIFI_RMT_AMPDU_TX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_TX_BA_WIN=32
|
||||
CONFIG_WIFI_RMT_AMPDU_RX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_RX_BA_WIN=32
|
||||
|
||||
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=65534
|
||||
CONFIG_LWIP_TCP_WND_DEFAULT=65534
|
||||
CONFIG_LWIP_TCP_RECVMBOX_SIZE=64
|
||||
CONFIG_LWIP_UDP_RECVMBOX_SIZE=64
|
||||
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=64
|
||||
|
||||
CONFIG_LWIP_TCP_SACK_OUT=y
|
||||
```
|
||||
|
||||
For other ESP32 hosts, you can merge above configs into the corresponding `sdkconfig.defaults.esp32XX` file.
|
||||
|
||||
To adjust other Wi-Fi parameters, run `idf.py menuconfig` and go to `Component config` ---> `Wi-Fi Remote` ---> `Wi-Fi configuration`.
|
||||
|
||||
Optimised parameters for other co-processors can be found in the [Performance Optimization Guide](performance_optimization.md).
|
||||
|
||||
###### 2. Set environment for your host ESP chip:
|
||||
|
||||
```
|
||||
idf.py set-target <host_target>
|
||||
```
|
||||
Replace `<host_target>` with your specific ESP chip (e.g., esp32, esp32s3, esp32p4).
|
||||
|
||||
###### 3. Flexible Menuconfig configurations
|
||||
|
||||
```
|
||||
idf.py menuconfig
|
||||
```
|
||||
ESP-Hosted-MCU host configurations are available under "Component config" -> "ESP-Hosted config"
|
||||
1. Select "SDIO" as the transport layer
|
||||
2. Change co-processor chipset currently in-use under, "Slave chipset to be used"
|
||||
3. Change SDIO Bus Width to 1-bit or 4-bit based on the co-processor using "Hosted SDIO Configuration" -> "SDIO Bus Width"
|
||||
4. Optionally, configure SDIO-specific settings like:
|
||||
|
||||
- SDIO Host GPIO Pins
|
||||
|
||||
- Lower SDIO Clock Speed
|
||||
You can use a lower clock speed to verify the connections. Start with a clock speed between 400 kHz to 20 MHz.
|
||||
To configure this, use `Menuconfig` on the Host: **Component config** ---> **ESP-Hosted config** ---> **Hosted SDIO Configuration** and set **SDIO Clock Freq (in kHz)**.
|
||||
> [!NOTE]
|
||||
>
|
||||
> The actual clock frequency used is determined by the hardware. Use an oscilloscope or logic analyzer to check the clock frequency.
|
||||
|
||||
- Using 1-bit SDIO Mode
|
||||
By default, SDIO operates in 4-Bit mode.
|
||||
You can set the SDIO Bus Width to 1-Bit. In 1-Bit mode, only `DAT0` and `DAT1` signals are used for data and are less affected by noise on the signal lines. This can help you verify that the SDIO protocol is working at the logical level, if you have issues getting 4-Bit SDIO to work on your prototype board.
|
||||
|
||||
To configure this, use `Menuconfig` on the Host: **Component config** ---> **ESP-Hosted config** ---> **Hosted SDIO Configuration** ---> **SDIO Bus Width** to **1 Bit**.
|
||||
|
||||
- SDIO Mode
|
||||
Packet or Streaming mode could be used, but co-processor has to use same SDIO mode used.
|
||||
|
||||
> [!NOTE]
|
||||
|
||||
> Pull-ups are still required on `DAT2` and `DAT3` lines to prevent
|
||||
> the SDIO slave from going into SPI mode upon startup.
|
||||
|
||||
After confirming the functionality of the 1-Bit SDIO mode, you can revert to the 4-Bit mode with PCB to benefit from increased data transfer rates. Using the previous configuration, switch back to `4 Bit`.
|
||||
|
||||
|
||||
###### 4. Build the project:
|
||||
```
|
||||
idf.py build
|
||||
```
|
||||
|
||||
###### 5. Flash the firmware:
|
||||
```
|
||||
idf.py -p <host_serial_port> flash
|
||||
```
|
||||
|
||||
###### 6. Monitor the output:
|
||||
```
|
||||
idf.py -p <host_serial_port> monitor
|
||||
```
|
||||
- If host was put into bootloader mode earlier, it may need manual reset
|
||||
|
||||
## 8 Testing and Troubleshooting
|
||||
|
||||
After flashing both the co-processor and host devices, follow these steps to connect and test your ESP-Hosted SDIO setup:
|
||||
|
||||
1. Connect the hardware:
|
||||
- Follow the pin assignments for SDIO as specified in [Hardware Setup](#4-hardware-setup).
|
||||
- Ensure all necessary connections are made, including power, ground, and the extra GPIO signals (Data_Ready and Reset).
|
||||
|
||||
2. Power on both devices. Apply correct input rating power for both chipsets.
|
||||
|
||||
3. Verify the connection:
|
||||
- Check the serial output of both devices for successful initialization messages.
|
||||
- Look for messages indicating that the SDIO transport layer has been established.
|
||||
|
||||
4. Logs at both sides:
|
||||
- Host:
|
||||
|
||||
```
|
||||
I (522) transport: Attempt connection with slave: retry[0]
|
||||
I (525) transport: Reset slave using GPIO[54]
|
||||
I (530) os_wrapper_esp: GPIO [54] configured
|
||||
I (535) gpio: GPIO[54]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
|
||||
I (1712) transport: Received INIT event from ESP32 peripheral
|
||||
I (1712) transport: EVENT: 12
|
||||
I (1712) transport: EVENT: 11
|
||||
I (1715) transport: capabilities: 0xe8
|
||||
I (1719) transport: Features supported are:
|
||||
I (1724) transport: - HCI over SDIO
|
||||
I (1728) transport: - BLE only
|
||||
I (1732) transport: EVENT: 13
|
||||
I (1736) transport: ESP board type is : 13
|
||||
|
||||
I (1741) transport: Base transport is set-up
|
||||
```
|
||||
|
||||
- Co-processor:
|
||||
|
||||
```
|
||||
I (492) fg_mcu_slave: *********************************************************************
|
||||
I (501) fg_mcu_slave: ESP-Hosted-MCU Slave FW version :: X.Y.Z
|
||||
|
||||
I (511) fg_mcu_slave: Transport used :: SDIO
|
||||
I (520) fg_mcu_slave: *********************************************************************
|
||||
I (529) fg_mcu_slave: Supported features are:
|
||||
I (534) fg_mcu_slave: - WLAN over SDIO
|
||||
I (538) h_bt: - BT/BLE
|
||||
I (541) h_bt: - HCI Over SDIO
|
||||
I (545) h_bt: - BLE only
|
||||
```
|
||||
|
||||
5. Test basic functionality:
|
||||
- The iperf example automatically attempts to connect to the configured Wi-Fi network. Watch the serial output for connection status.
|
||||
- If the automatic connection fails, you can manually initiate a Wi-Fi scan and connection:
|
||||
```
|
||||
sta_scan
|
||||
sta_connect <SSID> <password>
|
||||
```
|
||||
6. Additional commands to test:
|
||||
- Get IP address: `sta_ip`
|
||||
- Disconnect from Wi-Fi: `sta_disconnect`
|
||||
- Set Wi-Fi mode: `wifi_mode <mode>` (where mode can be 'sta', 'ap', or 'apsta')
|
||||
|
||||
7. Advanced iperf testing:
|
||||
Once connected, you can run iperf tests:
|
||||
|
||||
| Test Case | Host Command | External STA Command |
|
||||
|-----------|--------------|----------------------|
|
||||
| UDP Host TX | `iperf -u -c <STA_IP> -t 60 -i 3` | `iperf -u -s -i 3` |
|
||||
| UDP Host RX | `iperf -u -s -i 3` | `iperf -u -c <HOST_IP> -t 60 -i 3` |
|
||||
| TCP Host TX | `iperf -c <STA_IP> -t 60 -i 3` | `iperf -s -i 3` |
|
||||
| TCP Host RX | `iperf -s -i 3` | `iperf -c <HOST_IP> -t 60 -i 3` |
|
||||
|
||||
Note: Replace `<STA_IP>` with the IP address of the external STA, and `<HOST_IP>` with the IP address of the ESP-Hosted device.
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> To measure the optimal performance, check out the [Shield Box Test Setup](shield-box-test-setup.md).
|
||||
|
||||
8. Troubleshooting:
|
||||
- Consider using a lower clock speed or checking your [hardware setup](docs/sdio.md#7-hardware-setup) if you experience communication problems.
|
||||
- ESP-Hosted-MCU troubleshooting guide: [docs/troubleshooting.md](docs/troubleshooting.md)
|
||||
|
||||
9. Monitoring and debugging:
|
||||
- Use the serial monitor on both devices to observe the communication between the host and co-processor.
|
||||
- For more detailed debugging, consider using a logic analyzer to examine the SDIO signals.
|
||||
- Use a logic analyzer or oscilloscope to verify the SDIO signals.
|
||||
- Ensure that the power supply to both devices is stable and within the required voltage levels.
|
||||
|
||||
## 9 Performance and Memory Usage
|
||||
|
||||
Quick summary:
|
||||
|
||||
- for maximum network performance, at the cost of more memory usage on host and co-processor, use SDIO Streaming Mode (default mode of operation)
|
||||
- for lower memory usage, at the cost of lower network performance, use [SDIO Packet Mode](#94-switching-to-packet-mode)
|
||||
|
||||
### 9.1 Stream and Packet Mode
|
||||
|
||||
The co-processor SDIO can operate in two modes: Streaming Mode and Packet Mode.
|
||||
|
||||
| **Streaming Mode** | **Packet Mode** |
|
||||
| --- | --- |
|
||||
| Co-processor combines multiple queued Tx packets together into one large packet | Co-processor queues individual Tx packets |
|
||||
| Host fetches the large packet as one SDIO transfer | Host fetches each packet one at a time |
|
||||
| Host breaks the large packet back into individual packets to send to the Rx queue | Host sends each packet to the Rx queue |
|
||||
| More efficient (less SDIO overhead), but requires more memory at Host to hold the large packet | Less efficient (higher SDIO overhead for each packet), but minimises memory required at Host |
|
||||
|
||||
### 9.2 Double Buffering on the Host
|
||||
|
||||
The Host implements a double-buffering scheme to receive data. One thread fetches data (using hardware DMA) from the co-processor and stores it in one Rx buffer, while another thread breaks up previously received data into packets for processing.
|
||||
|
||||
### 9.3 Reducing Memory Usage in Streaming Mode
|
||||
|
||||
#### 9.3.1 Host Receive
|
||||
|
||||
> [!NOTE]
|
||||
> **Host Receive**: Router --Network Data--> Co-processor --SDIO--> Host
|
||||
|
||||
In SDIO streaming mode, the host receives SDIO data from the co-processor in one large SDIO transfer. For this reason, **Streaming mode consumes more heap memory** compared to Packet mode, and has a higher throughput (less SDIO overhead).
|
||||
|
||||
For Host systems with high heap memory usage, you can reduce the amount of heap memory used by ESP-Hosted for buffers, at the cost of reduced throughput, by adjusting the number of Tx buffers used by the co-processor.
|
||||
|
||||
**On the co-processor**: run `idf.py menuconfig` -> `Example Configuration` -> `Bus Config in between Host and Co-processor` -> `SDIO Configuration` and adjust `SDIO Tx queue size`. The default queue size is `20`.
|
||||
|
||||
The table below shows the effect of changing `SDIO Tx queue size` on throughput and memory usage on the Host. The throughput numbers are obtained by using the RawTP option in ESP-Hosted to send / receive raw SDIO data.
|
||||
|
||||
| SDIO Tx queue size | Host Rx Raw Throughput (Mbits/s) | Memory Used by Buffers (Tested) | Memory Used by Buffers (Theoretical) |
|
||||
| ---: | ---: | ---: | ---: |
|
||||
| 5 | 54 | 12,288 | 15,360 |
|
||||
| 10 | 70 | 26,624 | 30,720 |
|
||||
| 15 | 76 | 41,984 | 46,080 |
|
||||
| 20 | 80 | 56,320 | 61,440 |
|
||||
| 25 | 82 | 65,536 | 76,800 |
|
||||
| 30 | 84 | 65,536 | 92,160 |
|
||||
|
||||
> [!NOTE]
|
||||
> The SDIO packet size is 1536 bytes. The co-processor can send at most `(Tx queue size) * 1536` bytes. Since the Host does double buffering, the theoretical Buffer Size needed is `2 * (Tx queue size) * 1536`.
|
||||
|
||||
From the table above, throughput is more or less stagnant on and above Rx queue size of `25`. For a good trade off between memory consumption vs performance, the Rx queue sizes are currently defaulted to `20`.
|
||||
|
||||
#### 9.3.2 Host Transmit
|
||||
|
||||
> [!NOTE]
|
||||
> **Host Transmit**: Host --SDIO--> Co-Processor --Network Data--> Router
|
||||
|
||||
To reduce memory usage on the co-processor, you can reduce the number of buffers the co-processor uses to receive data from the Host.
|
||||
|
||||
**On the co-processor**: run `idf.py menuconfig`
|
||||
|
||||
```
|
||||
Example Configuration
|
||||
└── Bus Config in between Host and Co-processor
|
||||
└── SDIO Configuration
|
||||
└── SDIO Rx queue size (default: 20)
|
||||
```
|
||||
|
||||
Reducing the number of Rx buffers on the co-processor can affect the Tx throughput from the Host if the number of Rx buffers is set to a small value.
|
||||
|
||||
### 9.4 Switching to Packet Mode
|
||||
|
||||
For mimimal memory usage with a lower throughput, you can switch to Packet Mode. To do this:
|
||||
|
||||
- on the co-processor: run `idf.py menuconfig`
|
||||
|
||||
```
|
||||
Example Configuration
|
||||
└── Bus Config in between Host and Co-processor
|
||||
└── SDIO Configuration
|
||||
└── Enable SDIO Streaming Mode [Deselect this option]
|
||||
```
|
||||
|
||||
- on the host: run `idf.py menuconfig`
|
||||
```
|
||||
── Component config
|
||||
└── ESP-Hosted config
|
||||
└── Hosted SDIO Configuration
|
||||
└── SDIO Receive Optimization
|
||||
├── No optimization
|
||||
├── Always Rx Max Packet size [Change to this, preferably]
|
||||
└── Use Streaming Mode [Default was selected, change to one of above]
|
||||
```
|
||||
In Packet Mode, the host uses `2 * 1536` or `3,072` bytes of memory for Rx buffers.
|
||||
- with `No optimization`, Rx Raw Throughput is 33.0 Mbits/s
|
||||
- with `Always Rx Max Packet size`, Rx Raw Throughput is 33.2 Mbits/s
|
||||
|
||||
## 10 References
|
||||
|
||||
- [ESP-IDF Programming Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/)
|
||||
- [ESP32 Hardware Design Guidelines](https://www.espressif.com/en/products/hardware/esp32/resources)
|
||||
- [ESP SDIO Slave Communication](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/protocols/esp_sdio_slave_protocol.html)
|
||||
- [ESP SDIO Card Slave Driver](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/sdio_slave.html)
|
||||
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env fish
|
||||
|
||||
echo "Setting up ESP-IDF using fish"
|
||||
set SHELL_RC "$HOME/.config/fish/config.fish"
|
||||
|
||||
# Step 1: Check if curl and git are installed
|
||||
echo "============== Step 1: Checking if dependencies =========================="
|
||||
if not type -q curl
|
||||
echo "curl is not installed. Please install curl."
|
||||
exit 1
|
||||
end
|
||||
|
||||
if not type -q git
|
||||
echo "git is not installed. Please install git."
|
||||
exit 1
|
||||
end
|
||||
|
||||
echo "Dependencies for current script are installed."
|
||||
|
||||
# Step 2: Fetch the branches from the GitHub API and find the latest stable release branch
|
||||
echo "============== Step 2: Fetching branch list from ESP-IDF GitHub API =============="
|
||||
set LATEST_BRANCH (curl -s https://api.github.com/repos/espressif/esp-idf/branches | grep -o '"name": "release/[^"]*' | awk -F'"' '{print $4}' | sort -V | tail -n 1)
|
||||
|
||||
# Log the latest branch found
|
||||
echo "Latest stable branch found: $LATEST_BRANCH"
|
||||
|
||||
# Step 3: Clone or update the ESP-IDF repository
|
||||
if not test -d "$HOME/esp-idf"
|
||||
echo "============== Step 3: Cloning the ESP-IDF repository ================"
|
||||
git clone -b "$LATEST_BRANCH" --recursive --depth 1 https://github.com/espressif/esp-idf.git "$HOME/esp-idf"
|
||||
else
|
||||
echo "ESP-IDF repository already exists."
|
||||
cd "$HOME/esp-idf" || exit
|
||||
git checkout "$LATEST_BRANCH"
|
||||
git pull --recurse-submodules
|
||||
end
|
||||
|
||||
cd "$HOME/esp-idf" || exit
|
||||
set IDF_COMMIT (git rev-parse HEAD)
|
||||
echo "ESP-IDF is set to commit: $IDF_COMMIT"
|
||||
|
||||
# Step 4: Set up the ESP-IDF environment
|
||||
echo "============== Step 4: Setting up the ESP-IDF environment ================"
|
||||
"$HOME/esp-idf/install.fish"
|
||||
source "$HOME/esp-idf/export.fish" | source
|
||||
|
||||
# Step 5: Add alias to Fish config
|
||||
echo "============== Step 5: Adding alias to Fish configuration ==============="
|
||||
if not grep -q "alias get-idf" "$SHELL_RC"
|
||||
read -P "Do you want to add the alias 'get-idf' to $SHELL_RC? [yes/no] " response
|
||||
if string match -i -r '^yes$' $response
|
||||
echo "alias get-idf='source $HOME/esp-idf/export.fish | source'" >> "$SHELL_RC"
|
||||
echo "ESP-IDF setup alias added to $SHELL_RC. Run 'get-idf' to configure your environment."
|
||||
else
|
||||
echo "Alias not added. You can manually add 'alias get-idf=\". $HOME/esp-idf/export.fish | source\"' to $SHELL_RC."
|
||||
end
|
||||
else
|
||||
echo "ESP-IDF setup alias already exists in $SHELL_RC."
|
||||
end
|
||||
|
||||
# Step 6: Inform user to reload shell
|
||||
echo "============== Step 6: Informing user to reload shell ==============="
|
||||
echo "Please run 'source $SHELL_RC' to reload the shell with the new alias."
|
||||
echo "In new shell, run 'get-idf' to enable ESP-IDF environment."
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
SHELL_RC="$HOME/.bashrc"
|
||||
|
||||
# Step 1: Check if curl and git are installed
|
||||
echo "============== Step 1: Checking if dependencies are installed =============="
|
||||
if ! command -v curl &> /dev/null; then
|
||||
echo "curl is not installed. Please install curl."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v git &> /dev/null; then
|
||||
echo "git is not installed. Please install git."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "All required dependencies are installed."
|
||||
|
||||
# Step 2: Fetch the branches from the GitHub API and find the latest stable release branch
|
||||
echo "============== Step 2: Fetching branch list from ESP-IDF GitHub API =============="
|
||||
LATEST_BRANCH=$(curl -s https://api.github.com/repos/espressif/esp-idf/branches | grep -o '"name": "release/[^"]*' | awk -F'"' '{print $4}' | sort -V | tail -n 1)
|
||||
echo "Latest stable branch found: $LATEST_BRANCH"
|
||||
|
||||
# Step 3: Clone or update the ESP-IDF repository
|
||||
if [ ! -d "$HOME/esp-idf" ]; then
|
||||
echo "========= Step 3: Cloning the ESP-IDF repository (takes 3-4 mins) ============="
|
||||
git clone -b "$LATEST_BRANCH" --recursive --depth 1 https://github.com/espressif/esp-idf.git "$HOME/esp-idf"
|
||||
else
|
||||
echo "ESP-IDF repository already exists. Updating..."
|
||||
cd "$HOME/esp-idf" || exit
|
||||
git checkout "$LATEST_BRANCH"
|
||||
git pull --recurse-submodules
|
||||
fi
|
||||
|
||||
# Log the current commit hash
|
||||
cd "$HOME/esp-idf" || exit
|
||||
IDF_COMMIT=$(git rev-parse HEAD)
|
||||
echo "<< ESP-IDF is set to commit: $IDF_COMMIT >>"
|
||||
|
||||
# Step 4: Set up the ESP-IDF environment
|
||||
echo "============== Step 4: Setting up the ESP-IDF environment ================"
|
||||
"$HOME/esp-idf/install.sh"
|
||||
source "$HOME/esp-idf/export.sh"
|
||||
|
||||
# Step 5: Optionally add an alias to shell configuration for easy setup
|
||||
echo "============== Step 5: Adding alias to shell configuration ==============="
|
||||
if ! grep -q "alias get-idf" "$SHELL_RC"; then
|
||||
read -p "Do you want to add the alias 'get-idf' to $SHELL_RC? [yes/no] " -r
|
||||
if [[ $REPLY =~ ^[Yy][Ee][Ss]$ ]]; then
|
||||
echo "alias get-idf='source $HOME/esp-idf/export.sh'" >> "$SHELL_RC"
|
||||
echo "ESP-IDF setup alias added to $SHELL_RC. Run 'get-idf' to configure your environment."
|
||||
else
|
||||
echo "Alias not added. You can manually add 'alias get-idf=\"source $HOME/esp-idf/export.sh\"' to $SHELL_RC."
|
||||
fi
|
||||
else
|
||||
echo "ESP-IDF setup alias already exists in $SHELL_RC."
|
||||
fi
|
||||
|
||||
# Step 6: Inform the user to reload the shell
|
||||
echo "============== Step 6: Informing user to reload shell ==============="
|
||||
echo "\nPlease run 'source $SHELL_RC' to reload the shell with the new alias."
|
||||
echo "\nIn a new shell, run 'get-idf' to enable the ESP-IDF environment."
|
||||
@@ -0,0 +1,75 @@
|
||||
# Shield Box Test Setup for ESP-Hosted
|
||||
|
||||
Controlled RF environment for consistent throughput measurements and performance evaluation.
|
||||
|
||||
## Overview
|
||||
|
||||
**Shield Box Testing** uses RF-shielded enclosure to eliminate external interference and provide repeatable test conditions.
|
||||
|
||||
**Key Benefits:**
|
||||
- Controlled RF environment (no external Wi-Fi/cellular interference)
|
||||
- Repeatable, consistent results
|
||||
- Better measurement accuracy vs open air
|
||||
|
||||
|
||||
## Equipment Required
|
||||
|
||||
### Essential Components
|
||||
- **RF Shield Box/Chamber**: Faraday cage enclosure
|
||||
- **ESP32-P4 Function EV Board**: Host device
|
||||
- **ESP32-C6/C5 Test Board**: Co-processor device
|
||||
- **External PC**: For iPerf client/server
|
||||
- **Router/Access Point**: Wi-Fi infrastructure
|
||||
- **Ethernet Connection**: Wired backhaul to PC
|
||||
|
||||
Please change the host and co-processor nodes as per current use-case under test.
|
||||
|
||||
## Test Setup
|
||||
|
||||
### Physical Configuration
|
||||
|
||||
<img src="images/PerformanceSetup-ShieldBox.png" alt="Shield box testing setup" width="800" />
|
||||
|
||||
### Data Flow
|
||||
- **PC to MCU Host**:
|
||||
```
|
||||
PC -> Router -> ESP Co-processor == SDIO/SPI/UART ==> ESP32-P4
|
||||
```
|
||||
- **MCU Host to PC**:
|
||||
```
|
||||
PC <- Router <- ESP Co-processor <== SDIO/SPI/UART == ESP32-P4
|
||||
```
|
||||
|
||||
**Traffic route:**
|
||||
- PC-to-Router: Ethernet with static IP (eliminates wireless variables)
|
||||
- Router-to-ESP: Wi-Fi connection (only wireless link in test chain)
|
||||
|
||||
## Transport Configurations
|
||||
|
||||
### SDIO (Highest Performance)
|
||||
- **Clock**: 20-50 MHz (start low, optimize up)
|
||||
- **Bus Width**: 4-bit mode
|
||||
- **Hardware**: External pull-ups (51kΩ) on CMD, D0-D3
|
||||
|
||||
### SPI
|
||||
- **Clock**: ESP32: ≤10 MHz, Others: ≤40 MHz
|
||||
- **Mode**: Full-duplex (simple) or Quad SPI (highest throughput)
|
||||
|
||||
### UART
|
||||
- **Baud Rate**: 921600 (highest stable rate)
|
||||
- **Use Case**: Low-throughput validation, debugging
|
||||
|
||||
|
||||
## Shield Box vs Open Air
|
||||
|
||||
| Aspect | Shield Box | Open Air |
|
||||
|--------|------------|----------|
|
||||
| **Repeatability** | High | Variable |
|
||||
| **Interference** | Eliminated | Present |
|
||||
| **Debugging** | Easier | Complex |
|
||||
| **Reality** | Lower | Higher |
|
||||
|
||||
|
||||
---
|
||||
|
||||
*For transport setup details: [SDIO](sdio.md) | [SPI Full-Duplex](spi_full_duplex.md) | [SPI Half-Duplex](spi_half_duplex.md) | [UART](uart.md)*
|
||||
545
managed_components/espressif__esp_hosted/docs/spi_full_duplex.md
Normal file
@@ -0,0 +1,545 @@
|
||||
# ESP-Hosted SPI FD (Full Duplex) Operation
|
||||
|
||||
Sections 2 to 4 below covers the theoretical part where the SPI Full duplex design and implementation details are explained.
|
||||
|
||||
Section 5 to 9 covers the complete step-wise setup co-processor and host with SPI Full Duplex, using 2 or 4 data lines.
|
||||
|
||||
If you wish to skip the theory, you can refer the [Quick Start Guide](#1-quick-start-guide) below. For quick navigation, please unfold the Table of Contents below.
|
||||
|
||||
<details>
|
||||
<summary>Table of Contents</summary>
|
||||
|
||||
1. [Quick Start Guide](#1-quick-start-guide)
|
||||
|
||||
2. [Introduction](#2-introduction)
|
||||
|
||||
3. [High Level Design and Implementation](#3-high-level-design-and-implementation) || [3.1 Number of Pins Required](#31-number-of-pins-required) || [3.2 SPI Full Duplex Mode Implementation](#32-spi-full-duplex-mode-implementation) || [3.3 Code Reference](#35-code-reference)
|
||||
|
||||
4. [Hardware Considerations](#4-hardware-considerations) || [4.1 General Considerations](#41-general-considerations) || [4.2 Jumper Wires](#42-jumper-wires) || [4.3 PCB Design](#43-pcb-design) || [4.4 Advanced Considerations](#44-advanced-considerations)
|
||||
|
||||
5. [Hardware Setup](#5-hardware-setup)
|
||||
|
||||
6. [Set-Up ESP-IDF](#6-set-up-esp-idf)
|
||||
|
||||
7. [Flashing the Co-processor](#7-flashing-the-co-processor) || [7.1 Create Co-processor Project](#71-create-co-processor-project) || [7.2 Co-processor Config](#72-co-processor-config) || [7.3 Co-processor Build](#73-co-processor-build) || [7.4 Co-processor Flashing](#74-co-processor-flashing) || [7.4.1 Serial Flashing (Initial Setup)](#741-serial-flashing-initial-setup) || [7.4.2 Co-processor OTA Flashing (Subsequent Updates)](#742-co-processor-ota-flashing-subsequent-updates)
|
||||
|
||||
8. [Flashing the Host](#8-flashing-the-host) || [8.1 Select Example to Run in Hosted Mode](#81-select-example-to-run-in-hosted-mode) || [8.2 Host Project Component Configuration](#82-host-project-component-configuration) || [8.3 Menuconfig, Build and Flash Host](#83-menuconfig-build-and-flash-host)
|
||||
|
||||
9. [Testing and Troubleshooting](#9-testing-and-troubleshooting)
|
||||
|
||||
10. [References](#10-references)
|
||||
|
||||
</details>
|
||||
|
||||
## 1 Quick Start Guide
|
||||
|
||||
This section provides a brief overview of how to get started with ESP-Hosted using SPI FD mode. For detailed instructions on each step, please refer to the following sections:
|
||||
|
||||
- [5. Hardware Setup](#5-hardware-setup)
|
||||
- [6. Set-Up ESP-IDF](#6-set-up-esp-idf)
|
||||
- [7. Flashing the Co-processor](#7-flashing-the-co-processor)
|
||||
- [8. Flashing the Host](#8-flashing-the-host)
|
||||
- [9. Testing and Troubleshooting](#9-testing-and-troubleshooting)
|
||||
|
||||
These sections will guide you through the process of flashing both the co-processor and host devices, setting up the hardware connections, and verifying successful communication.
|
||||
|
||||
## 2 Introduction
|
||||
|
||||
The ESP32 family of chips supports the standard SPI FD (Full Duplex) Mode Protocol. In this mode, SPI uses two data lines (MISO and MOSI) to transfer data to and from the co-processor simultaneously during an SPI transaction.
|
||||
|
||||
## 3 High Level Design and Implementation
|
||||
|
||||
SPI Full duplex mode is the simplest mode of operation in ESP-Hosted. It can be easily tested with jumper wires. It doesn't require much complex hardware setup. For any non ESP chipsets as host also can prefer this mode for testing. This can also served as stepping stone before moving on to more complex modes of operations, like Dual SPI, Quad SPI and SDIO.
|
||||
|
||||
### 3.1 Number of Pins Required
|
||||
|
||||
In SPI Full Duplex mode, the following pins are required:
|
||||
|
||||
1. **MISO (Master In Slave Out)**: Data line for the co-processor to send data to the host.
|
||||
2. **MOSI (Master Out Slave In)**: Data line for the host to send data to the co-processor.
|
||||
3. **SCLK (Serial Clock)**: Clock signal generated by the host to synchronize data transmission.
|
||||
4. **CS (Chip Select)**: Signal used by the host to select the co-processor for communication.
|
||||
5. **Reset Pin**: An output signal from the host to the co-processor. When asserted, the host resets the co-processor to synchronize the state of the host and co-processor.
|
||||
6. **Handshake Pin**: An output signal from the co-processor to the host. When asserted, it tells the host that the co-processor is ready for an SPI transaction.
|
||||
7. **Data Ready Pin**: An output signal from the co-processor to the host. When asserted, the co-processor is telling the host that it has data to send.
|
||||
|
||||
The SPI used is full duplex. Handshake, Data Ready and Reset are additional GPIOs used in addition to MISO, MOSI, SCLK and CS. All pins are mandatory.
|
||||
|
||||
### 3.2 SPI Full Duplex Mode Implementation
|
||||
|
||||
- This solution uses SPI full duplex communication mode:
|
||||
- Read and write operations occur simultaneously in the same SPI transaction
|
||||
|
||||
- Handshake and Data ready are configured as interrupts at host. On loading host, it should automatically reset the co-processor using reset pin.
|
||||
|
||||
- Protocol rules:
|
||||
- Host must not start a transaction before ESP SPI peripheral is ready
|
||||
- ESP peripheral indicates readiness via Handshake pin
|
||||
|
||||
- ESP peripheral preparation:
|
||||
- Always ready for data reception from host
|
||||
- Queues next SPI transaction immediately after completing previous one
|
||||
|
||||
- SPI transaction structure:
|
||||
- Each transaction has a TX buffer and an RX buffer
|
||||
- TX buffer: Contains data ESP peripheral wants to send to host
|
||||
- RX buffer: Empty space to hold data received from host
|
||||
|
||||
- Buffer initialization:
|
||||
- ESP peripheral sets TX and RX buffers to 1600 bytes (maximum size)
|
||||
- Host can send/receive up to 1600 bytes per transaction
|
||||
|
||||
- TX buffer scenarios:
|
||||
1. No data to transfer:
|
||||
- Allocate 1600-byte dummy TX buffer
|
||||
- Set packet length field in payload header to 0
|
||||
2. Valid data to send:
|
||||
- TX buffer points to that data
|
||||
|
||||
- SPI transaction setup:
|
||||
- Set transaction length to 1600 bytes regardless of TX buffer size
|
||||
- Submit transaction to SPI driver on ESP peripheral
|
||||
- Pull Handshake pin high to signal readiness
|
||||
- If TX buffer has valid data, also pull Data ready pin high
|
||||
|
||||
- Host response to Handshake / Data ready interrupt:
|
||||
- Decide whether to perform SPI transaction (if Handshake is high)
|
||||
- Perform transfer if Data ready pin is high or host has data to transfer
|
||||
- If either condition is false, do not perform transfer, just ignore the interrupt
|
||||
|
||||
- During SPI transaction:
|
||||
- Exchange TX and RX buffers on SPI data lines
|
||||
|
||||
- Post-transaction processing:
|
||||
- Both ESP peripheral and host process received buffer based on payload header
|
||||
|
||||
- Transaction completion:
|
||||
- ESP peripheral pulls Handshake pin low
|
||||
- If transaction had valid co-processor TX buffer, also pulls Data ready pin low
|
||||
|
||||
### 3.3 Code Reference
|
||||
For a detailed implementation of SPI full duplex communication using the ESP-Hosted framework, refer to the following code files in the ESP-Hosted repository:
|
||||
|
||||
- **Master SPI Communication Code**:
|
||||
- [spi_drv.c](https://github.com/espressif/esp-hosted-mcu/blob/main/host/drivers/transport/spi/spi_drv.c): Contains the implementation for configuring and handling SPI transactions on the master side.
|
||||
- [spi_wrapper.c](https://github.com/espressif/esp-hosted-mcu/blob/main/host/port/spi_wrapper.c): Provides an OS abstraction layer for SPI operations, making it easier to handle SPI communication in a platform-independent manner.
|
||||
|
||||
- **Co-processor SPI Communication Code**:
|
||||
- [spi_slave_api.c](https://github.com/espressif/esp-hosted-mcu/blob/main/slave/main/spi_slave_api.c): Includes the setup and transaction handling for the SPI co-processor, detailing how the co-processor should configure its SPI interface and handle incoming and outgoing data.
|
||||
|
||||
## 4 Hardware Considerations
|
||||
|
||||
### 4.1 General Considerations
|
||||
|
||||
- Ensure equal trace lengths for all SPI connections, whether using jumper wires or PCB traces.
|
||||
- Use the lower clock frequency like 5 MHz for evaluation. Once solution verified, optimise the clock frequency in increasing steps to max possible value. To find out practical maximum SPI slave frequency for your co-processor, check `IDF_PERFORMANCE_MAX_SPI_CLK_FREQ` in [ESP-IDF SPI slave benchmark](https://github.com/espressif/esp-idf/blob/master/components/esp_driver_spi/test_apps/components/spi_bench_mark/include/spi_performance.h)
|
||||
- Verify voltage compatibility between host and co-processor devices.
|
||||
- Provide proper power supply decoupling for both host and co-processor devices.
|
||||
|
||||
### 4.2 Jumper Wires
|
||||
|
||||
- Jumper wires are suitable for initial testing and prototyping.
|
||||
- Use high-quality, low-capacitance jumper wires.
|
||||
- Keep wires as short as possible, ideally under 10 cm.
|
||||
- Arrange wires to minimize crosstalk, especially for clock and data lines.
|
||||
- Possibly, use twisted pairs for clock and data lines to reduce electromagnetic interference.
|
||||
- If possible, use a ground wire between every signal wire to improve signal integrity.
|
||||
- Connect as many grounds as possible to improve common ground reference and reduce ground noise.
|
||||
|
||||
### 4.3 PCB Design
|
||||
|
||||
For optimal performance and reliability in production designs:
|
||||
|
||||
- Ensure equal trace lengths for all SPI signals (CLK, MOSI, MISO, CS) as much as possible. This practice, known as length matching, is crucial for maintaining signal integrity and reducing timing skew, especially at higher frequencies.
|
||||
- If perfect length matching is not possible, prioritize matching the clock (CLK) trace length with the data lines.
|
||||
- Use controlled impedance traces for high-speed signals.
|
||||
- Place bypass capacitors close to the power pins of both the host and co-processor devices.
|
||||
- Consider using series termination resistors on the clock and data lines to reduce reflections.
|
||||
- For high-speed designs, use a 4-layer PCB with dedicated power and ground planes.
|
||||
|
||||
### 4.4 Advanced Considerations
|
||||
|
||||
- Calculate the maximum allowed trace length based on your clock frequency and PCB material.
|
||||
- Consider the capacitive load on the SPI bus, especially for longer traces or when using multiple co-processor devices.
|
||||
- For very high-speed designs, consider using differential signaling techniques.
|
||||
- Implement proper EMI/EMC design techniques to minimize electromagnetic interference.
|
||||
|
||||
|
||||
**Debugging Tips**
|
||||
|
||||
- Use an oscilloscope or logic analyzer to verify signal integrity and timing.
|
||||
- Start with a lower clock frequency and gradually increase it while monitoring performance.
|
||||
- Ensure proper grounding between the host and co-processor devices.
|
||||
- If using multiple power supplies, ensure they share a common ground.
|
||||
- Consider using level shifters if the host and co-processor operate at different voltage levels.
|
||||
|
||||
## 5 Hardware Setup
|
||||
|
||||
Setting up the hardware involves connecting the master and co-processor devices via the SPI pins and ensuring all extra GPIO signals are properly connected. Below is the table of connections for the SPI full duplex setup between an host ESP chipset and another ESP chipset as co-processor:
|
||||
|
||||
### Host connections
|
||||
|
||||
| Signal | ESP32 | ESP32-S2/S3 | ESP32-C2/C3/C5/C6 | ESP32-P4 |
|
||||
|-------------|-------|-------------|-------------------|----------|
|
||||
| CLK | 14 | 12 | 6 | 9 |
|
||||
| MOSI | 13 | 11 | 7 | 8 |
|
||||
| MISO | 12 | 13 | 2 | 10 |
|
||||
| CS | 15 | 10 | 10 | 7 |
|
||||
| Handshake | 26 | 17 | 3 | 6 |
|
||||
| Data Ready | 4 | 4 | 4 | 11 |
|
||||
| Reset Out | 5 | 5 | 5 | 12 |
|
||||
|
||||
> [!NOTE]
|
||||
> The GPIOs pins on the ESP32-P4 are SPI IO_MUX pins and powered by the `VDD_LP` pin. If you use a different set of GPIOs, check that they are powered to 3.3V by the pin(s) providing power for the GPIOs based on your ESP32-P4 schematic. See the ESP32-P4 Datasheet, [Table 2-1. Pin Overview](https://www.espressif.com/sites/default/files/documentation/esp32-p4_datasheet_en.pdf#table.2.1), for a list of GPIO pins and the pins providing the power for the GPIOs.
|
||||
>
|
||||
> If the pins providing power are connected to an internal Low Dropout Voltage Regulator (LDO), set the LDO to output 3.3V. See [Low Dropout Voltage Regulator (LDO)](https://docs.espressif.com/projects/esp-idf/en/latest/esp32p4/api-reference/peripherals/ldo_regulator.html) for more information on programming the internal LDOs.
|
||||
|
||||
### Co-processor connections
|
||||
|
||||
| Signal | ESP32 | ESP32-C2/C3/C5/C6 | ESP32-S2/S3 | ESP32-C6 on ESP32-P4-Function-EV-Board |
|
||||
|-------------|-------|-------------------|-------------|----------------------------------------|
|
||||
| CLK | 14 | 6 | 12 | 19 |
|
||||
| MOSI | 13 | 7 | 11 | 20 |
|
||||
| MISO | 12 | 2 | 13 | 21 |
|
||||
| CS | 15 | 10 | 10 | 18 |
|
||||
| Handshake | 26 | 3 | 17 | 22 |
|
||||
| Data Ready | 4 | 4 | 5 | 23 |
|
||||
| Reset In | EN | EN/RST | EN/RST | EN/RST |
|
||||
|
||||
> [!NOTE]
|
||||
> - Always try to use IO_MUX pins from the datasheet for optimal performance on both sides.
|
||||
> - These GPIO assignments are based on default Kconfig configurations & are configurable.
|
||||
> - Once ported, any other non ESP host with standard SPI can be used.
|
||||
> - All ESP chipsets support SPI Full Duplex mode. Chipsets with Wi-Fi/Bluetooth can be used as co-processor.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> - Ensure proper grounding between host and co-processor devices.
|
||||
> - Use short, high-quality cables for connections.
|
||||
> - For production designs, consider using a properly designed PCB with controlled impedance traces.
|
||||
|
||||
## 6 Set-Up ESP-IDF
|
||||
|
||||
Before setting up the ESP-Hosted host & co-processor for SPI Full Duplex mode, ensure that ESP-IDF is properly installed and set up on your system.
|
||||
|
||||
#### Option 1: Installer Way
|
||||
|
||||
- **Windows**
|
||||
- Install and setup ESP-IDF on Windows as documented in the [Standard Setup of Toolchain for Windows](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup.html).
|
||||
- Use the ESP-IDF [Powershell Command Prompt](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup.html#using-the-command-prompt) for subsequent commands.
|
||||
|
||||
- **Linux or MacOS**
|
||||
- For bash:
|
||||
```bash
|
||||
bash docs/setup_esp_idf__latest_stable__linux_macos.sh
|
||||
```
|
||||
- For fish:
|
||||
```fish
|
||||
fish docs/setup_esp_idf__latest_stable__linux_macos.fish
|
||||
```
|
||||
|
||||
#### Option 2: Manual Way
|
||||
|
||||
Please follow the [ESP-IDF Get Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html) for manual installation.
|
||||
|
||||
## 7 Flashing the Co-processor
|
||||
|
||||
| Supported Co-processor Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-S2 | ESP32-S3 |
|
||||
| ------------------------------ | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- |
|
||||
|
||||
There are two methods to flash the ESP-Hosted co-processor firmware:
|
||||
|
||||
### 7.1 Create Co-processor Project
|
||||
1. Create co-processor project possibly outside of ESP-IDF project directory using
|
||||
|
||||
```bash
|
||||
idf.py create-project-from-example "espressif/esp_hosted:slave"
|
||||
```
|
||||
|
||||
2. Navigate to the created project directory.
|
||||
|
||||
3. Configure the project for your target ESP chip:
|
||||
|
||||
```bash
|
||||
idf.py set-target <target>
|
||||
```
|
||||
Replace `<target>` with your specific ESP chip (e.g., esp32c3, esp32s3).
|
||||
|
||||
### 7.2 Co-processor Config
|
||||
Configure the co-processor project using
|
||||
```
|
||||
idf.py menuconfig
|
||||
```
|
||||
|
||||
#### 7.2.1 Transport config
|
||||
Navigate & change to following
|
||||
```
|
||||
-- "Example configuration"
|
||||
└── "Bus Config in between Host and Co-processor"
|
||||
└── "Transport layer"
|
||||
└── Select "SPI Full-duplex"
|
||||
```
|
||||
#### 7.2.2 Any other config
|
||||
Optionally, configure any additional SPI-specific settings under "SPI Full-duplex"
|
||||
- Set the GPIO pins for SPI signals (MOSI, MISO, CLK, CS), Handshake, Data Ready, Reset
|
||||
- Configure SPI mode (1, 2, or 3)
|
||||
- Set the SPI clock frequency
|
||||
- Checksum enable/disable (Checksum is recommended to be enabled as spi hardware doesn't have any error detection)
|
||||
|
||||
###### Generated files
|
||||
- Generated config files are (1) `sdkconfig` file and (2) internal `sdkconfig.h` file.
|
||||
- Please note, any manually changes done to these generated files, would not take effect.
|
||||
|
||||
###### Defaulting specific config (Optional)
|
||||
- This is advanced option, so please be careful.
|
||||
- To mark some config options as default, you can add specific config line in file, `sdkconfig.defaults.<target>`. So whenever next time building, you do not need to re-configure.
|
||||
|
||||
### 7.3 Co-processor Build
|
||||
Build the co-processor project
|
||||
|
||||
```
|
||||
idf.py build
|
||||
```
|
||||
|
||||
### 7.4 Co-processor Flashing
|
||||
|
||||
It is **recommended** to periodically upgrade the slave firmware to leverage new features, bug fixes, and performance improvements.
|
||||
|
||||
| Method | Description | Recommended Use |
|
||||
| -------------------------- | -------------------------------------------------- | ----------------------------------------------------- |
|
||||
| **Direct Serial Flashing** | Uses UART pins for direct firmware installation | First-time setup to install ESP-Hosted slave firmware |
|
||||
| **Slave OTA Update** | Performs slave firmware updates directly from Host | All subsequent updates after initial installation |
|
||||
|
||||
##### 7.4.1 Serial Flashing (Initial Setup)
|
||||
|
||||
For the initial setup or when OTA is not available, use serial flashing.
|
||||
|
||||
Flash the co-processor firmware using
|
||||
```
|
||||
idf.py -p <co-processor_serial_port> flash
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> If you are not able to flash the co-processor, there might be a chance that host is not allowing to to do so.
|
||||
>
|
||||
> Put host in bootloader mode using following command and then retry flashing the co-processor
|
||||
>
|
||||
> `esptool.py -p **<host_serial_port>** --before default_reset --after no_reset run`
|
||||
>
|
||||
> Flash the co-processor and log the output:
|
||||
>
|
||||
> `idf.py -p <co-processor_serial_port> flash monitor`
|
||||
|
||||
##### 7.4.2 Co-processor OTA Flashing (Subsequent Updates)
|
||||
|
||||
The ESP-Hosted link comes pre-configured and ready to use on first boot. You can update the slave firmware remotely from the host MCU using OTA (Over-The-Air) updates: **No** ESP-Prog, serial cable, or extra GPIO connections are required.
|
||||
|
||||
For step-by-step instructions, see the [Host Performs Slave OTA Example](../examples/host_performs_slave_ota/README.md).
|
||||
|
||||
## 8 Flashing the Host
|
||||
|
||||
| Supported Host Targets | Any ESP chipset | Any Non-ESP chipset |
|
||||
| ----------------------- | --------------- | ------------------- |
|
||||
|
||||
### 8.1 Select Example to Run in Hosted Mode
|
||||
|
||||
Select an example from the [ESP-IDF examples directory](https://github.com/espressif/esp-idf/tree/master/examples) that you wish to run in ESP-Hosted mode. All Wi-Fi and Bluetooth examples are supported. For simplicity and demonstration purposes, we will use the [ESP-IDF iperf example](https://github.com/espressif/esp-idf/tree/master/examples/wifi/iperf).
|
||||
|
||||
### 8.2 Host Project Component Configuration
|
||||
|
||||
Now that ESP-IDF is set up, follow these steps to prepare the host:
|
||||
|
||||
###### 1. Navigate to the iperf example in your ESP-IDF directory:
|
||||
```
|
||||
cd $IDF_PATH/examples/wifi/iperf
|
||||
```
|
||||
|
||||
###### 2. Dependency components
|
||||
Add the required components to the project's `idf_component.yml` file:
|
||||
```
|
||||
idf.py add-dependency "espressif/esp_wifi_remote"
|
||||
idf.py add-dependency "espressif/esp_hosted"
|
||||
```
|
||||
|
||||
###### 3. Remove conflicting configuration
|
||||
Open the `main/idf_component.yml` file and remove/comment the following block if present:
|
||||
```
|
||||
# ------- Delete or comment this block ---------
|
||||
espressif/esp-extconn:
|
||||
version: "~0.1.0"
|
||||
rules:
|
||||
- if: "target in [esp32p4]"
|
||||
# -----------------------------------
|
||||
```
|
||||
This step is necessary because esp-extconn and esp-hosted cannot work together.
|
||||
|
||||
###### 4. Disable native Wi-Fi if available
|
||||
If your host ESP chip already has native Wi-Fi support, disable it by editing the `components/soc/<soc>/include/soc/Kconfig.soc_caps.in` file and changing all `WIFI` related configs to `n`.
|
||||
|
||||
If you happen to have both, host and co-processor as same ESP chipset type (for example two ESP32-C2), note an [additional step](docs/troubleshooting/#1-esp-host-to-evaluate-already-has-native-wi-fi)
|
||||
|
||||
### 8.3 Menuconfig, Build and Flash Host
|
||||
|
||||
##### 1. High performance configurations
|
||||
This is optional step, suggested for high performance applications.
|
||||
|
||||
If using ESP32-P4 as host and the ESP32-C6 as the co-processor:
|
||||
|
||||
- Remove all `CONFIG_ESP_WIFI_` settings. They do not apply to ESP-Hosted.
|
||||
- Add the following settings to your `sdkconfig.defaults.esp32p4` file:
|
||||
```
|
||||
### sdkconfig for ESP32-P4 + C6 Dev board
|
||||
CONFIG_WIFI_RMT_STATIC_RX_BUFFER_NUM=16
|
||||
CONFIG_WIFI_RMT_DYNAMIC_RX_BUFFER_NUM=64
|
||||
CONFIG_WIFI_RMT_DYNAMIC_TX_BUFFER_NUM=64
|
||||
CONFIG_WIFI_RMT_AMPDU_TX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_TX_BA_WIN=32
|
||||
CONFIG_WIFI_RMT_AMPDU_RX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_RX_BA_WIN=32
|
||||
|
||||
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=65534
|
||||
CONFIG_LWIP_TCP_WND_DEFAULT=65534
|
||||
CONFIG_LWIP_TCP_RECVMBOX_SIZE=64
|
||||
CONFIG_LWIP_UDP_RECVMBOX_SIZE=64
|
||||
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=64
|
||||
|
||||
CONFIG_LWIP_TCP_SACK_OUT=y
|
||||
```
|
||||
|
||||
For other ESP32 hosts, you can merge above configs into the corresponding `sdkconfig.defaults.esp32XX` file.
|
||||
|
||||
To adjust other Wi-Fi parameters, run `idf.py menuconfig` and go to `Component config` ---> `Wi-Fi Remote` ---> `Wi-Fi configuration`.
|
||||
|
||||
Optimised parameters for other co-processors can be found in the [Performance Optimization Guide](performance_optimization.md).
|
||||
|
||||
###### 2. Set environment for your host ESP chip:
|
||||
|
||||
```
|
||||
idf.py set-target <host_target>
|
||||
```
|
||||
|
||||
###### 3. Flexible Menuconfig configurations
|
||||
|
||||
```
|
||||
idf.py menuconfig
|
||||
```
|
||||
ESP-Hosted-MCU host configurations are available under "Component config" -> "ESP-Hosted config"
|
||||
1. Select "SPI Full-duplex" as the transport layer
|
||||
2. Change co chipset to connect to under "slave chipset to be used"
|
||||
3. Optionally, configure SPI-specific settings in the "SPI Configuration" menu, like:
|
||||
- SPI Clock Freq (MHz)
|
||||
- SPI Mode
|
||||
- SPI Pins
|
||||
- SPI Checksum Enable/Disable (Checksum is recommended to be enabled as spi hardware doesn't have any error detection)
|
||||
|
||||
> [!NOTE]
|
||||
> The actual clock frequency used is determined by the hardware. Use an oscilloscope or logic analyzer to check the clock frequency.
|
||||
|
||||
###### 4. Build the project:
|
||||
```
|
||||
idf.py build
|
||||
```
|
||||
|
||||
###### 5. Flash the firmware:
|
||||
```
|
||||
idf.py -p <host_serial_port> flash
|
||||
```
|
||||
|
||||
###### 6. Monitor the output:
|
||||
|
||||
```
|
||||
idf.py -p <host_serial_port> monitor
|
||||
```
|
||||
|
||||
- If host was put into bootloader mode earlier, it may need manual reset
|
||||
|
||||
## 9 Testing and Troubleshooting
|
||||
|
||||
After flashing both the co-processor and host devices, follow these steps to connect and test your ESP-Hosted SPI Full Duplex setup:
|
||||
|
||||
1. Connect the hardware:
|
||||
- Follow the pin assignments for SPI Full Duplex as specified in [Hardware Setup](docs/spi_full_duplex.md#5-hardware-setup).
|
||||
- Ensure all necessary connections are made, including power, ground, and the extra GPIO signals (Data_Ready and Reset).
|
||||
|
||||
2. Power on both devices.
|
||||
|
||||
3. Verify the connection:
|
||||
- Check the serial output of both devices for successful initialization messages.
|
||||
- Look for messages indicating that the SPI Full Duplex transport layer has been established
|
||||
|
||||
4. Logs at both sides:
|
||||
- Host:
|
||||
|
||||
```
|
||||
I (522) transport: Attempt connection with slave: retry[0]
|
||||
I (525) transport: Reset slave using GPIO[54]
|
||||
I (530) os_wrapper_esp: GPIO [54] configured
|
||||
I (535) gpio: GPIO[54]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
|
||||
I (1712) transport: Received INIT event from ESP32 peripheral
|
||||
I (1712) transport: EVENT: 12
|
||||
I (1712) transport: EVENT: 11
|
||||
I (1715) transport: capabilities: 0xe8
|
||||
I (1719) transport: Features supported are:
|
||||
I (1724) transport: - HCI over SPI
|
||||
I (1728) transport: - BLE only
|
||||
I (1732) transport: EVENT: 13
|
||||
I (1736) transport: ESP board type is : 13
|
||||
|
||||
I (1741) transport: Base transport is set-up
|
||||
```
|
||||
|
||||
- Co-processor:
|
||||
|
||||
```
|
||||
I (492) fg_mcu_slave: *********************************************************************
|
||||
I (501) fg_mcu_slave: ESP-Hosted-MCU Slave FW version :: X.Y.Z
|
||||
|
||||
I (511) fg_mcu_slave: Transport used :: SPI
|
||||
I (520) fg_mcu_slave: *********************************************************************
|
||||
I (529) fg_mcu_slave: Supported features are:
|
||||
I (534) fg_mcu_slave: - WLAN over SPI
|
||||
I (538) h_bt: - BT/BLE
|
||||
I (541) h_bt: - HCI Over SPI
|
||||
I (545) h_bt: - BLE only
|
||||
```
|
||||
|
||||
5. Test basic functionality:
|
||||
- The iperf example automatically attempts to connect to the configured Wi-Fi network. Watch the serial output for connection status.
|
||||
- If the automatic connection fails, you can manually initiate a Wi-Fi scan and connection:
|
||||
```
|
||||
sta_scan
|
||||
sta_connect <SSID> <password>
|
||||
```
|
||||
6. Additional commands to test:
|
||||
- Get IP address: `sta_ip`
|
||||
- Disconnect from Wi-Fi: `sta_disconnect`
|
||||
- Set Wi-Fi mode: `wifi_mode <mode>` (where mode can be 'sta', 'ap', or 'apsta')
|
||||
|
||||
7. Advanced iperf testing:
|
||||
Once connected, you can run iperf tests to verify performance:
|
||||
|
||||
| Test Case | Host Command | External STA Command |
|
||||
|-----------|--------------|----------------------|
|
||||
| UDP Host TX | `iperf -u -c <STA_IP> -t 60 -i 3` | `iperf -u -s -i 3` |
|
||||
| UDP Host RX | `iperf -u -s -i 3` | `iperf -u -c <HOST_IP> -t 60 -i 3` |
|
||||
| TCP Host TX | `iperf -c <STA_IP> -t 60 -i 3` | `iperf -s -i 3` |
|
||||
| TCP Host RX | `iperf -s -i 3` | `iperf -c <HOST_IP> -t 60 -i 3` |
|
||||
|
||||
Note: Replace `<STA_IP>` with the IP address of the external STA, and `<HOST_IP>` with the IP address of the ESP-Hosted device.
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> To measure the optimal performance, check out the [Shield Box Test Setup](shield-box-test-setup.md).
|
||||
|
||||
8. Troubleshooting:
|
||||
- If you encounter issues, refer to section 6.3 for testing the SPI connection.
|
||||
- Consider using a lower clock speed or checking your [hardware connections](#5-hardware-setup) if you experience communication problems.
|
||||
- ESP-Hosted-MCU troubleshooting guide: [docs/troubleshooting.md](docs/troubleshooting.md)
|
||||
|
||||
9. Monitoring and debugging:
|
||||
- Use the serial monitor on both devices to observe the communication between the host and co-processor.
|
||||
- For more detailed debugging, consider using a logic analyzer to examine the SPI signals.
|
||||
|
||||
## 10 References
|
||||
- [ESP-IDF Programming Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/)
|
||||
- [ESP32 Hardware Design Guidelines](https://www.espressif.com/en/products/hardware/esp32/resources)
|
||||
- [SPI Protocol Basics](https://en.wikipedia.org/wiki/Serial_Peripheral_Interface)
|
||||
790
managed_components/espressif__esp_hosted/docs/spi_half_duplex.md
Normal file
@@ -0,0 +1,790 @@
|
||||
# ESP-Hosted SPI HD (Half Duplex) Operation
|
||||
|
||||
Sections 2 to 6 below covers the theoretical part where the SPI Half duplex protocol and expected framing structure is explained. This frame structure is flexible. Host and Co-processor follow the same frame structure.
|
||||
|
||||
Section 7 to 11 covers the complete step-wise setup co-processor and host with SPI Half Duplex, using 2 or 4 data lines.
|
||||
|
||||
If you wish to skip the theory, you can refer the [Quick Start Guide](#1-quick-start-guide) below. For quick navigation, please unfold the Table of Contents below.
|
||||
|
||||
<details>
|
||||
<summary>Table of Contents</summary>
|
||||
|
||||
|
||||
- [1. Quick Start Guide](#1-quick-start-guide)
|
||||
|
||||
- [2. Introduction](#2-introduction)
|
||||
|
||||
- [3. SPI HD Configuration](#3-spi-hd-configuration) => [1 Clock and Phase](#31-clock-and-phase) || [2 Data Lines](#32-data-lines) || [3 Extra GPIO Signals](#33-extra-gpio-signals) || [4 Pin Assignments](#34-pin-assignments)
|
||||
|
||||
- [4. SPI HD Protocol](#4-spi-hd-protocol) => [1 Data IO Modes](#41-data-io-modes) || [2 Supported Commands](#42-supported-commands) || [3 Registers Used](#43-registers-used) || [4 Timing Diagrams](#44-timing-diagrams)
|
||||
|
||||
- [5. SPI HD Operation](#5-spi-hd-operation) => [1 Initialization](#51-initialization) || [2 Co-processor to Host Transfer](#52-co-processor-to-host-transfer) || [3 Host to Co-processor Transfer](#53-host-to-co-processor-transfer) || [4 Code Reference](#54-code-reference)
|
||||
|
||||
- [6. Hardware Considerations](#6-hardware-considerations) => [1 General Considerations](#61-general-considerations) || [2 Jumper Wires](#62-jumper-wires) || [3 PCB Design](#63-pcb-design) || [4 Advanced Considerations](#64-advanced-considerations)
|
||||
|
||||
- [7. Hardware Setup](#7-hardware-setup)
|
||||
|
||||
- [8. Set-Up ESP-IDF](#8-set-up-esp-idf) => [Option 1: Installer Way](#option-1-installer-way) || [Option 2: Manual Way](#option-2-manual-way)
|
||||
|
||||
- [9. Flashing the Co-processor](#9-flashing-the-co-processor) => [1 Create Co-processor Project](#91-create-co-processor-project) || [2 Co-processor Config](#92-co-processor-config) || [3 Co-processor Build](#93-co-processor-build) || [4 Co-processor Flashing](#94-co-processor-flashing)
|
||||
|
||||
- [10. Flashing the Host](#10-flashing-the-host) => [1 Select Example to Run in Hosted Mode](#101-select-example-to-run-in-hosted-mode) || [2 Host Project Component Configuration](#102-host-project-component-configuration) || [3 Menuconfig, Build and Flash Host](#103-menuconfig-build-and-flash-host)
|
||||
|
||||
- [11. Testing and Troubleshooting](#11-testing-and-troubleshooting)
|
||||
|
||||
- [12. References](#12-references)
|
||||
|
||||
</details>
|
||||
|
||||
## 1 Quick Start Guide
|
||||
|
||||
This section provides a brief overview of how to get started with ESP-Hosted using SPI HD mode, bypassing the theory and explanation. Please refer to the following sections to quickly set-up demo.
|
||||
|
||||
- [7. Hardware Setup](#7-hardware-setup)
|
||||
- [8. Set-Up ESP-IDF](#8-set-up-esp-idf)
|
||||
- [9. Flashing the Co-processor](#9-flashing-the-co-processor)
|
||||
- [10. Flashing the Host](#10-flashing-the-host)
|
||||
- [11. Testing and Troubleshooting](#11-testing-and-troubleshooting)
|
||||
|
||||
These sections will guide you through the process of configuring and flashing both the co-processor and host devices, setting up the hardware connections, and verifying successful communication.
|
||||
|
||||
## 2 Introduction
|
||||
|
||||
The ESP32 family of chips (except the ESP32) support the SPI co-processor HD (Half Duplex) Mode Protocol.
|
||||
|
||||
In this mode of operation, SPI supports 2 or 4 data lines to transfer data to the co-processor or from the co-processor (half duplex) during an SPI transaction. This is different from 'standard' SPI mode which transfers data bidirectionally (full duplex) over two data lines (one for host to co-processor data [MOSI], one for co-processor to host data [MISO]) during an SPI transaction.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> SPI Half Duplex mode is not supported on the classic ESP32. Other all chipsets support half duplex.
|
||||
> Please use SPI full duplex for classic ESP32
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> SPI Half Duplex is not an industry standard and has multiple
|
||||
> implementations. Make sure your host processor supports the SPI HD
|
||||
> protocol implemented by the Hosted co-processor before proceeding. See [SPI HD protocol used by Hosted](#4-spi-hd-protocol).
|
||||
|
||||
## 3 SPI HD Configuration
|
||||
|
||||
To enable SPI HD on the Host and co-processor using `idf.py menuconfig`:
|
||||
|
||||
1. On Host: **Component config** ---> **ESP-Hosted config** --->
|
||||
**Transport layer** and choose **SPI Half-duplex**.
|
||||
2. On Co-processor: **Example configuration** ---> **Transport layer** and
|
||||
choose **SPI Half-duplex**.
|
||||
|
||||
### 3.1 Clock and Phase
|
||||
|
||||
The standard SPI CPOL clock and CPHA phase must be configured
|
||||
correctly on both the host and co-processor for the protocol to work.
|
||||
|
||||
### 3.2 Data Lines
|
||||
|
||||
Both the host and co-processor can support two or four data lines. Four data lines will be used to transfer data if configured on both the host and co-processor. If the host is configured to use two data lines, only two lines will be used to transfer data even if the co-processor is configured to use four data lines.
|
||||
|
||||
### 3.3 Extra GPIO Signals
|
||||
|
||||
Extra GPIO signals are required for SPI HD on Hosted and can be
|
||||
assigned to any free GPIO pins:
|
||||
|
||||
- `Data_Ready` signal: an output signal from the co-processor to the host. When asserted, the co-processor is telling the host that it has data to send. The host should perform a data read SPI transaction to fetch data from the co-processor.
|
||||
- `Reset` signal: an output signal from the host to the co-processor. When asserted, the host resets the co-processor. This is done when ESP-Hosted is started on the host, to synchronise the state of the host and co-processor.
|
||||
|
||||
> [!NOTE]
|
||||
> The `Reset` signal can be configured to connect to the `EN` or `RST`
|
||||
> pin on the co-processor, or assigned to a GPIO pin on the co-processor.
|
||||
>
|
||||
> To configure this, use `idf.py menuconfig` on the co-processor: **Example
|
||||
> configuration** ---> **SPI Half-duplex Configuration** --->
|
||||
> **GPIOs** and set **Slave GPIO pin to reset itself**.
|
||||
|
||||
### 3.4 Pin Assignments
|
||||
|
||||
Using the pins already assigned to SPI signals (dedicated `IO_MUX` pins) is recommended to minimise propagation delays. Using other GPIO pins for SPI signals will route the signals through the GPIO matrix which may limit the maximum clock frequency that can be used.
|
||||
|
||||
The following table shows the mapping between the SPI bus signals and
|
||||
their SPI HD Function:
|
||||
|
||||
| SPI Bus Signal | SPI HD Function | Applicable |
|
||||
| :-------------: | :--------------: | :--------------: |
|
||||
| SPI_CS | Chip Select | Dual, Quad SPI |
|
||||
| SPICLK | Clock | Dual, Quad SPI |
|
||||
| SPID | Data Bit 0 | Dual, Quad SPI |
|
||||
| SPIQ | Data Bit 1 | Dual, Quad SPI |
|
||||
| SPIWP | Data Bit 2 | Quad SPI |
|
||||
| SPIHD | Data Bit 3 | Quad SPI |
|
||||
| Data_Ready | Extra GPIO\* | Dual, Quad SPI |
|
||||
| Reset | Extra GPIO\* | Dual, Quad SPI |
|
||||
|
||||
- Extra GPIOs `Data_Ready`, `Reset` are explained above in [3.3 Extra GPIO Signals](#33-extra-gpio-signals)
|
||||
- The `SPI HD CS signal`, `Data_Ready` and `Reset` can be assigned to any GPIO pin on the host and co-processor.
|
||||
- By default, the SPI bus would idle (no CS, no clock, no data) when no transaction needed from either side, co-processor or host.
|
||||
- `Data_Ready` could be made optional with some code changes, but it would mean that the SPI bus would not be idled out when no transaction needed. This would be lower number of GPIOs used, but the power consumption would be higher. We are adding this feature soon.
|
||||
|
||||
## 4 SPI HD Protocol
|
||||
|
||||
Hosted uses the ESP SPI co-processor HD (Half Duplex) Mode Protocol (see [References](#11-references)) with some modifications.
|
||||
|
||||
### 4.1 Data IO Modes
|
||||
|
||||
When communicating with the co-processor, the master uses the Command, Address, Dummy and Data phases during an SPI transaction. The number of bits and number of data lines used in each phase are:
|
||||
|
||||
- **Command**: 8 bits, 1 data line
|
||||
- **Address**: 8 bits, 2 or 4 data lines
|
||||
- **Dummy**: 8 bits, 1 data line
|
||||
- **Data**: variable length, 2 or 4 data lines
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> The number of data lines used in the Address and Data phase depends
|
||||
> on the Command Mask in the Command sent by the host. See [Supported Commands](#44-supported-commands).
|
||||
|
||||
### 4.2 Supported Commands
|
||||
|
||||
Hosted uses the following SPI HD commands when communicating with the co-processor:
|
||||
|
||||
| Command | OpCode | Purpose |
|
||||
| :---: | :---: | :--- |
|
||||
| WRBUF | 0x01 | Write to a 32-bit buffer register on the co-processor |
|
||||
| RDBUF | 0x02 | Read from a 32-bit buffer register on the co-processor |
|
||||
| WRDMA | 0x03 | Write data to the co-processor using DMA |
|
||||
| RDDMA | 0x04 | Read data from the co-processor during DMA |
|
||||
| WR_DONE | 0x07 | End of DMA write |
|
||||
| CMD8 | 0x08 | End of DMA read |
|
||||
| CMD9 | 0x09 | End of register read |
|
||||
|
||||
#### 4.2.1 Command Mask
|
||||
|
||||
The Commands are masked with a command mask to tell the co-processor the correct number of data lines to use during the transaction (2 or 4 data lines). Hosted uses the following masks, which are bit ORed with the command during a SPI transactions:
|
||||
|
||||
| Mode | Mask |
|
||||
| :---: | :---: |
|
||||
| 2-bits | 0x50 |
|
||||
| 4-bits | 0xA0 |
|
||||
|
||||
For example, if the host sends command `0x51` (2-bit mask + WRBUF), the host and co-processor will use 2 data lines to send the address and data. If the host sends command `0xA1` (4-bit mask + WRBUF), the host and co-processor will use 4 data lines to send the address and data.
|
||||
|
||||
The Command Mask determines the number of data lines used for the transaction. Even if there are four data lines between the host and co-processor, the host can tell the co-processor to use only two data lines by applying the 0x50 command mask.
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> It is an error to apply the 4-bit data mask (0xA0) when there are
|
||||
> only two data lines connecting the host and co-processor.
|
||||
|
||||
### 4.3 Registers Used
|
||||
|
||||
The ESP SPI Co-processor HD Mode Protocol defines a number of registers on the co-processor. These registers are used in Hosted as follows:
|
||||
|
||||
| Register | Name | Purpose |
|
||||
| :---: | :---: | :--- |
|
||||
| 0x00 | COPROCESSOR\_READY | Indicates if co-processor is ready |
|
||||
| 0x04 | MAX\_TX\_BUF\_LEN | Maximum length of DMA data co-processor can transmit |
|
||||
| 0x08 | MAX\_RX\_BUF\_LEN | Maximum length of DMA data co-processor can receive |
|
||||
| 0x0C | TX\_BUF\_LEN | Updated whenever co-processor wants to transmit data |
|
||||
| 0x10 | RX\_BUF\_LEN | Updated whenever co-processor can receive data |
|
||||
| 0x14 | COPROCESSOR\_CONTROL | Controls co-processor operation |
|
||||
|
||||
### 4.4 Timing Diagrams
|
||||
|
||||
The following diagrams summarize the SPI transactions as used by Hosted:
|
||||
|
||||

|
||||
|
||||
*SPI Transaction using 4 data lines*
|
||||
|
||||

|
||||
|
||||
*SPI Transaction using 2 data lines*
|
||||
|
||||
|
||||
## 5 SPI HD Operation
|
||||
|
||||
### 5.1 Initialization
|
||||
|
||||
#### 5.1.1 Co-processor and Host Initialization
|
||||
|
||||
The co-processor starts up and initialises the SPI HD transport. When the co-processor is ready it writes the value `COPROCESSOR_IS_READY` (0xEE) to the COPROCESSOR\_READY register.
|
||||
|
||||
The Host starts up and initialises the SPI HD transport. When ready, it polls the COPROCESSOR\_READY register on the co-processor until it reads the value
|
||||
`COPROCESSOR_IS_READY`.
|
||||
|
||||
Once co-processor is ready, host prepare for interrupts triggered by `Data_Ready`, and sets bit 0 on the COPROCESSOR\_CONTROL register to 1. This opens the data path to the co-processor.
|
||||
|
||||
Both host and co-processor are now ready to communicate.
|
||||
|
||||
The first packet the co-processor transfers to the host is a Capabilities Packet, stating what the co-processor is capable of supporting:
|
||||
|
||||
- WLAN, Bluetooth, etc.
|
||||
- the number of data lines supported for SPI HD
|
||||
|
||||
The host uses this packet to determine what the co-processor is capable of supporting.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant h as Host
|
||||
participant s as Co-processor
|
||||
|
||||
note over s,h : Init
|
||||
|
||||
loop Executed periodically
|
||||
h ->> s : Read COPROCESSOR_READY reg
|
||||
s -->> h : Not Ready (!0xEE)
|
||||
end
|
||||
|
||||
note over s : Ready: COPROCESSOR_READY = 0xEE
|
||||
h ->> s : Read COPROCESSOR_READY reg
|
||||
s -->> h : Ready (0xEE)
|
||||
note over h : Enable Data_Ready interrupt
|
||||
h ->> s : Set COPROCESSOR_CONTROL reg = 1
|
||||
|
||||
note over s : Open Data Path
|
||||
note over s : Prepare Capability Data
|
||||
|
||||
note over s : Assert Data_Ready
|
||||
h ->> s : Read Data
|
||||
s -->> h : Capability
|
||||
note over s : Deassert Data_Ready
|
||||
|
||||
note over s,h : SPI HD Transport Ready
|
||||
```
|
||||
|
||||
*SPI HD Initialization Sequence*
|
||||
|
||||
#### 5.1.2 Number of Data Lines Used
|
||||
|
||||
After initialization, the host initially communicates with the co-processor using two data lines. If the co-processor is capable of supporting four data
|
||||
lines (from the Capabilities Packet sent by the co-processor), and the host is configured to also use four data lines, then four data lines will be used for subsequent data transfers.
|
||||
|
||||
If neither the host or co-processor is capable of transferring data using four data lines, then only two data lines will be used.
|
||||
|
||||
### 5.2 Co-processor to Host Transfer
|
||||
|
||||
Co-processor asserts `Data_Ready` to tell the host it has data to send.
|
||||
|
||||
Host reads the TX\_BUF\_LEN register.
|
||||
|
||||
> [!NOTE]
|
||||
> The upper 8-bits of the TX\_BUF\_LEN register are reserved, and
|
||||
> should be masked out to get the correct read length from the
|
||||
> TX\_BUF\_LEN register.
|
||||
|
||||
The host subtracts the read length from its cached read length
|
||||
(initial value is zero) to discover how much more data the co-processor wants to transfer to the host. The host can now read the data using the RDDMA command, ending the transfer with CMD8. The host now updates its cached read length with the co-processor's read length.
|
||||
|
||||
After reading TX\_BUF\_LEN register, host sends CMD9. This tells the co-processor that the host has read the register and it is safe for the co-processor to update the register (if required) and deassert the `Data_Ready` signal.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant h as Host
|
||||
participant s as Co-processor
|
||||
|
||||
note over s : Prepare data to send, update TX_BUF_LEN
|
||||
|
||||
note over s : Assert Data_Ready
|
||||
|
||||
h ->> s : Read TX_BUF_LEN
|
||||
note over h : Bytes to transfer = TX_BUF_LEN - (cached)TX_BUF_LEN
|
||||
|
||||
h ->> s : Send CMD9
|
||||
note over s : Deassert Data_Ready
|
||||
|
||||
h ->> s : Send RDDMA
|
||||
s -->> h : Transfer Data
|
||||
|
||||
h ->> s : CMD8 (at end of transfer)
|
||||
|
||||
note over h : update (cached)TX_BUF_LEN
|
||||
```
|
||||
|
||||
*SPI HD Read Sequence*
|
||||
|
||||
### 5.3 Host to Co-processor Transfer
|
||||
|
||||
Host reads the RX\_BUF\_LEN register to discover how many buffers are
|
||||
available on the co-processor (each buffer is of size MAX\_RX\_BUF\_LEN). If
|
||||
there are not enough buffers to store the data to be sent, the host
|
||||
should wait and re-read the register until there are enough buffers.
|
||||
|
||||
Once there are enough buffers, the host can use WRDMA to send data,
|
||||
ending each buffer transfer with WR_DONE.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant h as Host
|
||||
participant s as Co-processor
|
||||
|
||||
note over h : Prepare data to send
|
||||
|
||||
loop Read until got buffer space
|
||||
h ->> s : Read RX_BUF_LEN
|
||||
note over h : available buffers = RX_BUF_LEN - (cached)RX_BUF_LEN
|
||||
end
|
||||
|
||||
h ->> s : Send WRDMA
|
||||
h ->> s : Transfer Data
|
||||
h ->> s : WR_DONE (at end of transfer)
|
||||
|
||||
note over h : Update (cached)RX_BUF_LEN
|
||||
```
|
||||
|
||||
*SPI HD Write Sequence*
|
||||
|
||||
### 5.4 Code Reference
|
||||
|
||||
- [`slave/main/spi_hd_slave_api.c`](https://github.com/espressif/esp-hosted-mcu/blob/main/slave/main/spi_hd_slave_api.c) implements the code to run the SPI HD driver on the co-processor
|
||||
- [`host/drivers/transport/spi_hd/spi_hd_drv.c`](https://github.com/espressif/esp-hosted-mcu/blob/main/host/drivers/transport/spi_hd/spi_hd_drv.c) implements the generic code to run the SPI HD driver on the host
|
||||
- [`host/port/spi_hd_wrapper.c`](https://github.com/espressif/esp-hosted-mcu/blob/main/host/port/spi_hd_wrapper.c) implements the ESP-IDF specific code used by the generic SPI HD driver on the host
|
||||
|
||||
## 6 Hardware Considerations
|
||||
|
||||
### 6.1 General Considerations
|
||||
|
||||
- Ensure equal trace lengths for all SPI connections, whether using jumper wires or PCB traces.
|
||||
- Use the lower clock frequency like 5 MHz for evaluation. Once solution verified, optimise the clock frequency in increasing steps to max possible value. To find out practical maximum SPI co-processor frequency for your co-processor, check `IDF_PERFORMANCE_MAX_SPI_CLK_FREQ` in [ESP-IDF co-processor SPI clock benchmark](https://github.com/espressif/esp-idf/blob/master/components/esp_driver_spi/test_apps/components/spi_bench_mark/include/spi_performance.h)
|
||||
- Verify voltage compatibility between host and co-processor devices.
|
||||
- Provide proper power supply decoupling for both host and co-processor devices.
|
||||
|
||||
### 6.2 Jumper Wires
|
||||
|
||||
- Jumper wires are suitable for initial testing and prototyping.
|
||||
- Use high-quality, low-capacitance jumper wires.
|
||||
- Keep wires as short as possible, ideally under 10 cm.
|
||||
- Arrange wires to minimize crosstalk, especially for clock and data lines.
|
||||
- Possibly, use twisted pairs for clock and data lines to reduce electromagnetic interference.
|
||||
- If possible, use a ground wire between every signal wire to improve signal integrity.
|
||||
- Connect as many grounds as possible to improve common ground reference and reduce ground noise.
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> Quad SPI (QSPI) should not be used with jumper cables due to signal integrity issues. Use Dual SPI for evaluation with jumper cables.
|
||||
|
||||
### 6.3 PCB Design
|
||||
|
||||
For optimal performance and reliability in production designs:
|
||||
|
||||
- Ensure equal trace lengths for all SPI signals (CLK, MOSI, MISO, CS) as much as possible. This practice, known as length matching, is crucial for maintaining signal integrity and reducing timing skew, especially at higher frequencies.
|
||||
- If perfect length matching is not possible, prioritize matching the clock (CLK) trace length with the data lines.
|
||||
- Use controlled impedance traces for high-speed signals.
|
||||
- Place bypass capacitors close to the power pins of both the host and co-processor devices.
|
||||
- Consider using series termination resistors on the clock and data lines to reduce reflections.
|
||||
- For high-speed designs, use a 4-layer PCB with dedicated power and ground planes.
|
||||
- Quad SPI (QSPI) should only be implemented on a properly designed PCB.
|
||||
|
||||
|
||||
### 6.4 Advanced Considerations
|
||||
|
||||
- Calculate the maximum allowed trace length based on your clock frequency and PCB material.
|
||||
- Consider the capacitive load on the SPI bus, especially for longer traces or when using multiple co-processor devices.
|
||||
- For very high-speed designs, consider using differential signaling techniques.
|
||||
- Implement proper EMI/EMC design techniques to minimize electromagnetic interference.
|
||||
- Use an oscilloscope or logic analyzer to verify signal integrity and timing.
|
||||
- Start with a lower clock frequency and gradually increase it while monitoring performance.
|
||||
- Ensure proper grounding between the host and co-processor devices.
|
||||
- If using multiple power supplies, ensure they share a common ground.
|
||||
- Consider using level shifters if the host and co-processor operate at different voltage levels.
|
||||
|
||||
## 7 Hardware Setup
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> Remember that Quad SPI (using D2 and D3) should only be used with a properly designed PCB, not with jumper wires.
|
||||
|
||||
Before flashing the co-processor and host, ensure that you have made the correct hardware connections. The following tables show the recommended connections for SPI Half Duplex mode:
|
||||
|
||||
|
||||
|
||||
### Host connections
|
||||
| Signal | ESP32-S3 | ESP32-P4-Function-EV-Board | Applicable |
|
||||
| :--------: | :------: | :------------------------: | :------------: |
|
||||
| CLK | 19 | 18 | Dual, Quad SPI |
|
||||
| D0 | 13 | 14 | Dual, Quad SPI |
|
||||
| D1 | 35 | 15 | Dual, Quad SPI |
|
||||
| CS | 47 | 19 | Dual, Quad SPI |
|
||||
| Data Ready | 12 | 6 | Dual, Quad SPI |
|
||||
| Reset Out | 42 | 54 | Dual, Quad SPI |
|
||||
| GND | GND | GND | Dual, Quad SPI |
|
||||
| D2 | 20 | 16 | Quad SPI only |
|
||||
| D3 | 9 | 17 | Quad SPI only |
|
||||
|
||||
- Host GPIOs can be re-configured to any other GPIOs, while co-processor configuration is done.
|
||||
- Make sure the configuration and hardware connections match.
|
||||
- Classic ESP32
|
||||
- Not supported as host or co-processor
|
||||
- Rest all chipsets are supported as host
|
||||
- ESP32-S2/C2/C3/C5/C6/C61
|
||||
- Pins for SPI Half Duplex Host need to be figured out yet.
|
||||
- ESP32-P4
|
||||
- For ESP32-P4-Function-EV-Board, the SDIO onboard pins are re-used for SPI Half Duplex Host.
|
||||
- For Non ESP32-P4-Function-EV-Board, pins for SPI Half Duplex Host need to be figured out yet.
|
||||
|
||||
### Co-processor connections
|
||||
|
||||
| Signal | ESP32-C6 on ESP32-P4-Function-EV-Board | ESP32-C2/C3/C6 | ESP32-C5 | Applicable |
|
||||
| :---------: | :-----------------------------------: | :------------: | :------: | :------------: |
|
||||
| CLK | 19 | 6 | 6 | Dual, Quad SPI |
|
||||
| D0 | 20 | 7 | 7 | Dual, Quad SPI |
|
||||
| D1 | 21 | 2 | 2 | Dual, Quad SPI |
|
||||
| CS | 18 | 10 | 10 | Dual, Quad SPI |
|
||||
| Data Ready | 2 | 0 | 13 | Dual, Quad SPI |
|
||||
| Reset In | EN/RST | EN/RST | EN/RST | Dual, Quad SPI |
|
||||
| GND | GND | GND | GND | Dual, Quad SPI |
|
||||
| D2 | 22 | 5 | 5 | Quad SPI only |
|
||||
| D3 | 23 | 4 | 4 | Quad SPI only |
|
||||
|
||||
- Co-processor GPIOs can be re-configured to any other GPIOs, while co-processor configuration is done.
|
||||
- Make sure the configuration and hardware connections match.
|
||||
- ESP32-C2/C3/C5/C6/C61/S2/S3
|
||||
- All supported as SPI Half Duplex co-processor
|
||||
- Pins for SPI Half Duplex co-processor need to be figured out yet for other boards
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> A. QSPI Testing
|
||||
> - Tested on ESP32-P4-Function-EV-Board
|
||||
> - ESP32-P4 as host, ESP32-C6/C3 as QSPI co-processor
|
||||
> - Reused existing SDIO connections for QSPI on C6 and P4
|
||||
>
|
||||
> B. Dual SPI Testing
|
||||
> - ESP32-S3 host with ESP32-C5 co-processor
|
||||
> - Tested using jumper cables
|
||||
>
|
||||
> C. Performance Optimization
|
||||
> - Always prefer to use IO_MUX pins from datasheet for optimal performance on both sides
|
||||
>
|
||||
> D. Portability
|
||||
> - Once ported, any other non ESP host with Dual SPI or QSPI can be used
|
||||
|
||||
## 8 Set-Up ESP-IDF
|
||||
|
||||
Before setting up the ESP-Hosted co-processor & host for SPI Half Duplex mode, ensure that ESP-IDF is properly installed and set up on your system.
|
||||
|
||||
#### Option 1: Installer Way
|
||||
|
||||
- **Windows**
|
||||
- Install and setup ESP-IDF on Windows as documented in the [Standard Setup of Toolchain for Windows](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup.html).
|
||||
- Use the ESP-IDF [Powershell Command Prompt](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup.html#using-the-command-prompt) for subsequent commands.
|
||||
|
||||
- **Linux or MacOS**
|
||||
- For bash:
|
||||
```bash
|
||||
bash docs/setup_esp_idf__latest_stable__linux_macos.sh
|
||||
```
|
||||
- For fish:
|
||||
```fish
|
||||
fish docs/setup_esp_idf__latest_stable__linux_macos.fish
|
||||
```
|
||||
|
||||
#### Option 2: Manual Way
|
||||
|
||||
Please follow the [ESP-IDF Get Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html) for manual installation.
|
||||
|
||||
## 9 Flashing the Co-processor
|
||||
|
||||
| Supported Co-processor Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-S2 | ESP32-S3 |
|
||||
| ------------------------------ | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- |
|
||||
|
||||
### 9.1 Create Co-processor Project
|
||||
1. Create co-processor project possibly outside of ESP-IDF project directory using
|
||||
|
||||
```bash
|
||||
idf.py create-project-from-example "espressif/esp_hosted:slave"
|
||||
```
|
||||
|
||||
2. Navigate to the created project directory.
|
||||
|
||||
3. Configure the project for your target ESP chip:
|
||||
|
||||
```bash
|
||||
idf.py set-target <target>
|
||||
```
|
||||
Replace `<target>` with your specific co-processor ESP chip (e.g., esp32c3, esp32s3).
|
||||
|
||||
### 9.2 Co-processor Config
|
||||
Configure the co-processor project using
|
||||
```
|
||||
idf.py menuconfig
|
||||
```
|
||||
|
||||
#### 9.2.1 Transport config
|
||||
Navigate and change as following:
|
||||
```
|
||||
Example Configuration
|
||||
└── Bus Config in between Host and Co-processor
|
||||
└── Transport layer
|
||||
└── Select "SPI Half-duplex"
|
||||
```
|
||||
#### 9.2.2 Any other config
|
||||
- Optionally, Configure any additional SPI-specific settings in the "SPI Half-duplex Configuration" menu, like co-processor GPIOs, SPI mode, etc.
|
||||
|
||||
###### Generated files
|
||||
- Generated config files are (1) `sdkconfig` file and (2) internal `sdkconfig.h` file.
|
||||
- Please note, any manually changes done to these generated files, would not take effect.
|
||||
|
||||
###### Defaulting specific config (Optional)
|
||||
- This is advanced option, so please be careful.
|
||||
- To mark some config options as default, you can add specific config line in file, `sdkconfig.defaults.<target>`. So whenever next time building, you do not need to re-configure.
|
||||
|
||||
### 9.3 Co-processor Build
|
||||
Build the co-processor project
|
||||
|
||||
```
|
||||
idf.py build
|
||||
```
|
||||
|
||||
### 9.4 Co-processor Flashing
|
||||
|
||||
## Firmware Upgrade Guidelines
|
||||
|
||||
It is **recommended** to periodically upgrade the slave firmware to leverage new features, bug fixes, and performance improvements.
|
||||
|
||||
| Method | Description | Recommended Use |
|
||||
| -------------------------- | -------------------------------------------------- | ----------------------------------------------------- |
|
||||
| **Direct Serial Flashing** | Uses UART pins for direct firmware installation | First-time setup to install ESP-Hosted slave firmware |
|
||||
| **Slave OTA Update** | Performs slave firmware updates directly from Host | All subsequent updates after initial installation |
|
||||
|
||||
|
||||
##### 9.4.1 Serial Flashing (Initial Setup)
|
||||
|
||||
For the initial setup or when OTA is not available, use serial flashing.
|
||||
|
||||
Flash the co-processor firmware using
|
||||
```
|
||||
idf.py -p <co-processor_serial_port> flash
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> If you are not able to flash the co-processor, there might be a chance that host is not allowing to to do so.
|
||||
>
|
||||
> Put host in bootloader mode using following command and then retry flashing the co-processor
|
||||
>
|
||||
> `esptool.py -p **<host_serial_port>** --before default_reset --after no_reset run`
|
||||
>
|
||||
> Flash the co-processor and log the output:
|
||||
>
|
||||
> `idf.py -p <co-processor_serial_port> flash monitor`
|
||||
|
||||
##### 9.4.2 Co-processor OTA Flashing (Subsequent Updates)
|
||||
|
||||
The ESP-Hosted link comes pre-configured and ready to use on first boot. You can update the slave firmware remotely from the host MCU using OTA (Over-The-Air) updates: **No** ESP-Prog, serial cable, or extra GPIO connections are required.
|
||||
|
||||
For step-by-step instructions, see the [Host Performs Slave OTA Example](../examples/host_performs_slave_ota/README.md).
|
||||
|
||||
## 10 Flashing the Host
|
||||
|
||||
Host are required to support 2 data line SPI (dual SPI) or 4 line SPI (quad SPI or QSPI) in their hardware. All ESP chipsets hardware support dual, quad SPI.
|
||||
|
||||
| Supported Host Targets | Any ESP chipset | Any Non-ESP chipset |
|
||||
| ----------------------- | --------------- | ------------------- |
|
||||
|
||||
Non ESP chipset may need to port the porting layer. It is strongly recommanded to evaluate the solution using ESP chipset as host before porting to any non-esp chipset.
|
||||
For Quad SPI, PCB is only supported. Dual SPI could be evaluted using jumper cables.
|
||||
|
||||
Non-ESP Hosts, while porting, need to ensure that the Half duplex protocol and framing is exactly same as that of co-processor.
|
||||
|
||||
### 10.1 Select Example to Run in Hosted Mode
|
||||
|
||||
Select an example from the [ESP-IDF examples directory](https://github.com/espressif/esp-idf/tree/master/examples) that you wish to run in ESP-Hosted mode. All Wi-Fi and Bluetooth examples are supported. For simplicity and demonstration purposes, we will use the [ESP-IDF iperf example](https://github.com/espressif/esp-idf/tree/master/examples/wifi/iperf).
|
||||
|
||||
### 10.2 Host Project Component Configuration
|
||||
|
||||
Now that ESP-IDF is set up, follow these steps to prepare the host:
|
||||
|
||||
###### 1. Navigate to the iperf example in your ESP-IDF directory:
|
||||
```
|
||||
cd $IDF_PATH/examples/wifi/iperf
|
||||
```
|
||||
|
||||
###### 2. Dependency components
|
||||
Add the required components to the project's `idf_component.yml` file:
|
||||
```
|
||||
idf.py add-dependency "espressif/esp_wifi_remote"
|
||||
idf.py add-dependency "espressif/esp_hosted"
|
||||
```
|
||||
|
||||
###### 3. Remove conflicting configuration
|
||||
Open the `main/idf_component.yml` file and remove/comment the following block if present:
|
||||
```
|
||||
# ------- Delete or comment this block ---------
|
||||
espressif/esp-extconn:
|
||||
version: "~0.1.0"
|
||||
rules:
|
||||
- if: "target in [esp32p4]"
|
||||
# -----------------------------------
|
||||
```
|
||||
This step is necessary because esp-extconn and esp-hosted cannot work together.
|
||||
|
||||
###### 4. Disable native Wi-Fi if available
|
||||
If your host ESP chip already has native Wi-Fi support, disable it by editing the `components/soc/<soc>/include/soc/Kconfig.soc_caps.in` file and changing all `WIFI` related configs to `n`.
|
||||
|
||||
If you happen to have both, host and co-processor as same ESP chipset type (for example two ESP32-C2), note an [additional step](docs/troubleshooting/#1-esp-host-to-evaluate-already-has-native-wi-fi)
|
||||
|
||||
|
||||
### 10.3 Menuconfig, Build and Flash Host
|
||||
|
||||
###### 1. High performance configurations
|
||||
This is optional step, suggested for high performance applications.
|
||||
|
||||
If using ESP32-P4 as host and the ESP32-C6 as the co-processor:
|
||||
|
||||
- Remove all `CONFIG_ESP_WIFI_` settings. They do not apply to ESP-Hosted.
|
||||
- Add the following settings to your `sdkconfig.defaults.esp32p4` file:
|
||||
```
|
||||
### sdkconfig for ESP32-P4 + C6 Dev board
|
||||
CONFIG_WIFI_RMT_STATIC_RX_BUFFER_NUM=16
|
||||
CONFIG_WIFI_RMT_DYNAMIC_RX_BUFFER_NUM=64
|
||||
CONFIG_WIFI_RMT_DYNAMIC_TX_BUFFER_NUM=64
|
||||
CONFIG_WIFI_RMT_AMPDU_TX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_TX_BA_WIN=32
|
||||
CONFIG_WIFI_RMT_AMPDU_RX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_RX_BA_WIN=32
|
||||
|
||||
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=65534
|
||||
CONFIG_LWIP_TCP_WND_DEFAULT=65534
|
||||
CONFIG_LWIP_TCP_RECVMBOX_SIZE=64
|
||||
CONFIG_LWIP_UDP_RECVMBOX_SIZE=64
|
||||
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=64
|
||||
|
||||
CONFIG_LWIP_TCP_SACK_OUT=y
|
||||
```
|
||||
|
||||
For other ESP32 hosts, you can merge above configs into the corresponding `sdkconfig.defaults.esp32XX` file.
|
||||
|
||||
To adjust other Wi-Fi parameters, run `idf.py menuconfig` and go to `Component config` ---> `Wi-Fi Remote` ---> `Wi-Fi configuration`.
|
||||
|
||||
Optimised parameters for other co-processors can be found in the [Performance Optimization Guide](performance_optimization.md).
|
||||
|
||||
###### 2. Set environment for your host ESP chip:
|
||||
|
||||
```
|
||||
idf.py set-target <host_target>
|
||||
```
|
||||
Replace `<host_target>` with your specific ESP chip (one of esp32, esp32c2, esp32c3, esp32c5, esp32c6, esp32s2, esp32s3, esp32p4).
|
||||
|
||||
###### 3. Flexible Menuconfig configurations
|
||||
|
||||
```
|
||||
idf.py menuconfig
|
||||
```
|
||||
ESP-Hosted-MCU host configurations are available under "Component config" -> "ESP-Hosted config"
|
||||
1. Select "SPI Half-duplex" as the transport layer
|
||||
2. Change co-processor chipset to connect to under "Slave chipset to be used"
|
||||
3. Change Number of data lines to 2 or 4 based on the co-processor using "SPI Half-duplex Configuration" -> "Num Data Lines to use"
|
||||
4. Optionally, Configure SPI-specific settings in the "SPI Half-duplex Configuration" menu, like:
|
||||
- SPI Clock Freq (MHz)
|
||||
- SPI Mode
|
||||
- SPI Host GPIO Pins
|
||||
- SPI Checksum Enable/Disable (Checksum is recommended to be enabled as spi hardware doesn't have any error detection)
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> The actual clock frequency used is determined by the hardware. Use an oscilloscope or logic analyzer to check the clock frequency.
|
||||
|
||||
###### 4. Build the project:
|
||||
```
|
||||
idf.py build
|
||||
```
|
||||
|
||||
###### 5. Flash the firmware:
|
||||
```
|
||||
idf.py -p <host_serial_port> flash
|
||||
```
|
||||
|
||||
###### 6. Monitor the output:
|
||||
```
|
||||
idf.py -p <host_serial_port> monitor
|
||||
```
|
||||
- If host was put into bootloader mode earlier, it may need manual reset
|
||||
|
||||
## 11 Testing and Troubleshooting
|
||||
|
||||
After flashing both the co-processor and host devices, follow these steps to connect and test your ESP-Hosted SPI Half Duplex setup:
|
||||
|
||||
1. Connect the hardware:
|
||||
- Follow the pin assignments for SPI Half Duplex as specified in [Hardware Setup](#7-hardware-setup).
|
||||
- Ensure all necessary connections are made, including power, ground, and the extra GPIO signals (Data_Ready and Reset).
|
||||
|
||||
2. Power on both devices.
|
||||
|
||||
3. Verify the connection:
|
||||
- Check the serial output of both devices for successful initialization messages.
|
||||
- Look for messages indicating that the SPI Half Duplex transport layer has been established.
|
||||
|
||||
4. Logs at both sides:
|
||||
- Host:
|
||||
|
||||
```
|
||||
I (522) transport: Attempt connection with slave: retry[0]
|
||||
I (525) transport: Reset slave using GPIO[54]
|
||||
I (530) os_wrapper_esp: GPIO [54] configured
|
||||
I (535) gpio: GPIO[54]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
|
||||
I (1712) transport: Received INIT event from ESP32 peripheral
|
||||
I (1712) transport: EVENT: 12
|
||||
I (1712) transport: EVENT: 11
|
||||
I (1715) transport: capabilities: 0xe8
|
||||
I (1719) transport: Features supported are:
|
||||
I (1724) transport: - HCI over SPI
|
||||
I (1728) transport: - BLE only
|
||||
I (1732) transport: EVENT: 13
|
||||
I (1736) transport: ESP board type is : 13
|
||||
|
||||
I (1741) transport: Base transport is set-up
|
||||
```
|
||||
|
||||
- Co-processor:
|
||||
|
||||
```
|
||||
I (492) fg_mcu_slave: *********************************************************************
|
||||
I (501) fg_mcu_slave: ESP-Hosted-MCU Slave FW version :: X.Y.Z
|
||||
|
||||
I (511) fg_mcu_slave: Transport used :: <Dual/Quad SPI>
|
||||
I (520) fg_mcu_slave: *********************************************************************
|
||||
I (529) fg_mcu_slave: Supported features are:
|
||||
I (534) fg_mcu_slave: - WLAN over SPI
|
||||
I (538) h_bt: - BT/BLE
|
||||
I (541) h_bt: - HCI Over SPI
|
||||
I (545) h_bt: - BLE only
|
||||
```
|
||||
|
||||
5. Test basic functionality:
|
||||
- The iperf example automatically attempts to connect to the configured Wi-Fi network. Watch the serial output for connection status.
|
||||
- If the automatic connection fails, you can manually initiate a Wi-Fi scan and connection:
|
||||
```
|
||||
sta_scan
|
||||
sta_connect <SSID> <password>
|
||||
```
|
||||
6. Additional commands to test:
|
||||
- Get IP address: `sta_ip`
|
||||
- Disconnect from Wi-Fi: `sta_disconnect`
|
||||
- Set Wi-Fi mode: `wifi_mode <mode>` (where mode can be 'sta', 'ap', or 'apsta')
|
||||
|
||||
7. Advanced iperf testing:
|
||||
Once connected, you can run iperf tests to verify performance:
|
||||
|
||||
| Test Case | Host Command | External STA Command |
|
||||
| :-------: | :----------: | :------------------: |
|
||||
| UDP Host TX | `iperf -u -c <STA_IP> -t 60 -i 3` | `iperf -u -s -i 3` |
|
||||
| UDP Host RX | `iperf -u -s -i 3` | `iperf -u -c <HOST_IP> -t 60 -i 3` |
|
||||
| TCP Host TX | `iperf -c <STA_IP> -t 60 -i 3` | `iperf -s -i 3` |
|
||||
| TCP Host RX | `iperf -s -i 3` | `iperf -c <HOST_IP> -t 60 -i 3` |
|
||||
|
||||
Note: Replace `<STA_IP>` with the IP address of the external STA, and `<HOST_IP>` with the IP address of the ESP-Hosted device.
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> To measure the optimal performance, check out the [Shield Box Test Setup](shield-box-test-setup.md).
|
||||
|
||||
8. Troubleshooting:
|
||||
- If you encounter issues, refer to section 6.3 for testing the SPI connection.
|
||||
- Consider using a lower clock speed or checking your [hardware setup](#7-hardware-setup) if you experience communication problems.
|
||||
- ESP-Hosted-MCU troubleshooting guide: [docs/troubleshooting.md](docs/troubleshooting.md)
|
||||
|
||||
9. Monitoring and debugging:
|
||||
- Use the serial monitor on both devices to observe the communication between the host and co-processor.
|
||||
- For more detailed debugging, consider using a logic analyzer to examine the SPI signals.
|
||||
|
||||
## 12 References
|
||||
|
||||
- ESP SPI co-processor HD (Half Duplex) Mode Protocol: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/protocols/esp_spi_slave_protocol.html
|
||||
|
||||
149
managed_components/espressif__esp_hosted/docs/troubleshooting.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# Troubleshooting ESP-Hosted
|
||||
|
||||
**Table of Contents**
|
||||
|
||||
- [1. ESP host to evaluate already has Native Wi-Fi](#1-esp-host-to-evaluate-already-has-native-wi-fi)
|
||||
- [2. Raw Throughput Testing](#2-raw-throughput-testing)
|
||||
- [3. Make sure Hosted code is in sync for Master and Slave](#3-make-sure-hosted-code-is-in-sync-for-master-and-slave)
|
||||
- [4. Make sure GPIOs match on both the Host and Slave](#4-make-sure-gpios-match-on-both-the-host-and-slave)
|
||||
- [5. ESP-Hosted Master Not Connecting to Slave](#5-esp-hosted-master-not-connecting-to-slave)
|
||||
- [6. Getting `Drop Packet` Errors](#6-getting-drop-packet-errors)
|
||||
- [7. References](#7-references)
|
||||
|
||||
## 1 ESP host to evaluate already has Native Wi-Fi
|
||||
|
||||
Sometimes users have two ESPs, but both having Wi-Fi native capability.
|
||||
This section explains how to run ESP-Hosted-MCU on ESP host chipsets that already have native Wi-Fi support. To run ESP-Hosted-MCU on such hosts, native Wi-Fi support needs to be disabled from base ESP-IDF in use. There are alternatives to do this:
|
||||
|
||||
##### 1.1 Different ESP chipset types for host and slave
|
||||
If host and slave not the same ESP chipset types, Wi-Fi capability can be disabled for host ESP chipset alone. Edit the ESP-IDF file
|
||||
`components/soc/<soc>/include/soc/Kconfig.soc_caps.in` and change
|
||||
all `WIFI` related configs to `n`. For example:
|
||||
|
||||
```
|
||||
config SOC_WIFI_SUPPORTED
|
||||
bool
|
||||
# default y # original configuration
|
||||
default n
|
||||
```
|
||||
|
||||
This should be done for all `SOC_WIFI_xxx` configs found in the file.
|
||||
|
||||
For ESP Chipsets without native Wi-FI, `SOC_WIFI_xxx` configs will be
|
||||
`n` by default.
|
||||
|
||||
|
||||
##### 1.2 Same ESP chipset types for host and slave
|
||||
There is possibility that you have two chipsets to evaluate, but both are exactly same chipset type. For example, two ESP32-C3. In this case, it is a two step build, first for host and second for slave.
|
||||
While building for host ESP chipset, follow above (1) and flash, monitor. Once host is flashed fine, revert all the changes and flash the slave ESP chipset.
|
||||
|
||||
## 2 Raw Throughput Testing
|
||||
|
||||
While aiming the high performance and even while assessing the solution correctness, It is crucial to understand the bottlenecks in the system.
|
||||
'Raw throughput testing' is simple transport level testing, which would showcase the maximum throughput that the transport is able to achieve, right now in current set-up.
|
||||
In this test, dummy data is sent from one transport end to other continously, without involving Wi-Fi, Bluetooth or any other code legs. This test can be performed in following ways:
|
||||
- Host to slave (Half duplex) : dummy data to be sent from host to slave continously
|
||||
- Slave to Host (Half duplex) : dummy data to be sent from slave to host continously
|
||||
- Full duplex bi-directional : dummy data to be sent from both the directions simulataneously
|
||||
|
||||
This can verify hardware signal integrity and address porting issues. It also helps to assess the achievable throughput of the Hosted solution. It can be further optionally used for transport throughput fine-tuning.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Use Raw throughput test to verify that Hosted hardware and software are
|
||||
> working as expected before involving other software layers like
|
||||
> networking.
|
||||
|
||||
To enable the Raw Throughput Option on Slave, enter `Menuconfig` and
|
||||
enable **Example Configuration** ---> **Hosted Debugging** --->
|
||||
**RawTP**.
|
||||
|
||||
To enable the Raw Throughput Option and set Raw Throughput direction
|
||||
on Host, enter `Menuconfig` and enable **Component config** --->
|
||||
**ESP-Hosted config** ---> **Debug Settings** ---> **RawTP**. Set
|
||||
the data transfer direction: **Host to Slave**, **Slave to Host** or
|
||||
**Bidirectional**.
|
||||
|
||||
## 3 Make sure Hosted code is in sync for Master and Slave
|
||||
|
||||
The [README](../README.md) instructions will always fetch the latest
|
||||
version of ESP-Hosted from the Component Registry. Generally, this
|
||||
should be fine. But you can also fetch ESP-Hosted code based on a
|
||||
revision to get a fixed version of the code:
|
||||
|
||||
For example, to fetch version 0.0.9 of ESP-Hosted Master:
|
||||
|
||||
```
|
||||
idf.py add-dependency "espressif/esp_hosted^0.0.9"
|
||||
```
|
||||
|
||||
To fetch version 0.0.9 of the ESP-Hosted Slave:
|
||||
|
||||
```
|
||||
idf.py create-project-from-example "espressif/esp_hosted^0.0.9:slave"
|
||||
```
|
||||
|
||||
This will ensure that both the Master and Slave code are fixed and in
|
||||
sync for your project. Please ensure you use latest versions for bug-fixes
|
||||
|
||||
> [!NOTE]
|
||||
> When you switch Hosted versions, make sure you use the same version
|
||||
> of the Master and Slave code. There may be changes to the Hosted
|
||||
> implementation that may make different versions of Hosted Master and
|
||||
> Slave incompatible.
|
||||
|
||||
## 4 Make sure GPIOs match on both the Host and Slave
|
||||
|
||||
- Check that the GPIOs you use on the Host and Slave are correct and are connected together as expected
|
||||
- Verify that the GPIO values you set in `menuconfig` match the hardware GPIOs you are actually using
|
||||
- Ensure that you are not using incompatible GPIOs:
|
||||
- on the ESP32, some GPIOs are input only and cannot be used for output
|
||||
- on the ESP32 and ESP32-C6, the GPIOs used for SDIO are fixed and cannot be changed
|
||||
|
||||
## 5 ESP-Hosted Master Not Connecting to Slave
|
||||
|
||||
If you see the following error on the ESP-Hosted Master console using the SPI Interface:
|
||||
|
||||
```
|
||||
E (10645) transport: Not able to connect with ESP-Hosted slave device
|
||||
```
|
||||
|
||||
or this error on the ESP-Hosted Master console using the SDIO Interface:
|
||||
|
||||
```
|
||||
E (1735) sdmmc_common: sdmmc_init_ocr: send_op_cond (1) returned 0x107
|
||||
```
|
||||
|
||||
It means that something is wrong with the SPI or SDIO connection and
|
||||
the Host cannot communicate with the slave.
|
||||
|
||||
- Check your physical GPIO signals and verify that they are connected
|
||||
- Ensure that you have selected the same transports for the slave and
|
||||
host (both are using the same SPI or SDIO interface).
|
||||
- It is expected that slave and host uses exact same codebase (git commit)
|
||||
- Transport configured at slave matches to that of host
|
||||
- Firmware configured with incompatible configurations also would result in issues.
|
||||
- Verify that the physical GPIO signals is the same as those assigned to the system using `Menuconfig` on both the Host and Slave
|
||||
- If you selected SDIO as the interface and your host is a classic ESP32, there may be conflict with the GPIO used to bootstrap the ESP32 and used in SDIO. See "Conflicts Between Bootstrap and SDIO on DAT2" in
|
||||
[References](#7-references) for more information
|
||||
- for SDIO, verify that pull-ups and other signalling requirments (short, shielded connections) are also met. See the [SDIO interface](sdio.md) page for more information on SDIO requirements
|
||||
- If your transport allows on jumper cables, cross-check max length of jumper cables allowed
|
||||
|
||||
## 6 Getting `Drop Packet` Errors
|
||||
|
||||
For the SPI interface, if you see an error similar to this:
|
||||
|
||||
```
|
||||
I (478522) spi: rcvd_crc[30224] != exp_crc[36043], drop pkt
|
||||
```
|
||||
|
||||
Your SPI interface is facing signal integrity errors.
|
||||
|
||||
- try reducing the SPI `CLK` frequency (using `Menuconfig`). If the
|
||||
problem goes away, it indicates that there is an issue with the
|
||||
physcial SPI signals
|
||||
- use an oscilloscope to check the physical signals on the SPI
|
||||
interface for noise, ringing, etc. that may affect the signals
|
||||
|
||||
## 7 References
|
||||
|
||||
- [Conflicts Between Bootstrap and SDIO on DAT2](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/sd_pullup_requirements.html#conflicts-between-bootstrap-and-sdio-on-dat2)
|
||||
433
managed_components/espressif__esp_hosted/docs/uart.md
Normal file
@@ -0,0 +1,433 @@
|
||||
# ESP-Hosted UART Operation for Wi-Fi and Bluetooth
|
||||
|
||||
Section 6 to 8 covers the complete step-wise setup co-processor and host with UART.
|
||||
|
||||
If you wish to skip the theory, you can refer the [Quick Start Guide](#1-quick-start-guide) below. For quick navigation, please unfold the Table of Contents below.
|
||||
|
||||
<details>
|
||||
<summary>Table of Contents</summary>
|
||||
|
||||
- [1 Quick Start Guide](#1-quick-start-guide)
|
||||
|
||||
- [2 Introduction](#2-introduction)
|
||||
|
||||
- [3 Hardware Considerations](#3-hardware-considerations) => [1 GPIO Configuration for UART](#31-gpio-configuration-for-uart) || [2 Extra GPIO Signals Required](#32-extra-gpio-signals-required) || [3 General Hardware Considerations](#33-general-hardware-considerations) || [4 PCB Design](#34-pcb-design) || [5 Advanced Considerations](#35-advanced-considerations)
|
||||
|
||||
- [4 Hardware Setup](#4-hardware-setup)
|
||||
|
||||
- [5 Set-Up ESP-IDF](#5-set-up-esp-idf) => [Option 1: Installer Way](#option-1-installer-way) || [Option 2: Manual Way](#option-2-manual-way)
|
||||
|
||||
- [6 Flashing the Co-processor](#6-flashing-the-co-processor) => [1 Create Co-processor Project](#61-create-co-processor-project) || [2 Co-processor Config](#62-co-processor-config) || [3 Co-processor Build](#63-co-processor-build) || [4 Co-processor Flashing](#64-co-processor-flashing)
|
||||
|
||||
- [7 Flashing the Host](#7-flashing-the-host) => [1 Select Example to Run in Hosted Mode](#71-select-example-to-run-in-hosted-mode) || [2 Host Project Component Configuration](#72-host-project-component-configuration) || [3 Menuconfig, Build and Flash Host](#73-menuconfig-build-and-flash-host)
|
||||
|
||||
- [8 Testing and Troubleshooting](#8-testing-and-troubleshooting)
|
||||
|
||||
- [9 References](#9-references)
|
||||
|
||||
</details>
|
||||
|
||||
## 1 Quick Start Guide
|
||||
|
||||
This section provides a brief overview of how to get started with ESP-Hosted using UART mode.
|
||||
|
||||
These sections will guide you through the process of flashing both the co-processor and host devices, setting up the hardware connections, and verifying successful communication.
|
||||
|
||||
## 2 Introduction
|
||||
|
||||
UART is a low-speed bus that only requires two signal lines to communicate between the host and co-processor.
|
||||
|
||||
UART is supported on all ESP devices, and many other MCUs and operating systems. It is quick to bring up and test.
|
||||
|
||||
However, UART is a low-speed bus, and not recommended for environments where high network throughput (more than 1 Mbits/s) is required.
|
||||
|
||||
> [!NOTE]
|
||||
> UART is used to transport both Wi-Fi and Bluetooth data (as Hosted HCI). Do not confuse this with standard HCI sent over UART, which does not support Wi-Fi.
|
||||
|
||||
## 3 Hardware Considerations
|
||||
|
||||
### 3.1 GPIO Configuration for UART
|
||||
|
||||
The UART interface can use almost any GPIO pins. For maximum speed and minimal delays, it is recommended to select the SDIO pin configuration that uses the dedicated `IO_MUX` pins.
|
||||
|
||||
### 3.2 Extra GPIO Signals Required
|
||||
|
||||
Extra GPIO signals are required for UART on Hosted and can be assigned to any free GPIO pins:
|
||||
|
||||
- `Reset` signal: an output signal from the host to the co-processor. When asserted, the host resets the co-processor. This is done when ESP-Hosted is started on the host, to synchronise the state of the host and co-processor.
|
||||
|
||||
> [!NOTE]
|
||||
> The `Reset` signal suggested to connect to the `EN` or `RST` pin on the co-processor, It is however configurable to use another GPIO pin.
|
||||
>
|
||||
> To configure this, use `idf.py menuconfig` on the co-processor: **Example configuration** ---> **UART Configuration** and set **Slave GPIO pin to reset itself**.
|
||||
|
||||
### 3.3 General Hardware Considerations
|
||||
|
||||
- Due to UART's low speed, signal integrity is less of a concern compared to SPI or SDIO. However, general rules on signal routing and noise reduction still applies.
|
||||
- Jumper wires are only suitable for initial testing and prototyping.
|
||||
- Ensure equal trace lengths for all UART connections, whether using jumper wires or PCB traces.
|
||||
- Keep wires as short as possible, under 10 cm. Smaller the better.
|
||||
- Use the lower baud rates like 115200 for evaluation. Once solution verified, optimise the baud rate in increasing steps to max possible value.
|
||||
- Provide proper power supply for both host and co-processor devices. Lower or incorrect power supplies can cause communication issues & suboptimal performance.
|
||||
- If possible, use a ground wire between every signal wire to improve signal integrity.
|
||||
- Connect as many grounds as possible to improve common ground reference and reduce ground noise.
|
||||
|
||||
### 3.4 PCB Design
|
||||
|
||||
For optimal performance and reliability in production designs:
|
||||
|
||||
- Ensure equal trace lengths for all UART signals (Rx, Tx) as much as possible. This practice, known as length matching, is crucial for maintaining signal integrity and reducing timing skew, especially at higher frequencies.
|
||||
- Use controlled impedance traces for high-speed signals.
|
||||
- Place bypass capacitors close to the power pins of both the host and co-processor devices.
|
||||
- Consider using series termination resistors on the clock and data lines to reduce reflections.
|
||||
- For high-speed designs, use a 4-layer PCB with dedicated power and ground planes.
|
||||
|
||||
### 3.5 Advanced Considerations
|
||||
|
||||
- Calculate the maximum allowed trace length based on your baud rate and PCB material.
|
||||
- Consider the capacitive load on the UART signals, especially for longer traces
|
||||
- For very high-speed designs, consider using differential signaling techniques.
|
||||
- Implement proper EMI/EMC design techniques to minimize electromagnetic interference.
|
||||
|
||||
## 4 Hardware Setup
|
||||
|
||||
Setting up the hardware involves connecting the master and co-processor devices via the UART pins and ensuring all extra GPIO signals are properly connected.
|
||||
|
||||
Any GPIO pin can be used for ESP-Hosted UART Rx and Tx. But avoid using the ESP assigned UART Tx0 and Rx0 pins. There are for debugging output. (ESP-Hosted uses another UART controller.)
|
||||
|
||||
## 5 Set-Up ESP-IDF
|
||||
|
||||
Before setting up the ESP-Hosted co-processor & host for UART mode, ensure that ESP-IDF is properly installed and set up on your system.
|
||||
|
||||
### Option 1: Installer Way
|
||||
|
||||
- **Windows**
|
||||
- Install and setup ESP-IDF on Windows as documented in the [Standard Setup of Toolchain for Windows](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup.html).
|
||||
- Use the ESP-IDF [Powershell Command Prompt](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup.html#using-the-command-prompt) for subsequent commands.
|
||||
|
||||
- **Linux or MacOS**
|
||||
- For bash:
|
||||
```bash
|
||||
bash docs/setup_esp_idf__latest_stable__linux_macos.sh
|
||||
```
|
||||
- For fish:
|
||||
```fish
|
||||
fish docs/setup_esp_idf__latest_stable__linux_macos.fish
|
||||
```
|
||||
|
||||
### Option 2: Manual Way
|
||||
|
||||
Please follow the [ESP-IDF Get Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html) for manual installation.
|
||||
|
||||
## 6 Flashing the Co-processor
|
||||
|
||||
| Supported Co-processor Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-S2 | ESP32-S3 |
|
||||
| ------------------------------ | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- |
|
||||
|
||||
### 6.1 Create Co-processor Project
|
||||
1. Create co-processor project possibly outside of ESP-IDF project directory using
|
||||
|
||||
```bash
|
||||
idf.py create-project-from-example "espressif/esp_hosted:slave"
|
||||
```
|
||||
|
||||
2. Navigate to the created project directory.
|
||||
|
||||
3. Configure the project for your target ESP chip:
|
||||
|
||||
```bash
|
||||
idf.py set-target <target>
|
||||
```
|
||||
Replace `<target>` with your specific co-processor ESP chip (e.g., esp32c3, esp32s3).
|
||||
|
||||
### 6.2 Co-processor Config
|
||||
Configure the co-processor project using
|
||||
```
|
||||
idf.py menuconfig
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> When building with ESP-IDF v5.5, you may see this build error:
|
||||
>
|
||||
> `Building for UART transport can fail due to lack of IRAM space`
|
||||
>
|
||||
> To reduce IRAM usage, you can either:
|
||||
> - run `idf.py menuconfig` and enable `Component config` --> `ESP Ringbuf` ---> `Place non-ISR ringbuf functions into flash`, or
|
||||
> - uncomment `CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y` in `slave/sdkconfig.defaults.esp32` and regenerate the `sdkconfig`
|
||||
|
||||
#### 6.2.1 Transport config
|
||||
- Navigate to "Example configuration" -> "Bus Config in between Host and Co-processor"
|
||||
- In "Transport layer", select "UART"
|
||||
|
||||
#### 6.2.2 Any other config
|
||||
- Optionally, Configure any additional UART-specific settings in the "UART Configuration" menu, like TX and Rx GPIOs, baud rate, etc.
|
||||
|
||||
###### Generated files
|
||||
- Generated config files are (1) `sdkconfig` file and (2) internal `sdkconfig.h` file.
|
||||
- Please note, any manually changes done to these generated files, would not take effect.
|
||||
|
||||
###### Defaulting specific config (Optional)
|
||||
- This is advanced option, so please be careful.
|
||||
- To mark some config options as default, you can add specific config line in file, `sdkconfig.defaults.<target>`. So whenever next time building, you do not need to re-configure.
|
||||
|
||||
### 6.3 Co-processor Build
|
||||
Build the co-processor project
|
||||
|
||||
```
|
||||
idf.py build
|
||||
```
|
||||
|
||||
### 6.4 Co-processor Flashing
|
||||
|
||||
It is **recommended** to periodically upgrade the slave firmware to leverage new features, bug fixes, and performance improvements.
|
||||
|
||||
| Method | Description | Recommended Use |
|
||||
| -------------------------- | -------------------------------------------------- | ----------------------------------------------------- |
|
||||
| **Direct Serial Flashing** | Uses UART pins for direct firmware installation | First-time setup to install ESP-Hosted slave firmware |
|
||||
| **Slave OTA Update** | Performs slave firmware updates directly from Host | All subsequent updates after initial installation |
|
||||
|
||||
|
||||
##### 6.4.1 Serial Flashing (Initial Setup)
|
||||
|
||||
For the initial setup or when OTA is not available, use serial flashing.
|
||||
|
||||
Flash the co-processor firmware using
|
||||
```
|
||||
idf.py -p <co-processor_serial_port> flash
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> If you are not able to flash the co-processor, there might be a chance that host is not allowing to to do so.
|
||||
>
|
||||
> Put host in bootloader mode using following command and then retry flashing the co-processor
|
||||
>
|
||||
> `esptool.py -p **<host_serial_port>** --before default_reset --after no_reset run`
|
||||
>
|
||||
> Flash the co-processor and log the output:
|
||||
>
|
||||
> `idf.py -p <co-processor_serial_port> flash monitor`
|
||||
|
||||
##### 6.4.2 Co-processor OTA Flashing (Subsequent Updates)
|
||||
|
||||
The ESP-Hosted link comes pre-configured and ready to use on first boot. You can update the slave firmware remotely from the host MCU using OTA (Over-The-Air) updates: **No** ESP-Prog, serial cable, or extra GPIO connections are required.
|
||||
|
||||
For step-by-step instructions, see the [Host Performs Slave OTA Example](../examples/host_performs_slave_ota/README.md).
|
||||
|
||||
## 7 Flashing the Host
|
||||
|
||||
Host are required to support two-line UART and the required baud rate in their hardware. All ESP chipsets hardware support UART.
|
||||
|
||||
| Supported Host Targets | Any ESP chipset | Any Non-ESP chipset |
|
||||
| ----------------------- | --------------- | ------------------- |
|
||||
|
||||
Non ESP chipset may need to port the porting layer. It is strongly recommanded to evaluate the solution using ESP chipset as host before porting to any non-esp chipset.
|
||||
|
||||
### 7.1 Select Example to Run in Hosted Mode
|
||||
|
||||
Select an example from the [ESP-IDF examples directory](https://github.com/espressif/esp-idf/tree/master/examples) that you wish to run in ESP-Hosted mode. All Wi-Fi and Bluetooth examples are supported. For simplicity and demonstration purposes, we will use the [ESP-IDF iperf example](https://github.com/espressif/esp-idf/tree/master/examples/wifi/iperf).
|
||||
|
||||
### 7.2 Host Project Component Configuration
|
||||
|
||||
Now that ESP-IDF is set up, follow these steps to prepare the host:
|
||||
|
||||
###### 1. Navigate to the iperf example in your ESP-IDF directory:
|
||||
```
|
||||
cd $IDF_PATH/examples/wifi/iperf
|
||||
```
|
||||
|
||||
###### 2. Dependency components
|
||||
Add the required components to the project's `idf_component.yml` file:
|
||||
```
|
||||
idf.py add-dependency "espressif/esp_wifi_remote"
|
||||
idf.py add-dependency "espressif/esp_hosted"
|
||||
```
|
||||
|
||||
###### 3. Remove conflicting configuration
|
||||
Open the `main/idf_component.yml` file and remove/comment the following block if present:
|
||||
```
|
||||
# ------- Delete or comment this block ---------
|
||||
espressif/esp-extconn:
|
||||
version: "~0.1.0"
|
||||
rules:
|
||||
- if: "target in [esp32p4]"
|
||||
# -----------------------------------
|
||||
```
|
||||
This step is necessary because esp-extconn and esp-hosted cannot work together.
|
||||
|
||||
###### 4. Disable native Wi-Fi if available
|
||||
If your host ESP chip already has native Wi-Fi support, disable it by editing the `components/soc/<soc>/include/soc/Kconfig.soc_caps.in` file and changing all `WIFI` related configs to `n`.
|
||||
|
||||
If you happen to have both, host and co-processor as same ESP chipset type (for example two ESP32-C2), note an [additional step](docs/troubleshooting/#1-esp-host-to-evaluate-already-has-native-wi-fi)
|
||||
|
||||
|
||||
### 7.3 Menuconfig, Build and Flash Host
|
||||
|
||||
###### 1. High performance configurations
|
||||
This is optional step, suggested for high performance applications.
|
||||
|
||||
If using ESP32-P4 as host and the ESP32-C6 as the co-processor:
|
||||
|
||||
- Remove all `CONFIG_ESP_WIFI_` settings. They do not apply to ESP-Hosted.
|
||||
- Add the following settings to your `sdkconfig.defaults.esp32p4` file:
|
||||
```
|
||||
### sdkconfig for ESP32-P4 + C6 Dev board
|
||||
CONFIG_WIFI_RMT_STATIC_RX_BUFFER_NUM=16
|
||||
CONFIG_WIFI_RMT_DYNAMIC_RX_BUFFER_NUM=64
|
||||
CONFIG_WIFI_RMT_DYNAMIC_TX_BUFFER_NUM=64
|
||||
CONFIG_WIFI_RMT_AMPDU_TX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_TX_BA_WIN=32
|
||||
CONFIG_WIFI_RMT_AMPDU_RX_ENABLED=y
|
||||
CONFIG_WIFI_RMT_RX_BA_WIN=32
|
||||
|
||||
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=65534
|
||||
CONFIG_LWIP_TCP_WND_DEFAULT=65534
|
||||
CONFIG_LWIP_TCP_RECVMBOX_SIZE=64
|
||||
CONFIG_LWIP_UDP_RECVMBOX_SIZE=64
|
||||
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=64
|
||||
|
||||
CONFIG_LWIP_TCP_SACK_OUT=y
|
||||
```
|
||||
|
||||
For other ESP32 hosts, you can merge above configs into the corresponding `sdkconfig.defaults.esp32XX` file.
|
||||
|
||||
To adjust other Wi-Fi parameters, run `idf.py menuconfig` and go to `Component config` ---> `Wi-Fi Remote` ---> `Wi-Fi configuration`.
|
||||
|
||||
Optimised parameters for other co-processors can be found in the [Performance Optimization Guide](performance_optimization.md).
|
||||
|
||||
###### 2. Set environment for your host ESP chip:
|
||||
|
||||
```
|
||||
idf.py set-target <host_target>
|
||||
```
|
||||
Replace `<host_target>` with your specific ESP chip (one of esp32, esp32c2, esp32c3, esp32c5, esp32c6, esp32s2, esp32s3, esp32p4).
|
||||
|
||||
###### 3. Flexible Menuconfig configurations
|
||||
|
||||
```
|
||||
idf.py menuconfig
|
||||
```
|
||||
ESP-Hosted-MCU host configurations are available under "Component config" -> "ESP-Hosted config"
|
||||
1. Select "UART" as the transport layer
|
||||
2. Change co-processor chipset to connect to under "Slave chipset to be used"
|
||||
3. Optionally, Configure UART-specific settings in the "UART Configuration" menu, like:
|
||||
- UART Tx and Rx GPIOs
|
||||
- UART baud rate
|
||||
- UART Checksum Enable/Disable (Checksum is recommended to be enabled)
|
||||
|
||||
> [!NOTE]
|
||||
> The actual baud rate used is determined by the hardware. Use an oscilloscope or logic analyzer to check the baud rate and its accuracy. If the actual baud rate used to send data drifts by more than a few percent from the expected baud rate, the receiver may not be able to correctly decode the data.
|
||||
|
||||
###### 4. Build the project:
|
||||
```
|
||||
idf.py build
|
||||
```
|
||||
|
||||
###### 5. Flash the firmware:
|
||||
```
|
||||
idf.py -p <host_serial_port> flash
|
||||
```
|
||||
|
||||
###### 6. Monitor the output:
|
||||
```
|
||||
idf.py -p <host_serial_port> monitor
|
||||
```
|
||||
- If host was put into bootloader mode earlier, it may need manual reset
|
||||
|
||||
## 8 Testing and Troubleshooting
|
||||
|
||||
After flashing both the co-processor and host devices, follow these steps to connect and test your ESP-Hosted UART setup:
|
||||
|
||||
1. Connect the hardware:
|
||||
- Follow the pin assignments for UART as specified in [Hardware Setup](#4-hardware-setup).
|
||||
- Ensure all necessary connections are made, including power, ground.
|
||||
|
||||
2. Power on both devices.
|
||||
|
||||
3. Verify the connection:
|
||||
- Check the serial output of both devices for successful initialization messages.
|
||||
- Look for messages indicating that the UART transport layer has been established.
|
||||
|
||||
4. Logs at both sides:
|
||||
- Host:
|
||||
|
||||
```
|
||||
I (465) transport: Attempt connection with slave: retry[0]
|
||||
I (468) transport: Reset slave using GPIO[54]
|
||||
I (473) os_wrapper_esp: GPIO [54] configured
|
||||
I (478) gpio: GPIO[54]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
|
||||
I (1650) transport: Received INIT event from ESP32 peripheral
|
||||
I (1650) transport: EVENT: 12
|
||||
I (1650) transport: EVENT: 11
|
||||
I (1652) transport: capabilities: 0x88
|
||||
I (1657) transport: Features supported are:
|
||||
I (1662) transport: - BLE only
|
||||
I (1666) transport: EVENT: 16
|
||||
I (1669) transport: extended capabilities: 0x120
|
||||
I (1675) transport: Extended Features supported:
|
||||
I (1680) transport: * WLAN over UART
|
||||
I (1684) transport: EVENT: 13
|
||||
I (1688) transport: ESP board type is : 13
|
||||
|
||||
I (1693) transport: Base transport is set-up
|
||||
```
|
||||
|
||||
- Co-processor:
|
||||
|
||||
```
|
||||
I (484) fg_mcu_slave: *********************************************************************
|
||||
I (493) fg_mcu_slave: ESP-Hosted-MCU Slave FW version :: 0.0.6
|
||||
|
||||
I (503) fg_mcu_slave: Transport used :: UART only
|
||||
I (512) fg_mcu_slave: *********************************************************************
|
||||
I (521) fg_mcu_slave: Supported features are:
|
||||
I (526) h_bt: - BT/BLE
|
||||
I (529) h_bt: - BLE only
|
||||
I (532) fg_mcu_slave: capabilities: 0x88
|
||||
I (537) fg_mcu_slave: Supported extended features are:
|
||||
I (543) fg_mcu_slave: - WLAN over UART
|
||||
I (547) h_bt: - BT/BLE (extended)
|
||||
I (551) h_bt: - HCI Over UART (VHCI)
|
||||
I (556) fg_mcu_slave: extended capabilities: 0x120
|
||||
```
|
||||
|
||||
5. Test basic functionality:
|
||||
- The iperf example automatically attempts to connect to the configured Wi-Fi network. Watch the serial output for connection status.
|
||||
- If the automatic connection fails, you can manually initiate a Wi-Fi scan and connection:
|
||||
```
|
||||
sta_scan
|
||||
sta_connect <SSID> <password>
|
||||
```
|
||||
6. Additional commands to test:
|
||||
- Get IP address: `sta_ip`
|
||||
- Disconnect from Wi-Fi: `sta_disconnect`
|
||||
- Set Wi-Fi mode: `wifi_mode <mode>` (where mode can be 'sta', 'ap', or 'apsta')
|
||||
|
||||
7. Advanced iperf testing:
|
||||
Once connected, you can run iperf tests to verify performance:
|
||||
|
||||
| Test Case | Host Command | External STA Command |
|
||||
|-----------|--------------|----------------------|
|
||||
| UDP Host TX | `iperf -u -c <STA_IP> -t 60 -i 3` | `iperf -u -s -i 3` |
|
||||
| UDP Host RX | `iperf -u -s -i 3` | `iperf -u -c <HOST_IP> -t 60 -i 3` |
|
||||
| TCP Host TX | `iperf -c <STA_IP> -t 60 -i 3` | `iperf -s -i 3` |
|
||||
| TCP Host RX | `iperf -s -i 3` | `iperf -c <HOST_IP> -t 60 -i 3` |
|
||||
|
||||
Note: Replace `<STA_IP>` with the IP address of the external STA, and `<HOST_IP>` with the IP address of the ESP-Hosted device.
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> To measure the optimal performance, check out the [Shield Box Test Setup](shield-box-test-setup.md).
|
||||
|
||||
8. Troubleshooting:
|
||||
- If you encounter issues, refer to section 3.3 for checking the UART connection.
|
||||
- Consider using a lower baud rate or checking your [hardware setup](#4-hardware-setup) if you experience communication problems.
|
||||
- ESP-Hosted-MCU troubleshooting guide: [docs/troubleshooting.md](docs/troubleshooting.md)
|
||||
|
||||
9. Monitoring and debugging:
|
||||
- Use the serial monitor on both devices to observe the communication between the host and co-processor.
|
||||
- For more detailed debugging, consider using a logic analyzer to examine the UART signals.
|
||||
|
||||
## 9 References
|
||||
|
||||
- ESP Universal Asynchronous Receiver/Transmitter (UART): https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/uart.html
|
||||
79
managed_components/espressif__esp_hosted/docs/wifi_design.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# ESP-Hosted-MCU Wi-Fi Design & Implementation details
|
||||
|
||||
|
||||
## Sequence Diagram for Wi-Fi communication
|
||||
|
||||
On a ESP chipset with native Wi-Fi, a Wi-Fi api call or network data
|
||||
from the application is processed internally on the chip and a Wi-Fi
|
||||
response is returned to the application.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box rgb(128, 128, 128) Host With Native WI-Fi
|
||||
participant app as Application
|
||||
participant api as ESP-IDF Wi-Fi Library
|
||||
participant wifi as Wi-Fi Hardware
|
||||
end
|
||||
|
||||
app ->> api : esp_wifi_xxx() or Network Data
|
||||
api ->> wifi :
|
||||
Note over wifi : Do Wi-Fi action
|
||||
wifi -->> api : Wi-Fi response or Data
|
||||
api -->> app : Response or Network Data
|
||||
```
|
||||
|
||||
Using Wi-Remote and ESP-Hosted, the Wi-Fi api call from the
|
||||
application is converted into a Hosted Call and transported to the
|
||||
slave. The slave converts the Hosted Call back into an Wi-Fi api
|
||||
call. The response (optionally with data) is converted into a Hosted
|
||||
Response and transported back to the host. On the host, the Hosted
|
||||
Response is converted back into a Wi-Fi response (optionally with
|
||||
data) is returned to the application.
|
||||
|
||||
For Network Data, Hosted does not do data conversion and only
|
||||
encapsulates the data for transport.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box rgb(128, 128, 128) Host with ESP-Hosted
|
||||
participant app as Application
|
||||
participant remote as Wi-Fi Remote
|
||||
participant hostedh as ESP-Hosted
|
||||
participant transporth as Host Transport
|
||||
end
|
||||
|
||||
box rgb(128, 128, 128) Slave ESP-Hosted
|
||||
participant transports as Slave Transport
|
||||
participant hosteds as Slave Hosted
|
||||
participant api as ESP-IDF Wi-Fi Library
|
||||
participant wifi as Wi-Fi Hardware
|
||||
end
|
||||
|
||||
app ->> remote : esp_wifi_xxx()
|
||||
remote ->> hostedh : esp_wifi_remote_xxx()
|
||||
app ->> hostedh : Network Data
|
||||
Note over hostedh : add Hosted header
|
||||
hostedh ->> transporth :
|
||||
|
||||
transporth ->> transports : SPI/SDIO
|
||||
|
||||
transports ->> hosteds :
|
||||
Note over hosteds : remove Hosted header
|
||||
hosteds ->> api : esp_wifi_xxx()
|
||||
hosteds ->> wifi : Network Data
|
||||
api ->> wifi : Wi-Fi command or Data
|
||||
Note over wifi: Do Wi-Fi action
|
||||
wifi -->> api : Wi-Fi response or Data
|
||||
wifi -->> hosteds : Network Data
|
||||
api -->> hosteds : Response
|
||||
Note over hosteds : add Hosted header
|
||||
hosteds -->> transports :
|
||||
|
||||
transports -->> transporth : SPI/SDIO
|
||||
|
||||
transporth -->> hostedh :
|
||||
Note over hostedh : remove Hosted header
|
||||
hostedh -->> app : Network Data
|
||||
hostedh -->> remote : Wi-Fi Command response
|
||||
remote -->> app : Response
|
||||
```
|
||||