mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'change/bu_lp_i2c_c5' into 'master'
change(ulp): bring up lp i2c on esp32c5 Closes IDF-8634 See merge request espressif/esp-idf!32142
This commit is contained in:
commit
4d03f63de0
@ -19,6 +19,8 @@
|
||||
#include "soc/pcr_struct.h"
|
||||
#include "hal/i2c_types.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "soc/lp_clkrst_struct.h"
|
||||
#include "soc/lpperi_struct.h"
|
||||
#include "hal/misc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -69,7 +71,7 @@ typedef enum {
|
||||
} i2c_ll_slave_intr_t;
|
||||
|
||||
// Get the I2C hardware instance
|
||||
#define I2C_LL_GET_HW(i2c_num) (&I2C0)
|
||||
#define I2C_LL_GET_HW(i2c_num) (((i2c_num) == I2C_NUM_0) ? (&I2C0) : (&LP_I2C))
|
||||
#define I2C_LL_MASTER_EVENT_INTR (I2C_NACK_INT_ENA_M|I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M)
|
||||
#define I2C_LL_SLAVE_EVENT_INTR (I2C_TRANS_COMPLETE_INT_ENA_M|I2C_TXFIFO_WM_INT_ENA_M|I2C_RXFIFO_WM_INT_ENA_M | I2C_SLAVE_STRETCH_INT_ENA_M)
|
||||
#define I2C_LL_SLAVE_RX_EVENT_INTR (I2C_TRANS_COMPLETE_INT_ENA_M | I2C_RXFIFO_WM_INT_ENA_M | I2C_SLAVE_STRETCH_INT_ENA_M)
|
||||
@ -77,6 +79,14 @@ typedef enum {
|
||||
#define I2C_LL_RESET_SLV_SCL_PULSE_NUM_DEFAULT (9)
|
||||
#define I2C_LL_SCL_WAIT_US_VAL_DEFAULT (2500) // Approximate value for SCL timeout regs (in us).
|
||||
|
||||
// Record for Pins usage logs
|
||||
|
||||
#define LP_I2C_SCL_PIN_ERR_LOG "SCL pin can only be configured as GPIO#7"
|
||||
#define LP_I2C_SDA_PIN_ERR_LOG "SDA pin can only be configured as GPIO#6"
|
||||
|
||||
#define LP_I2C_SDA_IOMUX_PAD 6
|
||||
#define LP_I2C_SCL_IOMUX_PAD 7
|
||||
|
||||
/**
|
||||
* @brief Calculate I2C bus frequency
|
||||
* Note that the clock accuracy is affected by the external pull-up resistor,
|
||||
@ -752,6 +762,20 @@ static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw, uint32_t slave_pulses)
|
||||
hw->ctr.conf_upgate = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the ACK level that the I2C master must send when the Rx FIFO count has reached the threshold value.
|
||||
* ack_level: 1 (NACK)
|
||||
* ack_level: 0 (ACK)
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_master_rx_full_ack_level(i2c_dev_t *hw, int ack_level)
|
||||
{
|
||||
hw->ctr.rx_full_ack_level = ack_level;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2C source clock
|
||||
*
|
||||
@ -762,10 +786,73 @@ static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw, uint32_t slave_pulses)
|
||||
*/
|
||||
static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_clk)
|
||||
{
|
||||
if (hw == &LP_I2C) {
|
||||
// Do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
// src_clk : (1) for RTC_CLK, (0) for XTAL
|
||||
PCR.i2c[0].i2c_sclk_conf.i2c_sclk_sel = (src_clk == I2C_CLK_SRC_RC_FAST) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set LP I2C source clock
|
||||
*
|
||||
* @param hw Address offset of the LP I2C peripheral registers
|
||||
* @param src_clk Source clock for the LP I2C peripheral
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void lp_i2c_ll_set_source_clk(i2c_dev_t *hw, soc_periph_lp_i2c_clk_src_t src_clk)
|
||||
{
|
||||
(void)hw;
|
||||
// src_clk : (0) for LP_FAST_CLK (RTC Fast), (1) for XTAL_D2_CLK
|
||||
switch (src_clk) {
|
||||
case LP_I2C_SCLK_LP_FAST:
|
||||
LP_CLKRST.lpperi.lp_i2c_clk_sel = 0;
|
||||
break;
|
||||
case LP_I2C_SCLK_XTAL_D2:
|
||||
LP_CLKRST.lpperi.lp_i2c_clk_sel = 1;
|
||||
break;
|
||||
default:
|
||||
// Invalid source clock selected
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/// LP_CLKRST.lpperi is a shared register, so this function must be used in an atomic way
|
||||
#define lp_i2c_ll_set_source_clk(...) (void)__DECLARE_RCC_ATOMIC_ENV; lp_i2c_ll_set_source_clk(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Enable bus clock for the LP I2C module
|
||||
*
|
||||
* @param hw_id LP I2C instance ID
|
||||
* @param enable True to enable, False to disable
|
||||
*/
|
||||
static inline void _lp_i2c_ll_enable_bus_clock(int hw_id, bool enable)
|
||||
{
|
||||
(void)hw_id;
|
||||
LPPERI.clk_en.lp_ext_i2c_ck_en = enable;
|
||||
}
|
||||
|
||||
/// LPPERI.clk_en is a shared register, so this function must be used in an atomic way
|
||||
#define lp_i2c_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _lp_i2c_ll_enable_bus_clock(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Reset LP I2C module
|
||||
*
|
||||
* @param hw_id LP I2C instance ID
|
||||
*/
|
||||
static inline void lp_i2c_ll_reset_register(int hw_id)
|
||||
{
|
||||
(void)hw_id;
|
||||
LPPERI.reset_en.lp_ext_i2c_reset_en = 1;
|
||||
LPPERI.reset_en.lp_ext_i2c_reset_en = 0;
|
||||
}
|
||||
|
||||
/// LPPERI.reset_en is a shared register, so this function must be used in an atomic way
|
||||
#define lp_i2c_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; lp_i2c_ll_reset_register(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Enable I2C peripheral controller clock
|
||||
*
|
||||
@ -774,7 +861,11 @@ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_c
|
||||
*/
|
||||
static inline void i2c_ll_enable_controller_clock(i2c_dev_t *hw, bool en)
|
||||
{
|
||||
(void)hw;
|
||||
if (hw == &LP_I2C) {
|
||||
// Do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
PCR.i2c[0].i2c_sclk_conf.i2c_sclk_en = en;
|
||||
}
|
||||
|
||||
|
@ -10,13 +10,35 @@
|
||||
/*
|
||||
Bunch of constants for every I2C peripheral: GPIO signals, irqs, hw addr of registers etc
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LP_I2C_MUX_FUNC = 0,
|
||||
LP_GPIO_MUX_FUNC = 1,
|
||||
LP_IO_MUX_FUNC_NUM = 2,
|
||||
LP_MUX_FUNC_NOT_USED = 0xFF,
|
||||
} lp_io_mux_func_t;
|
||||
|
||||
static_assert(SOC_I2C_NUM == (SOC_HP_I2C_NUM + SOC_LP_I2C_NUM));
|
||||
|
||||
const i2c_signal_conn_t i2c_periph_signal[SOC_I2C_NUM] = {
|
||||
/* I2C_NUM_0*/
|
||||
{
|
||||
.sda_out_sig = I2CEXT0_SDA_OUT_IDX,
|
||||
.sda_in_sig = I2CEXT0_SDA_IN_IDX,
|
||||
.scl_out_sig = I2CEXT0_SCL_OUT_IDX,
|
||||
.scl_in_sig = I2CEXT0_SCL_IN_IDX,
|
||||
.iomux_func = (uint8_t)LP_MUX_FUNC_NOT_USED,
|
||||
.irq = ETS_I2C_EXT0_INTR_SOURCE,
|
||||
.module = PERIPH_I2C0_MODULE,
|
||||
},
|
||||
/* LP_I2C_NUM_0*/
|
||||
{
|
||||
.sda_out_sig = 0,
|
||||
.sda_in_sig = 0,
|
||||
.scl_out_sig = 0,
|
||||
.scl_in_sig = 0,
|
||||
.iomux_func = (uint8_t)LP_I2C_MUX_FUNC,
|
||||
.irq = ETS_LP_I2C_INTR_SOURCE,
|
||||
.module = PERIPH_LP_I2C0_MODULE,
|
||||
},
|
||||
};
|
||||
|
@ -167,6 +167,10 @@ config SOC_LP_PERIPHERALS_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LP_I2C_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ULP_LP_UART_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
@ -509,7 +513,7 @@ config SOC_DEDIC_PERIPH_ALWAYS_ENABLE
|
||||
|
||||
config SOC_I2C_NUM
|
||||
int
|
||||
default 1
|
||||
default 2
|
||||
|
||||
config SOC_HP_I2C_NUM
|
||||
int
|
||||
@ -559,6 +563,14 @@ config SOC_I2C_SLAVE_SUPPORT_SLAVE_UNMATCH
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LP_I2C_NUM
|
||||
int
|
||||
default 1
|
||||
|
||||
config SOC_LP_I2C_FIFO_LEN
|
||||
int
|
||||
default 16
|
||||
|
||||
config SOC_I2S_NUM
|
||||
int
|
||||
default 1
|
||||
|
@ -340,15 +340,15 @@ typedef enum { // TODO: [ESP32C5] IDF-8694, IDF-8696 (inherit from C6)
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of LP_I2C
|
||||
*/
|
||||
#define SOC_LP_I2C_CLKS {SOC_MOD_CLK_RTC_FAST, SOC_MOD_CLK_XTAL_D2}
|
||||
#define SOC_LP_I2C_CLKS {SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL_D2}
|
||||
|
||||
/**
|
||||
* @brief Type of LP_I2C clock source.
|
||||
*/
|
||||
typedef enum { // TODO: [ESP32C5] IDF-8695 (inherit from C6)
|
||||
LP_I2C_SCLK_LP_FAST = SOC_MOD_CLK_RTC_FAST, /*!< LP_I2C source clock is RTC_FAST */
|
||||
LP_I2C_SCLK_LP_FAST = SOC_MOD_CLK_RC_FAST, /*!< LP_I2C source clock is RC_FAST */
|
||||
LP_I2C_SCLK_XTAL_D2 = SOC_MOD_CLK_XTAL_D2, /*!< LP_I2C source clock is XTAL_D2 */
|
||||
LP_I2C_SCLK_DEFAULT = SOC_MOD_CLK_RTC_FAST, /*!< LP_I2C source clock default choice is RTC_FAST */
|
||||
LP_I2C_SCLK_DEFAULT = SOC_MOD_CLK_RC_FAST, /*!< LP_I2C source clock default choice is RC_FAST */
|
||||
} soc_periph_lp_i2c_clk_src_t;
|
||||
|
||||
/////////////////////////////////////////////////SPI////////////////////////////////////////////////////////////////////
|
||||
|
@ -1103,6 +1103,7 @@ typedef struct {
|
||||
} i2c_dev_t;
|
||||
|
||||
extern i2c_dev_t I2C0;
|
||||
extern i2c_dev_t LP_I2C;
|
||||
|
||||
#ifndef __cplusplus
|
||||
_Static_assert(sizeof(i2c_dev_t) == 0x200, "Invalid size of i2c_dev_t structure");
|
||||
|
@ -63,7 +63,7 @@
|
||||
#define SOC_LP_TIMER_SUPPORTED 1
|
||||
// #define SOC_LP_AON_SUPPORTED 1 // TODO: [ESP32C5] IDF-8638
|
||||
#define SOC_LP_PERIPHERALS_SUPPORTED 1
|
||||
// #define SOC_LP_I2C_SUPPORTED 1 // TODO: [ESP32C5] IDF-8634
|
||||
#define SOC_LP_I2C_SUPPORTED 1
|
||||
#define SOC_ULP_LP_UART_SUPPORTED 1
|
||||
#define SOC_CLK_TREE_SUPPORTED 1
|
||||
// #define SOC_ASSIST_DEBUG_SUPPORTED 1 // TODO: [ESP32C5] IDF-8663
|
||||
@ -243,8 +243,7 @@
|
||||
#define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */
|
||||
|
||||
/*-------------------------- I2C CAPS ----------------------------------------*/
|
||||
// ESP32-C5 has 1 I2C
|
||||
#define SOC_I2C_NUM (1U)
|
||||
#define SOC_I2C_NUM (2U)
|
||||
#define SOC_HP_I2C_NUM (1U)
|
||||
|
||||
#define SOC_I2C_FIFO_LEN (32) /*!< I2C hardware FIFO depth */
|
||||
@ -264,9 +263,9 @@
|
||||
|
||||
/*-------------------------- LP_I2C CAPS -------------------------------------*/
|
||||
// ESP32-C5 has 1 LP_I2C
|
||||
// #define SOC_LP_I2C_NUM (1U)
|
||||
#define SOC_LP_I2C_NUM (1U)
|
||||
|
||||
// #define SOC_LP_I2C_FIFO_LEN (16) /*!< LP_I2C hardware FIFO depth */
|
||||
#define SOC_LP_I2C_FIFO_LEN (16) /*!< LP_I2C hardware FIFO depth */
|
||||
|
||||
/*-------------------------- I2S CAPS ----------------------------------------*/
|
||||
#define SOC_I2S_NUM (1U)
|
||||
|
@ -881,7 +881,7 @@ typedef struct lp_i2c_dev_t {
|
||||
volatile lp_i2c_rxfifo_start_addr_reg_t rxfifo_start_addr;
|
||||
} lp_i2c_dev_t;
|
||||
|
||||
// We map the LP_I2C instance to the i2c_dev_t struct for convinience of using the same HAL/LL. See soc/i2c_struct.h
|
||||
// We map the LP_I2C instance to the i2c_dev_t struct for convenience of using the same HAL/LL. See soc/i2c_struct.h
|
||||
//extern lp_i2c_dev_t LP_I2C;
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
@ -14,12 +14,7 @@
|
||||
|
||||
static const char *LPI2C_TAG = "lp_core_i2c";
|
||||
|
||||
#if !SOC_LP_GPIO_MATRIX_SUPPORTED
|
||||
#include "soc/lp_io_struct.h"
|
||||
|
||||
/* Use the register structure to access LP_IO module registers */
|
||||
lp_io_dev_t *lp_io_dev = &LP_IO;
|
||||
#else
|
||||
#if SOC_LP_GPIO_MATRIX_SUPPORTED
|
||||
#include "driver/lp_io.h"
|
||||
#include "soc/lp_gpio_sig_map.h"
|
||||
#endif /* !SOC_LP_GPIO_MATRIX_SUPPORTED */
|
||||
@ -94,11 +89,9 @@ static esp_err_t lp_i2c_set_pin(const lp_core_i2c_cfg_t *cfg)
|
||||
ESP_RETURN_ON_ERROR(lp_i2c_configure_io(sda_io_num, sda_pullup_en), LPI2C_TAG, "LP I2C SDA pin config failed");
|
||||
|
||||
#if !SOC_LP_GPIO_MATRIX_SUPPORTED
|
||||
/* Select LP I2C function for the SDA Pin */
|
||||
lp_io_dev->gpio[sda_io_num].mcu_sel = 1;
|
||||
|
||||
/* Select LP I2C function for the SCL Pin */
|
||||
lp_io_dev->gpio[scl_io_num].mcu_sel = 1;
|
||||
const i2c_signal_conn_t *p_i2c_pin = &i2c_periph_signal[LP_I2C_NUM_0];
|
||||
ret = rtc_gpio_iomux_func_sel(sda_io_num, p_i2c_pin->iomux_func);
|
||||
ret = rtc_gpio_iomux_func_sel(scl_io_num, p_i2c_pin->iomux_func);
|
||||
#else
|
||||
/* Connect the SDA pin of the LP_I2C peripheral to the LP_IO Matrix */
|
||||
ret = lp_gpio_connect_out_signal(sda_io_num, LP_I2C_SDA_PAD_OUT_IDX, 0, 0);
|
||||
|
@ -301,7 +301,7 @@ examples/system/ulp/lp_core/interrupt:
|
||||
|
||||
examples/system/ulp/lp_core/lp_i2c:
|
||||
enable:
|
||||
- if: SOC_LP_I2C_SUPPORTED == 1
|
||||
- if: SOC_LP_I2C_SUPPORTED == 1 and SOC_DEEP_SLEEP_SUPPORTED == 1
|
||||
disable:
|
||||
- if: IDF_TARGET == "esp32p4"
|
||||
temporary: true
|
||||
|
@ -7,13 +7,13 @@
|
||||
|
||||
## Overview
|
||||
|
||||
This example demonstrates basic usage of the LP I2C driver from the LP core by reading to and writing from a sensor connected over I2C.
|
||||
This example demonstrates the basic usage of the LP I2C driver from the LP core by reading to and writing from a sensor connected over I2C.
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
To run this example, you should have a ESP32-C6 based development board as well as a BH1750 sensor. BH1750 is an ambient light sensor. More information about it can be found in the [BH1750 datasheet](https://www.mouser.com/datasheet/2/348/bh1750fvi-e-186247.pdf).
|
||||
To run this example, you should have an ESP based development board that supports the LP I2C peripheral on the LP Core as well as a BH1750 sensor. BH1750 is an ambient light sensor. More information about it can be found in the [BH1750 datasheet](https://www.mouser.com/datasheet/2/348/bh1750fvi-e-186247.pdf).
|
||||
|
||||
#### Pin Assignment:
|
||||
|
||||
@ -22,9 +22,10 @@ To run this example, you should have a ESP32-C6 based development board as well
|
||||
| | SDA | SCL |
|
||||
| ----------------------- | ------| ------|
|
||||
| ESP32-C6 LP I2C Master | GPIO6 | GPIO7 |
|
||||
| ESP32-C5 LP I2C Master | GPIO6 | GPIO7 |
|
||||
| BH1750 Sensor | SDA | SCL |
|
||||
|
||||
**Note:** There's no need to add an 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.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
@ -51,7 +52,7 @@ LP core woke up the main CPU
|
||||
Lux = 3
|
||||
Entering deep sleep...
|
||||
|
||||
(When the BH1750 sensor is exposed to a direct light source, the Lux value should be larger and the LP core should wakup the main CPU)
|
||||
(When the BH1750 sensor is exposed to a direct light source, the Lux value should be larger and the LP core should wakeup the main CPU)
|
||||
|
||||
LP core woke up the main CPU
|
||||
Lux = 1222
|
||||
|
Loading…
Reference in New Issue
Block a user