esp-idf/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_common.c

348 wiersze
12 KiB
C

/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "unity.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_err.h"
#include "soc/gpio_periph.h"
#include "soc/clk_tree_defs.h"
#include "soc/soc_caps.h"
#include "hal/gpio_hal.h"
#include "hal/uart_ll.h"
#include "esp_private/periph_ctrl.h"
#include "driver/gpio.h"
#include "driver/i2c_master.h"
#include "esp_rom_gpio.h"
#include "esp_log.h"
#include "test_utils.h"
#include "test_board.h"
static const char TAG[] = "test-i2c";
// Make it as a local test, because don't know where there happened to be any pull-up on CI.
TEST_CASE("I2C master initialize without pins pull-up ", "[i2c][ignore]")
{
i2c_master_bus_config_t i2c_mst_config_1 = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = TEST_I2C_PORT,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_io_num = I2C_MASTER_SDA_IO,
.flags.enable_internal_pullup = false, // no pull-up
};
i2c_master_bus_handle_t bus_handle;
TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config_1, &bus_handle));
TEST_ESP_ERR(ESP_ERR_TIMEOUT, i2c_master_probe(bus_handle, 0x22, 20));
vTaskDelay(1000);
TEST_ESP_OK(i2c_del_master_bus(bus_handle));
}
TEST_CASE("I2C bus install-uninstall test", "[i2c]")
{
i2c_master_bus_config_t i2c_mst_config_1 = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = TEST_I2C_PORT,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_io_num = I2C_MASTER_SDA_IO,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t i2c_mst_handle1;
#if SOC_HP_I2C_NUM > 1
i2c_master_bus_config_t i2c_mst_config_2 = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = 1,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_io_num = I2C_MASTER_SDA_IO,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t i2c_mst_handle2;
#endif
// Install master bus 0
ESP_LOGI(TAG, "Initialize bus0");
TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config_1, &i2c_mst_handle1));
#if SOC_HP_I2C_NUM > 1
// Install master bus 1
ESP_LOGI(TAG, "Initialize bus1");
TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config_2, &i2c_mst_handle2));
#endif
// Install master bus 0 again
ESP_LOGI(TAG, "Initialize bus0 again");
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, i2c_new_master_bus(&i2c_mst_config_1, &i2c_mst_handle1));
ESP_LOGI(TAG, "Delete bus0");
TEST_ESP_OK(i2c_del_master_bus(i2c_mst_handle1));
#if SOC_HP_I2C_NUM > 1
ESP_LOGI(TAG, "Delete bus1");
TEST_ESP_OK(i2c_del_master_bus(i2c_mst_handle2));
#endif
}
TEST_CASE("I2C driver memory leaking check", "[i2c]")
{
i2c_master_bus_config_t i2c_mst_config_1 = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = TEST_I2C_PORT,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_io_num = I2C_MASTER_SDA_IO,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle;
int size = esp_get_free_heap_size();
for (uint32_t i = 0; i <= 5; i++) {
TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config_1, &bus_handle));
vTaskDelay(10 / portTICK_PERIOD_MS);
TEST_ESP_OK(i2c_del_master_bus(bus_handle));
}
TEST_ASSERT_INT_WITHIN(300, size, esp_get_free_heap_size());
}
TEST_CASE("I2C device add & remove check", "[i2c]")
{
i2c_master_bus_config_t i2c_mst_config_1 = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = TEST_I2C_PORT,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_io_num = I2C_MASTER_SDA_IO,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle;
TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config_1, &bus_handle));
i2c_device_config_t dev_cfg_1 = {
.scl_speed_hz = 100 * 1000,
.device_address = 0x10,
};
i2c_master_dev_handle_t dev_1;
i2c_master_bus_add_device(bus_handle, &dev_cfg_1, &dev_1);
i2c_device_config_t dev_cfg_2 = {
.scl_speed_hz = 100 * 1000,
.device_address = 0x20,
};
i2c_master_dev_handle_t dev_2;
i2c_master_bus_add_device(bus_handle, &dev_cfg_2, &dev_2);
i2c_device_config_t dev_cfg_3 = {
.scl_speed_hz = 100 * 1000,
.device_address = 0x30,
};
i2c_master_dev_handle_t dev_3;
i2c_master_bus_add_device(bus_handle, &dev_cfg_3, &dev_3);
i2c_master_bus_rm_device(dev_1);
i2c_master_bus_rm_device(dev_2);
i2c_master_bus_rm_device(dev_3);
TEST_ESP_OK(i2c_del_master_bus(bus_handle));
}
TEST_CASE("I2C master probe device test", "[i2c]")
{
// 0x22,33,44,55 does not exist on the I2C bus, so it's expected to return `not found` error
// TODO: Add exist slave for testing probe success after i2c slave is merged.
i2c_master_bus_config_t i2c_mst_config_1 = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = TEST_I2C_PORT,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_io_num = I2C_MASTER_SDA_IO,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle;
TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config_1, &bus_handle));
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, i2c_master_probe(bus_handle, 0x22, -1));
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, i2c_master_probe(bus_handle, 0x33, -1));
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, i2c_master_probe(bus_handle, 0x44, -1));
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, i2c_master_probe(bus_handle, 0x55, -1));
TEST_ESP_OK(i2c_del_master_bus(bus_handle));
}
TEST_CASE("probe test after general call (0x00 0x06)", "[i2c]")
{
uint8_t data_wr[1] = { 0x06 };
i2c_master_bus_config_t i2c_mst_config = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = TEST_I2C_PORT,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_io_num = I2C_MASTER_SDA_IO,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle;
TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));
i2c_device_config_t dev_cfg1 = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = 0x00,
.scl_speed_hz = 100000,
};
i2c_master_dev_handle_t dev_handle1;
TEST_ESP_OK(i2c_master_bus_add_device(bus_handle, &dev_cfg1, &dev_handle1));
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, i2c_master_transmit(dev_handle1, data_wr, 1, 200));
for (int i = 1; i < 0x7f; i++) {
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, i2c_master_probe(bus_handle, i, 800));
}
TEST_ESP_OK(i2c_master_bus_rm_device(dev_handle1));
TEST_ESP_OK(i2c_del_master_bus(bus_handle));
}
#define LENGTH 48
static IRAM_ATTR bool test_master_tx_done_callback(i2c_master_dev_handle_t i2c_dev, const i2c_master_event_data_t *evt_data, void *arg)
{
return true;
}
/*******************************************************************************
*
* This test aim to test I2C non-blocking transaction function. Several things have been
* done in this test for testing its memory/concurrency issues.
*
* 1. See the depth of queue is 37, but the number of transaction is 42, that means some
* queue must be reused.
* 2. There are some delay randomly set there, for testing the concurrency or any I2C state
* might be met.
*******************************************************************************
*/
TEST_CASE("I2C master transaction non-blocking mode with large amount of transaction", "[i2c]")
{
i2c_master_bus_config_t i2c_bus_config = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = TEST_I2C_PORT,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_io_num = I2C_MASTER_SDA_IO,
.glitch_ignore_cnt = 7,
.trans_queue_depth = 37,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle;
TEST_ESP_OK(i2c_new_master_bus(&i2c_bus_config, &bus_handle));
i2c_device_config_t dev_cfg = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = 0x58,
.scl_speed_hz = 400000,
.flags.disable_ack_check = true,
};
i2c_master_dev_handle_t dev_handle;
TEST_ESP_OK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));
i2c_master_event_callbacks_t cbs = {
.on_trans_done = test_master_tx_done_callback,
};
i2c_master_register_event_callbacks(dev_handle, &cbs, NULL);
uint32_t cnt = 7;
uint8_t *buf[6];
for (int i = 0; i < 6; i++) {
buf[i] = (uint8_t*)heap_caps_calloc(1, LENGTH, MALLOC_CAP_8BIT);
for (int j = 0; j < LENGTH; j++) {
buf[i][j] = i + j;
}
}
while (cnt--) {
i2c_master_transmit(dev_handle, buf[0], LENGTH, -1);
esp_rom_delay_us(1000);
i2c_master_transmit(dev_handle, buf[1], LENGTH, -1);
esp_rom_delay_us(500);
i2c_master_transmit(dev_handle, buf[2], LENGTH, -1);
esp_rom_delay_us(200);
i2c_master_transmit(dev_handle, buf[3], LENGTH, -1);
esp_rom_delay_us(400);
i2c_master_transmit(dev_handle, buf[4], LENGTH, -1);
esp_rom_delay_us(700);
i2c_master_transmit(dev_handle, buf[5], LENGTH, -1);
esp_rom_delay_us(200);
}
i2c_master_bus_wait_all_done(bus_handle, -1);
for (int i = 0; i < 6; i++) {
if (buf[i]) {
free(buf[i]);
}
}
TEST_ESP_OK(i2c_master_bus_rm_device(dev_handle));
TEST_ESP_OK(i2c_del_master_bus(bus_handle));
}
static void _test_i2c_new_bus_device(i2c_master_bus_handle_t *bus_handle, i2c_master_dev_handle_t *dev_handle)
{
i2c_master_bus_config_t i2c_mst_config = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = TEST_I2C_PORT,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_io_num = I2C_MASTER_SDA_IO,
.flags.enable_internal_pullup = true,
};
TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config, bus_handle));
i2c_device_config_t dev_cfg = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = 0x58,
.scl_speed_hz = 100000,
};
TEST_ESP_OK(i2c_master_bus_add_device(*bus_handle, &dev_cfg, dev_handle));
}
static void _test_i2c_del_bus_device(i2c_master_bus_handle_t bus_handle, i2c_master_dev_handle_t dev_handle)
{
TEST_ESP_OK(i2c_master_bus_rm_device(dev_handle));
TEST_ESP_OK(i2c_del_master_bus(bus_handle));
}
TEST_CASE("I2C master transaction transmit check nack return value", "[i2c]")
{
uint8_t data_wr[DATA_LENGTH] = { 0 };
i2c_master_bus_handle_t bus_handle;
i2c_master_dev_handle_t dev_handle;
_test_i2c_new_bus_device(&bus_handle, &dev_handle);
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, i2c_master_transmit(dev_handle, data_wr, DATA_LENGTH, -1));
_test_i2c_del_bus_device(bus_handle, dev_handle);
}
TEST_CASE("I2C master transaction transmit receive check nack return value", "[i2c]")
{
uint8_t data_wr[DATA_LENGTH] = { 0 };
uint8_t data_rd[DATA_LENGTH] = { 0 };
i2c_master_bus_handle_t bus_handle;
i2c_master_dev_handle_t dev_handle;
_test_i2c_new_bus_device(&bus_handle, &dev_handle);
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, i2c_master_transmit_receive(dev_handle, data_wr, DATA_LENGTH, data_rd, DATA_LENGTH, -1));
_test_i2c_del_bus_device(bus_handle, dev_handle);
}
TEST_CASE("I2C master transaction receive check nack return value", "[i2c]")
{
uint8_t data_rd[DATA_LENGTH] = { 0 };
i2c_master_bus_handle_t bus_handle;
i2c_master_dev_handle_t dev_handle;
_test_i2c_new_bus_device(&bus_handle, &dev_handle);
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, i2c_master_receive(dev_handle, data_rd, DATA_LENGTH, -1));
_test_i2c_del_bus_device(bus_handle, dev_handle);
}