Fork fix: the SDIO wedge is FIXED (esp-hosted-mcu #167)
Test, Build and Push / test-gateway (push) Successful in 12s
Test, Build and Push / release (push) Skipped
Test, Build and Push / build-gateway (push) Skipped

Root cause (verified against our exact IDF tree, not the community guess):
the "258" in "sdio_write_task: Failed to send data: 258" is NOT a timeout
(that is 263). 258 = 0x102 = ESP_ERR_INVALID_ARG. On the ESP32-P4, block-
mode CMD53 writes require the SOURCE buffer to be 64-byte (cache-line)
aligned; the IDF sdmmc driver rejects a misaligned source with INVALID_ARG
BEFORE any bus activity. esp_hosts write loop then declares "Unrecoverable
host sdio state" and reboots the whole P4. The audio TX payload is not
64-aligned, so streaming mic audio wedged on the very FIRST frame (which is
exactly what we saw: listening -> instant Failed to send -> reboot).

This also explains why buffer/queue/clock/retry tuning all did nothing: the
write never reached the bus. And why our symptom was instant, not after
~100 writes (the community block-mode-desync theory) — it is the first
misaligned buffer, every time.

Fix: vendored esp_hosted 2.12.11 as an editable local component (overrides
the registry copy) and bounce a misaligned TX payload through one aligned
DMA scratch buffer in hosted_sdio_write_block (port_esp_hosted_host_sdio.c).
TX is serialized by the bus lock so a single static bounce buffer is safe;
freed in hosted_sdio_deinit. Host-only change — no C6 reflash.

VERIFIED ON HARDWARE (autonomous self-test): 40s of continuous mic-audio
upstream streaming — the traffic that previously wedged on the first frame
— ran clean, zero timeouts, zero reboots. A guarded SDIO_TX_SELFTEST harness
is kept (compiled out) for future SDIO stress testing.

Credit: root cause + patch designed via multi-agent investigation; the
precise 258=INVALID_ARG decode (correcting the upstream community timeout
assumption) came from checking our actual esp_err.h.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-15 09:50:27 +02:00
co-authored by Claude Fable 5
parent ac9d24e0f9
commit cb5826e02b
666 changed files with 216925 additions and 0 deletions
@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(hosted_meminfo)
@@ -0,0 +1,445 @@
| Supported Hosts | ESP32 | ESP32-P Series | ESP32-H Series | ESP32-C Series | ESP32-S Series | Any other MCU hosts |
| --------------- | ----- | -------------- | -------------- | -------------- | -------------- | ------------------- |
| Supported Co-Processors | ESP32 | ESP32-C Series | ESP32-S Series |
| ----------------------- | ----- | -------------- | -------------- |
# ESP-Hosted Co-processor Memory Info Example
This host example enables a memory monitor on the co-processor. This can be used to monitor the heap usage on the co-processor. Once enabled, the host can:
- query the heap usage on the co-processor at any time, or
- get a periodic memory report from the co-processor, or
- get a memory report only when the heap size on the co-processor falls below memory thresholds set by the host
This has been tested with the ESP32-C5 co-processor, flashed with the standard [ESP-Hosted slave example](https://components.espressif.com/components/espressif/esp_hosted/examples/slave) from the ESP Component Registry, or built from the `slave` directory from ESP-Hosted Github.
To show the heap size changing on the co-processor, the example enables Wi-Fi, then connects and disconnects from an AP.
## Prerequisite
### Setting up the Co-Processor
Fetch the co-processor code using the ESP Registry [ESP-Hosted-MCU Slave example](https://components.espressif.com/components/espressif/esp_hosted/examples/slave?language=en).
Quick steps:
```sh
idf.py create-project-from-example "espressif/esp_hosted:slave"
cd slave
idf.py set-target <cp_chip_type>
```
Start `idf.py menuconfig` and ensure that `Example Configuration` ---> `Enable Memory Monitor Interface` is enabled.
> [!NOTE]
> PSRAM must be enabled on the co-processor to get memory reports on external memory and to set the external memory thresholds. Ensure that `Component config` ---> `ESP PSRAM` ---> `Support for external, SPI-connected RAM` is enabled.
Now build and flash the code on the co-processor.
```sh
idf.py -p <cp_port> flash monitor
```
Where `cp_chip_type` is one of ESP32, ESP32-C Series or ESP32-S Series as the co-processor.
Alternatively, you built from the [slave directory](https://github.com/espressif/esp-hosted-mcu/tree/main/slave) of the ESP-Hosted-MCU GitHub repository.
### Building the Host
Start `idf.py menuconfig` and ensure that `Component Config` ---> `ESP-Hosted config` ---> `Enable Memory Monitor Interface` is enabled. There are three ways to configure the example:
1. **Do a one time query**: enable `Query Memory Info only once`
2. **Get a periodic report**: enter a `Memory Monitor Interval` (default is `10` seconds) and enable `Always send a memory report`
3. **Get a report only when memory falls below a threshold**: disable `Always send a memory report` and enter one or more threshold values for DMA / 8-bit for internal / external memory
**See [the section below](#how-to-use-this-example) for more information on how to configure the example.**
Now build and flash the code on the host.
```sh
idf.py -p <host_port> flash monitor
```
## Setting up the Memory Info Request
The example uses this API call to set the memory monitor:
`esp_err_t esp_hosted_set_mem_monitor(esp_hosted_config_mem_monitor_t *config, esp_hosted_curr_mem_info_t *curr_mem_info)`
where:
- `esp_hosted_config_mem_monitor_t`: pointer to the structure containing the mem monitor configuration
- `esp_hosted_curr_mem_info_t`: pointer to a structure that will hold the returned memory report when the call returns. This is valid only if the return value is `ESP_OK`
See [`esp_hosted_misc_types.h`](https://github.com/espressif/esp-hosted-mcu/blob/main/host/esp_hosted_misc_types.h) for details on the structures.
For example, to enable the memory monitor to periodically return a report every 10 seconds:
```
esp_hosted_curr_mem_info_t curr_mem_info = { 0 };
esp_hosted_config_mem_monitor_t config = {
.config = ESP_HOSTED_MEMMONITOR_ENABLE,
.report_always = true,
.interval_sec = 10,
// since we always get a report, no need to set thresholds
.internal_mem.threshold_mem_dma = 0,
.internal_mem.threshold_mem_8bit = 0,
.external_mem.threshold_mem_dma = 0,
.external_mem.threshold_mem_8bit = 0,
};
esp_err_t res = esp_hosted_set_mem_monitor(&config, &curr_mem_info);
```
`curr_mem_info` contains the current heap info from the co-processor if res is `ESP_OK`.
## Memory Info Reported
The returned memory report contains this information from the co-processor:
- the current memory report configuration on the co-processor
- the current total heap size
- the current internal and external free and largest free block for DMA or for 8/16/...-bit access
## Memory Monitor Event
If periodic reporting is enabled, or when heap memory falls below a set threshold, a memory report event is sent to the host by the co-processor, with an event base of `ESP_HOSTED_EVENT`:
- `ESP_HOSTED_EVENT_MEM_MONITOR`: sent by the co-processor to the Host with a memory usage report of type `esp_hosted_event_mem_info_t` as the event data.
The event data contains this information from the co-processor:
- the current total free heap size
- the minimum free heap size since boot
- the current internal and external free and largest free block for DMA or for 8/16/...-bit access
## How to Use This Example
The example shows how heap usage on the co-processor changes when Wi-Fi operations are performed:
1. Starts the example with Wi-Fi disabled
2. Enable Wi-Fi
3. Connect to an AP
4. Disconnected from an AP
Delays are deliberately introduced after each step to give time for memory reports to be returned (if enabled).
The example also shows how to use the memory monitor in the following ways:
1. Get a one time report: the memory report is read once on app start up.
2. Periodically generate a memory report: a memory report is generated periodically.
3. Generate a memory report when memory usage drops below a threshold: no memory report is received until after the Wi-Fi connection has cause heap space to drop below a set threshold.
The hardware used in the example is a ESP32-P4 connected to a ESP32-C5 as the co-processor with PSRAM on the C5 enabled.
### Configuring the memory report options on the ESP32-P4 host
Set the correct chip target:
```bash
idf.py set-target esp32p4
```
Open the project configuration menu:
```bash
idf.py menuconfig
```
Set the memory report configuration as required. The sections below show the configuration setup. Then, configure the Wi-Fi station parameters at needed:
- Set WiFi SSID.
- Set WiFi Password.
Optional: If you need, change the other Wi-Fi options according to your requirements.
### Build and Flash
Run `idf.py -p HOST_PORT flash monitor` to build, flash and monitor the
project.
(To exit the serial monitor, type ``Ctrl-]``.)
See the [Getting Started Guide](https://idf.espressif.com/) for full
steps to configure and use ESP-IDF to build projects.
## Example Output
### Example 1: Generate a one time report
A one-time memory report is queried by the host.
In the Kconfig `Example Configuration`:
- enable `Query Memory Info only once` (other memory report settings are now hidden)
- set the required Wi-Fi settings
This is the example output. A report is generated only once.
<details>
<summary>Select to see output</summary>
```
[...]
I (1867) hosted_meminfo: ESP-Hosted Transport is UP
I (1997) hosted_meminfo: ESP-Hosted is ready
I (2137) RPC_WRAP: Coprocessor Boot-up
I (2137) hosted_meminfo: *** got INIT event from co-processor ***
I (2137) hosted_meminfo: *** Co-processor Reset Reason 1 ***
I (2137) hosted_meminfo: ======= Current Co-processor Mem Info =====
I (2137) hosted_meminfo: mem monitoring enabled : 0
I (2137) hosted_meminfo: report always : 0
I (2137) hosted_meminfo: reporting interval : 0
I (2137) hosted_meminfo: current heap size : 4299348
I (2137) hosted_meminfo: ----------------------------------------------
I (2137) hosted_meminfo: | | | Largest |
I (2137) hosted_meminfo: | Current Heap Size | Free Size | Free Block |
I (2137) hosted_meminfo: |-------------------|-----------|------------|
I (2137) hosted_meminfo: | Internal DMA | 123359 | 86016 |
I (2137) hosted_meminfo: | Internal 8Bit | 139303 | 86016 |
I (2137) hosted_meminfo: | External DMA | 0 | 0 |
I (2137) hosted_meminfo: | External 8Bit | 4191920 | 4128768 |
I (2137) hosted_meminfo: ----------------------------------------------
I (2137) hosted_meminfo: delaying for 10 secs before connecting
I (12137) transport: Attempt connection with slave: retry[0]
I (12137) transport: Transport is already up
I (13187) wifi station: wifi_init_sta finished.
I (13187) RPC_WRAP: ESP Event: wifi station started
I (13187) H_API: esp_wifi_remote_connect
I (13207) RPC_WRAP: ESP Event: wifi station started
I (13807) RPC_WRAP: ESP Event: Station mode: Connected
I (14217) RPC_WRAP: ESP Event: Station mode: Connected
I (14217) RPC_WRAP: ESP Event: Station mode: Connected
I (14237) esp_wifi_remote: esp_wifi_internal_reg_rxcb: sta: 0x40046e20
--- 0x40046e20: wifi_sta_receive at /home/kysoh/esp/github_esp-idf/components/esp_wifi/src/wifi_netif.c:38
I (15257) wifi station: got ip:10.10.2.152
I (15257) esp_netif_handlers: sta ip: 10.10.2.152, mask: 255.255.255.0, gw: 10.10.2.1
I (15257) wifi station: connected to ap SSID:xxx password:yyy
I (15257) hosted_meminfo: delaying for 10 secs before disconnecting
I (25277) main_task: Returned from app_main()
I (25287) RPC_WRAP: ESP Event: Station mode: Disconnected
I (25287) wifi station: do not reconnect
[...]
```
</details>
### Example 2: Periodically generate a memory report
The co-processor sends a memory report periodically.
In the `Example Configuration`:
- disable `Query Memory Info only once`
- set `Memory Monitor Interval (in seconds)`. Default is 10 seconds
- enable `Always send a memory report`
- set the required Wi-Fi settings
This is the example output. A report is generated at every reporting interval.
<details>
<summary>Select to see output</summary>
```
[...]
I (1867) hosted_meminfo: ESP-Hosted Transport is UP
I (1997) hosted_meminfo: ESP-Hosted is ready
I (2137) RPC_WRAP: Coprocessor Boot-up
I (2137) hosted_meminfo: *** got INIT event from co-processor ***
I (2137) hosted_meminfo: *** Co-processor Reset Reason 1 ***
I (2137) hosted_meminfo: ======= Current Co-processor Mem Info =====
I (2137) hosted_meminfo: mem monitoring enabled : 1
I (2137) hosted_meminfo: report always : 1
I (2137) hosted_meminfo: reporting interval : 10
I (2137) hosted_meminfo: current heap size : 4299280
I (2137) hosted_meminfo: ----------------------------------------------
I (2137) hosted_meminfo: | | | Largest |
I (2137) hosted_meminfo: | Current Heap Size | Free Size | Free Block |
I (2137) hosted_meminfo: |-------------------|-----------|------------|
I (2137) hosted_meminfo: | Internal DMA | 123291 | 86016 |
I (2137) hosted_meminfo: | Internal 8Bit | 139235 | 86016 |
I (2137) hosted_meminfo: | External DMA | 0 | 0 |
I (2137) hosted_meminfo: | External 8Bit | 4191920 | 4128768 |
I (2137) hosted_meminfo: ----------------------------------------------
I (2137) hosted_meminfo: delaying for 20 secs before connecting
I (12137) hosted_meminfo: ======== Event: Co-processor Mem Info ========
I (12137) hosted_meminfo: Total free heap size : 4299532
I (12137) hosted_meminfo: Min free heap size : 4295348
I (12137) hosted_meminfo: ----------------------------------------------
I (12137) hosted_meminfo: | | | Largest |
I (12137) hosted_meminfo: | Heap Size | Free Size | Free Block |
I (12137) hosted_meminfo: |-------------------|-----------|------------|
I (12137) hosted_meminfo: | Internal DMA | 123699 | 86016 |
I (12137) hosted_meminfo: | Internal 8Bit | 139643 | 86016 |
I (12137) hosted_meminfo: | External DMA | 0 | 0 |
I (12137) hosted_meminfo: | External 8Bit | 4191920 | 4128768 |
I (12137) hosted_meminfo: ----------------------------------------------
I (22137) transport: Attempt connection with slave: retry[0]
I (22137) transport: Transport is already up
I (22287) hosted_meminfo: ======== Event: Co-processor Mem Info ========
I (22287) hosted_meminfo: Total free heap size : 4288288
I (22287) hosted_meminfo: Min free heap size : 4288288
I (22287) hosted_meminfo: ----------------------------------------------
I (22287) hosted_meminfo: | | | Largest |
I (22287) hosted_meminfo: | Heap Size | Free Size | Free Block |
I (22287) hosted_meminfo: |-------------------|-----------|------------|
I (22287) hosted_meminfo: | Internal DMA | 112455 | 77824 |
I (22287) hosted_meminfo: | Internal 8Bit | 128399 | 77824 |
I (22287) hosted_meminfo: | External DMA | 0 | 0 |
I (22287) hosted_meminfo: | External 8Bit | 4191920 | 4128768 |
I (22287) hosted_meminfo: ----------------------------------------------
I (23187) wifi station: wifi_init_sta finished.
I (23197) RPC_WRAP: ESP Event: wifi station started
I (23197) H_API: esp_wifi_remote_connect
I (23207) RPC_WRAP: ESP Event: wifi station started
I (23717) RPC_WRAP: ESP Event: Station mode: Connected
I (24227) RPC_WRAP: ESP Event: Station mode: Connected
I (24227) RPC_WRAP: ESP Event: Station mode: Connected
I (24237) esp_wifi_remote: esp_wifi_internal_reg_rxcb: sta: 0x40046e38
--- 0x40046e38: wifi_sta_receive at /home/kysoh/esp/github_esp-idf/components/esp_wifi/src/wifi_netif.c:38
I (25277) wifi station: got ip:10.10.2.152
I (25277) esp_netif_handlers: sta ip: 10.10.2.152, mask: 255.255.255.0, gw: 10.10.2.1
I (25277) wifi station: connected to ap SSID:xxx password:yyy
I (25277) hosted_meminfo: delaying for 20 secs before disconnecting
I (32137) hosted_meminfo: ======== Event: Co-processor Mem Info ========
I (32137) hosted_meminfo: Total free heap size : 4256044
I (32137) hosted_meminfo: Min free heap size : 4253944
I (32137) hosted_meminfo: ----------------------------------------------
I (32137) hosted_meminfo: | | | Largest |
I (32137) hosted_meminfo: | Heap Size | Free Size | Free Block |
I (32137) hosted_meminfo: |-------------------|-----------|------------|
I (32137) hosted_meminfo: | Internal DMA | 80279 | 45056 |
I (32137) hosted_meminfo: | Internal 8Bit | 96223 | 45056 |
I (32137) hosted_meminfo: | External DMA | 0 | 0 |
I (32137) hosted_meminfo: | External 8Bit | 4191852 | 4128768 |
I (32137) hosted_meminfo: ----------------------------------------------
I (42137) hosted_meminfo: ======== Event: Co-processor Mem Info ========
I (42137) hosted_meminfo: Total free heap size : 4256044
I (42137) hosted_meminfo: Min free heap size : 4253944
I (42137) hosted_meminfo: ----------------------------------------------
I (42137) hosted_meminfo: | | | Largest |
I (42137) hosted_meminfo: | Heap Size | Free Size | Free Block |
I (42137) hosted_meminfo: |-------------------|-----------|------------|
I (42137) hosted_meminfo: | Internal DMA | 80279 | 45056 |
I (42137) hosted_meminfo: | Internal 8Bit | 96223 | 45056 |
I (42137) hosted_meminfo: | External DMA | 0 | 0 |
I (42137) hosted_meminfo: | External 8Bit | 4191852 | 4128768 |
I (42137) hosted_meminfo: ----------------------------------------------
I (45297) main_task: Returned from app_main()
I (45307) RPC_WRAP: ESP Event: Station mode: Disconnected
I (45307) wifi station: do not reconnect
I (52137) hosted_meminfo: ======== Event: Co-processor Mem Info ========
I (52137) hosted_meminfo: Total free heap size : 4256900
I (52137) hosted_meminfo: Min free heap size : 4253944
I (52137) hosted_meminfo: ----------------------------------------------
I (52137) hosted_meminfo: | | | Largest |
I (52137) hosted_meminfo: | Heap Size | Free Size | Free Block |
I (52137) hosted_meminfo: |-------------------|-----------|------------|
I (52137) hosted_meminfo: | Internal DMA | 81135 | 45056 |
I (52137) hosted_meminfo: | Internal 8Bit | 97079 | 45056 |
I (52137) hosted_meminfo: | External DMA | 0 | 0 |
I (52137) hosted_meminfo: | External 8Bit | 4191852 | 4128768 |
I (52137) hosted_meminfo: ----------------------------------------------
[...]
```
</details>
### Example 3: Generate a memory report when heap memory drops below threshold
The co-processor only sends a memory report when heap memory drops below a threshold value. Here, a report is only sent while the station is connected to the AP.
In the previous example, the `Internal DMA` free size after connecting is `80279`, and after disconnecting is `81135`. We choose a value that is in between for the threshold: `81000`. Adjust this value as required based on your system.
In the `Example Configuration`:
- disable `Query Memory Info only once`
- set `Memory Monitor Interval (in seconds)`. Default is 10 seconds
- disable `Always send a memory report`
- set `Threshold for internal DMA Heap Memory (in bytes)` to `81000`
- set the threshold for other parameters to `0` to disable them
- set the required Wi-Fi settings
This is the example output. A report is generated only when the internal DMA heap memory is lower than the threshold of 81,000 bytes (only when connected to the AP).
<details>
<summary>Select to see output</summary>
```
[...]
I (1867) hosted_meminfo: ESP-Hosted Transport is UP
I (1997) hosted_meminfo: ESP-Hosted is ready
I (2137) RPC_WRAP: Coprocessor Boot-up
I (2137) hosted_meminfo: *** got INIT event from co-processor ***
I (2137) hosted_meminfo: *** Co-processor Reset Reason 1 ***
I (2137) hosted_meminfo: ======= Current Co-processor Mem Info =====
I (2137) hosted_meminfo: mem monitoring enabled : 1
I (2137) hosted_meminfo: report always : 0
I (2137) hosted_meminfo: reporting interval : 10
I (2137) hosted_meminfo: current heap size : 4299292
I (2137) hosted_meminfo: ----------------------------------------------
I (2137) hosted_meminfo: | | | Largest |
I (2137) hosted_meminfo: | Current Heap Size | Free Size | Free Block |
I (2137) hosted_meminfo: |-------------------|-----------|------------|
I (2137) hosted_meminfo: | Internal DMA | 123303 | 86016 |
I (2137) hosted_meminfo: | Internal 8Bit | 139247 | 86016 |
I (2137) hosted_meminfo: | External DMA | 0 | 0 |
I (2137) hosted_meminfo: | External 8Bit | 4191920 | 4128768 |
I (2137) hosted_meminfo: ----------------------------------------------
I (2137) hosted_meminfo: delaying for 20 secs before connecting
I (22147) transport: Attempt connection with slave: retry[0]
I (22147) transport: Transport is already up
I (23197) wifi station: wifi_init_sta finished.
I (23207) RPC_WRAP: ESP Event: wifi station started
I (23207) H_API: esp_wifi_remote_connect
I (23217) RPC_WRAP: ESP Event: wifi station started
I (23817) RPC_WRAP: ESP Event: Station mode: Connected
I (24237) RPC_WRAP: ESP Event: Station mode: Connected
I (24237) RPC_WRAP: ESP Event: Station mode: Connected
I (24247) esp_wifi_remote: esp_wifi_internal_reg_rxcb: sta: 0x40046e32
--- 0x40046e32: wifi_sta_receive at /home/kysoh/esp/github_esp-idf/components/esp_wifi/src/wifi_netif.c:38
I (25267) wifi station: got ip:10.10.2.152
I (25267) esp_netif_handlers: sta ip: 10.10.2.152, mask: 255.255.255.0, gw: 10.10.2.1
I (25267) wifi station: connected to ap SSID:xxx password:yyy
I (25267) hosted_meminfo: delaying for 20 secs before disconnecting
I (32137) hosted_meminfo: ======== Event: Co-processor Mem Info ========
I (32137) hosted_meminfo: Total free heap size : 4256020
I (32137) hosted_meminfo: Min free heap size : 4253572
I (32137) hosted_meminfo: ----------------------------------------------
I (32137) hosted_meminfo: | | | Largest |
I (32137) hosted_meminfo: | Heap Size | Free Size | Free Block |
I (32137) hosted_meminfo: |-------------------|-----------|------------|
I (32137) hosted_meminfo: | Internal DMA | 80255 | 47104 |
I (32137) hosted_meminfo: | Internal 8Bit | 96199 | 47104 |
I (32137) hosted_meminfo: | External DMA | 0 | 0 |
I (32137) hosted_meminfo: | External 8Bit | 4191852 | 4128768 |
I (32137) hosted_meminfo: ----------------------------------------------
I (42137) hosted_meminfo: ======== Event: Co-processor Mem Info ========
I (42137) hosted_meminfo: Total free heap size : 4256020
I (42137) hosted_meminfo: Min free heap size : 4253572
I (42137) hosted_meminfo: ----------------------------------------------
I (42137) hosted_meminfo: | | | Largest |
I (42137) hosted_meminfo: | Heap Size | Free Size | Free Block |
I (42137) hosted_meminfo: |-------------------|-----------|------------|
I (42137) hosted_meminfo: | Internal DMA | 80255 | 47104 |
I (42137) hosted_meminfo: | Internal 8Bit | 96199 | 47104 |
I (42137) hosted_meminfo: | External DMA | 0 | 0 |
I (42137) hosted_meminfo: | External 8Bit | 4191852 | 4128768 |
I (42137) hosted_meminfo: ----------------------------------------------
[...]
```
</details>
# References
- ESP-IDF documentation on [Memory Capabilities](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/mem_alloc.html#memory-capabilities)
- ESP-IDF documentation on [Heap information](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/heap_debug.html#heap-information).
- ESP-IDF [capabilities of memory systems](https://github.com/espressif/esp-idf/blob/master/components/heap/include/esp_heap_caps.h)
@@ -0,0 +1,4 @@
set(srcs "main.c" "station_example.c")
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS ".")
@@ -0,0 +1,121 @@
menu "Example Configuration"
config EXAMPLE_MEM_MONITOR_QUERY_ONLY_ONCE
bool "Query Memory Info only once"
default n
help
Query the memory on the co-processor only once
if !EXAMPLE_MEM_MONITOR_QUERY_ONLY_ONCE
config EXAMPLE_MEM_MONITOR_INTERVAL_SEC
int "Memory Monitor Interval (in seconds)"
default 10
help
Set the interval for doing memory checks on the co-processor
config EXAMPLE_MEM_MONITOR_REPORT_ALWAYS
bool "Always send a memory report"
default y
help
When enabled, co-processor will always send a memory report while doing the memory check at the set interval. When disable, co-processor will only send a memory report if memory check shows memory has dropped below a set threshold
config EXAMPLE_MEM_MONITOR_INTERNAL_DMA_THRESHOLD
depends on !EXAMPLE_MEM_MONITOR_REPORT_ALWAYS
int "Threshold for internal DMA Heap Memory (in bytes)"
default 8192
help
Sets the memory threshold that will trigger a report. 0 disables the threshold.
config EXAMPLE_MEM_MONITOR_INTERNAL_8BIT_THRESHOLD
depends on !EXAMPLE_MEM_MONITOR_REPORT_ALWAYS
int "Threshold for internal 8-Bit Heap Memory (in bytes)"
default 8192
help
Sets the memory threshold that will trigger a report. 0 disables the threshold.
config EXAMPLE_MEM_MONITOR_EXTERNAL_DMA_THRESHOLD
depends on !EXAMPLE_MEM_MONITOR_REPORT_ALWAYS
int "Threshold for external DMA Heap Memory (in bytes)"
default 8192
help
Sets the memory threshold that will trigger a report. 0 disables the threshold.
config EXAMPLE_MEM_MONITOR_EXTERNAL_8BIT_THRESHOLD
depends on !EXAMPLE_MEM_MONITOR_REPORT_ALWAYS
int "Threshold for external 8-Bit Heap Memory (in bytes)"
default 8192
help
Sets the memory threshold that will trigger a report. 0 disables the threshold.
endif
menu "Wifi Config"
config ESP_WIFI_SSID
string "WiFi SSID"
default "myssid"
help
SSID (network name) for the example to connect to.
config ESP_WIFI_PASSWORD
string "WiFi Password"
default "mypassword"
help
WiFi password (WPA or WPA2) for the example to use.
choice ESP_WIFI_SAE_MODE
prompt "WPA3 SAE mode selection"
default ESP_STATION_EXAMPLE_WPA3_SAE_PWE_BOTH
help
Select mode for SAE as Hunt and Peck, H2E or both.
config ESP_STATION_EXAMPLE_WPA3_SAE_PWE_HUNT_AND_PECK
bool "HUNT AND PECK"
config ESP_STATION_EXAMPLE_WPA3_SAE_PWE_HASH_TO_ELEMENT
bool "H2E"
depends on ESP_WIFI_ENABLE_SAE_H2E
config ESP_STATION_EXAMPLE_WPA3_SAE_PWE_BOTH
bool "BOTH"
depends on ESP_WIFI_ENABLE_SAE_H2E
endchoice
config ESP_WIFI_PW_ID
string "PASSWORD IDENTIFIER"
depends on ESP_STATION_EXAMPLE_WPA3_SAE_PWE_HASH_TO_ELEMENT|| ESP_STATION_EXAMPLE_WPA3_SAE_PWE_BOTH
default ""
help
password identifier for SAE H2E
config ESP_MAXIMUM_RETRY
int "Maximum retry"
default 5
help
Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent.
choice ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD
prompt "WiFi Scan auth mode threshold"
default ESP_WIFI_AUTH_WPA2_PSK
help
The weakest authmode to accept in the scan mode.
This value defaults to ESP_WIFI_AUTH_WPA2_PSK in case password is present and ESP_WIFI_AUTH_OPEN is used.
Please select ESP_WIFI_AUTH_WEP/ESP_WIFI_AUTH_WPA_PSK in case AP is operating in WEP/WPA mode.
config ESP_WIFI_AUTH_OPEN
bool "OPEN"
config ESP_WIFI_AUTH_WEP
bool "WEP"
config ESP_WIFI_AUTH_WPA_PSK
bool "WPA PSK"
config ESP_WIFI_AUTH_WPA2_PSK
bool "WPA2 PSK"
config ESP_WIFI_AUTH_WPA_WPA2_PSK
bool "WPA/WPA2 PSK"
config ESP_WIFI_AUTH_WPA3_PSK
bool "WPA3 PSK"
config ESP_WIFI_AUTH_WPA2_WPA3_PSK
bool "WPA2/WPA3 PSK"
config ESP_WIFI_AUTH_WAPI_PSK
bool "WAPI PSK"
endchoice
endmenu
endmenu
@@ -0,0 +1,14 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __APP_COMMON_H__
#define __APP_COMMON_H__
void example_wifi_init_once(void);
void example_wifi_init_sta(void);
void example_wifi_sta_disconnect(void);
void example_wifi_deinit_sta(void);
#endif
@@ -0,0 +1,10 @@
dependencies:
espressif/esp_hosted:
rules:
- if: target in [esp32p4, esp32h2]
version: '*'
espressif/esp_wifi_remote:
rules:
- if: target in [esp32p4, esp32h2]
- if: idf_version <6.1
version: '>=1.3.1'
@@ -0,0 +1,258 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_log.h"
#include "esp_event.h"
#include "esp_hosted.h"
#include "esp_timer.h"
#include "esp_system.h"
#include "app_common.h"
static SemaphoreHandle_t sem_hosted_is_up;
static const char* TAG = "hosted_meminfo";
#ifndef CONFIG_EXAMPLE_MEM_MONITOR_QUERY_ONLY_ONCE
#define MEM_MONITOR_INTERVAL_SEC CONFIG_EXAMPLE_MEM_MONITOR_INTERVAL_SEC
#if MEM_MONITOR_INTERVAL_SEC <= 0
#error "Monitor interval should be 1 sec or greater"
#endif
// we delay by twice the monitor interval to give time for the monitor event to be sent
#define WIFI_DELAY_BEFORE_CONNECTING_SEC (2 * MEM_MONITOR_INTERVAL_SEC)
#define WIFI_DELAY_BEFORE_DISCONNECTING_SEC (2 * MEM_MONITOR_INTERVAL_SEC)
#ifdef CONFIG_EXAMPLE_MEM_MONITOR_REPORT_ALWAYS
#define MEM_MONITOR_REPORT_ALWAYS true
#else
#define MEM_MONITOR_REPORT_ALWAYS false
#endif
#ifndef CONFIG_EXAMPLE_MEM_MONITOR_REPORT_ALWAYS
/*
* If free heap memory falls below these threshold values on the co-processor,
* a mem info event is generated.
*
* Note: external threshold values will trigger the event only if external memory (SPIRAM)
* is enabled on the co-processor.
*/
#define MEM_MONITOR_INTERNAL_DMA_THRESHOLD CONFIG_EXAMPLE_MEM_MONITOR_INTERNAL_DMA_THRESHOLD
#define MEM_MONITOR_INTERNAL_8BIT_THRESHOLD CONFIG_EXAMPLE_MEM_MONITOR_INTERNAL_8BIT_THRESHOLD
#define MEM_MONITOR_EXTERNAL_DMA_THRESHOLD CONFIG_EXAMPLE_MEM_MONITOR_EXTERNAL_DMA_THRESHOLD
#define MEM_MONITOR_EXTERNAL_8BIT_THRESHOLD CONFIG_EXAMPLE_MEM_MONITOR_EXTERNAL_8BIT_THRESHOLD
#else // ifndef CONFIG_EXAMPLE_MEM_MONITOR_REPORT_ALWAYS
// since we are reporting always, no need to set thresholds
#define MEM_MONITOR_INTERNAL_DMA_THRESHOLD 0
#define MEM_MONITOR_INTERNAL_8BIT_THRESHOLD 0
#define MEM_MONITOR_EXTERNAL_DMA_THRESHOLD 0
#define MEM_MONITOR_EXTERNAL_8BIT_THRESHOLD 0
#endif // ifndef CONFIG_EXAMPLE_MEM_MONITOR_REPORT_ALWAYS
#else // ifndef CONFIG_EXAMPLE_MEM_MONITOR_QUERY_ONLY_ONCE
#define MEM_MONITOR_ENABLE false
#define MEM_MONITOR_INTERVAL_SEC 0
#define MEM_MONITOR_REPORT_ALWAYS false
#define MEM_MONITOR_INTERNAL_DMA_THRESHOLD 0
#define MEM_MONITOR_INTERNAL_8BIT_THRESHOLD 0
#define MEM_MONITOR_EXTERNAL_DMA_THRESHOLD 0
#define MEM_MONITOR_EXTERNAL_8BIT_THRESHOLD 0
#define WIFI_DELAY_BEFORE_CONNECTING_SEC (10)
#define WIFI_DELAY_BEFORE_DISCONNECTING_SEC (10)
#endif // ifndef CONFIG_EXAMPLE_MEM_MONITOR_QUERY_ONLY_ONCE
/**
* This event handler handles ESP-Hosted events
*
* See station_example.c for the event handler for Wi-Fi and IP events
*/
static void esp_hosted_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_base == ESP_HOSTED_EVENT) {
if (event_id == ESP_HOSTED_EVENT_MEM_MONITOR) {
esp_hosted_event_mem_info_t *event = (esp_hosted_event_mem_info_t *)event_data;
ESP_LOGI(TAG, "======== Event: Co-processor Mem Info ========");
ESP_LOGI(TAG, "Total free heap size : % 7"PRIu32, event->curr_total_free_heap_size);
ESP_LOGI(TAG, "Min free heap size : % 7"PRIu32, event->curr_min_free_heap_size);
ESP_LOGI(TAG, "----------------------------------------------");
ESP_LOGI(TAG, "| | | Largest |");
ESP_LOGI(TAG, "| Heap Size | Free Size | Free Block |");
ESP_LOGI(TAG, "|-------------------|-----------|------------|");
ESP_LOGI(TAG, "| Internal DMA | % 7"PRIu32" | % 7"PRIu32" |",
event->curr_internal.cap_dma.free_size,
event->curr_internal.cap_dma.largest_free_block);
ESP_LOGI(TAG, "| Internal 8Bit | % 7"PRIu32" | % 7"PRIu32" |",
event->curr_internal.cap_8bit.free_size,
event->curr_internal.cap_8bit.largest_free_block);
ESP_LOGI(TAG, "| External DMA | % 7"PRIu32" | % 7"PRIu32" |",
event->curr_external.cap_dma.free_size,
event->curr_external.cap_dma.largest_free_block);
ESP_LOGI(TAG, "| External 8Bit | % 7"PRIu32" | % 7"PRIu32" |",
event->curr_external.cap_8bit.free_size,
event->curr_external.cap_8bit.largest_free_block);
ESP_LOGI(TAG, "----------------------------------------------");
} else if (event_id == ESP_HOSTED_EVENT_CP_INIT) {
ESP_LOGI(TAG, "*** got INIT event from co-processor ***");
esp_hosted_event_init_t *event = (esp_hosted_event_init_t *)event_data;
ESP_LOGI(TAG, "*** Co-processor Reset Reason %"PRIu16" ***", event->reason);
} else if (event_id == ESP_HOSTED_EVENT_TRANSPORT_UP) {
ESP_LOGI(TAG, "ESP-Hosted Transport is UP");
xSemaphoreGive(sem_hosted_is_up);
} else if (event_id == ESP_HOSTED_EVENT_TRANSPORT_DOWN) {
ESP_LOGI(TAG, "ESP-Hosted Transport is DOWN");
} else if (event_id == ESP_HOSTED_EVENT_TRANSPORT_FAILURE) {
ESP_LOGI(TAG, "*** Transport Failure ***");
} else if (event_id == ESP_HOSTED_EVENT_CP_HEARTBEAT) {
esp_hosted_event_heartbeat_t *event = (esp_hosted_event_heartbeat_t *)event_data;
ESP_LOGI(TAG, "*** Heartbeat %"PRIu32" ***", event->heartbeat);
} else {
ESP_LOGI(TAG, "Got UNKNOWN ESP_HOSTED event");
}
}
}
static void app_init_once(void)
{
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_event_handler_instance_t instance_got_hosted_event;
ESP_ERROR_CHECK(esp_event_handler_instance_register(ESP_HOSTED_EVENT,
ESP_EVENT_ANY_ID,
&esp_hosted_event_handler,
NULL,
&instance_got_hosted_event));
// create a binary semaphore for app to wait on until ESP-Hosted transport is up
sem_hosted_is_up = xSemaphoreCreateBinary();
assert(sem_hosted_is_up);
xSemaphoreGive(sem_hosted_is_up);
xSemaphoreTake(sem_hosted_is_up, portMAX_DELAY);
}
static void app_esp_hosted_init(void)
{
esp_hosted_init();
esp_hosted_connect_to_slave();
}
static esp_err_t app_mem_monitor_set(esp_hosted_curr_mem_info_t *curr_mem_info)
{
if (!curr_mem_info) {
return ESP_FAIL;
}
// set up configuration for memory monitoring
esp_hosted_config_mem_monitor_t config = {
#ifdef CONFIG_EXAMPLE_MEM_MONITOR_QUERY_ONLY_ONCE
// don't change monitor configuration for one time query
.config = ESP_HOSTED_MEMMONITOR_NO_CHANGE,
#else
.config = ESP_HOSTED_MEMMONITOR_ENABLE,
#endif
.report_always = MEM_MONITOR_REPORT_ALWAYS,
.interval_sec = MEM_MONITOR_INTERVAL_SEC,
.internal_mem.threshold_mem_dma = MEM_MONITOR_INTERNAL_DMA_THRESHOLD,
.internal_mem.threshold_mem_8bit = MEM_MONITOR_INTERNAL_8BIT_THRESHOLD,
.external_mem.threshold_mem_dma = MEM_MONITOR_EXTERNAL_DMA_THRESHOLD,
.external_mem.threshold_mem_8bit = MEM_MONITOR_EXTERNAL_8BIT_THRESHOLD,
};
return esp_hosted_set_mem_monitor(&config, curr_mem_info);
}
void print_mem_info_resp(esp_hosted_curr_mem_info_t *info)
{
char *config_str = "";
if (info->config == ESP_HOSTED_MEMMONITOR_NO_CHANGE) {
config_str = "No Change";
} else if (info->config == ESP_HOSTED_MEMMONITOR_DISABLE) {
config_str = "Disabled";
} else if (info->config == ESP_HOSTED_MEMMONITOR_ENABLE) {
config_str = "Enabled";
}
// print out current mem info
ESP_LOGI(TAG, "======= Current Co-processor Mem Info =====");
ESP_LOGI(TAG, "mem monitoring config : %s", config_str);
ESP_LOGI(TAG, "report always : %"PRIu16, info->report_always);
ESP_LOGI(TAG, "reporting interval : %"PRIu32, info->interval_sec);
ESP_LOGI(TAG, "current heap size : %"PRIu32, info->curr_total_heap_size);
#if 1
ESP_LOGI(TAG, "----------------------------------------------");
ESP_LOGI(TAG, "| | | Largest |");
ESP_LOGI(TAG, "| Current Heap Size | Free Size | Free Block |");
ESP_LOGI(TAG, "|-------------------|-----------|------------|");
ESP_LOGI(TAG, "| Internal DMA | % 7"PRIu32" | % 7"PRIu32" |",
info->curr_internal.cap_dma.free_size,
info->curr_internal.cap_dma.largest_free_block);
ESP_LOGI(TAG, "| Internal 8Bit | % 7"PRIu32" | % 7"PRIu32" |",
info->curr_internal.cap_8bit.free_size,
info->curr_internal.cap_8bit.largest_free_block);
ESP_LOGI(TAG, "| External DMA | % 7"PRIu32" | % 7"PRIu32" |",
info->curr_external.cap_dma.free_size,
info->curr_external.cap_dma.largest_free_block);
ESP_LOGI(TAG, "| External 8Bit | % 7"PRIu32" | % 7"PRIu32" |",
info->curr_external.cap_8bit.free_size,
info->curr_external.cap_8bit.largest_free_block);
ESP_LOGI(TAG, "----------------------------------------------");
#else
ESP_LOGI(TAG, "Current Internal DMA Heap:");
ESP_LOGI(TAG, " Free Size : %"PRIu32, info->curr_internal.cap_dma.free_size);
ESP_LOGI(TAG, " Largest Free Block: %"PRIu32, info->curr_internal.cap_dma.largest_free_block);
ESP_LOGI(TAG, "Current Internal 8bit Heap:");
ESP_LOGI(TAG, " Free Size : %"PRIu32, info->curr_internal.cap_8bit.free_size);
ESP_LOGI(TAG, " Largest Free Block: %"PRIu32, info->curr_internal.cap_8bit.largest_free_block);
ESP_LOGI(TAG, "Current External DMA Heap:");
ESP_LOGI(TAG, " Free Size : %"PRIu32, info->curr_external.cap_dma.free_size);
ESP_LOGI(TAG, " Largest Free Block: %"PRIu32, info->curr_external.cap_dma.largest_free_block);
ESP_LOGI(TAG, "Current External 8bit Heap:");
ESP_LOGI(TAG, " Free Size : %"PRIu32, info->curr_external.cap_8bit.free_size);
ESP_LOGI(TAG, " Largest Free Block: %"PRIu32, info->curr_external.cap_8bit.largest_free_block);
ESP_LOGI(TAG, "=========================================");
#endif
}
void app_main(void)
{
esp_err_t res;
esp_hosted_curr_mem_info_t curr_mem_info = { 0 };
app_init_once();
app_esp_hosted_init();
example_wifi_init_once(); // one time wifi init
// wait until ESP-Hosted is up before continuing
xSemaphoreTake(sem_hosted_is_up, portMAX_DELAY);
ESP_LOGI(TAG, "ESP-Hosted is ready");
res = app_mem_monitor_set(&curr_mem_info);
if (ESP_OK != res) {
ESP_LOGE(TAG, "Failed to set up mem monitor: %s", esp_err_to_name(res));
if (res == ESP_ERR_NOT_SUPPORTED) {
ESP_LOGE(TAG, "Mem Monitor Interface support on co-processor must be enabled");
}
return;
}
print_mem_info_resp(&curr_mem_info);
// wait a while to get a report before we connect
ESP_LOGI(TAG, "delaying for %"PRIu16 " secs before connecting", WIFI_DELAY_BEFORE_CONNECTING_SEC);
vTaskDelay((WIFI_DELAY_BEFORE_CONNECTING_SEC * 1000) / portTICK_PERIOD_MS);
// connect to an AP
example_wifi_init_sta();
// wait a while to get a report before we disconnect
ESP_LOGI(TAG, "delaying for %"PRIu16 " secs before disconnecting", WIFI_DELAY_BEFORE_DISCONNECTING_SEC);
vTaskDelay((WIFI_DELAY_BEFORE_DISCONNECTING_SEC * 1000) / portTICK_PERIOD_MS);
// disconnect from the AP
example_wifi_sta_disconnect();
}
@@ -0,0 +1,223 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* WiFi station Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "app_common.h"
/* The examples use WiFi configuration that you can set via project configuration menu
If you'd rather not, just change the below entries to strings with
the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID
#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY
#if CONFIG_ESP_STATION_EXAMPLE_WPA3_SAE_PWE_HUNT_AND_PECK
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HUNT_AND_PECK
#define EXAMPLE_H2E_IDENTIFIER ""
#elif CONFIG_ESP_STATION_EXAMPLE_WPA3_SAE_PWE_HASH_TO_ELEMENT
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HASH_TO_ELEMENT
#define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID
#elif CONFIG_ESP_STATION_EXAMPLE_WPA3_SAE_PWE_BOTH
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_BOTH
#define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID
#endif
#if CONFIG_ESP_WIFI_AUTH_OPEN
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN
#elif CONFIG_ESP_WIFI_AUTH_WEP
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP
#elif CONFIG_ESP_WIFI_AUTH_WPA_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK
#endif
/* FreeRTOS event group to signal when we are connected*/
static EventGroupHandle_t s_wifi_event_group;
/* The event group allows multiple bits for each event, but we only care about two events:
* - we are connected to the AP with an IP
* - we failed to connect after the maximum amount of retries */
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
static const char *TAG = "wifi station";
static int s_retry_num = 0;
static bool do_not_reconnect = false;
static bool station_connected = false;
static esp_event_handler_instance_t instance_any_id = NULL;
static esp_event_handler_instance_t instance_got_ip = NULL;
static esp_netif_t *sta_netif = NULL;
static void event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
// mark that we want to auto reconnect
do_not_reconnect = false;
esp_wifi_connect();
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
if (!do_not_reconnect) {
if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
esp_wifi_connect();
s_retry_num++;
ESP_LOGI(TAG, "retry to connect to the AP");
} else {
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
ESP_LOGI(TAG,"connect to the AP fail");
}
} else {
ESP_LOGI(TAG,"do not reconnect");
}
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
s_retry_num = 0;
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
}
}
void example_wifi_deinit_sta(void)
{
if (sta_netif) {
esp_netif_destroy_default_wifi(sta_netif);
sta_netif = NULL;
}
if (!instance_any_id) {
ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT,
ESP_EVENT_ANY_ID,
instance_any_id));
instance_any_id = NULL;
}
if (!instance_got_ip) {
ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT,
ESP_EVENT_ANY_ID,
instance_got_ip));
instance_got_ip = NULL;
}
vEventGroupDelete(s_wifi_event_group);
}
void example_wifi_init_once(void)
{
ESP_ERROR_CHECK(esp_netif_init());
}
void example_wifi_init_sta(void)
{
s_wifi_event_group = xEventGroupCreate();
if (!instance_any_id) {
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&event_handler,
NULL,
&instance_any_id));
}
if (!instance_got_ip) {
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
IP_EVENT_STA_GOT_IP,
&event_handler,
NULL,
&instance_got_ip));
}
if (!sta_netif) {
sta_netif = esp_netif_create_default_wifi_sta();
}
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
wifi_config_t wifi_config = {
.sta = {
.ssid = EXAMPLE_ESP_WIFI_SSID,
.password = EXAMPLE_ESP_WIFI_PASS,
/* Authmode threshold resets to WPA2 as default if password matches WPA2 standards (password len => 8).
* If you want to connect the device to deprecated WEP/WPA networks, Please set the threshold value
* to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with length and format matching to
* WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK standards.
*/
.threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD,
.sae_pwe_h2e = ESP_WIFI_SAE_MODE,
.sae_h2e_identifier = EXAMPLE_H2E_IDENTIFIER,
#ifdef CONFIG_ESP_WIFI_WPA3_COMPATIBLE_SUPPORT
.disable_wpa3_compatible_mode = 0,
#endif
},
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
ESP_ERROR_CHECK(esp_wifi_start() );
ESP_LOGI(TAG, "wifi_init_sta finished.");
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
pdFALSE,
pdFALSE,
portMAX_DELAY);
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
* happened. */
if (bits & WIFI_CONNECTED_BIT) {
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
station_connected = true;
} else if (bits & WIFI_FAIL_BIT) {
ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
} else {
ESP_LOGE(TAG, "UNEXPECTED EVENT");
}
}
void example_wifi_sta_disconnect(void)
{
if (!station_connected) {
ESP_LOGW(TAG, "not connected to a station");
}
// mark that we don't want to auto reconnect
do_not_reconnect = true;
esp_wifi_disconnect();
}
@@ -0,0 +1,2 @@
# enable mem monitor configuration
CONFIG_ESP_HOSTED_MEM_MONITOR=y