diff --git a/.gitlab/ci/host-test.yml b/.gitlab/ci/host-test.yml index ba1d635693..d22e609862 100644 --- a/.gitlab/ci/host-test.yml +++ b/.gitlab/ci/host-test.yml @@ -364,6 +364,13 @@ test_cxx_gpio: - idf.py build - build/test_gpio_cxx_host.elf +test_i2c_cxx: + extends: .host_test_template + script: + - cd ${IDF_PATH}/examples/cxx/experimental/experimental_cpp_component/host_test/i2c + - idf.py build + - build/test_i2c_cxx_host.elf + test_spi_cxx: extends: .host_test_template script: diff --git a/components/driver/include/driver/i2c.h b/components/driver/include/driver/i2c.h index 22dcc8ab24..aa559bad14 100644 --- a/components/driver/include/driver/i2c.h +++ b/components/driver/include/driver/i2c.h @@ -18,7 +18,6 @@ extern "C" { #include "freertos/semphr.h" #include "freertos/task.h" #include "freertos/queue.h" -#include "freertos/ringbuf.h" #include "driver/gpio.h" #include "soc/soc_caps.h" #include "hal/i2c_types.h" diff --git a/examples/cxx/experimental/experimental_cpp_component/CMakeLists.txt b/examples/cxx/experimental/experimental_cpp_component/CMakeLists.txt index aee7a370aa..164a39845e 100644 --- a/examples/cxx/experimental/experimental_cpp_component/CMakeLists.txt +++ b/examples/cxx/experimental/experimental_cpp_component/CMakeLists.txt @@ -1,11 +1,10 @@ idf_build_get_property(target IDF_TARGET) -set(srcs "esp_timer_cxx.cpp" "esp_exception.cpp" "gpio_cxx.cpp" "spi_cxx.cpp" "spi_host_cxx.cpp") +set(srcs "esp_timer_cxx.cpp" "esp_exception.cpp" "gpio_cxx.cpp" "i2c_cxx.cpp" "spi_cxx.cpp" "spi_host_cxx.cpp") set(requires "esp_timer" "driver") if(NOT ${target} STREQUAL "linux") list(APPEND srcs - "i2c_cxx.cpp" "esp_event_api.cpp" "esp_event_cxx.cpp") list(APPEND requires "esp_event") diff --git a/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/CMakeLists.txt b/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/CMakeLists.txt new file mode 100644 index 0000000000..22310e13a1 --- /dev/null +++ b/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(COMPONENTS main) + +idf_build_set_property(COMPILE_DEFINITIONS "-DNO_DEBUG_STORAGE" APPEND) + +# Overriding components which should be mocked +list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/driver/") +list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/") +list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/esp_timer/") + +# Including experimental component here because it's outside IDF's main component directory +list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/cxx/experimental/experimental_cpp_component/") + +project(test_i2c_cxx_host) diff --git a/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/README.md b/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/README.md new file mode 100644 index 0000000000..e2981b6ec1 --- /dev/null +++ b/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/README.md @@ -0,0 +1,8 @@ +| Supported Targets | Linux | +| ----------------- | ----- | + +# Build +`idf.py build` (sdkconfig.defaults sets the linux target by default) + +# Run +`build/host_i2c_cxx_test.elf` diff --git a/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/main/CMakeLists.txt b/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/main/CMakeLists.txt new file mode 100644 index 0000000000..259c3de2ba --- /dev/null +++ b/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/main/CMakeLists.txt @@ -0,0 +1,9 @@ +idf_component_get_property(cpp_component experimental_cpp_component COMPONENT_DIR) + +idf_component_register(SRCS "i2c_cxx_test.cpp" + INCLUDE_DIRS + "." + "${cpp_component}/host_test/fixtures" + "${cpp_component}/private_include" + $ENV{IDF_PATH}/tools/catch + REQUIRES cmock driver experimental_cpp_component) 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 new file mode 100644 index 0000000000..3c38763cc3 --- /dev/null +++ b/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/main/i2c_cxx_test.cpp @@ -0,0 +1,56 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0 + * + * I2C C++ unit tests + * + * This example code is in the Public Domain (or CC0 licensed, at your option.) + * + * Unless required by applicable law or agreed to in writing, this + * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. +*/ +#define CATCH_CONFIG_MAIN +#include +#include "unity.h" +#include "freertos/portmacro.h" +#include "i2c_cxx.hpp" +#include "system_cxx.hpp" +#include "test_fixtures.hpp" + +#include "catch.hpp" + +extern "C" { +#include "Mocki2c.h" +} + +// TODO: IDF-2693, function definition just to satisfy linker, mock esp_common instead +const char *esp_err_to_name(esp_err_t code) { + return "host_test error"; +} + +using namespace std; +using namespace idf; + +TEST_CASE("I2CBus") +{ + I2CBus bus(static_cast(0)); +} + +TEST_CASE("I2CMaster parameter configuration fails") +{ + CMockFixture fix; + i2c_param_config_ExpectAnyArgsAndReturn(ESP_FAIL); + + CHECK_THROWS_AS(I2CMaster(0, 1, 2, 400000), I2CException&); +} + +TEST_CASE("I2CMaster driver install failure") +{ + CMockFixture fix; + i2c_param_config_ExpectAnyArgsAndReturn(ESP_OK); + i2c_driver_install_ExpectAnyArgsAndReturn(ESP_FAIL); + + CHECK_THROWS_AS(I2CMaster(0, 1, 2, 400000), I2CException&); +} diff --git a/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/sdkconfig.defaults b/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/sdkconfig.defaults new file mode 100644 index 0000000000..a057733348 --- /dev/null +++ b/examples/cxx/experimental/experimental_cpp_component/host_test/i2c/sdkconfig.defaults @@ -0,0 +1,3 @@ +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n +CONFIG_IDF_TARGET="linux" +CONFIG_CXX_EXCEPTIONS=y diff --git a/examples/cxx/experimental/experimental_cpp_component/test/test_i2c.cpp b/examples/cxx/experimental/experimental_cpp_component/test/test_i2c.cpp index ee07e4ed78..bf578d28d5 100644 --- a/examples/cxx/experimental/experimental_cpp_component/test/test_i2c.cpp +++ b/examples/cxx/experimental/experimental_cpp_component/test/test_i2c.cpp @@ -1,16 +1,8 @@ -// Copyright 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: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "unity.h" #include "unity_cxx.hpp" @@ -59,16 +51,6 @@ struct MasterFixture { vector data; }; -TEST_CASE("I2CMaster GPIO out of range", "[cxx i2c][leaks=300]") -{ - TEST_THROW(I2CMaster(0, 255, 255, 400000), I2CException); -} - -TEST_CASE("I2CMaster SDA and SCL equal", "[cxx i2c][leaks=300]") -{ - TEST_THROW(I2CMaster(0, 0, 0, 400000), I2CException); -} - TEST_CASE("I2Transfer timeout", "[cxx i2c][leaks=300]") { std::vector data = {MAGIC_TEST_NUMBER}; diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 3d062fe318..94df47ad4e 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -3153,7 +3153,6 @@ examples/cxx/experimental/experimental_cpp_component/include/esp_timer_cxx.hpp examples/cxx/experimental/experimental_cpp_component/test/test_cxx_exceptions.cpp examples/cxx/experimental/experimental_cpp_component/test/test_esp_event_cxx.cpp examples/cxx/experimental/experimental_cpp_component/test/test_esp_timer.cpp -examples/cxx/experimental/experimental_cpp_component/test/test_i2c.cpp examples/cxx/experimental/sensor_mcp9808/main/sensor_mcp9808.cpp examples/cxx/pthread/example_test.py examples/cxx/pthread/main/cpp_pthread.cpp diff --git a/tools/mocks/driver/CMakeLists.txt b/tools/mocks/driver/CMakeLists.txt index c672cf5aac..cb68badac0 100644 --- a/tools/mocks/driver/CMakeLists.txt +++ b/tools/mocks/driver/CMakeLists.txt @@ -2,7 +2,7 @@ # On Espressif chips, too many dependencies are missing at the moment. # Furthermore, this component can only mock the interfaces of # spi_master.h and gpio.h. -message(STATUS "building DRIVER MOCKS (only SPI and GPIO driver)") +message(STATUS "building DRIVER MOCKS (only SPI, I2C and GPIO driver)") idf_component_get_property(original_driver_dir driver COMPONENT_OVERRIDEN_DIR) @@ -10,6 +10,7 @@ set(include_dirs "${original_driver_dir}/include" "${original_driver_dir}/include/driver" "${CMAKE_CURRENT_SOURCE_DIR}/../hal/include" + "${CMAKE_CURRENT_SOURCE_DIR}/../soc/include" # for I2C SOC caps "${CMAKE_CURRENT_SOURCE_DIR}/../esp_hw_support/include") idf_component_mock(INCLUDE_DIRS ${include_dirs} @@ -17,6 +18,7 @@ idf_component_mock(INCLUDE_DIRS ${include_dirs} MOCK_HEADER_FILES ${original_driver_dir}/include/driver/spi_master.h ${original_driver_dir}/include/driver/spi_common.h + ${original_driver_dir}/include/driver/i2c.h ${original_driver_dir}/include/driver/gpio.h) idf_build_set_property(COMPILE_DEFINITIONS "-DSPI_MOCK" APPEND) diff --git a/tools/mocks/hal/include/hal/i2c_types.h b/tools/mocks/hal/include/hal/i2c_types.h new file mode 100644 index 0000000000..1eaf5216ab --- /dev/null +++ b/tools/mocks/hal/include/hal/i2c_types.h @@ -0,0 +1,54 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * NOTE: this is not the original header file from the hal component. It is a stripped-down copy to support mocking. + */ + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int i2c_port_t; + +typedef enum{ + I2C_MODE_SLAVE = 0, /*!< I2C slave mode */ + I2C_MODE_MASTER, /*!< I2C master mode */ + I2C_MODE_MAX, +} i2c_mode_t; + +typedef enum { + I2C_MASTER_WRITE = 0, /*!< I2C write data */ + I2C_MASTER_READ, /*!< I2C read data */ +} i2c_rw_t; + +typedef enum { + I2C_DATA_MODE_MSB_FIRST = 0, /*!< I2C data msb first */ + I2C_DATA_MODE_LSB_FIRST = 1, /*!< I2C data lsb first */ + I2C_DATA_MODE_MAX +} i2c_trans_mode_t; + +typedef enum { + I2C_ADDR_BIT_7 = 0, /*!< I2C 7bit address for slave mode */ + I2C_ADDR_BIT_10, /*!< I2C 10bit address for slave mode */ + I2C_ADDR_BIT_MAX, +} i2c_addr_mode_t; + +typedef enum { + I2C_MASTER_ACK = 0x0, /*!< I2C ack for each byte read */ + I2C_MASTER_NACK = 0x1, /*!< I2C nack for each byte read */ + I2C_MASTER_LAST_NACK = 0x2, /*!< I2C nack for the last byte*/ + I2C_MASTER_ACK_MAX, +} i2c_ack_type_t; + +#ifdef __cplusplus +} +#endif diff --git a/tools/mocks/soc/include/soc/soc_caps.h b/tools/mocks/soc/include/soc/soc_caps.h new file mode 100644 index 0000000000..5d60ac48f5 --- /dev/null +++ b/tools/mocks/soc/include/soc/soc_caps.h @@ -0,0 +1,11 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * NOTE: this is not the original header file from the soc component. It is a stripped-down copy to support mocking. + */ + +#define SOC_I2C_NUM (2)