From ebe7d997190ff54140fdc544c1e013b2e251c501 Mon Sep 17 00:00:00 2001 From: Chen Chen Date: Wed, 25 Feb 2026 11:55:29 +0800 Subject: [PATCH] fix(i2c_slave): filter out fake request for esp32 Closes https://github.com/espressif/esp-idf/issues/18268 --- components/esp_driver_i2c/i2c_slave_v2.c | 2 +- components/hal/esp32/include/hal/i2c_ll.h | 14 +++++++++++++- docs/en/api-reference/peripherals/i2c.rst | 6 ++++++ docs/zh_CN/api-reference/peripherals/i2c.rst | 6 ++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/components/esp_driver_i2c/i2c_slave_v2.c b/components/esp_driver_i2c/i2c_slave_v2.c index 017a2454d7a..baccf2b7dcf 100644 --- a/components/esp_driver_i2c/i2c_slave_v2.c +++ b/components/esp_driver_i2c/i2c_slave_v2.c @@ -183,7 +183,7 @@ IRAM_ATTR static void i2c_slave_isr_handler(void *arg) if (slave_rw == I2C_SLAVE_READ_BY_MASTER) { #if !SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE i2c_slave_request_event_data_t evt_data = {}; - if (i2c_slave->request_callback) { + if (i2c_slave->request_callback && i2c_ll_slave_wait_ack(hal->dev)) { pxHigherPriorityTaskWoken |= i2c_slave->request_callback(i2c_slave, &evt_data, i2c_slave->user_ctx); } #endif diff --git a/components/hal/esp32/include/hal/i2c_ll.h b/components/hal/esp32/include/hal/i2c_ll.h index de9bb8be5c0..7bac2a14798 100644 --- a/components/hal/esp32/include/hal/i2c_ll.h +++ b/components/hal/esp32/include/hal/i2c_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -875,6 +875,18 @@ static inline i2c_slave_read_write_status_t i2c_ll_slave_get_read_write_status(i return (hw->status_reg.slave_rw == 0) ? I2C_SLAVE_WRITE_BY_MASTER : I2C_SLAVE_READ_BY_MASTER; } +/** + * @brief Check whether the slave is waiting for ACK + * + * @param hw Beginning address of the peripheral registers + * @return true if this slave is waiting for ACK, false otherwise + */ +__attribute__((always_inline)) +static inline bool i2c_ll_slave_wait_ack(i2c_dev_t *hw) +{ + return hw->status_reg.scl_main_state_last == 6; +} + //////////////////////////////////////////Deprecated Functions////////////////////////////////////////////////////////// /////////////////////////////The following functions are only used by the legacy driver///////////////////////////////// /////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)////////////////////////////// diff --git a/docs/en/api-reference/peripherals/i2c.rst b/docs/en/api-reference/peripherals/i2c.rst index 1f91e93dc67..d287cc4697c 100644 --- a/docs/en/api-reference/peripherals/i2c.rst +++ b/docs/en/api-reference/peripherals/i2c.rst @@ -45,6 +45,12 @@ Typically, an I2C slave device has a 7-bit address or 10-bit address. {IDF_TARGE We realized that our first version of the I2C slave driver had some problems and was not easy to use, so we have prepared a second version of the I2C slave driver, which solves many of the problems with our current I2C slave and which will be the focus of our maintenance. We encourage and recommend that you use the second version of the I2C slave driver, which you can do by enabling :ref:`CONFIG_I2C_ENABLE_SLAVE_DRIVER_VERSION_2`. This document focuses on the content of I2C slave v2.0. If you still want to read programming guide of I2C slave v1.0, please refer to :ref:`i2c-slave-v1`. The I2C slave v1.0 driver will be removed with the IDF v6.0 update. +.. only:: esp32 + + .. note:: + + The ESP32 I2C controller does not support clock stretching when operating as a slave. Therefore, in addition to driver configuration, the application layer should pay attention to speed matching and synchronization between master and slave devices: if the master processes too fast while the slave responds slowly, communication errors or data loss may occur. It is recommended to use application-layer data verification, GPIO signal synchronization, or other methods to achieve data synchronization between master and slave. Please confirm whether the ESP32 slave mode meets your project requirements according to your use case before use. + I2C Clock Configuration ----------------------- diff --git a/docs/zh_CN/api-reference/peripherals/i2c.rst b/docs/zh_CN/api-reference/peripherals/i2c.rst index d1a29f8e324..564faf19ec2 100644 --- a/docs/zh_CN/api-reference/peripherals/i2c.rst +++ b/docs/zh_CN/api-reference/peripherals/i2c.rst @@ -45,6 +45,12 @@ I2C 是一种串行同步半双工通信协议,总线上可以同时挂载多 我们发现 :ref:`i2c-slave-v1` 存在一些问题,且使用体验不够友好。为此,我们推出了 I2C 从机驱动 v2.0,此版本不仅解决了现有问题,还将成为我们未来的主要维护版本。我们建议并鼓励你使用 I2C 从机驱动 v2.0,你可以通过配置选项 :ref:`CONFIG_I2C_ENABLE_SLAVE_DRIVER_VERSION_2` 启用该功能。本文档主要介绍 I2C 从机驱动 v2.0 的功能。如果你想使用 I2C 从机驱动 v1.0,请参考 :ref:`i2c-slave-v1`。I2C 从机驱动 v1.0 将在 ESP-IDF v6.0 中移除。 +.. only:: esp32 + + .. note:: + + ESP32 的 I2C 控制器作为从机时不支持时钟拉伸(clock stretching)。因此除驱动配置外,应用层还需关注主从设备之间的速度匹配与同步:若主机处理速度过快、从机处理较慢,可能导致通信异常或数据丢失。建议使用应用层数据校验、gpio 信号同步等方式实现主从之间数据同步。使用前请根据使用场景确认 ESP32 的从机模式是否满足您的项目需求。 + I2C 时钟配置 ------------