diff --git a/components/driver/i2c.c b/components/driver/i2c.c index 78b779858a..fa0a2906e7 100644 --- a/components/driver/i2c.c +++ b/components/driver/i2c.c @@ -105,6 +105,14 @@ static const char *I2C_TAG = "i2c"; #define I2C_CLOCK_INVALID (-1) +/** + * I2C bus are defined in the header files, let's check that the values are correct + */ +#if SOC_I2C_NUM >= 2 +_Static_assert(I2C_NUM_1 == 1, "I2C_NUM_1 must be equal to 1"); +#endif // SOC_I2C_NUM >= 2 +_Static_assert(I2C_NUM_MAX == SOC_I2C_NUM, "I2C_NUM_MAX must be equal to SOC_I2C_NUM"); + typedef struct { i2c_hw_cmd_t hw_cmd; union { @@ -193,7 +201,9 @@ typedef struct static i2c_context_t i2c_context[I2C_NUM_MAX] = { I2C_CONTEX_INIT_DEF(I2C_NUM_0), -#if I2C_NUM_MAX > 1 +/* Now that I2C_NUM_MAX is part of an enum (i2c_port_t), we cannot use + * it anomore in the preprocessor! */ +#if SOC_I2C_NUM > 1 I2C_CONTEX_INIT_DEF(I2C_NUM_1), #endif }; diff --git a/components/driver/include/driver/i2c.h b/components/driver/include/driver/i2c.h index e8da6df2de..6ce0885c21 100644 --- a/components/driver/include/driver/i2c.h +++ b/components/driver/include/driver/i2c.h @@ -24,12 +24,6 @@ extern "C" { #define I2C_APB_CLK_FREQ APB_CLK_FREQ /*!< I2C source clock is APB clock, 80MHz */ -#define I2C_NUM_MAX (SOC_I2C_NUM) /*!< I2C port max */ -#define I2C_NUM_0 (0) /*!< I2C port 0 */ -#if SOC_I2C_NUM >= 2 -#define I2C_NUM_1 (1) /*!< I2C port 1 */ -#endif - // I2C clk flags for users to use, can be expanded in the future. #define I2C_SCLK_SRC_FLAG_FOR_NOMAL (0) /*!< Any one clock source that is available for the specified frequency may be choosen*/ #define I2C_SCLK_SRC_FLAG_AWARE_DFS (1 << 0) /*!< For REF tick clock, it won't change with APB.*/ diff --git a/components/hal/i2c_hal.c b/components/hal/i2c_hal.c index 80d194bd94..a59ba0c519 100644 --- a/components/hal/i2c_hal.c +++ b/components/hal/i2c_hal.c @@ -152,7 +152,7 @@ void i2c_hal_disable_slave_rx_it(i2c_hal_context_t *hal) i2c_ll_slave_disable_rx_it(hal->dev); } -void i2c_hal_slave_init(i2c_hal_context_t *hal, int i2c_num) +void i2c_hal_slave_init(i2c_hal_context_t *hal, i2c_port_t i2c_num) { i2c_ll_slave_init(hal->dev); //Use fifo mode @@ -183,7 +183,7 @@ void i2c_hal_master_fsm_rst(i2c_hal_context_t *hal) i2c_ll_master_fsm_rst(hal->dev); } -void i2c_hal_master_init(i2c_hal_context_t *hal, int i2c_num) +void i2c_hal_master_init(i2c_hal_context_t *hal, i2c_port_t i2c_num) { hal->version = i2c_ll_get_hw_version(hal->dev); i2c_ll_master_init(hal->dev); diff --git a/components/hal/include/hal/i2c_types.h b/components/hal/include/hal/i2c_types.h index 35bddc7511..553d80ab38 100644 --- a/components/hal/include/hal/i2c_types.h +++ b/components/hal/include/hal/i2c_types.h @@ -18,7 +18,13 @@ extern "C" { /** * @brief I2C port number, can be I2C_NUM_0 ~ (I2C_NUM_MAX-1). */ -typedef int i2c_port_t; +typedef enum { + I2C_NUM_0 = 0, /*!< I2C port 0 */ +#if SOC_I2C_NUM >= 2 + I2C_NUM_1, /*!< I2C port 1 */ +#endif + I2C_NUM_MAX, /*!< I2C port max */ +} i2c_port_t; typedef enum{ #if SOC_I2C_SUPPORT_SLAVE diff --git a/examples/cxx/experimental/experimental_cpp_component/host_test/fixtures/test_fixtures.hpp b/examples/cxx/experimental/experimental_cpp_component/host_test/fixtures/test_fixtures.hpp index 484762c249..1de85ab65f 100644 --- a/examples/cxx/experimental/experimental_cpp_component/host_test/fixtures/test_fixtures.hpp +++ b/examples/cxx/experimental/experimental_cpp_component/host_test/fixtures/test_fixtures.hpp @@ -300,7 +300,7 @@ struct SPITransactionDescriptorFix { }; struct I2CMasterFix { - I2CMasterFix(i2c_port_t port_arg = 0) : i2c_conf(), port(port_arg) + I2CMasterFix(i2c_port_t port_arg = I2C_NUM_0) : i2c_conf(), port(port_arg) { i2c_conf.mode = i2c_mode_t::I2C_MODE_MASTER; i2c_conf.sda_io_num = 2; @@ -320,7 +320,7 @@ struct I2CMasterFix { #if CONFIG_SOC_I2C_SUPPORT_SLAVE struct I2CSlaveFix { - I2CSlaveFix(CreateAnd flags, i2c_port_t port_arg = 0, size_t buffer_size = 64) : i2c_conf(), port(port_arg) + I2CSlaveFix(CreateAnd flags, i2c_port_t port_arg = I2C_NUM_0, size_t buffer_size = 64) : i2c_conf(), port(port_arg) { if (flags == CreateAnd::SUCCEED) { i2c_conf.mode = i2c_mode_t::I2C_MODE_SLAVE; diff --git a/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/main/i2c_cxx_test.cpp b/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/main/i2c_cxx_test.cpp index a3d2bcc085..60e274087b 100644 --- a/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/main/i2c_cxx_test.cpp +++ b/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/main/i2c_cxx_test.cpp @@ -183,7 +183,7 @@ TEST_CASE("I2CWrite calls driver correctly") // will actually write the data but for the tests it is enough for now i2c_master_write_ExpectWithArrayAndReturn(&cmd_fix.dummy_handle, expected_write, WRITE_SIZE, EXPECTED_DATA_LEN, true, ESP_OK); i2c_master_stop_ExpectAndReturn(&cmd_fix.dummy_handle, ESP_OK); - i2c_master_cmd_begin_ExpectAndReturn(0, &cmd_fix.dummy_handle, 1000 / portTICK_PERIOD_MS, ESP_OK); + i2c_master_cmd_begin_ExpectAndReturn(I2C_NUM_0, &cmd_fix.dummy_handle, 1000 / portTICK_PERIOD_MS, ESP_OK); std::vector WRITE_BYTES = {0xAB, 0xBA}; I2CWrite write(WRITE_BYTES); @@ -218,7 +218,7 @@ TEST_CASE("I2CRead calls driver correctly") // will actually read the data but for the tests it is enough for now i2c_master_read_ReturnArrayThruPtr_data(READ_DATA, READ_SIZE); i2c_master_stop_ExpectAndReturn(&cmd_fix.dummy_handle, ESP_OK); - i2c_master_cmd_begin_ExpectAndReturn(0, &cmd_fix.dummy_handle, 1000 / portTICK_PERIOD_MS, ESP_OK); + i2c_master_cmd_begin_ExpectAndReturn(I2C_NUM_0, &cmd_fix.dummy_handle, 1000 / portTICK_PERIOD_MS, ESP_OK); I2CRead reader(READ_SIZE); std::vector result = reader.do_transfer(I2CNumber::I2C0(), I2CAddress(0x47)); @@ -261,7 +261,7 @@ TEST_CASE("I2CComposed calls driver correctly") // will actually read the data but for the tests it is enough for now i2c_master_read_ReturnArrayThruPtr_data(READ_DATA, READ_SIZE); i2c_master_stop_ExpectAndReturn(&cmd_fix.dummy_handle, ESP_OK); - i2c_master_cmd_begin_ExpectAndReturn(0, &cmd_fix.dummy_handle, 1000 / portTICK_PERIOD_MS, ESP_OK); + i2c_master_cmd_begin_ExpectAndReturn(I2C_NUM_0, &cmd_fix.dummy_handle, 1000 / portTICK_PERIOD_MS, ESP_OK); I2CComposed composed_transfer; composed_transfer.add_write({0x47, 0x48, 0x49}); @@ -289,7 +289,7 @@ TEST_CASE("I2CWrite transfer calls driver correctly") // will actually write the data but for the tests it is enough for now i2c_master_write_ExpectWithArrayAndReturn(&cmd_fix.dummy_handle, expected_write, WRITE_SIZE, EXPECTED_DATA_LEN, true, ESP_OK); i2c_master_stop_ExpectAndReturn(&cmd_fix.dummy_handle, ESP_OK); - i2c_master_cmd_begin_ExpectAndReturn(0, &cmd_fix.dummy_handle, 1000 / portTICK_PERIOD_MS, ESP_OK); + i2c_master_cmd_begin_ExpectAndReturn(I2C_NUM_0, &cmd_fix.dummy_handle, 1000 / portTICK_PERIOD_MS, ESP_OK); I2CMaster master(I2CNumber::I2C0(), SCL_GPIO(1), SDA_GPIO(2), Frequency(400000)); std::vector WRITE_BYTES = {0xAB, 0xBA}; @@ -310,7 +310,7 @@ TEST_CASE("I2CMaster synchronous write") // will actually write the data but for the tests it is enough for now i2c_master_write_ExpectWithArrayAndReturn(&cmd_fix.dummy_handle, expected_write, WRITE_SIZE, EXPECTED_DATA_LEN, true, ESP_OK); i2c_master_stop_ExpectAndReturn(&cmd_fix.dummy_handle, ESP_OK); - i2c_master_cmd_begin_ExpectAndReturn(0, &cmd_fix.dummy_handle, 1000 / portTICK_PERIOD_MS, ESP_OK); + i2c_master_cmd_begin_ExpectAndReturn(I2C_NUM_0, &cmd_fix.dummy_handle, 1000 / portTICK_PERIOD_MS, ESP_OK); I2CMaster master(I2CNumber::I2C0(), SCL_GPIO(1), SDA_GPIO(2), Frequency(400000)); std::vector WRITE_BYTES = {0xAB, 0xBA}; @@ -332,7 +332,7 @@ TEST_CASE("I2CMaster synchronous read") // will actually read the data but for the tests it is enough for now i2c_master_read_ReturnArrayThruPtr_data(READ_DATA, READ_SIZE); i2c_master_stop_ExpectAndReturn(&cmd_fix.dummy_handle, ESP_OK); - i2c_master_cmd_begin_ExpectAndReturn(0, &cmd_fix.dummy_handle, 1000 / portTICK_PERIOD_MS, ESP_OK); + i2c_master_cmd_begin_ExpectAndReturn(I2C_NUM_0, &cmd_fix.dummy_handle, 1000 / portTICK_PERIOD_MS, ESP_OK); I2CMaster master(I2CNumber::I2C0(), SCL_GPIO(1), SDA_GPIO(2), Frequency(400000)); std::vector result = master.sync_read(I2CAddress(0x47), READ_SIZE); @@ -365,7 +365,7 @@ TEST_CASE("I2CMaster syncronous transfer (read and write)") // will actually read the data but for the tests it is enough for now i2c_master_read_ReturnArrayThruPtr_data(READ_DATA, READ_SIZE); i2c_master_stop_ExpectAndReturn(&cmd_fix.dummy_handle, ESP_OK); - i2c_master_cmd_begin_ExpectAndReturn(0, &cmd_fix.dummy_handle, 1000 / portTICK_PERIOD_MS, ESP_OK); + i2c_master_cmd_begin_ExpectAndReturn(I2C_NUM_0, &cmd_fix.dummy_handle, 1000 / portTICK_PERIOD_MS, ESP_OK); I2CMaster master(I2CNumber::I2C0(), SCL_GPIO(1), SDA_GPIO(2), Frequency(400000)); vector read_result = master.sync_transfer(I2CAddress(0x47), {0x47, 0x48, 0x49}, READ_SIZE); diff --git a/examples/cxx/experimental/experimental_cpp_component/i2c_cxx.cpp b/examples/cxx/experimental/experimental_cpp_component/i2c_cxx.cpp index e549aef15a..fab4ed85b4 100644 --- a/examples/cxx/experimental/experimental_cpp_component/i2c_cxx.cpp +++ b/examples/cxx/experimental/experimental_cpp_component/i2c_cxx.cpp @@ -15,6 +15,20 @@ namespace idf { #define I2C_CHECK_THROW(err) CHECK_THROW_SPECIFIC((err), I2CException) +/** + * I2C bus are defined in the header files, let's check that the values are correct + */ +#if SOC_I2C_NUM >= 2 +static_assert(I2C_NUM_1 == 1, "I2C_NUM_1 must be equal to 1"); +#endif // SOC_I2C_NUM >= 2 +static_assert(I2C_NUM_MAX == SOC_I2C_NUM, "I2C_NUM_MAX must be equal to SOC_I2C_NUM"); + +namespace { +i2c_port_t i2c_num_to_driver_type(I2CNumber num) { + return static_cast(num.get_num()); +} +} + esp_err_t check_i2c_num(uint32_t i2c_num) noexcept { if (i2c_num >= I2C_NUM_MAX) { @@ -96,7 +110,7 @@ void I2CCommandLink::stop() void I2CCommandLink::execute_transfer(I2CNumber i2c_num, chrono::milliseconds driver_timeout) { - esp_err_t err = i2c_master_cmd_begin(i2c_num.get_num(), handle, driver_timeout.count() / portTICK_PERIOD_MS); + esp_err_t err = i2c_master_cmd_begin(i2c_num_to_driver_type(i2c_num), handle, driver_timeout.count() / portTICK_PERIOD_MS); if (err != ESP_OK) { throw I2CTransferException(err); } @@ -121,13 +135,13 @@ I2CMaster::I2CMaster(I2CNumber i2c_number, conf.sda_io_num = sda_gpio.get_num(); conf.sda_pullup_en = sda_pullup; conf.master.clk_speed = clock_speed.get_value(); - I2C_CHECK_THROW(i2c_param_config(i2c_num.get_value(), &conf)); - I2C_CHECK_THROW(i2c_driver_install(i2c_num.get_value(), conf.mode, 0, 0, 0)); + I2C_CHECK_THROW(i2c_param_config(i2c_num_to_driver_type(i2c_num), &conf)); + I2C_CHECK_THROW(i2c_driver_install(i2c_num_to_driver_type(i2c_num), conf.mode, 0, 0, 0)); } I2CMaster::~I2CMaster() { - i2c_driver_delete(i2c_num.get_value()); + i2c_driver_delete(i2c_num_to_driver_type(i2c_num)); } void I2CMaster::sync_write(I2CAddress i2c_addr, const vector &data) @@ -174,23 +188,23 @@ I2CSlave::I2CSlave(I2CNumber i2c_number, conf.sda_pullup_en = sda_pullup; conf.slave.addr_10bit_en = 0; conf.slave.slave_addr = slave_addr.get_addr(); - I2C_CHECK_THROW(i2c_param_config(i2c_num.get_value(), &conf)); - I2C_CHECK_THROW(i2c_driver_install(i2c_num.get_value(), conf.mode, rx_buf_len, tx_buf_len, 0)); + I2C_CHECK_THROW(i2c_param_config(i2c_num_to_driver_type(i2c_num), &conf)); + I2C_CHECK_THROW(i2c_driver_install(i2c_num_to_driver_type(i2c_num), conf.mode, rx_buf_len, tx_buf_len, 0)); } I2CSlave::~I2CSlave() { - i2c_driver_delete(i2c_num.get_value()); + i2c_driver_delete(i2c_num_to_driver_type(i2c_num)); } int I2CSlave::write_raw(const uint8_t *data, size_t data_len, chrono::milliseconds timeout) { - return i2c_slave_write_buffer(i2c_num.get_value(), data, data_len, (TickType_t) timeout.count() / portTICK_PERIOD_MS); + return i2c_slave_write_buffer(i2c_num_to_driver_type(i2c_num), data, data_len, (TickType_t) timeout.count() / portTICK_PERIOD_MS); } int I2CSlave::read_raw(uint8_t *buffer, size_t buffer_len, chrono::milliseconds timeout) { - return i2c_slave_read_buffer(i2c_num.get_value(), buffer, buffer_len, (TickType_t) timeout.count() / portTICK_PERIOD_MS); + return i2c_slave_read_buffer(i2c_num_to_driver_type(i2c_num), buffer, buffer_len, (TickType_t) timeout.count() / portTICK_PERIOD_MS); } #endif // CONFIG_SOC_I2C_SUPPORT_SLAVE diff --git a/tools/mocks/hal/include/hal/i2c_types.h b/tools/mocks/hal/include/hal/i2c_types.h index 1eaf5216ab..ad76ed43e7 100644 --- a/tools/mocks/hal/include/hal/i2c_types.h +++ b/tools/mocks/hal/include/hal/i2c_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,7 +17,16 @@ extern "C" { #endif -typedef int i2c_port_t; +/** + * @brief I2C port number, can be I2C_NUM_0 ~ (I2C_NUM_MAX-1). + */ +typedef enum { + I2C_NUM_0 = 0, /*!< I2C port 0 */ +#if SOC_I2C_NUM >= 2 + I2C_NUM_1, /*!< I2C port 1 */ +#endif + I2C_NUM_MAX, /*!< I2C port max */ +} i2c_port_t; typedef enum{ I2C_MODE_SLAVE = 0, /*!< I2C slave mode */