Merge branch 'feature/s31_lp_i2c' into 'master'

feat(ulp): support I2C on ULP for S31

Closes IDF-14635

See merge request espressif/esp-idf!48405
This commit is contained in:
Marius Vikhammer
2026-05-13 08:31:29 +08:00
7 changed files with 34 additions and 18 deletions
@@ -325,6 +325,12 @@ static inline void i2c_ll_get_intr_mask(i2c_dev_t *hw, uint32_t *intr_status)
*intr_status = hw->int_status.val; *intr_status = hw->int_status.val;
} }
__attribute__((always_inline))
static inline void i2c_ll_get_intr_raw_mask(i2c_dev_t *hw, uint32_t *intr_status)
{
*intr_status = hw->int_raw.val;
}
/** /**
* @brief Configure I2C memory access mode, FIFO mode or non-FIFO mode * @brief Configure I2C memory access mode, FIFO mode or non-FIFO mode
* *
@@ -1219,6 +1219,10 @@ config SOC_LP_CORE_CONFIGURABLE_BOOT_ADDR
bool bool
default y default y
config SOC_LP_CORE_SUPPORT_I2C
bool
default y
config SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE config SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE
bool bool
default y default y
@@ -483,7 +483,7 @@
#define SOC_LP_MAILBOX_SUPPORTED (1) /*!< LP Core supports LP-mailbox */ #define SOC_LP_MAILBOX_SUPPORTED (1) /*!< LP Core supports LP-mailbox */
#define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM wakeup */ #define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM wakeup */
#define SOC_LP_CORE_CONFIGURABLE_BOOT_ADDR (1) /*!< LP Core has no LP ROM; HP must write the reset_vector address (LP_RAM_BASE+0x80) to LP_SYS.lp_core_boot_addr before triggering LP wake */ #define SOC_LP_CORE_CONFIGURABLE_BOOT_ADDR (1) /*!< LP Core has no LP ROM; HP must write the reset_vector address (LP_RAM_BASE+0x80) to LP_SYS.lp_core_boot_addr before triggering LP wake */
//#define SOC_LP_CORE_SUPPORT_I2C (1) /*!< LP Core supports I2C */ TODO IDF-14635 #define SOC_LP_CORE_SUPPORT_I2C (1) /*!< LP Core supports I2C */
#define SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE (1) /*!< LP core requests sleep, PMU clears both HP and LP wakeup causes */ #define SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE (1) /*!< LP core requests sleep, PMU clears both HP and LP wakeup causes */
#define SOC_LP_CORE_HAS_PMP (1) /*!< LP Core RISC-V has 16 PMP entries (128-byte granularity, RISC-V v1.10) */ #define SOC_LP_CORE_HAS_PMP (1) /*!< LP Core RISC-V has 16 PMP entries (128-byte granularity, RISC-V v1.10) */
@@ -54,6 +54,9 @@ typedef struct {
#elif CONFIG_IDF_TARGET_ESP32C6 #elif CONFIG_IDF_TARGET_ESP32C6
#define LP_I2C_SCL_IO GPIO_NUM_7 #define LP_I2C_SCL_IO GPIO_NUM_7
#define LP_I2C_SDA_IO GPIO_NUM_6 #define LP_I2C_SDA_IO GPIO_NUM_6
#elif CONFIG_IDF_TARGET_ESP32S31
#define LP_I2C_SCL_IO GPIO_NUM_7
#define LP_I2C_SDA_IO GPIO_NUM_6
#else #else
#error "Default LP core I2C pin not set for this chip" #error "Default LP core I2C pin not set for this chip"
#endif #endif
+9 -10
View File
@@ -9,7 +9,6 @@
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "ulp_lp_core_i2c.h" #include "ulp_lp_core_i2c.h"
#include "ulp_lp_core_utils.h" #include "ulp_lp_core_utils.h"
#include "soc/lp_i2c_reg.h"
#include "soc/i2c_struct.h" #include "soc/i2c_struct.h"
#include "hal/i2c_ll.h" #include "hal/i2c_ll.h"
@@ -73,13 +72,13 @@ static inline esp_err_t lp_core_i2c_wait_for_interrupt(uint32_t intr_mask, int32
while (1) { while (1) {
i2c_ll_get_intr_raw_mask(dev, &intr_status); i2c_ll_get_intr_raw_mask(dev, &intr_status);
if (intr_status & intr_mask) { if (intr_status & intr_mask) {
if (intr_status & LP_I2C_NACK_INT_ST) { if (intr_status & I2C_LL_INTR_NACK) {
/* The ACK/NACK received during a WRITE operation does not match the expected ACK/NACK level /* The ACK/NACK received during a WRITE operation does not match the expected ACK/NACK level
* Abort and return an error. * Abort and return an error.
*/ */
i2c_ll_clear_intr_mask(dev, intr_mask); i2c_ll_clear_intr_mask(dev, intr_mask);
return ESP_ERR_INVALID_RESPONSE; return ESP_ERR_INVALID_RESPONSE;
} else if (intr_status & LP_I2C_TRANS_COMPLETE_INT_ST_M) { } else if (intr_status & I2C_LL_INTR_MST_COMPLETE) {
/* Transaction complete. /* Transaction complete.
* Clear interrupt bits and break * Clear interrupt bits and break
*/ */
@@ -158,7 +157,7 @@ esp_err_t lp_core_i2c_master_read_from_device(i2c_port_t lp_i2c_num, uint16_t de
lp_core_i2c_config_device_addr(cmd_idx++, device_addr, LP_I2C_READ_MODE, &addr_len); lp_core_i2c_config_device_addr(cmd_idx++, device_addr, LP_I2C_READ_MODE, &addr_len);
/* Enable trans complete interrupt and end detect interrupt for read/write operation */ /* Enable trans complete interrupt and end detect interrupt for read/write operation */
uint32_t intr_mask = (1 << LP_I2C_TRANS_COMPLETE_INT_ST_S) | (1 << LP_I2C_END_DETECT_INT_ST_S); uint32_t intr_mask = I2C_LL_INTR_MST_COMPLETE | I2C_LL_INTR_END_DETECT;
i2c_ll_clear_intr_mask(dev, intr_mask); i2c_ll_clear_intr_mask(dev, intr_mask);
/* Read data */ /* Read data */
@@ -258,10 +257,10 @@ esp_err_t lp_core_i2c_master_write_to_device(i2c_port_t lp_i2c_num, uint16_t dev
lp_core_i2c_config_device_addr(cmd_idx++, device_addr, LP_I2C_WRITE_MODE, &addr_len); lp_core_i2c_config_device_addr(cmd_idx++, device_addr, LP_I2C_WRITE_MODE, &addr_len);
/* Enable trans complete interrupt and end detect interrupt for read/write operation */ /* Enable trans complete interrupt and end detect interrupt for read/write operation */
uint32_t intr_mask = (1 << LP_I2C_TRANS_COMPLETE_INT_ST_S) | (1 << LP_I2C_END_DETECT_INT_ST_S); uint32_t intr_mask = I2C_LL_INTR_MST_COMPLETE | I2C_LL_INTR_END_DETECT;
if (s_ack_check_en) { if (s_ack_check_en) {
/* Enable LP_I2C_NACK_INT to check for ACK errors */ /* Enable NACK interrupt to check for ACK errors */
intr_mask |= (1 << LP_I2C_NACK_INT_ST_S); intr_mask |= I2C_LL_INTR_NACK;
} }
i2c_ll_clear_intr_mask(dev, intr_mask); i2c_ll_clear_intr_mask(dev, intr_mask);
@@ -343,10 +342,10 @@ esp_err_t lp_core_i2c_master_write_read_device(i2c_port_t lp_i2c_num, uint16_t d
i2c_ll_rxfifo_rst(dev); i2c_ll_rxfifo_rst(dev);
/* Enable trans complete interrupt and end detect interrupt for read/write operation */ /* Enable trans complete interrupt and end detect interrupt for read/write operation */
uint32_t intr_mask = (1 << LP_I2C_TRANS_COMPLETE_INT_ST_S) | (1 << LP_I2C_END_DETECT_INT_ST_S); uint32_t intr_mask = I2C_LL_INTR_MST_COMPLETE | I2C_LL_INTR_END_DETECT;
if (s_ack_check_en) { if (s_ack_check_en) {
/* Enable LP_I2C_NACK_INT to check for ACK errors */ /* Enable NACK interrupt to check for ACK errors */
intr_mask |= (1 << LP_I2C_NACK_INT_ST_S); intr_mask |= I2C_LL_INTR_NACK;
} }
i2c_ll_clear_intr_mask(dev, intr_mask); i2c_ll_clear_intr_mask(dev, intr_mask);
+2
View File
@@ -13,12 +13,14 @@ INPUT += \
$(PROJECT_PATH)/components/esp_phy/include/esp_phy_cert_test.h \ $(PROJECT_PATH)/components/esp_phy/include/esp_phy_cert_test.h \
$(PROJECT_PATH)/components/bt/include/esp32s31/include/esp_bt.h \ $(PROJECT_PATH)/components/bt/include/esp32s31/include/esp_bt.h \
$(PROJECT_PATH)/components/bt/include/esp32s31/include/esp_bt_vs.h \ $(PROJECT_PATH)/components/bt/include/esp32s31/include/esp_bt_vs.h \
$(PROJECT_PATH)/components/ulp/lp_core/include/lp_core_i2c.h \
$(PROJECT_PATH)/components/ulp/lp_core/include/lp_core_etm.h \ $(PROJECT_PATH)/components/ulp/lp_core/include/lp_core_etm.h \
$(PROJECT_PATH)/components/ulp/lp_core/include/lp_core_uart.h \ $(PROJECT_PATH)/components/ulp/lp_core/include/lp_core_uart.h \
$(PROJECT_PATH)/components/ulp/lp_core/include/lp_core_spi.h \ $(PROJECT_PATH)/components/ulp/lp_core/include/lp_core_spi.h \
$(PROJECT_PATH)/components/ulp/lp_core/include/ulp_lp_core.h \ $(PROJECT_PATH)/components/ulp/lp_core/include/ulp_lp_core.h \
$(PROJECT_PATH)/components/ulp/lp_core/shared/include/ulp_lp_core_lp_uart_shared.h \ $(PROJECT_PATH)/components/ulp/lp_core/shared/include/ulp_lp_core_lp_uart_shared.h \
$(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_gpio.h \ $(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_gpio.h \
$(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_i2c.h \
$(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_print.h \ $(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_print.h \
$(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_uart.h \ $(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_uart.h \
$(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_utils.h \ $(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_utils.h \
+6 -4
View File
@@ -1,5 +1,5 @@
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 | | Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 | ESP32-S31 |
| ----------------- | -------- | -------- | -------- | | ----------------- | -------- | -------- | -------- | --------- |
# LP I2C Example # LP I2C Example
@@ -20,9 +20,11 @@ To run this example, you should have an ESP based development board that support
**Note:** The following pin assignments are used by default. **Note:** The following pin assignments are used by default.
| | SDA | SCL | | | SDA | SCL |
| ----------------------- | ------| ------| | ------------------------ | ----- | ----- |
| ESP32-C6 LP I2C Master | GPIO6 | GPIO7 | | ESP32-C6 LP I2C Master | GPIO6 | GPIO7 |
| ESP32-C5 LP I2C Master | GPIO6 | GPIO7 | | ESP32-C5 LP I2C Master | GPIO2 | GPIO3 |
| ESP32-P4 LP I2C Master | GPIO5 | GPIO4 |
| ESP32-S31 LP I2C Master | GPIO6 | GPIO7 |
| BH1750 Sensor | SDA | SCL | | BH1750 Sensor | SDA | SCL |
**Note:** There's no need to add external pull-up resistors for SDA/SCL pin, because the driver enables the internal pull-up resistors. **Note:** There's no need to add external pull-up resistors for SDA/SCL pin, because the driver enables the internal pull-up resistors.