From 1d1ba47a7ac4edc32a3d6b6b783d853e5263ebc8 Mon Sep 17 00:00:00 2001 From: LiPeng Date: Mon, 23 Jun 2025 15:09:30 +0800 Subject: [PATCH] feat(sdio): add sdio_slave_reset_hw --- .../include/driver/sdio_slave.h | 18 ++++++++++++++---- components/esp_driver_sdio/src/sdio_slave.c | 7 +++++++ .../host_sdmmc/main/test_sdio_sdhost.c | 12 +++++++++++- .../sdio/main/test_sdio_slave.c | 18 ++++++++++++++++-- .../api-reference/peripherals/sdio_slave.rst | 10 ++++++++++ .../api-reference/peripherals/sdio_slave.rst | 10 ++++++++++ 6 files changed, 68 insertions(+), 7 deletions(-) diff --git a/components/esp_driver_sdio/include/driver/sdio_slave.h b/components/esp_driver_sdio/include/driver/sdio_slave.h index 16225507ce..3359c6a9a0 100644 --- a/components/esp_driver_sdio/include/driver/sdio_slave.h +++ b/components/esp_driver_sdio/include/driver/sdio_slave.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -92,10 +92,20 @@ void sdio_slave_stop(void); /** Clear the data still in the driver, as well as reset the PKT_LEN and TOKEN1 counting. * - * @return always return ESP_OK. + * @return + * - ESP_ERR_INVALID_STATE if already started. + * - ESP_OK otherwise. */ esp_err_t sdio_slave_reset(void); +/** Reset sdio hardware, and clear the data still in the driver, as well as reset the PKT_LEN and TOKEN1 counting. + * + * @return + * - ESP_ERR_INVALID_STATE if already started. + * - ESP_OK otherwise. + */ +esp_err_t sdio_slave_reset_hw(void); + /*--------------------------------------------------------------------------- * Receive *--------------------------------------------------------------------------*/ @@ -220,7 +230,7 @@ esp_err_t sdio_slave_transmit(uint8_t* addr, size_t len); /*--------------------------------------------------------------------------- * Host *--------------------------------------------------------------------------*/ -/** Read the spi slave register shared with host. +/** Read the sdio slave register shared with host. * * @param pos register address, 0-27 or 32-63. * @@ -230,7 +240,7 @@ esp_err_t sdio_slave_transmit(uint8_t* addr, size_t len); */ uint8_t sdio_slave_read_reg(int pos); -/** Write the spi slave register shared with host. +/** Write the sdio slave register shared with host. * * @param pos register address, 0-11, 14-15, 18-19, 24-27 and 32-63, other address are reserved. * @param reg the value to write. diff --git a/components/esp_driver_sdio/src/sdio_slave.c b/components/esp_driver_sdio/src/sdio_slave.c index 3767568463..34d13bb396 100644 --- a/components/esp_driver_sdio/src/sdio_slave.c +++ b/components/esp_driver_sdio/src/sdio_slave.c @@ -456,6 +456,13 @@ esp_err_t sdio_slave_reset(void) return err; } +esp_err_t sdio_slave_reset_hw(void) +{ + sdio_slave_hw_deinit(); + sdio_slave_hw_init(&context.config); + return sdio_slave_reset(); +} + void sdio_slave_stop(void) { sdio_slave_hal_set_ioready(context.hal, false); diff --git a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/host_sdmmc/main/test_sdio_sdhost.c b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/host_sdmmc/main/test_sdio_sdhost.c index 673f5ec03f..732ac2940f 100644 --- a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/host_sdmmc/main/test_sdio_sdhost.c +++ b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/host_sdmmc/main/test_sdio_sdhost.c @@ -203,7 +203,7 @@ TEST_CASE("SDIO_SDMMC: test register", "[sdio]") /*--------------------------------------------------------------- SDMMC_SDIO: test reset ---------------------------------------------------------------*/ -TEST_CASE("SDIO_SDMMC: test reset", "[sdio]") +static void test_reset(void) { essl_handle_t handle = NULL; test_sdio_param_t test_param = { @@ -243,6 +243,16 @@ TEST_CASE("SDIO_SDMMC: test reset", "[sdio]") s_master_deinit(); } +TEST_CASE("SDIO_SDMMC: test reset", "[sdio]") +{ + test_reset(); +} + +TEST_CASE("SDIO_SDMMC: test reset hw", "[sdio]") +{ + test_reset(); +} + /*--------------------------------------------------------------- SDMMC_SDIO: test fixed addr ---------------------------------------------------------------*/ diff --git a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/main/test_sdio_slave.c b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/main/test_sdio_slave.c index a5ff22fd7e..59fabaf6b0 100644 --- a/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/main/test_sdio_slave.c +++ b/components/esp_driver_sdio/test_apps/sdio/sdio_common_tests/sdio/main/test_sdio_slave.c @@ -105,14 +105,18 @@ TEST_CASE("SDIO_Slave: test register", "[sdio]") /*--------------------------------------------------------------- SDMMC_SDIO: test reset ---------------------------------------------------------------*/ -TEST_CASE("SDIO_Slave: test reset", "[sdio]") +static void test_reset(bool reset_hw) { s_slave_init(SDIO_SLAVE_SEND_PACKET); TEST_ESP_OK(sdio_slave_start()); ESP_LOGI(TAG, "slave ready"); sdio_slave_stop(); - TEST_ESP_OK(sdio_slave_reset()); + if (!reset_hw) { + TEST_ESP_OK(sdio_slave_reset()); + } else { + TEST_ESP_OK(sdio_slave_reset_hw()); + } TEST_ESP_OK(sdio_slave_start()); //tx @@ -155,6 +159,16 @@ TEST_CASE("SDIO_Slave: test reset", "[sdio]") sdio_slave_deinit(); } +TEST_CASE("SDIO_Slave: test reset", "[sdio]") +{ + test_reset(false); +} + +TEST_CASE("SDIO_Slave: test reset hw", "[sdio]") +{ + test_reset(true); +} + /*--------------------------------------------------------------- SDMMC_SDIO: test fixed addr ---------------------------------------------------------------*/ diff --git a/docs/en/api-reference/peripherals/sdio_slave.rst b/docs/en/api-reference/peripherals/sdio_slave.rst index 75b09571c2..15575985f5 100644 --- a/docs/en/api-reference/peripherals/sdio_slave.rst +++ b/docs/en/api-reference/peripherals/sdio_slave.rst @@ -276,6 +276,16 @@ There are several ways to use the ``arg`` in the queue parameter: For more about this, see :example:`peripherals/sdio`. +Reset SDIO +^^^^^^^^^^^^ + +Calling ``sdio_slave_reset`` can reset PKT_LEN (Packet length accumulator value) and TOKEN1 (Receiving buffers accumulated number) at the SDIO slave driver software level to resynchronize the transmit and receive counts with the host. + +If there is a usage scenario where the ESP chip remains powered on but the HOST is powered off. During the power-off period of the HOST, some unknown signals may be generated on the SDIO signal line, causing the SDIO hardware state machine to be abnormal. The HOST restarts and executes the card identification process, and the ESP will not respond normally. In this case, consider calling ``sdio_slave_reset_hw`` to reset the SDIO hardware. + +.. note:: + + Reset the SDIO hardware. The interrupt enable status and shared register values ​​will be lost. You may need to call ``sdio_slave_set_host_intena`` and ``sdio_slave_write_reg`` to set them. Application Example ------------------- diff --git a/docs/zh_CN/api-reference/peripherals/sdio_slave.rst b/docs/zh_CN/api-reference/peripherals/sdio_slave.rst index fbe7359b9f..ea88f0843b 100644 --- a/docs/zh_CN/api-reference/peripherals/sdio_slave.rst +++ b/docs/zh_CN/api-reference/peripherals/sdio_slave.rst @@ -276,6 +276,16 @@ SDIO 从机驱动程序的相关术语如下: 更多详情,请参阅 :example:`peripherals/sdio`。 +重置 SDIO +^^^^^^^^^^^^ + +调用 ``sdio_slave_reset`` 可以重置 SDIO 从机驱动程序软件层面的 PKT_LEN (从机发送包长度累加值) 和 TOKEN1 (接收 buffer 累计数量), 便于与主机重新同步收发计数。 + +如果存在 ESP 芯片保持上电状态,但 HOST 端会下电的使用场景。HOST 端下电期间, SDIO 信号线上可能会产生一些未知的信号导致 SDIO 硬件状态机异常。HOST 重新启动, 执行卡识别流程, ESP 将不会正常响应。这种情况下,考虑调用 ``sdio_slave_reset_hw``, 重置 SDIO 硬件。 + +.. note:: + + 重置 SDIO 硬件,中断使能状态和共享寄存器的值会丢失,可能需要调用 ``sdio_slave_set_host_intena``、 ``sdio_slave_write_reg`` 设置。 应用示例 --------