# ESP-Hosted: Co-Processor External Coexistence (EXT_COEX)
This host side example demonstrates how to configure and use **External Coexistence (EXT_COEX)** in **ESP-Hosted** co-processor.
The ESP co-processor (slave) has a built-in hardware **Packet Traffic Arbitrator (PTA)** that manages 2.4 GHz ISM band access between its own Wi-Fi and an external peer radio (such as BLE, Zigbee, or Thread running on the host MCU). In a typical standalone setup, this PTA is configured directly on the ESP device. With ESP-Hosted, the host MCU can configure and control the slave's PTA remotely over RPC — without modifying slave firmware.
The arbitration operates over 1, 2, or 3 GPIO lines depending on the chosen mode:
- **1-wire** — The peer radio asserts **Request** whenever it needs the band; ESP Wi-Fi always yields. Simple, but can impact Wi-Fi performance.
- **2-wire** — Adds a **Grant** signal. The PTA arbitrates and returns the result: Grant high means the peer radio may transmit; Grant low means ESP Wi-Fi may transmit.
- **3-wire** — Adds a **Priority** signal, allowing the peer radio to indicate middle or high priority. The PTA compares this against the internal Wi-Fi priority before granting.
## 1 Supported Platforms
**Host MCU**
| Platform |
| -------- |
| ESP32 |
| ESP32-C Series |
| ESP32-S Series |
**Co-processor (Slave)**
| Platform |
| -------- |
| ESP32-C6 / C61 |
| ESP32-C5 |
| ESP32-S3 |
> **Note:** ESP32 as a co-processor is not supported.
>
> **Bluetooth + EXT_COEX:** On chips with advanced coexistence hardware
> (`SOC_EXTERNAL_COEX_ADVANCE` — **ESP32-C2 / C5 / C6 / C61 / H2 / H4 / H21**), external
> coexistence works **alongside** Bluetooth/BLE — both can stay enabled. On other chips
> (e.g. **ESP32-S3**), the BT controller must be disabled when EXT_COEX is enabled.
>
> ⚠️ **ESP-IDF version:** EXT_COEX with **Bluetooth disabled** is supported across all
> ESP-IDF tags. EXT_COEX **with Bluetooth enabled** currently requires **ESP-IDF `master`** —
> as of Jun-26 the stable/released tags do not yet include this support, so test on the
> latest `master`.
## 2 Setup
EXT_COEX requires configuration on both the **slave** and the **host** before use.
### 2.1 Slave Setup
Run `idf.py menuconfig` on the slave and apply the following:
**Advanced-coex chips (ESP32-C6 / C61 / C5)** — Bluetooth/BLE may stay enabled:
```
├── Component config → Bluetooth
│ └── [*] Bluetooth <---- Keep enabled if BLE needed ✔
└── Example Configuration
├── [*] Enable BT sharing via hosted <---- Keep enabled if BLE needed ✔
└── [*] External Coexistence support <---- Enable ✔
```
**Other chips (e.g. ESP32-S3)** — Bluetooth must be disabled:
```
├── Component config → Bluetooth
│ └── [ ] Bluetooth <---- DISABLE ✘
└── Example Configuration
├── [ ] Enable BT sharing via hosted <---- DISABLE ✘
└── [*] External Coexistence support <---- Enable ✔
```
Flash the slave:
```bash
idf.py -p <slave_serial_port> flash monitor
```
### 2.2 Host Setup
Run `idf.py menuconfig` on the host and enable the following:
```
Component config → ESP-Hosted config
├── [*] Co-Processor External Coexistence <---- Enable ✔
└── [*] Co-Processor External Coexistence - Advanced <---- Enable ✔
```
Flash the host:
```bash
idf.py -p <host_serial_port> flash monitor
```
## 3 Host-Side APIs
Include the following header to access all EXT_COEX APIs:
```c
#include "esp_hosted.h"
```
This pulls in `esp_hosted_cp_ext_coex.h`, which exposes the APIs below.
#### 3.1 `esp_hosted_cp_ext_coex_set_work_mode()`
```c
esp_err_t esp_hosted_cp_ext_coex_set_work_mode(
esp_hosted_ext_coex_work_mode_t work_mode
);
```
Sets the coexistence operating mode, determining whether the host leads or follows in radio arbitration.
**Parameters**
- `work_mode` — Role to assign to the host:
- `ESP_HOSTED_EXT_COEX_LEADER_ROLE` — Host acts as the leader.
- `ESP_HOSTED_EXT_COEX_FOLLOWER_ROLE` — Host acts as the follower.
- `ESP_HOSTED_EXT_COEX_UNKNOWN_ROLE` — Role is unspecified.
**Returns** `ESP_OK` on success, error code otherwise.
#### 3.2 `esp_hosted_cp_ext_coex_set_gpio_pin()`
```c
esp_err_t esp_hosted_cp_ext_coex_set_gpio_pin(
uint32_t wire_type,
const esp_hosted_ext_coex_gpio_set_t *gpio_pins
);
```
Configures the GPIO pins used for external coexistence signaling on the co-processor.
**Parameters**
- `wire_type` — Number of wires used for coexistence signaling:
- `ESP_HOSTED_EXT_COEX_WIRE_1`
- `ESP_HOSTED_EXT_COEX_WIRE_2`
- `ESP_HOSTED_EXT_COEX_WIRE_3`
- `ESP_HOSTED_EXT_COEX_WIRE_4`
- `gpio_pins` — Pointer to an `esp_hosted_ext_coex_gpio_set_t` structure with the following fields:
| Field | Description |
| ---------- | ------------------------------------ |
| `request` | GPIO number for the Request signal |
| `priority` | GPIO number for the Priority signal |
| `grant` | GPIO number for the Grant signal |
| `tx_line` | GPIO number for the TX Line signal |
**Returns** `ESP_OK` on success, error code otherwise.
#### 3.3 `esp_hosted_cp_ext_coex_set_grant_delay()` *(advanced)*
```c
esp_err_t esp_hosted_cp_ext_coex_set_grant_delay(uint8_t delay_us);
```
Sets the delay (in microseconds) applied to the GRANT signal for timing optimization. Available when `CONFIG_ESP_HOSTED_CP_EXT_COEX_ADVANCE` is enabled.
**Parameters**
- `delay_us` — Grant signal delay in microseconds.
**Returns** `ESP_OK` on success, error code otherwise.
#### 3.4 `esp_hosted_cp_ext_coex_set_validate_high()` *(advanced)*
```c
esp_err_t esp_hosted_cp_ext_coex_set_validate_high(bool is_high_valid);
```
#### 3.5 `esp_hosted_cp_ext_coex_disable()`
```c
esp_err_t esp_hosted_cp_ext_coex_disable(void);
```
Disables external coexistence on the co-processor and releases the associated GPIOs.
**Returns** `ESP_OK` on success, error code otherwise.
Configures the polarity of the validate signal. Available when `CONFIG_ESP_HOSTED_CP_EXT_COEX_ADVANCE` is enabled.
**Parameters**
- `is_high_valid`:
- `true` — Validate signal is active-high.
- `false` — Validate signal is active-low.
**Returns** `ESP_OK` on success, error code otherwise.
## 4 Host ↔ Slave API Mapping
| Host API | Slave API | Purpose |
| :------- | :-------- | :------ |
| `esp_hosted_cp_ext_coex_set_work_mode()` | `esp_external_coex_set_work_mode` | Set coexistence operating mode |
| `esp_hosted_cp_ext_coex_set_gpio_pin()` | `esp_enable_extern_coex_gpio_pin` | Configure coexistence GPIOs (REQ, PRI, GRANT, TX) |
| `esp_hosted_cp_ext_coex_set_grant_delay()` | `esp_external_coex_set_grant_delay` | Adjust GRANT signal delay for timing |
| `esp_hosted_cp_ext_coex_set_validate_high()` | `esp_external_coex_set_validate_high` | Set validate signal polarity |
| `esp_hosted_cp_ext_coex_disable()` | `esp_disable_extern_coex_gpio_pin` | Disable coexistence and release GPIOs |
## 5 References
- [External Coexistence Design (Application Note)](https://documentation.espressif.com/external_coexistence_design_en.pdf)
To create a project from this example, run:
idf.py create-project-from-example "espressif/esp_hosted=2.12.9:host_manage_copro_ext_coex"