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_events)
|
||||
@@ -0,0 +1,287 @@
|
||||
| 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 Events Example
|
||||
|
||||
This host example uses ESP-Hosted events to detect that the co-processor has reset or hanged. It then takes action to reinitialised ESP-Hosted to restore connectivity with the co-processor.
|
||||
|
||||
This has been tested with the ESP32-C6 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.
|
||||
|
||||
It makes use of ESP-Hosted events, with event base of `ESP_HOSTED_EVENT`:
|
||||
|
||||
- `ESP_HOSTED_EVENT_CP_INIT`: this event is sent by the co-processor after it has started and ESP-Hosted transport has been setup. Receiving this event for a second time indicates that the co-process has restarted. An `esp_reset_reason_t` value is provided so the host can discover why the co-processor sent the event
|
||||
- `ESP_HOSTED_EVENT_CP_HEARTBEAT`: when configured by the host, the co-processor will periodically send a heartbeat event at the required interval (in seconds). If this event is not received after the interval, it indicates the the co-processor may have hanged and is unable to send the event.
|
||||
- `ESP_HOSTED_EVENT_TRANSPORT_FAILURE`: indicates a ESP-Hosted transport failure
|
||||
|
||||
This example sets up the detection of ESP-Hosted events, then connects to a station. After connecting, if the co-processor reboots (INIT event received) or hangs (timeout getting HEARTBEAT), it will tell NETIF that the connection is lost, then proceed to reinitialise the ESP-Hosted transport.
|
||||
|
||||
## How to Use This Example on ESP Hosts
|
||||
|
||||
Before project configuration and build, be sure to set the correct
|
||||
chip target using:
|
||||
|
||||
```bash
|
||||
idf.py set-target <ESP Host chip_name>
|
||||
```
|
||||
|
||||
### Configure the project
|
||||
|
||||
Open the project configuration menu:
|
||||
|
||||
```bash
|
||||
idf.py menuconfig
|
||||
```
|
||||
|
||||
In the `Example Configuration` menu:
|
||||
|
||||
* set `Heartbeat Interval in Seconds`. Default is 5 seconds
|
||||
* toggle `Enable heartbeat timeout detection` to enable heartbeat timeout detection
|
||||
* if heartbeat timeout detection is enabled, you can set `Heartbeat Timeout in Seconds`. This value should be larger than `Heartbeat Interval in Seconds`. A value should be set based on app requirements (how long to wait after a timeout before triggering a timeout alert).
|
||||
|
||||
Configure the Station parameters at needed:
|
||||
|
||||
- Set WiFi SSID.
|
||||
- Set WiFi Password.
|
||||
|
||||
Optional: If you need, change the other Station 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
|
||||
|
||||
> [!NOTE]
|
||||
> To simulate a co-processor reset or hang, a ESP-Prog is connected to the ESP32-C6 on the ESP32-P4 Dev Board. The `RST` and `BOOT` buttons on the ESP-Prog is then used to reset or put the C6 into boot mode (to simulate a hang).
|
||||
|
||||
### Example Output using SDIO interface
|
||||
|
||||
```
|
||||
I (6327) esp_netif_handlers: sta ip: 192.168.50.217, mask: 255.255.255.0, gw: 192.168.50.1
|
||||
I (6327) wifi station: got ip:192.168.50.217
|
||||
I (6327) wifi station: connected to ap SSID:xxx password:yyy
|
||||
I (7377) hosted_events: *** Heartbeat 0***
|
||||
W (13377) hosted_events: *** HEARTBEAT timeout ***
|
||||
I (14327) hosted_events: heartbeat timeout, transport failure or got INIT event: reinit Hosted
|
||||
E (14327) sdmmc_io: sdmmc_io_rw_extended: sdmmc_send_cmd returned 0x107
|
||||
E (14327) H_SDIO_DRV: sdio_write_task: 0: Failed to send data: 263 54 54
|
||||
E (14327) sdmmc_io: sdmmc_io_rw_extended: sdmmc_send_cmd returned 0x107
|
||||
E (14337) H_SDIO_DRV: sdio_write_task: 1: Failed to send data: 263 54 54
|
||||
E (14347) H_SDIO_DRV: Unrecoverable host sdio state
|
||||
I (14347) wifi station: do not reconnect
|
||||
I (14347) hosted_events: *** Transport Failure ***
|
||||
I (14527) H_API: ESP-Hosted deinit
|
||||
|
||||
I (14527) serial_ll: Clean-up serial queue
|
||||
W (14527) H_SDIO_DRV: free buffer[0] 0x4ff3d8c0
|
||||
W (14527) H_SDIO_DRV: free buffer[1] 0x4ff3e1c0
|
||||
I (14527) transport: TRANSPORT_INACTIVE
|
||||
I (14527) hosted_events: restarting ESP-Hosted
|
||||
I (14537) hosted_events: init ESP-Hosted
|
||||
I (14537) H_API: ESP-Hosted starting. Hosted_Tasks: prio:23, stack: 5120 RPC_task_stack: 5120
|
||||
W (14547) H_API: Transport already initialized, skipping initialization
|
||||
I (14557) H_API: ** add_esp_wifi_remote_channels **
|
||||
I (14557) H_SDIO_DRV: sdio_data_to_rx_buf_task started
|
||||
I (14567) H_API: ESP-Hosted Try to communicate with ESP-Hosted slave
|
||||
|
||||
I (14567) transport: Attempt connection with slave: retry[0]
|
||||
W (14577) H_SDIO_DRV: Reset slave using GPIO[54]
|
||||
I (14577) os_wrapper_esp: GPIO [54] configured
|
||||
I (16107) sdio_wrapper: SDIO master: Slot 1, Data-Lines: 4-bit Freq(KHz)[40000 KHz]
|
||||
I (16107) sdio_wrapper: GPIOs: CLK[18] CMD[19] D0[14] D1[15] D2[16] D3[17] Slave_Reset[54]
|
||||
I (16107) sdio_wrapper: Queues: Tx[20] Rx[20] SDIO-Rx-Mode[1]
|
||||
I (16147) sdio_wrapper: Function 0 Blocksize: 512
|
||||
I (16147) sdio_wrapper: Function 1 Blocksize: 512
|
||||
I (16247) H_SDIO_DRV: Card init success, TRANSPORT_RX_ACTIVE
|
||||
I (16247) transport: set_transport_state: 1
|
||||
I (16247) transport: Waiting for esp_hosted slave to be ready
|
||||
I (16267) H_SDIO_DRV: SDIO Host operating in STREAMING MODE
|
||||
I (16267) H_SDIO_DRV: Open data path at slave
|
||||
I (16267) H_SDIO_DRV: Starting SDIO process rx task
|
||||
I (16287) H_SDIO_DRV: Received ESP_PRIV_IF type message
|
||||
I (16287) transport: Received INIT event from ESP32 peripheral
|
||||
I (16287) transport: EVENT: 12
|
||||
I (16287) transport: Identified slave [esp32c6]
|
||||
I (16297) transport: EVENT: 11
|
||||
I (16297) transport: capabilities: 0xd
|
||||
I (16307) transport: Features supported are:
|
||||
I (16307) transport: * WLAN
|
||||
I (16307) transport: - HCI over SDIO
|
||||
I (16317) transport: - BLE only
|
||||
I (16317) transport: EVENT: 13
|
||||
I (16317) transport: ESP board type is : 13
|
||||
|
||||
I (16327) transport: Base transport is set-up, TRANSPORT_TX_ACTIVE
|
||||
I (16327) H_API: Transport active
|
||||
I (16327) transport: Slave chip Id[12]
|
||||
I (16337) transport: raw_tp_dir[-], flow_ctrl: low[60] high[80]
|
||||
I (16337) transport: transport_delayed_init
|
||||
I (16347) esp_cli: Remove any existing deep_sleep cmd in cli
|
||||
I (16347) esp_cli: Registering command: crash
|
||||
I (16357) esp_cli: Registering command: reboot
|
||||
I (16357) esp_cli: Registering command: mem-dump
|
||||
I (16367) esp_cli: Registering command: task-dump
|
||||
I (16367) esp_cli: Registering command: cpu-dump
|
||||
I (16367) esp_cli: Registering command: heap-trace
|
||||
I (16377) esp_cli: Registering command: sock-dump
|
||||
I (16377) esp_cli: Registering command: host-power-save
|
||||
I (16387) hci_stub_drv: Host BT Support: Disabled
|
||||
I (16387) H_SDIO_DRV: Received INIT event
|
||||
I (16397) H_SDIO_DRV: Event type: 0x22
|
||||
I (16397) H_SDIO_DRV: Write thread started
|
||||
I (16447) hosted_events: getting fw version
|
||||
I (16567) hosted_events: *** got INIT event from co-processor ***
|
||||
I (16567) hosted_events: *** Co-processor Reset Reason 1***
|
||||
I (16567) hosted_events: Expected INIT event
|
||||
I (16567) hosted_events: FW Version: 2.8.1
|
||||
I (16577) hosted_events: heartbeat timer started
|
||||
I (16577) transport: Attempt connection with slave: retry[0]
|
||||
I (16577) transport: Transport is already up
|
||||
I (16877) wifi station: wifi_init_sta finished.
|
||||
I (16877) RPC_WRAP: ESP Event: wifi station started
|
||||
I (16887) RPC_WRAP: ESP Event: wifi station started
|
||||
I (19327) RPC_WRAP: ESP Event: Station mode: Disconnected
|
||||
I (19327) H_API: esp_wifi_remote_connect
|
||||
I (19347) wifi station: retry to connect to the AP
|
||||
I (21567) hosted_events: *** Heartbeat 0***
|
||||
I (21757) RPC_WRAP: ESP Event: Station mode: Disconnected
|
||||
I (21757) H_API: esp_wifi_remote_connect
|
||||
I (21767) wifi station: retry to connect to the AP
|
||||
I (24377) RPC_WRAP: ESP Event: Station mode: Connected
|
||||
I (24377) esp_wifi_remote: esp_wifi_internal_reg_rxcb: sta: 0x400477f6
|
||||
--- 0x400477f6: wifi_sta_receive at /home/kysoh/esp/gitlab_esp-idf/components/esp_wifi/src/wifi_netif.c:38
|
||||
I (25387) esp_netif_handlers: sta ip: 192.168.50.217, mask: 255.255.255.0, gw: 192.168.50.1
|
||||
I (25387) wifi station: got ip:192.168.50.217
|
||||
I (25387) wifi station: connected to ap SSID:xxx password:yyy
|
||||
I (26577) hosted_events: *** Heartbeat 1***
|
||||
```
|
||||
|
||||
### Example Output using SPI-FD interface
|
||||
|
||||
```
|
||||
I (5323) esp_netif_handlers: sta ip: 192.168.50.82, mask: 255.255.255.0, gw: 192.168.50.1
|
||||
I (5323) wifi station: got ip:192.168.50.82
|
||||
I (5323) wifi station: connected to ap SSID:xxx password:yyy
|
||||
I (6383) hosted_events: *** Heartbeat 0***
|
||||
I (11383) hosted_events: *** Heartbeat 1***
|
||||
I (16383) hosted_events: *** Heartbeat 2***
|
||||
I (18523) spi: rx packet ignored: len [65535], rcvd_offset[65535], exp_offset[12]
|
||||
|
||||
I (19173) transport: Received INIT event from ESP32 peripheral
|
||||
I (19173) transport: EVENT: 12
|
||||
I (19173) transport: Identified slave [esp32c6]
|
||||
I (19173) transport: EVENT: 11
|
||||
I (19183) transport: capabilities: 0xe8
|
||||
I (19183) transport: Features supported are:
|
||||
I (19183) transport: - HCI over SPI
|
||||
I (19193) transport: - BLE only
|
||||
I (19193) transport: EVENT: 13
|
||||
I (19193) transport: ESP board type is : 13
|
||||
|
||||
I (19203) transport: Base transport is set-up, TRANSPORT_TX_ACTIVE
|
||||
I (19203) H_API: Transport active
|
||||
I (19213) transport: Slave chip Id[12]
|
||||
I (19213) transport: raw_tp_dir[-], flow_ctrl: low[60] high[90]
|
||||
I (19223) transport: transport_delayed_init
|
||||
I (19223) esp_cli: Remove any existing deep_sleep cmd in cli
|
||||
I (19233) esp_cli: Registering command: crash
|
||||
I (19233) esp_cli: Registering command: reboot
|
||||
I (19233) esp_cli: Registering command: mem-dump
|
||||
I (19243) esp_cli: Registering command: task-dump
|
||||
I (19243) esp_cli: Registering command: cpu-dump
|
||||
I (19253) esp_cli: Registering command: heap-trace
|
||||
I (19253) esp_cli: Registering command: sock-dump
|
||||
I (19263) esp_cli: Registering command: host-power-save
|
||||
I (19263) hci_stub_drv: Host BT Support: Disabled
|
||||
I (19263) spi: Received INIT event
|
||||
I (19273) hosted_events: *** got INIT event from co-processor ***
|
||||
I (19273) hosted_events: *** Co-processor Reset Reason 1***
|
||||
W (19283) hosted_events: *** Unexpected INIT event
|
||||
I (19323) hosted_events: heartbeat timeout, transport failure or got INIT event: reinit Hosted
|
||||
I (19323) wifi station: do not reconnect
|
||||
I (19523) H_API: ESP-Hosted deinit
|
||||
|
||||
I (19523) serial_ll: Clean-up serial queue
|
||||
I (19523) spi: Deinitializing SPI bus
|
||||
I (19523) spi_wrapper: SPI deinitialized
|
||||
I (19523) spi: SPI bus deinitialized
|
||||
I (19523) transport: TRANSPORT_INACTIVE
|
||||
I (19523) hosted_events: restarting ESP-Hosted
|
||||
I (19533) hosted_events: init ESP-Hosted
|
||||
I (19533) H_API: ESP-Hosted starting. Hosted_Tasks: prio:23, stack: 5120 RPC_task_stack: 5120
|
||||
W (19543) H_API: Transport already initialized, skipping initialization
|
||||
I (19553) H_API: ** add_esp_wifi_remote_channels **
|
||||
I (19553) spi_wrapper: Transport: SPI, Mode:3 Freq:40MHz TxQ:20 RxQ:20
|
||||
GPIOs: CLK:18 MOSI:14 MISO:15 CS:19 HS:16 DR:17 SlaveReset:54
|
||||
I (19563) spi: Staring SPI task
|
||||
I (19573) os_wrapper_esp: GPIO [16] configuring as Interrupt
|
||||
I (19573) os_wrapper_esp: GPIO [17] configuring as Interrupt
|
||||
I (19583) H_API: ESP-Hosted Try to communicate with ESP-Hosted slave
|
||||
|
||||
I (19583) transport: Attempt connection with slave: retry[0]
|
||||
I (19593) spi: Resetting slave
|
||||
I (19593) spi: Resetting slave on SPI bus with pin 54
|
||||
I (19603) os_wrapper_esp: GPIO [54] configured
|
||||
I (20123) transport: Waiting for esp_hosted slave to be ready
|
||||
I (20183) transport: Received INIT event from ESP32 peripheral
|
||||
I (20183) transport: EVENT: 12
|
||||
I (20183) transport: Identified slave [esp32c6]
|
||||
I (20183) transport: EVENT: 11
|
||||
I (20183) transport: capabilities: 0xe8
|
||||
I (20183) transport: Features supported are:
|
||||
I (20193) transport: - HCI over SPI
|
||||
I (20193) transport: - BLE only
|
||||
I (20193) transport: EVENT: 13
|
||||
I (20203) transport: ESP board type is : 13
|
||||
|
||||
I (20203) transport: Base transport is set-up, TRANSPORT_TX_ACTIVE
|
||||
I (20213) H_API: Transport active
|
||||
I (20213) transport: Slave chip Id[12]
|
||||
I (20213) transport: raw_tp_dir[-], flow_ctrl: low[60] high[90]
|
||||
I (20223) transport: transport_delayed_init
|
||||
I (20223) esp_cli: Remove any existing deep_sleep cmd in cli
|
||||
I (20233) esp_cli: Registering command: crash
|
||||
I (20233) esp_cli: Registering command: reboot
|
||||
I (20243) esp_cli: Registering command: mem-dump
|
||||
I (20243) esp_cli: Registering command: task-dump
|
||||
I (20253) esp_cli: Registering command: cpu-dump
|
||||
I (20253) esp_cli: Registering command: heap-trace
|
||||
I (20253) esp_cli: Registering command: sock-dump
|
||||
I (20263) esp_cli: Registering command: host-power-save
|
||||
I (20263) hci_stub_drv: Host BT Support: Disabled
|
||||
I (20273) spi: Received INIT event
|
||||
I (20323) hosted_events: getting fw version
|
||||
I (20583) hosted_events: *** got INIT event from co-processor ***
|
||||
I (20583) hosted_events: *** Co-processor Reset Reason 1***
|
||||
I (20583) hosted_events: Expected INIT event
|
||||
I (20583) hosted_events: FW Version: 2.7.4
|
||||
I (20593) transport: Attempt connection with slave: retry[0]
|
||||
I (20593) transport: Transport is already up
|
||||
I (20893) wifi station: wifi_init_sta finished.
|
||||
I (20893) RPC_WRAP: ESP Event: wifi station started
|
||||
I (20903) RPC_WRAP: ESP Event: wifi station started
|
||||
I (23343) RPC_WRAP: ESP Event: Station mode: Disconnected
|
||||
I (23343) H_API: esp_wifi_remote_connect
|
||||
I (23373) wifi station: retry to connect to the AP
|
||||
I (25593) hosted_events: *** Heartbeat 0***
|
||||
I (25783) RPC_WRAP: ESP Event: Station mode: Disconnected
|
||||
I (25783) H_API: esp_wifi_remote_connect
|
||||
I (25793) wifi station: retry to connect to the AP
|
||||
I (28403) RPC_WRAP: ESP Event: Station mode: Connected
|
||||
I (28403) esp_wifi_remote: esp_wifi_internal_reg_rxcb: sta: 0x400408f2
|
||||
--- 0x400408f2: wifi_sta_receive at /home/kysoh/esp/gitlab_esp-idf/components/esp_wifi/src/wifi_netif.c:38
|
||||
I (29423) esp_netif_handlers: sta ip: 192.168.50.82, mask: 255.255.255.0, gw: 192.168.50.1
|
||||
I (29423) wifi station: got ip:192.168.50.82
|
||||
I (29423) wifi station: connected to ap SSID:xxx password:yyy
|
||||
I (30593) hosted_events: *** Heartbeat 1***
|
||||
I (32213) spi: rx packet ignored: len [65535], rcvd_offset[65535], exp_offset[12]
|
||||
```
|
||||
@@ -0,0 +1,4 @@
|
||||
set(srcs "main.c" "station_example.c")
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,110 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config EXAMPLE_HEARTBEAT_INTERVAL_SEC
|
||||
int "Heartbeat Interval in Seconds"
|
||||
default 5
|
||||
help
|
||||
Set the co-processor heartbeat interval
|
||||
|
||||
config EXAMPLE_ENABLE_HEARTBEAT_MONITOR
|
||||
bool "Enable heartbeat timeout monitor"
|
||||
default y
|
||||
help
|
||||
Detect if there is a Heartbeat timeout
|
||||
|
||||
config EXAMPLE_HEARTBEAT_TIMEOUT_SEC
|
||||
depends on EXAMPLE_ENABLE_HEARTBEAT_MONITOR
|
||||
int "Heartbeat Timeout in Seconds"
|
||||
default 6
|
||||
help
|
||||
Set the co-processor heartbeat timeout interval (minimum value should be the Heartbeat interval)
|
||||
|
||||
choice EXAMPLE_HOSTED_RECOVERY_METHOD
|
||||
bool "Co-processor Recovery method"
|
||||
default EXAMPLE_DO_HOSTED_RECOVERY
|
||||
help
|
||||
Select the recovery method to use
|
||||
|
||||
config EXAMPLE_DO_HOSTED_RECOVERY
|
||||
bool "Restart ESP-Hosted transport"
|
||||
help
|
||||
Restart the ESP-Hosted transport to attempt recovery
|
||||
|
||||
config EXAMPLE_DO_HOST_RESET
|
||||
bool "Restart the Host"
|
||||
help
|
||||
Restart the Host to recover the system
|
||||
|
||||
config EXAMPLE_DO_NOTHING
|
||||
bool "Do nothing"
|
||||
help
|
||||
Don't do anything when error is received
|
||||
endchoice
|
||||
|
||||
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
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025-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_deinit_sta(void);
|
||||
void example_wifi_sta_netif_close(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,332 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025-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"
|
||||
|
||||
#define HEARTBEAT_INTERVAL_SEC CONFIG_EXAMPLE_HEARTBEAT_INTERVAL_SEC
|
||||
#define ENABLE_HEARTBEAT_MONITOR CONFIG_EXAMPLE_ENABLE_HEARTBEAT_MONITOR
|
||||
#define DO_HOSTED_RECOVERY CONFIG_EXAMPLE_DO_HOSTED_RECOVERY
|
||||
#define DO_HOST_RESET CONFIG_EXAMPLE_DO_HOST_RESET
|
||||
#define DO_NOTHING CONFIG_EXAMPLE_DO_NOTHING
|
||||
|
||||
#if ENABLE_HEARTBEAT_MONITOR
|
||||
#define HEARTBEAT_TIMEOUT_SEC CONFIG_EXAMPLE_HEARTBEAT_TIMEOUT_SEC
|
||||
#define HEARTBEAT_TIMEOUT_NSEC (HEARTBEAT_TIMEOUT_SEC * 1000 * 1000)
|
||||
|
||||
static esp_timer_handle_t heartbeat_timer_handle = NULL;
|
||||
#endif
|
||||
|
||||
#define ESP_HOSTED_RESET_BIT BIT0
|
||||
static EventGroupHandle_t s_esp_hosted_event_group;
|
||||
|
||||
static bool resetting_esp_hosted_transport = false;
|
||||
static bool first_init_event = false;
|
||||
static bool first_heartbeat = false;
|
||||
static uint32_t prev_heartbeat = 0;
|
||||
static SemaphoreHandle_t sem_hosted_is_up;
|
||||
|
||||
static const char* TAG = "hosted_events";
|
||||
|
||||
#if ENABLE_HEARTBEAT_MONITOR
|
||||
void my_timer_cb(void *arg)
|
||||
{
|
||||
ESP_LOGI(TAG, "*** TIMER: HEARTBEAT timeout ***");
|
||||
|
||||
if (!resetting_esp_hosted_transport) {
|
||||
xEventGroupSetBits(s_esp_hosted_event_group, ESP_HOSTED_RESET_BIT);
|
||||
}
|
||||
|
||||
// destroy the timer
|
||||
esp_timer_delete(heartbeat_timer_handle);
|
||||
heartbeat_timer_handle = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void init_cp_error_detection(void)
|
||||
{
|
||||
first_init_event = false;
|
||||
|
||||
first_heartbeat = false;
|
||||
prev_heartbeat = 0;
|
||||
}
|
||||
|
||||
static void deinit_cp_error_detection(void)
|
||||
{
|
||||
// currently does nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_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);
|
||||
if (!first_init_event) {
|
||||
// this is the first init event and is expected
|
||||
first_init_event = true;
|
||||
ESP_LOGI(TAG, "Expected INIT event");
|
||||
} else if (!resetting_esp_hosted_transport) {
|
||||
// unexpected init event
|
||||
xEventGroupSetBits(s_esp_hosted_event_group, ESP_HOSTED_RESET_BIT);
|
||||
ESP_LOGI(TAG, "*** Unexpected INIT event");
|
||||
}
|
||||
} 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) {
|
||||
if (!resetting_esp_hosted_transport) {
|
||||
xEventGroupSetBits(s_esp_hosted_event_group, ESP_HOSTED_RESET_BIT);
|
||||
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);
|
||||
uint32_t curr_heartbeat = event->heartbeat;
|
||||
#if ENABLE_HEARTBEAT_MONITOR
|
||||
if (heartbeat_timer_handle) {
|
||||
if (esp_timer_is_active(heartbeat_timer_handle)) {
|
||||
// restart the timer
|
||||
if (ESP_OK != esp_timer_restart(heartbeat_timer_handle, HEARTBEAT_TIMEOUT_NSEC)) {
|
||||
ESP_LOGE(TAG, "Failed to restart the timer");
|
||||
}
|
||||
} else {
|
||||
// start the timer
|
||||
if (ESP_OK != esp_timer_start_once(heartbeat_timer_handle, HEARTBEAT_TIMEOUT_NSEC)) {
|
||||
ESP_LOGE(TAG, "Failed to start the timer");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!first_heartbeat) {
|
||||
first_heartbeat = true;
|
||||
} else if (curr_heartbeat != (prev_heartbeat + 1)) {
|
||||
ESP_LOGW(TAG, "heartbeat: expected %"PRIu32", but got %"PRIu32, prev_heartbeat + 1, curr_heartbeat);
|
||||
}
|
||||
prev_heartbeat = curr_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));
|
||||
|
||||
// set up event group, used to signal that ESP-Hosted transport has gone down
|
||||
s_esp_hosted_event_group = xEventGroupCreate();
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
#if DO_HOSTED_RECOVERY
|
||||
static void app_esp_hosted_deinit(void)
|
||||
{
|
||||
esp_hosted_deinit();
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool app_esp_hosted_verify_up(void)
|
||||
{
|
||||
// to verify ESP-Hosted is UP, we get the co-processor fw info
|
||||
ESP_LOGI(TAG, "getting fw version");
|
||||
esp_hosted_coprocessor_fwver_t fwver;
|
||||
if (ESP_OK == esp_hosted_get_coprocessor_fwversion(&fwver)) {
|
||||
ESP_LOGI(TAG, "FW Version: %" PRIu32 ".%" PRIu32 ".%" PRIu32,
|
||||
fwver.major1, fwver.minor1, fwver.patch1);
|
||||
return true;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "failed to get fw version");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_HEARTBEAT_MONITOR
|
||||
static esp_err_t app_setup_heartbeat_monitor(void)
|
||||
{
|
||||
esp_err_t res;
|
||||
|
||||
if (!heartbeat_timer_handle) {
|
||||
// create heartbeat timer
|
||||
esp_timer_create_args_t my_timer = {
|
||||
.callback = my_timer_cb,
|
||||
.arg = NULL,
|
||||
.dispatch_method = ESP_TIMER_TASK,
|
||||
.name = "Heartbeat Timer",
|
||||
.skip_unhandled_events = true,
|
||||
};
|
||||
res = esp_timer_create(&my_timer, &heartbeat_timer_handle);
|
||||
if (res == ESP_OK) {
|
||||
// start the timer
|
||||
res = esp_timer_start_once(heartbeat_timer_handle, HEARTBEAT_TIMEOUT_NSEC);
|
||||
if (res == ESP_OK) {
|
||||
ESP_LOGI(TAG, "heartbeat timer started");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "failed to start heartbeat timer");
|
||||
return res;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "failed to create heartbeat timer");
|
||||
heartbeat_timer_handle = NULL;
|
||||
return res;
|
||||
}
|
||||
} else {
|
||||
// heartbeat timer already created: restart it
|
||||
if (esp_timer_is_active(heartbeat_timer_handle)) {
|
||||
// restart the timer
|
||||
res = esp_timer_restart(heartbeat_timer_handle, HEARTBEAT_TIMEOUT_NSEC);
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to restart the timer");
|
||||
return res;
|
||||
}
|
||||
} else {
|
||||
// start the timer
|
||||
res = esp_timer_start_once(heartbeat_timer_handle, HEARTBEAT_TIMEOUT_NSEC);
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to start the timer");
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* this function handles what to do when a co-processor error is encountered
|
||||
*
|
||||
* here, we either try to recover from the error, or reset the host
|
||||
*/
|
||||
static bool app_do_cp_recovery(void)
|
||||
{
|
||||
#if DO_HOSTED_RECOVERY
|
||||
example_wifi_sta_netif_close(); // inform netif for sta that connection was lost
|
||||
example_wifi_deinit_sta(); // deinit the station
|
||||
app_esp_hosted_deinit();
|
||||
return true;
|
||||
#elif DO_HOST_RESET
|
||||
ESP_LOGI(TAG, "********* Restarting host to avoid sync issues **********************");
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
esp_restart();
|
||||
return true;
|
||||
#elif DO_NOTHING
|
||||
ESP_LOGI(TAG, "Nothing done to recover");
|
||||
return false;
|
||||
#else
|
||||
#error No co-processor recovery method selected
|
||||
#endif
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
app_init_once(); // one time app init
|
||||
example_wifi_init_once(); // one time wifi init
|
||||
|
||||
while (true) {
|
||||
init_cp_error_detection();
|
||||
|
||||
ESP_LOGI(TAG, "init ESP-Hosted");
|
||||
app_esp_hosted_init();
|
||||
|
||||
// wait until ESP-Hosted is up before continuing
|
||||
xSemaphoreTake(sem_hosted_is_up, portMAX_DELAY);
|
||||
ESP_LOGI(TAG, "ESP-Hosted is ready");
|
||||
|
||||
bool esp_hosted_is_okay = app_esp_hosted_verify_up();
|
||||
|
||||
if (esp_hosted_is_okay) {
|
||||
// configure heartbeat
|
||||
if (ESP_OK != esp_hosted_configure_heartbeat(true, HEARTBEAT_INTERVAL_SEC)) {
|
||||
ESP_LOGE(TAG, "failed to set heartbeat");
|
||||
}
|
||||
|
||||
#if ENABLE_HEARTBEAT_MONITOR
|
||||
if (ESP_OK != app_setup_heartbeat_monitor()) {
|
||||
ESP_LOGE(TAG, "failed to setup heartbeat monitor");
|
||||
}
|
||||
#endif
|
||||
|
||||
// connect to an AP
|
||||
example_wifi_init_sta();
|
||||
|
||||
// here, you can start a thread to do data transfers with the AP
|
||||
|
||||
// we wait until we encounter an error and need to reset the transport
|
||||
EventBits_t bits = xEventGroupWaitBits(s_esp_hosted_event_group,
|
||||
ESP_HOSTED_RESET_BIT,
|
||||
pdTRUE, // clear on exit
|
||||
pdTRUE, // wait for all bits to be set
|
||||
portMAX_DELAY);
|
||||
if (bits & !ESP_HOSTED_RESET_BIT) {
|
||||
ESP_LOGW(TAG, "*** Unexpected group event event bits ***");
|
||||
return;
|
||||
}
|
||||
|
||||
// here, you should tell the data transfer thread to abort data transfer
|
||||
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to start up ESP-Hosted");
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* should only come here if ESP-Hosted encountered a transport error
|
||||
* or failed to connect
|
||||
*/
|
||||
|
||||
// connection to ESP-Hosted has now failed
|
||||
ESP_LOGI(TAG, "heartbeat timeout, transport failure or unexpected INIT event: reinit Hosted");
|
||||
|
||||
// restart the ESP-Hosted transport
|
||||
resetting_esp_hosted_transport = true;
|
||||
|
||||
bool result = app_do_cp_recovery();
|
||||
|
||||
resetting_esp_hosted_transport = false;
|
||||
|
||||
deinit_cp_error_detection();
|
||||
|
||||
if (!result) {
|
||||
// do cp recovery failed
|
||||
ESP_LOGI(TAG, "Did not recover from co-processor failure. Exiting app");
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "restarting ESP-Hosted");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025-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 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* these events will inform netif to close its current network connection
|
||||
* so it is ready for the next sta connection
|
||||
*/
|
||||
void example_wifi_sta_netif_close(void)
|
||||
{
|
||||
|
||||
// broadcast a wi-fi disconnect event so NETIF is aware that the connection went down
|
||||
do_not_reconnect = true; // we don't try to reconnect
|
||||
wifi_event_sta_disconnected_t event = { 0 };
|
||||
event.reason = WIFI_REASON_CONNECTION_FAIL;
|
||||
esp_event_post(WIFI_EVENT,
|
||||
WIFI_EVENT_STA_DISCONNECTED,
|
||||
&event,
|
||||
sizeof(wifi_event_sta_disconnected_t),
|
||||
portMAX_DELAY);
|
||||
// sleep for a while to give NETIF time to react to the event
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
|
||||
// this informs the event handler not to try to reconnect
|
||||
do_not_reconnect = false;
|
||||
|
||||
// broadcast a wi-fi stop event so NETIF is aware the station has stopped
|
||||
esp_event_post(WIFI_EVENT,
|
||||
WIFI_EVENT_STA_STOP,
|
||||
NULL,
|
||||
0,
|
||||
portMAX_DELAY);
|
||||
// sleep for a while to give NETIF time to react to the event
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
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);
|
||||
} 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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
### Disable transport option to restart on failure, so application will handle transport failures
|
||||
CONFIG_ESP_HOSTED_TRANSPORT_RESTART_ON_FAILURE=n
|
||||
Reference in New Issue
Block a user