Files
desklock/firmware/components/esp_hosted/host/esp_hosted_misc.h
T
jpmschweitzerandClaude Fable 5 cb5826e02b
Test, Build and Push / test-gateway (push) Successful in 12s
Test, Build and Push / release (push) Skipped
Test, Build and Push / build-gateway (push) Skipped
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>
2026-07-15 09:50:27 +02:00

180 lines
6.4 KiB
C

/*
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __ESP_HOSTED_MISC_H__
#define __ESP_HOSTED_MISC_H__
#include <stdbool.h>
#include "esp_mac.h"
#include "esp_hosted_misc_types.h"
#define ESP_HOSTED_APP_DESC_MAGIC_WORD (0xABCD5432) /*!< The magic word for the esp_hosted_app_desc structure */
/**
* @brief Description about ESP-Hosted application on co-processor.
*
* @note Some fields may be empty if config to enable full app descriptor
* is not enabled on the co-processor
*/
typedef struct {
uint32_t magic_word; /*!< Magic word ESP_HOSTED_APP_DESC_MAGIC_WORD */
uint32_t secure_version; /*!< Secure version */
uint32_t reserv1[2]; /*!< reserv1 */
char version[32]; /*!< Application version */
char project_name[32]; /*!< Project name */
char time[16]; /*!< Compile time */
char date[16]; /*!< Compile date*/
char idf_ver[32]; /*!< Version IDF */
uint8_t app_elf_sha256[32]; /*!< sha256 of elf file */
uint16_t min_efuse_blk_rev_full; /*!< Minimal eFuse block revision supported by image, in format: major * 100 + minor */
uint16_t max_efuse_blk_rev_full; /*!< Maximal eFuse block revision supported by image, in format: major * 100 + minor */
uint8_t mmu_page_size; /*!< MMU page size in log base 2 format */
uint8_t reserv3[3]; /*!< reserv3 */
uint32_t reserv2[18]; /*!< reserv2 */
} esp_hosted_app_desc_t;
/**
* @brief Initialise the BT Controller on the co-processor
*
* @return ESP_OK on success
*/
esp_err_t esp_hosted_bt_controller_init(void);
/**
* @brief Deinitialise the BT Controller on the co-processor
*
* @param mem_release. Also releases memory used by controller. Once released, the BT controller cannot reuse the memory and cannot be initialised
*
* @return ESP_OK on success
*/
esp_err_t esp_hosted_bt_controller_deinit(bool mem_release);
/**
* @brief Enables the BT Controller on the co-processor. Call only after initialising the BT controller.
*
* @return ESP_OK on success
*/
esp_err_t esp_hosted_bt_controller_enable(void);
/**
* @brief Disables the BT Controller on the co-processor. Call before deinitialising the BT controller.
*
* @return ESP_OK on success
*/
esp_err_t esp_hosted_bt_controller_disable(void);
/**
* @brief Set custom MAC address of the interface.
*
* This function allows you to overwrite the MAC addresses of the
* interfaces set by the base MAC address.
*
* @param mac MAC address, length: 6 bytes/8 bytes.
* length: 6 bytes for MAC-48
* 8 bytes for EUI-64(used for ESP_MAC_IEEE802154 type)
* @param mac_len Length of the mac array
* @param type Type of MAC address
*
* @return ESP_OK on success
*/
esp_err_t esp_hosted_iface_mac_addr_set(uint8_t *mac, size_t mac_len, esp_mac_type_t type);
/**
* @brief Read MAC address of the interface.
*
* @param mac base MAC address, length: 6 bytes/8 bytes.
* length: 6 bytes for MAC-48
* 8 bytes for EUI-64(used for IEEE 802.15.4)
* @param mac_len Length of the mac array
* @param type Type of MAC address
*
* @return ESP_OK on success
*/
esp_err_t esp_hosted_iface_mac_addr_get(uint8_t *mac, size_t mac_len, esp_mac_type_t type);
/**
* @brief Return the size of the MAC type in bytes.
*
* @param type Type of MAC address
*
* @return 0 MAC type not found (not supported)
* 6 bytes for MAC-48.
* 8 bytes for EUI-64.
*/
size_t esp_hosted_iface_mac_addr_len_get(esp_mac_type_t type);
/**
* @brief Return the co-processor application descriptor
*
* @param app_desc Pointer to Application Descriptor structure to fill
*
* @return ESP_OK on success
*/
esp_err_t esp_hosted_get_coprocessor_app_desc(esp_hosted_app_desc_t *app_desc);
/**
* @brief Send custom data to co-processor
*
* @param msg_id Message ID (any uint32_t except 0xFFFFFFFF which is reserved)
* @param data Data buffer to send
* @param data_len Length of data buffer
*
* @return ESP_OK on success, ESP_ERR_* on failure
*/
esp_err_t esp_hosted_send_custom_data(uint32_t msg_id_to_send, const uint8_t *data_to_send, size_t data_len_to_send);
/**
* @brief Register callback for custom data reception
*
* @param msg_id_exp Message ID to listen for (any uint32_t except 0xFFFFFFFF)
* @param callback Function called when data with matching msg_id is received (NULL to deregister)
* @param local_context Opaque pointer returned as-is to the callback on every invocation.
* May be NULL. Caller is responsible for ensuring the pointed-to object
* remains valid until the callback is deregistered.
*
* @return ESP_OK on success, ESP_ERR_* on failure
*/
esp_err_t esp_hosted_register_custom_callback(uint32_t msg_id_exp,
void (*callback)(uint32_t msg_id_recvd, const uint8_t *data_recvd, size_t data_len_recvd, void *local_context),
void *local_context);
/**
* @brief Configure the co-processor heartbeat
*
* @param enable Enable or disable co-processor heartbeat
* @param duration_sec Duration between heartbeats (in secs)
*
* @return ESP_OK on success, ESP_ERR_INVALID_ARG if duration is out of range
*
* @note Minimum heartbeat interval is 1 secs, maximum is 24 hours
*/
esp_err_t esp_hosted_configure_heartbeat(bool enable, int duration_sec);
/**
* @brief Configure the co-processor memory monitor
*
* @param config Configures the memory monitor
* @param curr_mem_info Current heap memory info of co-processor after configuration succeeds
*
* @return ESP_OK on success, ESP_ERR_INVALID_ARG if an argument is invalid
*
* @note 1. To do a one-time query:
* - set `enable` to `false` (this will also disable any on-going memory reporting)
* 2. To get periodic reports:
* - set `enable` to `true`
* - set `report_always` to `true`
* - set `interval_sec` to the reporting interval (in secs)
* 3. To get periodic reports only when heap memory falls below a threshold value
* - set `enable` to `true`
* - set `report_always` to `false`
* - set `interval_sec` to the reporting interval (in secs)
* - set required threshold values in `internal_mem` and/or `external_mem`
*/
esp_err_t esp_hosted_set_mem_monitor(esp_hosted_config_mem_monitor_t *config, esp_hosted_curr_mem_info_t *curr_mem_info);
#endif