Skip to content

Commit

Permalink
i2c: support esp32h2
Browse files Browse the repository at this point in the history
  • Loading branch information
L-KAYA committed Feb 23, 2022
1 parent 7da023c commit cf353c5
Show file tree
Hide file tree
Showing 28 changed files with 210 additions and 182 deletions.
2 changes: 1 addition & 1 deletion components/driver/i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,7 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf)
}
#if SOC_I2C_SUPPORT_SLAVE
else {
#if CONFIG_IDF_TARGET_ESP32S2
#if SOC_I2C_SUPPORT_REF_TICK
/* On ESP32-S2, APB clock shall always be used in slave mode as the
* other one, I2C_SCLK_REF_TICK, is too slow, even for sampling a
* 100KHz SCL. */
Expand Down
3 changes: 2 additions & 1 deletion components/driver/include/driver/i2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,10 @@ typedef void *i2c_cmd_handle_t; /*!< I2C command handle */

/**
* @brief Install an I2C driver
* @note Not all Espressif chips can support slave mode (e.g. ESP32C2)
*
* @param i2c_num I2C port number
* @param mode I2C mode (either master or slave). ESP8684 doesn't support i2c slave mode
* @param mode I2C mode (either master or slave).
* @param slv_rx_buf_len Receiving buffer size. Only slave mode will use this value, it is ignored in master mode.
* @param slv_tx_buf_len Sending buffer size. Only slave mode will use this value, it is ignored in master mode.
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values.
Expand Down
3 changes: 3 additions & 0 deletions components/driver/test/test_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "hal/gpio_hal.h"
#include "hal/uart_ll.h"

#if SOC_I2C_SUPPORT_SLAVE // i2c test can't work without slave

#define DATA_LENGTH 512 /*!<Data buffer length for test buffer*/
#define RW_TEST_LENGTH 129 /*!<Data length for r/w test, any value from 0-DATA_LENGTH*/
Expand Down Expand Up @@ -723,3 +724,5 @@ TEST_CASE("I2C SCL freq test (local test)", "[i2c][ignore]")
}

#endif // TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP32C3)

#endif // SOC_I2C_SUPPORT_SLAVE
2 changes: 1 addition & 1 deletion components/driver/test/test_spi_slave.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ TEST_CASE("test slave send unaligned","[spi]")
/********************************************************************************
* Test By Master & Slave (2 boards)
*
* Master (C3, 8684, H2) && Slave (C3, 8684, H2):
* Master (C3, C2, H2) && Slave (C3, C2, H2):
* PIN | Master | Slave |
* ----| --------- | --------- |
* CS | 10 | 10 |
Expand Down
2 changes: 1 addition & 1 deletion components/driver/test/test_spi_slave_hd.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ TEST_CASE("test spi slave hd segment mode, master too long", "[spi][spi_slv_hd]"
/********************************************************************************
* Test By Master & Slave (2 boards)
*
* Master (C3, 8684, H2) && Slave (C3, 8684, H2):
* Master (C3, C2, H2) && Slave (C3, C2, H2):
* PIN | Master | Slave |
* ----| --------- | --------- |
* CS | 10 | 10 |
Expand Down
2 changes: 1 addition & 1 deletion components/hal/esp32c2/include/hal/gpspi_flash_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
extern "C" {
#endif

//NOTE: These macros are changed on 8684 for build. MODIFY these when bringup flash.
//NOTE: These macros are changed on ESP32-C2 for build. MODIFY these when bringup flash.
#define gpspi_flash_ll_get_hw(host_id) ( ((host_id)==SPI2_HOST) ? &GPSPI2 : ({abort();(spi_dev_t*)0;}) )
#define gpspi_flash_ll_hw_get_id(dev) ( ((dev) == (void*)&GPSPI2) ? SPI2_HOST : -1 )

Expand Down
2 changes: 1 addition & 1 deletion components/hal/esp32c2/include/hal/i2c_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,7 @@ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_sclk_t src_clk)
// rtc_clk needs to switch on.
if (src_clk == I2C_SCLK_RTC) {
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); // TODO: IDF-4535
}
// src_clk : (1) for RTC_CLK, (0) for XTAL
hw->clk_conf.sclk_sel = (src_clk == I2C_SCLK_RTC) ? 1 : 0;
Expand Down
4 changes: 2 additions & 2 deletions components/hal/esp32h2/include/hal/i2c_ll.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -87,7 +87,7 @@ typedef struct {
// I2C slave RX interrupt bitmap
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_WM_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
// I2C source clock
#define I2C_LL_CLK_SRC_FREQ(src_clk) (((src_clk) == I2C_SCLK_RTC) ? 20*1000*1000 : 40*1000*1000); // Another clock is XTAL clock
#define I2C_LL_CLK_SRC_FREQ(src_clk) (((src_clk) == I2C_SCLK_RTC) ? 8*1000*1000 : 32*1000*1000); // Another clock is XTAL clock
// delay time after rtc_clk swiching on
#define DELAY_RTC_CLK_SWITCH (5)
// I2C max timeout value
Expand Down
33 changes: 20 additions & 13 deletions components/hal/esp32h2/rtc_cntl_hal.c
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

// The HAL layer for RTC CNTL (common part)

#include "soc/soc_caps.h"
#include "soc/lldesc.h"
#include "hal/rtc_hal.h"
#include "hal/assert.h"
#include "esp_attr.h"

#define RTC_CNTL_HAL_LINK_BUF_SIZE_MIN (SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE) /* The minimum size of dma link buffer */

Expand All @@ -44,6 +37,7 @@ void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next)
return (void *)plink;
}

#if SOC_PM_SUPPORT_CPU_PD
void rtc_cntl_hal_enable_cpu_retention(void *addr)
{
if (addr) {
Expand All @@ -59,3 +53,16 @@ void rtc_cntl_hal_enable_cpu_retention(void *addr)
rtc_cntl_ll_enable_cpu_retention((uint32_t)addr);
}
}

void IRAM_ATTR rtc_cntl_hal_disable_cpu_retention(void *addr)
{
rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr;

if (addr) {
if (retent->cpu_pd_mem) {
rtc_cntl_ll_disable_cpu_retention();
}
}
}

#endif // SOC_PM_SUPPORT_CPU_PD
2 changes: 1 addition & 1 deletion components/hal/spi_flash_hal_iram.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ void spi_flash_hal_setup_auto_resume_mode(spi_flash_host_inst_t *host);

// HAL for
// - MEMSPI
// - SPI1~3 on ESP32/S2/S3/C3/H2/8684
// - SPI1~3 on ESP32/S2/S3/C3/H2/C2
// The common part is in spi_flash_hal_common.inc

void spi_flash_hal_erase_chip(spi_flash_host_inst_t *host)
Expand Down
1 change: 0 additions & 1 deletion components/soc/esp32c2/include/soc/i2c_struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,6 @@ typedef struct {
} i2c_dev_t;

extern i2c_dev_t I2C0;
extern i2c_dev_t I2C1;

#ifndef __cplusplus
_Static_assert(sizeof(i2c_dev_t) == 0x184, "Invalid size of i2c_dev_t structure");
Expand Down
32 changes: 4 additions & 28 deletions components/soc/esp32s3/include/soc/Kconfig.soc_caps.in
Original file line number Diff line number Diff line change
Expand Up @@ -47,34 +47,6 @@ config SOC_GPIO_SUPPORT_SLP_SWITCH
bool
default y

config SOC_I2C_NUM
int
default 2

config SOC_I2C_FIFO_LEN
int
default 32

config SOC_I2C_SUPPORT_SLAVE
bool
default y

config SOC_I2C_SUPPORT_HW_FSM_RST
bool
default y

config SOC_I2C_SUPPORT_HW_CLR_BUS
bool
default y

config SOC_I2C_SUPPORT_XTAL
bool
default y

config SOC_I2C_SUPPORT_RTC
bool
default y

config SOC_LEDC_SUPPORT_XTAL_CLOCK
bool
default y
Expand Down Expand Up @@ -383,6 +355,10 @@ config SOC_I2C_FIFO_LEN
int
default 32

config SOC_I2C_SUPPORT_SLAVE
bool
default y

config SOC_I2C_SUPPORT_HW_FSM_RST
bool
default y
Expand Down
1 change: 1 addition & 0 deletions components/soc/esp32s3/include/soc/soc_caps.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
#define SOC_I2C_NUM (2)

#define SOC_I2C_FIFO_LEN (32) /*!< I2C hardware FIFO depth */
#define SOC_I2C_SUPPORT_SLAVE (1)

//ESP32-S3 support hardware FSM reset
#define SOC_I2C_SUPPORT_HW_FSM_RST (1)
Expand Down
97 changes: 60 additions & 37 deletions docs/en/api-reference/peripherals/i2c.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Inter-Integrated Circuit (I2C)

:link_to_translation:`zh_CN:[中文]`

{IDF_TARGET_I2C_NUM:default="2", esp32c3="1", esp32h2="1", esp328684="1"}
{IDF_TARGET_I2C_NUM:default="2", esp32c3="1", esp32h2="1", esp32c2="1"}

Overview
--------
Expand All @@ -20,21 +20,30 @@ Driver Features
I2C driver governs communications of devices over the I2C bus. The driver supports the following features:

- Reading and writing bytes in Master mode
- Slave mode

.. only:: SOC_I2C_SUPPORT_SLAVE

- Slave mode

- Reading and writing to registers which are in turn read/written by the master


Driver Usage
------------

{IDF_TARGET_I2C_ROLE:default="master or slave", esp32c2="master"}

The following sections describe typical steps of configuring and operating the I2C driver:

1. :ref:`i2c-api-configure-driver` - set the initialization parameters (master or slave mode, GPIO pins for SDA and SCL, clock speed, etc.)
2. :ref:`i2c-api-install-driver`- activate the driver on one of the two I2C controllers as a master or slave
3. Depending on whether you configure the driver for a master or slave, choose the appropriate item
1. :ref:`i2c-api-configure-driver` - set the initialization parameters ({IDF_TARGET_I2C_ROLE} mode, GPIO pins for SDA and SCL, clock speed, etc.)
2. :ref:`i2c-api-install-driver`- activate the driver on one of the two I2C controllers as a {IDF_TARGET_I2C_ROLE}
3. Depending on whether you configure the driver for a {IDF_TARGET_I2C_ROLE}, choose the appropriate item

a) :ref:`i2c-api-master-mode` - handle communications (master)

a) :ref:`i2c-api-master-mode` - handle communications (master)
b) :ref:`i2c-api-slave-mode` - respond to messages from the master (slave)
.. only:: SOC_I2C_SUPPORT_SLAVE

b) :ref:`i2c-api-slave-mode` - respond to messages from the master (slave)

4. :ref:`i2c-api-interrupt-handling` - configure and service I2C interrupts
5. :ref:`i2c-api-customized-configuration` - adjust default I2C communication parameters (timings, bit order, etc.)
Expand All @@ -49,17 +58,20 @@ Configuration

To establish I2C communication, start by configuring the driver. This is done by setting the parameters of the structure :cpp:type:`i2c_config_t`:

- Set I2C **mode of operation** - slave or master from :cpp:type:`i2c_mode_t`
- Set I2C **mode of operation** - {IDF_TARGET_I2C_ROLE} from :cpp:type:`i2c_mode_t`
- Configure **communication pins**

- Assign GPIO pins for SDA and SCL signals
- Set whether to enable {IDF_TARGET_NAME}'s internal pull-ups

- (Master only) Set I2C **clock speed**
- (Slave only) Configure the following

* Whether to enable **10 bit address mode**
* Define **slave address**
.. only:: SOC_I2C_SUPPORT_SLAVE

- (Slave only) Configure the following

* Whether to enable **10 bit address mode**
* Define **slave address**

After that, initialize the configuration for a given I2C port. For this, call the function :cpp:func:`i2c_param_config` and pass to it the port number and the structure :cpp:type:`i2c_config_t`.

Expand All @@ -78,20 +90,22 @@ Configuration example (master):
// .clk_flags = 0, /*!< Optional, you can use I2C_SCLK_SRC_FLAG_* flags to choose i2c source clock here. */
};
Configuration example (slave):
.. only:: SOC_I2C_SUPPORT_SLAVE

.. code-block:: c
Configuration example (slave):

int i2c_slave_port = I2C_SLAVE_NUM;
i2c_config_t conf_slave = {
.sda_io_num = I2C_SLAVE_SDA_IO, // select GPIO specific to your project
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_io_num = I2C_SLAVE_SCL_IO, // select GPIO specific to your project
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.mode = I2C_MODE_SLAVE,
.slave.addr_10bit_en = 0,
.slave.slave_addr = ESP_SLAVE_ADDR, // address of your project
};
.. code-block:: c
int i2c_slave_port = I2C_SLAVE_NUM;
i2c_config_t conf_slave = {
.sda_io_num = I2C_SLAVE_SDA_IO, // select GPIO specific to your project
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_io_num = I2C_SLAVE_SCL_IO, // select GPIO specific to your project
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.mode = I2C_MODE_SLAVE,
.slave.addr_10bit_en = 0,
.slave.slave_addr = ESP_SLAVE_ADDR, // address of your project
};
At this stage, :cpp:func:`i2c_param_config` also sets a few other I2C configuration parameters to default values that are defined by the I2C specification. For more details on the values and how to modify them, see :ref:`i2c-api-customized-configuration`.

Expand Down Expand Up @@ -200,8 +214,12 @@ Install Driver
After the I2C driver is configured, install it by calling the function :cpp:func:`i2c_driver_install` with the following parameters:

- Port number, one of the two port numbers from :cpp:type:`i2c_port_t`
- Master or slave, selected from :cpp:type:`i2c_mode_t`
- (Slave only) Size of buffers to allocate for sending and receiving data. As I2C is a master-centric bus, data can only go from the slave to the master at the master's request. Therefore, the slave will usually have a send buffer where the slave application writes data. The data remains in the send buffer to be read by the master at the master's own discretion.
- {IDF_TARGET_I2C_ROLE}, selected from :cpp:type:`i2c_mode_t`

.. only:: SOC_I2C_SUPPORT_SLAVE

- (Slave only) Size of buffers to allocate for sending and receiving data. As I2C is a master-centric bus, data can only go from the slave to the master at the master's request. Therefore, the slave will usually have a send buffer where the slave application writes data. The data remains in the send buffer to be read by the master at the master's own discretion.

- Flags for allocating the interrupt (see ESP_INTR_FLAG_* values in :component_file:`esp_hw_support/include/esp_intr_alloc.h`)

.. _i2c-api-master-mode:
Expand Down Expand Up @@ -278,27 +296,32 @@ Likewise, the command link to read from the slave looks as follows:
i2c_master_write_byte(cmd, (ESP_SLAVE_ADDR << 1) | I2C_MASTER_READ, ACK_EN);
.. _i2c-api-slave-mode:
.. only:: SOC_I2C_SUPPORT_SLAVE

Communication as Slave
^^^^^^^^^^^^^^^^^^^^^^
.. _i2c-api-slave-mode:

After installing the I2C driver, {IDF_TARGET_NAME} is ready to communicate with other I2C devices.
Communication as Slave
^^^^^^^^^^^^^^^^^^^^^^

After installing the I2C driver, {IDF_TARGET_NAME} is ready to communicate with other I2C devices.

The API provides the following functions for slaves

The API provides the following functions for slaves
- :cpp:func:`i2c_slave_read_buffer`

- :cpp:func:`i2c_slave_read_buffer`
Whenever the master writes data to the slave, the slave will automatically store it in the receive buffer. This allows the slave application to call the function :cpp:func:`i2c_slave_read_buffer` at its own discretion. This function also has a parameter to specify block time if no data is in the receive buffer. This will allow the slave application to wait with a specified timeout for data to arrive to the buffer.

Whenever the master writes data to the slave, the slave will automatically store it in the receive buffer. This allows the slave application to call the function :cpp:func:`i2c_slave_read_buffer` at its own discretion. This function also has a parameter to specify block time if no data is in the receive buffer. This will allow the slave application to wait with a specified timeout for data to arrive to the buffer.
- :cpp:func:`i2c_slave_write_buffer`

- :cpp:func:`i2c_slave_write_buffer`
The send buffer is used to store all the data that the slave wants to send to the master in FIFO order. The data stays there until the master requests for it. The function :cpp:func:`i2c_slave_write_buffer` has a parameter to specify block time if the send buffer is full. This will allow the slave application to wait with a specified timeout for the adequate amount of space to become available in the send buffer.

The send buffer is used to store all the data that the slave wants to send to the master in FIFO order. The data stays there until the master requests for it. The function :cpp:func:`i2c_slave_write_buffer` has a parameter to specify block time if the send buffer is full. This will allow the slave application to wait with a specified timeout for the adequate amount of space to become available in the send buffer.
A code example showing how to use these functions can be found in :example:`peripherals/i2c`.

A code example showing how to use these functions can be found in :example:`peripherals/i2c`.
.. _i2c-api-interrupt-handling:

.. only:: not SOC_I2C_SUPPORT_SLAVE

.. _i2c-api-interrupt-handling:
.. _i2c-api-interrupt-handling:

Interrupt Handling
^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -369,7 +392,7 @@ Before calling :cpp:func:`i2c_driver_delete` to remove i2c driver, please make s
Application Example
-------------------

I2C master and slave example: :example:`peripherals/i2c`.
I2C examples: :example:`peripherals/i2c`.


API Reference
Expand Down
2 changes: 1 addition & 1 deletion docs/zh_CN/api-reference/peripherals/i2c.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ I2C 驱动程序

:link_to_translation:`en:[English]`

{IDF_TARGET_I2C_NUM:default="2", esp32c3="1", esp32h2="1", esp328684="1"}
{IDF_TARGET_I2C_NUM:default="2", esp32c3="1", esp32h2="1", esp32c2="1"}

概述
---------
Expand Down
Loading

0 comments on commit cf353c5

Please sign in to comment.