Skip to content

Commit

Permalink
Merge branch 'feature/i2c_support_on_esp8684_esp32h2' into 'master'
Browse files Browse the repository at this point in the history
i2c: support i2c on esp32c2 and esp32h2

Closes IDF-3918

See merge request espressif/esp-idf!16444
  • Loading branch information
L-KAYA committed Feb 28, 2022
2 parents 44e5ac2 + cf353c5 commit cc1d89e
Show file tree
Hide file tree
Showing 44 changed files with 565 additions and 670 deletions.
61 changes: 44 additions & 17 deletions components/driver/i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,14 @@ static const char *I2C_TAG = "i2c";
#define I2C_TIMING_VAL_ERR_STR "i2c timing value error"
#define I2C_ADDR_ERROR_STR "i2c null address error"
#define I2C_DRIVER_NOT_INSTALL_ERR_STR "i2c driver not installed"
#define I2C_SLAVE_BUFFER_LEN_ERR_STR "i2c buffer size too small for slave mode"
#if SOC_I2C_SUPPORT_SLAVE
#define I2C_SLAVE_BUFFER_LEN_ERR_STR "i2c buffer size too small for slave mode"
#define I2C_MODE_SLAVE_ERR_STR "Only allowed in slave mode"
#endif
#define I2C_EVT_QUEUE_ERR_STR "i2c evt queue error"
#define I2C_SEM_ERR_STR "i2c semaphore error"
#define I2C_BUF_ERR_STR "i2c ringbuffer error"
#define I2C_MASTER_MODE_ERR_STR "Only allowed in master mode"
#define I2C_MODE_SLAVE_ERR_STR "Only allowed in slave mode"
#define I2C_CMD_MALLOC_ERR_STR "i2c command link malloc error"
#define I2C_CMD_USER_ALLOC_ERR_STR "i2c command link allocation error: the buffer provided is too small."
#define I2C_TRANS_MODE_ERR_STR "i2c trans mode error"
Expand All @@ -70,9 +72,11 @@ static const char *I2C_TAG = "i2c";
#define I2C_CMD_EVT_ALIVE (0)
#define I2C_CMD_EVT_DONE (1)
#define I2C_EVT_QUEUE_LEN (1)
#define I2C_SLAVE_TIMEOUT_DEFAULT (32000) /* I2C slave timeout value, APB clock cycle number */
#define I2C_SLAVE_SDA_SAMPLE_DEFAULT (10) /* I2C slave sample time after scl positive edge default value */
#define I2C_SLAVE_SDA_HOLD_DEFAULT (10) /* I2C slave hold time after scl negative edge default value */
#if SOC_I2C_SUPPORT_SLAVE
#define I2C_SLAVE_TIMEOUT_DEFAULT (32000) /* I2C slave timeout value, APB clock cycle number */
#define I2C_SLAVE_SDA_SAMPLE_DEFAULT (10) /* I2C slave sample time after scl positive edge default value */
#define I2C_SLAVE_SDA_HOLD_DEFAULT (10) /* I2C slave hold time after scl negative edge default value */
#endif
#define I2C_MASTER_TOUT_CNUM_DEFAULT (8) /* I2C master timeout cycle number of I2C clock, after which the timeout interrupt will be triggered */
#define I2C_ACKERR_CNT_MAX (10)
#define I2C_FILTER_CYC_NUM_DEF (7) /* The number of apb cycles filtered by default*/
Expand Down Expand Up @@ -157,9 +161,10 @@ typedef struct {
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_handle_t pm_lock;
#endif

#if SOC_I2C_SUPPORT_SLAVE
SemaphoreHandle_t slv_rx_mux; /*!< slave rx buffer mux */
SemaphoreHandle_t slv_tx_mux; /*!< slave tx buffer mux */
#endif // SOC_I2C_SUPPORT_SLAVE
size_t rx_buf_length; /*!< rx buffer length */
RingbufHandle_t rx_ring_buf; /*!< rx ringbuffer handler of slave mode */
size_t tx_buf_length; /*!< tx buffer length */
Expand Down Expand Up @@ -242,8 +247,10 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
int intr_alloc_flags)
{
ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_NUM_ERROR_STR);
#if SOC_I2C_SUPPORT_SLAVE
ESP_RETURN_ON_FALSE(mode == I2C_MODE_MASTER || ( slv_rx_buf_len > 100 || slv_tx_buf_len > 100 ),
ESP_ERR_INVALID_ARG, I2C_TAG, I2C_SLAVE_BUFFER_LEN_ERR_STR);
#endif // SOC_I2C_SUPPORT_SLAVE
esp_err_t ret = ESP_OK;

if (p_i2c_obj[i2c_num] == NULL) {
Expand Down Expand Up @@ -271,7 +278,7 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
#if CONFIG_SPIRAM_USE_MALLOC
p_i2c->intr_alloc_flags = intr_alloc_flags;
#endif

#if SOC_I2C_SUPPORT_SLAVE
if (mode == I2C_MODE_SLAVE) {
//we only use ringbuffer for slave mode.
if (slv_rx_buf_len > 0) {
Expand Down Expand Up @@ -302,7 +309,9 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
ESP_LOGE(I2C_TAG, I2C_SEM_ERR_STR);
goto err;
}
} else {
} else
#endif // SOC_I2C_SUPPORT_SLAVE
{
//semaphore to sync sending process, because we only have 32 bytes for hardware fifo.
p_i2c->cmd_mux = xSemaphoreCreateMutex();
#ifdef CONFIG_PM_ENABLE
Expand Down Expand Up @@ -353,10 +362,12 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
i2c_isr_handler_default, p_i2c_obj[i2c_num],
&p_i2c_obj[i2c_num]->intr_handle);
ESP_GOTO_ON_ERROR(ret, err, I2C_TAG, I2C_INTR_ALLOC_ERR_STR);
#if SOC_I2C_SUPPORT_SLAVE
//Enable I2C slave rx interrupt
if (mode == I2C_MODE_SLAVE) {
i2c_hal_enable_slave_rx_it(&(i2c_context[i2c_num].hal));
}
#endif // SOC_I2C_SUPPORT_SLAVE
return ESP_OK;

err:
Expand All @@ -379,12 +390,14 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
if (p_i2c_obj[i2c_num]->cmd_mux) {
vSemaphoreDelete(p_i2c_obj[i2c_num]->cmd_mux);
}
#if SOC_I2C_SUPPORT_SALVE
if (p_i2c_obj[i2c_num]->slv_rx_mux) {
vSemaphoreDelete(p_i2c_obj[i2c_num]->slv_rx_mux);
}
if (p_i2c_obj[i2c_num]->slv_tx_mux) {
vSemaphoreDelete(p_i2c_obj[i2c_num]->slv_tx_mux);
}
#endif
#ifdef CONFIG_PM_ENABLE
if (p_i2c_obj[i2c_num]->pm_lock) {
esp_pm_lock_delete(p_i2c_obj[i2c_num]->pm_lock);
Expand Down Expand Up @@ -423,12 +436,14 @@ esp_err_t i2c_driver_delete(i2c_port_t i2c_num)
vQueueDelete(p_i2c_obj[i2c_num]->cmd_evt_queue);
p_i2c_obj[i2c_num]->cmd_evt_queue = NULL;
}
#if SOC_I2C_SUPPORT_SLAVE
if (p_i2c->slv_rx_mux) {
vSemaphoreDelete(p_i2c->slv_rx_mux);
}
if (p_i2c->slv_tx_mux) {
vSemaphoreDelete(p_i2c->slv_tx_mux);
}
#endif

if (p_i2c->rx_ring_buf) {
vRingbufferDelete(p_i2c->rx_ring_buf);
Expand Down Expand Up @@ -510,7 +525,9 @@ static void IRAM_ATTR i2c_isr_handler_default(void *arg)
.type = I2C_CMD_EVT_ALIVE
};
xQueueSendFromISR(p_i2c->cmd_evt_queue, &evt, &HPTaskAwoken);
} else {
}
#if SOC_I2C_SUPPORT_SLAVE
else {
i2c_hal_slave_handle_event(&(i2c_context[i2c_num].hal), &evt_type);
if (evt_type == I2C_INTR_EVENT_TRANS_DONE || evt_type == I2C_INTR_EVENT_RXFIFO_FULL) {
uint32_t rx_fifo_cnt;
Expand All @@ -532,6 +549,7 @@ static void IRAM_ATTR i2c_isr_handler_default(void *arg)
i2c_hal_slave_clr_tx_it(&(i2c_context[i2c_num].hal));
}
}
#endif // SOC_I2C_SUPPORT_SLAVE
//We only need to check here if there is a high-priority task needs to be switched.
if (HPTaskAwoken == pdTRUE) {
portYIELD_FROM_ISR();
Expand Down Expand Up @@ -666,17 +684,20 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf)
if (i2c_conf->mode == I2C_MODE_MASTER) {
src_clk = i2c_get_clk_src(i2c_conf->clk_flags, i2c_conf->master.clk_speed);
ESP_RETURN_ON_FALSE(src_clk != I2C_SCLK_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_CLK_FLAG_ERR_STR);
} else {
#if CONFIG_IDF_TARGET_ESP32S2
}
#if SOC_I2C_SUPPORT_SLAVE
else {
#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. */
src_clk = I2C_SCLK_APB;
#else
#else
src_clk = i2c_get_clk_src(i2c_conf->clk_flags, i2c_conf->slave.maximum_speed);
ESP_RETURN_ON_FALSE(src_clk != I2C_SCLK_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_CLK_FLAG_ERR_STR);
#endif
#endif // CONFIG_IDF_TARGET_ESP32S2
}
#endif // SOC_I2C_SUPPORT_SLAVE

ret = i2c_set_pin(i2c_num, i2c_conf->sda_io_num, i2c_conf->scl_io_num,
i2c_conf->sda_pullup_en, i2c_conf->scl_pullup_en, i2c_conf->mode);
Expand All @@ -687,6 +708,7 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf)
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_disable_intr_mask(&(i2c_context[i2c_num].hal), I2C_LL_INTR_MASK);
i2c_hal_clr_intsts_mask(&(i2c_context[i2c_num].hal), I2C_LL_INTR_MASK);
#if SOC_I2C_SUPPORT_SLAVE
if (i2c_conf->mode == I2C_MODE_SLAVE) { //slave mode
i2c_hal_slave_init(&(i2c_context[i2c_num].hal), i2c_num);
i2c_hal_set_source_clk(&(i2c_context[i2c_num].hal), src_clk);
Expand All @@ -697,7 +719,9 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf)
i2c_hal_set_sda_timing(&(i2c_context[i2c_num].hal), I2C_SLAVE_SDA_SAMPLE_DEFAULT, I2C_SLAVE_SDA_HOLD_DEFAULT);
i2c_hal_set_tout(&(i2c_context[i2c_num].hal), I2C_SLAVE_TIMEOUT_DEFAULT);
i2c_hal_enable_slave_rx_it(&(i2c_context[i2c_num].hal));
} else {
} else
#endif // SOC_I2C_SUPPORT_SLAVE
{
i2c_hal_master_init(&(i2c_context[i2c_num].hal), i2c_num);
//Default, we enable hardware filter
i2c_hal_set_filter(&(i2c_context[i2c_num].hal), I2C_FILTER_CYC_NUM_DEF);
Expand Down Expand Up @@ -840,8 +864,10 @@ esp_err_t i2c_set_pin(i2c_port_t i2c_num, int sda_io_num, int scl_io_num, bool s
ESP_RETURN_ON_FALSE(( i2c_num < I2C_NUM_MAX ), ESP_ERR_INVALID_ARG, I2C_TAG, I2C_NUM_ERROR_STR);
ESP_RETURN_ON_FALSE(((sda_io_num < 0) || ((GPIO_IS_VALID_OUTPUT_GPIO(sda_io_num)))), ESP_ERR_INVALID_ARG, I2C_TAG, I2C_SDA_IO_ERR_STR);
ESP_RETURN_ON_FALSE(scl_io_num < 0 ||
(GPIO_IS_VALID_OUTPUT_GPIO(scl_io_num)) ||
(GPIO_IS_VALID_GPIO(scl_io_num) && mode == I2C_MODE_SLAVE),
#if SOC_I2C_SUPPORT_SLAVE
(GPIO_IS_VALID_GPIO(scl_io_num) && mode == I2C_MODE_SLAVE) ||
#endif // SOC_I2C_SUPPORT_SLAVE
(GPIO_IS_VALID_OUTPUT_GPIO(scl_io_num)),
ESP_ERR_INVALID_ARG, I2C_TAG,
I2C_SCL_IO_ERR_STR);
ESP_RETURN_ON_FALSE(sda_io_num < 0 ||
Expand Down Expand Up @@ -1499,7 +1525,7 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle,
xSemaphoreGive(p_i2c->cmd_mux);
return ret;
}

#if SOC_I2C_SUPPORT_SLAVE
int i2c_slave_write_buffer(i2c_port_t i2c_num, const uint8_t *data, int size, TickType_t ticks_to_wait)
{
ESP_RETURN_ON_FALSE(( i2c_num < I2C_NUM_MAX ), ESP_FAIL, I2C_TAG, I2C_NUM_ERROR_STR);
Expand Down Expand Up @@ -1563,3 +1589,4 @@ int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t *data, size_t max_size, Ti
xSemaphoreGive(p_i2c->slv_rx_mux);
return max_size - size_rem;
}
#endif
7 changes: 6 additions & 1 deletion components/driver/include/driver/i2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,13 @@ typedef struct{
struct {
uint32_t clk_speed; /*!< I2C clock frequency for master mode, (no higher than 1MHz for now) */
} master; /*!< I2C master config */
#if SOC_I2C_SUPPORT_SLAVE
struct {
uint8_t addr_10bit_en; /*!< I2C 10bit address mode enable for slave mode */
uint16_t slave_addr; /*!< I2C address for slave mode */
uint32_t maximum_speed; /*!< I2C expected clock speed from SCL. */
} slave; /*!< I2C slave config */
#endif // SOC_I2C_SUPPORT_SLAVE
};
uint32_t clk_flags; /*!< Bitwise of ``I2C_SCLK_SRC_FLAG_**FOR_DFS**`` for clk source choice*/
} i2c_config_t;
Expand All @@ -89,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)
* @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 Expand Up @@ -418,6 +421,7 @@ esp_err_t i2c_master_stop(i2c_cmd_handle_t cmd_handle);
*/
esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, TickType_t ticks_to_wait);

#if SOC_I2C_SUPPORT_SLAVE
/**
* @brief Write bytes to internal ringbuffer of the I2C slave data. When the TX fifo empty, the ISR will
* fill the hardware FIFO with the internal ringbuffer's data.
Expand Down Expand Up @@ -450,6 +454,7 @@ int i2c_slave_write_buffer(i2c_port_t i2c_num, const uint8_t *data, int size, Ti
* - Others(>=0) The number of data bytes read from I2C slave buffer.
*/
int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t *data, size_t max_size, TickType_t ticks_to_wait);
#endif // SOC_I2C_SUPPORT_SLAVE

/**
* @brief Set I2C master clock period
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
18 changes: 5 additions & 13 deletions components/esp_rom/include/esp32c3/rom/apb_backup_dma.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
// Copyright 2010-2020 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: 2010-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

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
Loading

0 comments on commit cc1d89e

Please sign in to comment.