Fork fix: the SDIO wedge is FIXED (esp-hosted-mcu #167)
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:
@@ -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 ".")
|
||||
+121
@@ -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();
|
||||
}
|
||||
+223
@@ -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
|
||||
Reference in New Issue
Block a user