mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
i2c: Add supports on esp32s3
This commit is contained in:
parent
f5939c9e68
commit
6eee601cf6
@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2015-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.
|
||||
@ -70,6 +70,7 @@ static const char *I2C_TAG = "i2c";
|
||||
#define I2C_DATA_LEN_ERR_STR "i2c data read length error"
|
||||
#define I2C_PSRAM_BUFFER_WARN_STR "Using buffer allocated from psram"
|
||||
#define I2C_LOCK_ERR_STR "Power lock creation error"
|
||||
#define I2C_CLK_FLAG_ERR_STR "i2c clock choice is invalid, please check flag and frequency"
|
||||
#define I2C_FIFO_FULL_THRESH_VAL (28)
|
||||
#define I2C_FIFO_EMPTY_THRESH_VAL (5)
|
||||
#define I2C_IO_INIT_LEVEL (1)
|
||||
@ -92,6 +93,12 @@ static const char *I2C_TAG = "i2c";
|
||||
.hw_enabled = false,\
|
||||
}
|
||||
|
||||
// Freq limitation when using different clock sources
|
||||
#define I2C_CLK_LIMIT_REF_TICK (1 * 1000 * 1000 / 20) /*!< Limited by REF_TICK, no more than REF_TICK/20*/
|
||||
#define I2C_CLK_LIMIT_APB (80 * 1000 * 1000 / 20) /*!< Limited by APB, no more than APB/20*/
|
||||
#define I2C_CLK_LIMIT_RTC (20 * 1000 * 1000 / 20) /*!< Limited by RTC, no more than RTC/20*/
|
||||
#define I2C_CLK_LIMIT_XTAL (40 * 1000 * 1000 / 20) /*!< Limited by RTC, no more than XTAL/20*/
|
||||
|
||||
typedef struct {
|
||||
i2c_hw_cmd_t hw_cmd;
|
||||
uint8_t *data; /*!< data address */
|
||||
@ -161,11 +168,34 @@ typedef struct {
|
||||
#endif
|
||||
} i2c_context_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t character; /*!< I2C source clock characteristic */
|
||||
uint32_t clk_freq; /*!< I2C source clock frequency */
|
||||
} i2c_clk_alloc_t;
|
||||
|
||||
static i2c_context_t i2c_context[I2C_NUM_MAX] = {
|
||||
I2C_CONTEX_INIT_DEF(I2C_NUM_0),
|
||||
I2C_CONTEX_INIT_DEF(I2C_NUM_1),
|
||||
};
|
||||
|
||||
// i2c clock characteristic, The order is the same as i2c_sclk_t.
|
||||
static i2c_clk_alloc_t i2c_clk_alloc[I2C_SCLK_MAX] = {
|
||||
{0, 0},
|
||||
#if SOC_I2C_SUPPORT_APB
|
||||
{0, I2C_CLK_LIMIT_APB}, /*!< I2C APB clock characteristic*/
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_XTAL
|
||||
{0, I2C_CLK_LIMIT_XTAL}, /*!< I2C XTAL characteristic*/
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_RTC
|
||||
{I2C_SCLK_SRC_FLAG_LIGHT_SLEEP, I2C_CLK_LIMIT_RTC}, /*!< I2C 20M RTC characteristic*/
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_REF_TICK
|
||||
{I2C_SCLK_SRC_FLAG_AWARE_DFS | I2C_SCLK_SRC_FLAG_LIGHT_SLEEP, I2C_CLK_LIMIT_REF_TICK}, /*!< I2C REF_TICK characteristic*/
|
||||
#endif
|
||||
};
|
||||
|
||||
static i2c_obj_t *p_i2c_obj[I2C_NUM_MAX] = {0};
|
||||
static void i2c_isr_handler_default(void *arg);
|
||||
static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num);
|
||||
@ -590,6 +620,21 @@ static esp_err_t i2c_hw_fsm_reset(i2c_port_t i2c_num)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static i2c_sclk_t i2c_get_clk_src(const i2c_config_t *i2c_conf)
|
||||
{
|
||||
for (i2c_sclk_t clk = I2C_SCLK_DEFAULT + 1; clk < I2C_SCLK_MAX; clk++) {
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
if (clk == I2C_SCLK_RTC) { // RTC clock for s3 is unaccessable now.
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (((i2c_conf->clk_flags | i2c_clk_alloc[clk].character) == i2c_clk_alloc[clk].character) && (i2c_conf->master.clk_speed <= i2c_clk_alloc[clk].clk_freq)) {
|
||||
return clk;
|
||||
}
|
||||
}
|
||||
return I2C_SCLK_MAX; // flag invalid;
|
||||
}
|
||||
|
||||
esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
@ -614,11 +659,13 @@ 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));
|
||||
i2c_hal_update_config(&(i2c_context[i2c_num].hal));
|
||||
} else {
|
||||
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);
|
||||
i2c_hal_set_bus_timing(&(i2c_context[i2c_num].hal), i2c_conf->master.clk_speed, I2C_SCLK_APB);
|
||||
I2C_CHECK(i2c_get_clk_src(i2c_conf) != I2C_SCLK_MAX, I2C_CLK_FLAG_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
i2c_hal_set_bus_timing(&(i2c_context[i2c_num].hal), i2c_conf->master.clk_speed, i2c_get_clk_src(i2c_conf));
|
||||
}
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
return ESP_OK;
|
||||
@ -882,7 +929,7 @@ esp_err_t i2c_master_start(i2c_cmd_handle_t cmd_handle)
|
||||
cmd.hw_cmd.ack_en = 0;
|
||||
cmd.hw_cmd.ack_exp = 0;
|
||||
cmd.hw_cmd.ack_val = 0;
|
||||
cmd.hw_cmd.op_code = I2C_CMD_RESTART;
|
||||
cmd.hw_cmd.op_code = I2C_LL_CMD_RESTART;
|
||||
cmd.hw_cmd.byte_num = 0;
|
||||
cmd.data = NULL;
|
||||
return i2c_cmd_link_append(cmd_handle, &cmd);
|
||||
@ -895,7 +942,7 @@ esp_err_t i2c_master_stop(i2c_cmd_handle_t cmd_handle)
|
||||
cmd.hw_cmd.ack_en = 0;
|
||||
cmd.hw_cmd.ack_exp = 0;
|
||||
cmd.hw_cmd.ack_val = 0;
|
||||
cmd.hw_cmd.op_code = I2C_CMD_STOP;
|
||||
cmd.hw_cmd.op_code = I2C_LL_CMD_STOP;
|
||||
cmd.hw_cmd.byte_num = 0;
|
||||
cmd.data = NULL;
|
||||
return i2c_cmd_link_append(cmd_handle, &cmd);
|
||||
@ -916,7 +963,7 @@ esp_err_t i2c_master_write(i2c_cmd_handle_t cmd_handle, const uint8_t *data, siz
|
||||
cmd.hw_cmd.ack_en = ack_en;
|
||||
cmd.hw_cmd.ack_exp = 0;
|
||||
cmd.hw_cmd.ack_val = 0;
|
||||
cmd.hw_cmd.op_code = I2C_CMD_WRITE;
|
||||
cmd.hw_cmd.op_code = I2C_LL_CMD_WRITE;
|
||||
cmd.hw_cmd.byte_num = len_tmp;
|
||||
cmd.data = (uint8_t*) data + data_offset;
|
||||
ret = i2c_cmd_link_append(cmd_handle, &cmd);
|
||||
@ -935,7 +982,7 @@ esp_err_t i2c_master_write_byte(i2c_cmd_handle_t cmd_handle, uint8_t data, bool
|
||||
cmd.hw_cmd.ack_en = ack_en;
|
||||
cmd.hw_cmd.ack_exp = 0;
|
||||
cmd.hw_cmd.ack_val = 0;
|
||||
cmd.hw_cmd.op_code = I2C_CMD_WRITE;
|
||||
cmd.hw_cmd.op_code = I2C_LL_CMD_WRITE;
|
||||
cmd.hw_cmd.byte_num = 1;
|
||||
cmd.data = NULL;
|
||||
cmd.byte_cmd = data;
|
||||
@ -955,7 +1002,7 @@ static esp_err_t i2c_master_read_static(i2c_cmd_handle_t cmd_handle, uint8_t *da
|
||||
cmd.hw_cmd.ack_exp = 0;
|
||||
cmd.hw_cmd.ack_val = ack & 0x1;
|
||||
cmd.hw_cmd.byte_num = len_tmp;
|
||||
cmd.hw_cmd.op_code = I2C_CMD_READ;
|
||||
cmd.hw_cmd.op_code = I2C_LL_CMD_READ;
|
||||
cmd.data = data + data_offset;
|
||||
ret = i2c_cmd_link_append(cmd_handle, &cmd);
|
||||
data_offset += len_tmp;
|
||||
@ -977,7 +1024,7 @@ esp_err_t i2c_master_read_byte(i2c_cmd_handle_t cmd_handle, uint8_t *data, i2c_a
|
||||
cmd.hw_cmd.ack_exp = 0;
|
||||
cmd.hw_cmd.ack_val = ((ack == I2C_MASTER_LAST_NACK) ? I2C_MASTER_NACK : (ack & 0x1));
|
||||
cmd.hw_cmd.byte_num = 1;
|
||||
cmd.hw_cmd.op_code = I2C_CMD_READ;
|
||||
cmd.hw_cmd.op_code = I2C_LL_CMD_READ;
|
||||
cmd.data = data;
|
||||
return i2c_cmd_link_append(cmd_handle, &cmd);
|
||||
}
|
||||
@ -1036,12 +1083,12 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
|
||||
return;
|
||||
}
|
||||
const i2c_hw_cmd_t hw_end_cmd = {
|
||||
.op_code = I2C_CMD_END
|
||||
.op_code = I2C_LL_CMD_END
|
||||
};
|
||||
while (p_i2c->cmd_link.head) {
|
||||
i2c_cmd_t *cmd = &p_i2c->cmd_link.head->cmd;
|
||||
i2c_hw_cmd_t hw_cmd = cmd->hw_cmd;
|
||||
if (cmd->hw_cmd.op_code == I2C_CMD_WRITE) {
|
||||
if (cmd->hw_cmd.op_code == I2C_LL_CMD_WRITE) {
|
||||
uint8_t wr_filled = 0;
|
||||
uint8_t *write_pr = NULL;
|
||||
//TODO: to reduce interrupt number
|
||||
@ -1066,7 +1113,7 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
|
||||
}
|
||||
p_i2c->status = I2C_STATUS_WRITE;
|
||||
break;
|
||||
} else if (cmd->hw_cmd.op_code == I2C_CMD_READ) {
|
||||
} else if (cmd->hw_cmd.op_code == I2C_LL_CMD_READ) {
|
||||
//TODO: to reduce interrupt number
|
||||
p_i2c->rx_cnt = cmd->hw_cmd.byte_num > SOC_I2C_FIFO_LEN ? SOC_I2C_FIFO_LEN : cmd->hw_cmd.byte_num;
|
||||
cmd->hw_cmd.byte_num -= p_i2c->rx_cnt;
|
||||
@ -1086,6 +1133,7 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
|
||||
break;
|
||||
}
|
||||
}
|
||||
i2c_hal_update_config(&(i2c_context[i2c_num].hal));
|
||||
i2c_hal_trans_start(&(i2c_context[i2c_num].hal));
|
||||
return;
|
||||
}
|
||||
@ -1096,7 +1144,7 @@ static bool is_cmd_link_buffer_internal(i2c_cmd_link_t *link)
|
||||
{
|
||||
i2c_cmd_link_t *cmd_link = link;
|
||||
while (cmd_link != NULL) {
|
||||
if (cmd_link->cmd.hw_cmd.op_code == I2C_CMD_WRITE || cmd_link->cmd.hw_cmd.op_code == I2C_CMD_READ) {
|
||||
if (cmd_link->cmd.hw_cmd.op_code == I2C_LL_CMD_WRITE || cmd_link->cmd.hw_cmd.op_code == I2C_LL_CMD_READ) {
|
||||
if (cmd_link->cmd.data != NULL && !esp_ptr_internal(cmd_link->cmd.data)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2015-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.
|
||||
|
@ -19,8 +19,6 @@
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
#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*/
|
||||
#define DELAY_TIME_BETWEEN_ITEMS_MS 1234 /*!< delay time between different test items */
|
||||
@ -75,6 +73,7 @@ static i2c_config_t i2c_master_init(void)
|
||||
.master.clk_speed = I2C_MASTER_FREQ_HZ,
|
||||
.sda_io_num = I2C_MASTER_SDA_IO,
|
||||
.scl_io_num = I2C_MASTER_SCL_IO,
|
||||
.clk_flags = 0,
|
||||
};
|
||||
return conf_master;
|
||||
}
|
||||
@ -249,7 +248,7 @@ TEST_CASE("I2C driver memory leaking check", "[i2c]")
|
||||
TEST_ASSERT_INT_WITHIN(100, size, esp_get_free_heap_size());
|
||||
}
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3)
|
||||
|
||||
// print the reading buffer
|
||||
static void disp_buf(uint8_t *buf, int len)
|
||||
@ -590,7 +589,12 @@ TEST_CASE("test i2c_slave_write_buffer is not blocked when ticks_to_wait=0", "[i
|
||||
|
||||
TEST_CASE("I2C general API test", "[i2c]")
|
||||
{
|
||||
const int i2c_num = 1;
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
||||
#define I2C_TEST_TIME 0x3ff
|
||||
#else
|
||||
#define I2C_TEST_TIME 0x1f
|
||||
#endif
|
||||
const int i2c_num = 0;
|
||||
i2c_config_t conf_master = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
@ -601,7 +605,7 @@ TEST_CASE("I2C general API test", "[i2c]")
|
||||
};
|
||||
TEST_ESP_OK(i2c_param_config( i2c_num, &conf_master));
|
||||
int time_get0, time_get1;
|
||||
for(int i = 10; i < 0x3ff; i++) {
|
||||
for(int i = 10; i < I2C_TEST_TIME; i++) {
|
||||
//set period test
|
||||
TEST_ESP_OK(i2c_set_period(i2c_num, i, i));
|
||||
TEST_ESP_OK(i2c_get_period(i2c_num, &time_get0, &time_get1));
|
||||
@ -625,6 +629,7 @@ TEST_CASE("I2C general API test", "[i2c]")
|
||||
}
|
||||
}
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
//Init uart baud rate detection
|
||||
static void uart_aut_baud_det_init(int rxd_io_num)
|
||||
{
|
||||
|
@ -67,6 +67,13 @@ typedef struct {
|
||||
uint16_t tout; /*!< I2C bus timeout period */
|
||||
} i2c_clk_cal_t;
|
||||
|
||||
// I2C operation mode command
|
||||
#define I2C_LL_CMD_RESTART 0 /*!<I2C restart command */
|
||||
#define I2C_LL_CMD_WRITE 1 /*!<I2C write command */
|
||||
#define I2C_LL_CMD_READ 2 /*!<I2C read command */
|
||||
#define I2C_LL_CMD_STOP 3 /*!<I2C stop command */
|
||||
#define I2C_LL_CMD_END 4 /*!<I2C end command */
|
||||
|
||||
// Get the I2C hardware instance
|
||||
#define I2C_LL_GET_HW(i2c_num) (((i2c_num) == 0) ? &I2C0 : &I2C1)
|
||||
// Get the I2C hardware FIFO address
|
||||
@ -79,10 +86,8 @@ typedef struct {
|
||||
#define I2C_LL_SLAVE_TX_INT (I2C_TXFIFO_EMPTY_INT_ENA_M)
|
||||
// I2C slave RX interrupt bitmap
|
||||
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_FULL_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
|
||||
//I2C base clock freq 80M
|
||||
#define I2C_BASE_CLK_FREQ (80000000)
|
||||
|
||||
|
||||
// I2C source clock frequency
|
||||
#define I2C_LL_CLK_SRC_FREQ(src_clk) (80*1000*1000)
|
||||
/**
|
||||
* @brief Calculate I2C bus frequency
|
||||
*
|
||||
@ -856,6 +861,18 @@ static inline void i2c_ll_slave_init(i2c_dev_t *hw)
|
||||
hw->fifo_conf.fifo_addr_cfg_en = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update I2C configuration
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_update(i2c_dev_t *hw)
|
||||
{
|
||||
;// ESP32 do not support
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -68,6 +68,13 @@ typedef struct {
|
||||
uint16_t tout; /*!< I2C bus timeout period */
|
||||
} i2c_clk_cal_t;
|
||||
|
||||
// I2C operation mode command
|
||||
#define I2C_LL_CMD_RESTART 0 /*!<I2C restart command */
|
||||
#define I2C_LL_CMD_WRITE 1 /*!<I2C write command */
|
||||
#define I2C_LL_CMD_READ 2 /*!<I2C read command */
|
||||
#define I2C_LL_CMD_STOP 3 /*!<I2C stop command */
|
||||
#define I2C_LL_CMD_END 4 /*!<I2C end command */
|
||||
|
||||
// Get the I2C hardware instance
|
||||
#define I2C_LL_GET_HW(i2c_num) (((i2c_num) == 0) ? &I2C0 : &I2C1)
|
||||
// Get the I2C hardware FIFO address
|
||||
@ -80,8 +87,8 @@ typedef struct {
|
||||
#define I2C_LL_SLAVE_TX_INT (I2C_TXFIFO_WM_INT_ENA_M)
|
||||
// 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_REF_TICK) ? 1000*1000 : 80*1000*1000); // Another clock is APB clock
|
||||
/**
|
||||
* @brief Calculate I2C bus frequency
|
||||
*
|
||||
@ -781,7 +788,8 @@ static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw)
|
||||
*/
|
||||
static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_sclk_t src_clk)
|
||||
{
|
||||
hw->ctr.ref_always_on = src_clk;
|
||||
// src_clk : (1) for APB_CLK, (0) for REF_CLK
|
||||
hw->ctr.ref_always_on = (src_clk == I2C_SCLK_REF_TICK) ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -846,8 +854,6 @@ static inline void i2c_ll_master_init(i2c_dev_t *hw)
|
||||
ctrl_reg.ms_mode = 1;
|
||||
ctrl_reg.sda_force_out = 1;
|
||||
ctrl_reg.scl_force_out = 1;
|
||||
//Disable REF tick;
|
||||
ctrl_reg.ref_always_on = 1;
|
||||
hw->ctr.val = ctrl_reg.val;
|
||||
}
|
||||
|
||||
@ -881,13 +887,23 @@ static inline void i2c_ll_slave_init(i2c_dev_t *hw)
|
||||
//Open-drain output via GPIO
|
||||
ctrl_reg.sda_force_out = 1;
|
||||
ctrl_reg.scl_force_out = 1;
|
||||
//Disable REF tick;
|
||||
ctrl_reg.ref_always_on = 1;
|
||||
hw->ctr.val = ctrl_reg.val;
|
||||
hw->fifo_conf.fifo_addr_cfg_en = 0;
|
||||
hw->scl_stretch_conf.slave_scl_stretch_en = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update I2C configuration
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_update(i2c_dev_t *hw)
|
||||
{
|
||||
;// ESP32S2 do not support
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
// 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.
|
||||
@ -23,7 +23,6 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */
|
||||
|
||||
/**
|
||||
* @brief I2C hardware cmd register filed.
|
||||
*/
|
||||
@ -58,8 +57,10 @@ typedef enum {
|
||||
* @brief Data structure for calculating I2C bus timing.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t clkm_div; /*!< I2C core clock devider */
|
||||
uint16_t scl_low; /*!< I2C scl low period */
|
||||
uint16_t scl_high; /*!< I2C scl hight period */
|
||||
uint16_t scl_wait_high; /*!< I2C scl wait_high period */
|
||||
uint16_t sda_hold; /*!< I2C scl low period */
|
||||
uint16_t sda_sample; /*!< I2C sda sample time */
|
||||
uint16_t setup; /*!< I2C start and stop condition setup period */
|
||||
@ -67,24 +68,33 @@ typedef struct {
|
||||
uint16_t tout; /*!< I2C bus timeout period */
|
||||
} i2c_clk_cal_t;
|
||||
|
||||
// I2C operation mode command
|
||||
#define I2C_LL_CMD_RESTART 6 /*!<I2C restart command */
|
||||
#define I2C_LL_CMD_WRITE 1 /*!<I2C write command */
|
||||
#define I2C_LL_CMD_READ 3 /*!<I2C read command */
|
||||
#define I2C_LL_CMD_STOP 2 /*!<I2C stop command */
|
||||
#define I2C_LL_CMD_END 4 /*!<I2C end command */
|
||||
|
||||
// Get the I2C hardware instance
|
||||
#define I2C_LL_GET_HW(i2c_num) (((i2c_num) == 0) ? &I2C0 : &I2C1)
|
||||
// Get the I2C hardware FIFO address
|
||||
#define I2C_LL_GET_FIFO_ADDR(i2c_num) (I2C_DATA_APB_REG(i2c_num))
|
||||
// I2C master TX interrupt bitmap
|
||||
#define I2C_LL_MASTER_TX_INT (I2C_ACK_ERR_INT_ENA_M|I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M)
|
||||
#define I2C_LL_MASTER_TX_INT (I2C_NACK_INT_ENA_M|I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M)
|
||||
// I2C master RX interrupt bitmap
|
||||
#define I2C_LL_MASTER_RX_INT (I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M)
|
||||
// I2C slave TX interrupt bitmap
|
||||
#define I2C_LL_SLAVE_TX_INT (I2C_TXFIFO_EMPTY_INT_ENA_M)
|
||||
#define I2C_LL_SLAVE_TX_INT (I2C_TXFIFO_WM_INT_ENA_M)
|
||||
// I2C slave RX interrupt bitmap
|
||||
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_FULL_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
|
||||
//I2C base clock freq 80M
|
||||
#define I2C_BASE_CLK_FREQ (80000000)
|
||||
|
||||
#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) ? 8*1000*1000 : 40*1000*1000); // Another clock is XTAL clock
|
||||
|
||||
/**
|
||||
* @brief Calculate I2C bus frequency
|
||||
* Note that the clock accuracy is affected by the external pull-up resistor,
|
||||
* here we try to to calculate a configuration parameter which is close to the required clock.
|
||||
* But in I2C communication, the clock accuracy is not very concerned.
|
||||
*
|
||||
* @param source_clk I2C source clock
|
||||
* @param bus_freq I2C bus frequency
|
||||
@ -94,14 +104,35 @@ typedef struct {
|
||||
*/
|
||||
static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2c_clk_cal_t *clk_cal)
|
||||
{
|
||||
uint32_t half_cycle = source_clk / bus_freq / 2;
|
||||
uint32_t clkm_div = source_clk / (bus_freq * 1024) +1;
|
||||
uint32_t sclk_freq = source_clk / clkm_div;
|
||||
uint32_t half_cycle = sclk_freq / bus_freq / 2;
|
||||
//SCL
|
||||
clk_cal->clkm_div = clkm_div;
|
||||
clk_cal->scl_low = half_cycle;
|
||||
clk_cal->scl_high = half_cycle;
|
||||
// default, scl_wait_high < scl_high
|
||||
clk_cal->scl_high = (bus_freq <= 50000) ? half_cycle : (half_cycle / 5 * 4 + 4);
|
||||
clk_cal->scl_wait_high = half_cycle - clk_cal->scl_high;
|
||||
clk_cal->sda_hold = half_cycle / 2;
|
||||
clk_cal->sda_sample = clk_cal->scl_high / 2;
|
||||
// scl_wait_high < sda_sample <= scl_high
|
||||
clk_cal->sda_sample = half_cycle / 2;
|
||||
clk_cal->setup = half_cycle;
|
||||
clk_cal->hold = half_cycle;
|
||||
clk_cal->tout = half_cycle * 20; //default we set the timeout value to 10 bus cycles.
|
||||
//default we set the timeout value to about 10 bus cycles
|
||||
// log(20*half_cycle)/log(2) = log(half_cycle)/log(2) + log(20)/log(2)
|
||||
clk_cal->tout = (int)(sizeof(half_cycle) * 8 - __builtin_clz(5 * half_cycle)) + 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update I2C configuration
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_update(i2c_dev_t *hw)
|
||||
{
|
||||
hw->ctr.conf_upgate = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -114,8 +145,9 @@ static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2
|
||||
*/
|
||||
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg)
|
||||
{
|
||||
hw->clk_conf.sclk_div_num = bus_cfg->clkm_div - 1;
|
||||
//scl period
|
||||
hw->scl_low_period.period = bus_cfg->scl_low;
|
||||
hw->scl_low_period.period = bus_cfg->scl_low - 1;
|
||||
hw->scl_high_period.period = bus_cfg->scl_high;
|
||||
//sda sample
|
||||
hw->sda_hold.time = bus_cfg->sda_hold;
|
||||
@ -124,9 +156,10 @@ static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg)
|
||||
hw->scl_rstart_setup.time = bus_cfg->setup;
|
||||
hw->scl_stop_setup.time = bus_cfg->setup;
|
||||
//hold
|
||||
hw->scl_start_hold.time = bus_cfg->hold;
|
||||
hw->scl_start_hold.time = bus_cfg->hold - 1;
|
||||
hw->scl_stop_hold.time = bus_cfg->hold;
|
||||
hw->timeout.tout = bus_cfg->tout;
|
||||
hw->timeout.time_out_value = bus_cfg->tout;
|
||||
hw->timeout.time_out_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -159,15 +192,17 @@ static inline void i2c_ll_rxfifo_rst(i2c_dev_t *hw)
|
||||
* @brief Configure I2C SCL timing
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param hight_period The I2C SCL hight period (in APB cycle)
|
||||
* @param low_period The I2C SCL low period (in APB cycle)
|
||||
* @param high_period The I2C SCL hight period (in core clock cycle, hight_period > 2)
|
||||
* @param low_period The I2C SCL low period (in core clock cycle, low_period > 1)
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void i2c_ll_set_scl_timing(i2c_dev_t *hw, int hight_period, int low_period)
|
||||
static inline void i2c_ll_set_scl_timing(i2c_dev_t *hw, int high_period, int low_period)
|
||||
{
|
||||
hw->scl_low_period.period = low_period;
|
||||
hw->scl_high_period.period = hight_period;
|
||||
int high_period_output = high_period - 10; // The rising edge by open-drain output + internal pullup (about 50K) is slow
|
||||
hw->scl_low_period.period = low_period - 1;
|
||||
hw->scl_high_period.period = high_period_output;
|
||||
hw->scl_high_period.scl_wait_high_period = high_period - high_period_output;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -238,13 +273,13 @@ static inline void i2c_ll_set_fifo_mode(i2c_dev_t *hw, bool fifo_mode_en)
|
||||
* @brief Configure I2C timeout
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param tout_num The I2C timeout value needs to be set (in APB cycle)
|
||||
* @param tout_num The I2C timeout value needs to be set (2^tout in core clock cycle)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_tout(i2c_dev_t *hw, int tout)
|
||||
{
|
||||
hw->timeout.tout = tout;
|
||||
hw->timeout.time_out_value = tout;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -280,23 +315,23 @@ static inline void i2c_ll_write_cmd_reg(i2c_dev_t *hw, i2c_hw_cmd_t cmd, int cmd
|
||||
* @brief Configure I2C start timing
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param start_setup The start condition setup period (in APB cycle)
|
||||
* @param start_hold The start condition hold period (in APB cycle)
|
||||
* @param start_setup The start condition setup period (in core clock cycle)
|
||||
* @param start_hold The start condition hold period (in core clock cycle)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_start_timing(i2c_dev_t *hw, int start_setup, int start_hold)
|
||||
{
|
||||
hw->scl_rstart_setup.time = start_setup;
|
||||
hw->scl_start_hold.time = start_hold;
|
||||
hw->scl_start_hold.time = start_hold - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure I2C stop timing
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param stop_setup The stop condition setup period (in APB cycle)
|
||||
* @param stop_hold The stop condition hold period (in APB cycle)
|
||||
* @param stop_setup The stop condition setup period (in core clock cycle)
|
||||
* @param stop_hold The stop condition hold period (in core clock cycle)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
@ -310,8 +345,8 @@ static inline void i2c_ll_set_stop_timing(i2c_dev_t *hw, int stop_setup, int sto
|
||||
* @brief Configure I2C stop timing
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param sda_sample The SDA sample time (in APB cycle)
|
||||
* @param sda_hold The SDA hold time (in APB cycle)
|
||||
* @param sda_sample The SDA sample time (in core clock cycle)
|
||||
* @param sda_hold The SDA hold time (in core clock cycle)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
@ -331,7 +366,7 @@ static inline void i2c_ll_set_sda_timing(i2c_dev_t *hw, int sda_sample, int sda_
|
||||
*/
|
||||
static inline void i2c_ll_set_txfifo_empty_thr(i2c_dev_t *hw, uint8_t empty_thr)
|
||||
{
|
||||
hw->fifo_conf.tx_fifo_empty_thrhd = empty_thr;
|
||||
hw->fifo_conf.tx_fifo_wm_thrhd = empty_thr;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -344,7 +379,7 @@ static inline void i2c_ll_set_txfifo_empty_thr(i2c_dev_t *hw, uint8_t empty_thr)
|
||||
*/
|
||||
static inline void i2c_ll_set_rxfifo_full_thr(i2c_dev_t *hw, uint8_t full_thr)
|
||||
{
|
||||
hw->fifo_conf.rx_fifo_full_thrhd = full_thr;
|
||||
hw->fifo_conf.rx_fifo_wm_thrhd = full_thr;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -461,7 +496,7 @@ static inline uint32_t i2c_ll_get_txfifo_len(i2c_dev_t *hw)
|
||||
*/
|
||||
static inline uint32_t i2c_ll_get_tout(i2c_dev_t *hw)
|
||||
{
|
||||
return hw->timeout.tout;
|
||||
return hw->timeout.time_out_value;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -488,7 +523,7 @@ static inline void i2c_ll_trans_start(i2c_dev_t *hw)
|
||||
static inline void i2c_ll_get_start_timing(i2c_dev_t *hw, int *setup_time, int *hold_time)
|
||||
{
|
||||
*setup_time = hw->scl_rstart_setup.time;
|
||||
*hold_time = hw->scl_start_hold.time;
|
||||
*hold_time = hw->scl_start_hold.time + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -517,8 +552,8 @@ static inline void i2c_ll_get_stop_timing(i2c_dev_t *hw, int *setup_time, int *h
|
||||
*/
|
||||
static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *low_period)
|
||||
{
|
||||
*high_period = hw->scl_high_period.period;
|
||||
*low_period = hw->scl_low_period.period;
|
||||
*high_period = hw->scl_high_period.period + hw->scl_high_period.scl_wait_high_period;
|
||||
*low_period = hw->scl_low_period.period + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -532,9 +567,8 @@ static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *l
|
||||
*/
|
||||
static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
|
||||
{
|
||||
uint32_t fifo_addr = (hw == &I2C0) ? 0x6001301c : 0x6002701c;
|
||||
for(int i = 0; i < len; i++) {
|
||||
WRITE_PERI_REG(fifo_addr, ptr[i]);
|
||||
for (int i = 0; i< len; i++) {
|
||||
hw->fifo_data.data = ptr[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -565,14 +599,14 @@ static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
|
||||
*/
|
||||
static inline void i2c_ll_set_filter(i2c_dev_t *hw, uint8_t filter_num)
|
||||
{
|
||||
if(filter_num > 0) {
|
||||
hw->scl_filter_cfg.thres = filter_num;
|
||||
hw->sda_filter_cfg.thres = filter_num;
|
||||
hw->scl_filter_cfg.en = 1;
|
||||
hw->sda_filter_cfg.en = 1;
|
||||
if (filter_num > 0) {
|
||||
hw->filter_cfg.scl_thres = filter_num;
|
||||
hw->filter_cfg.sda_thres = filter_num;
|
||||
hw->filter_cfg.scl_en = 1;
|
||||
hw->filter_cfg.sda_en = 1;
|
||||
} else {
|
||||
hw->scl_filter_cfg.en = 0;
|
||||
hw->sda_filter_cfg.en = 0;
|
||||
hw->filter_cfg.scl_en = 0;
|
||||
hw->filter_cfg.sda_en = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -585,7 +619,7 @@ static inline void i2c_ll_set_filter(i2c_dev_t *hw, uint8_t filter_num)
|
||||
*/
|
||||
static inline uint8_t i2c_ll_get_filter(i2c_dev_t *hw)
|
||||
{
|
||||
return hw->sda_filter_cfg.thres;
|
||||
return hw->filter_cfg.scl_thres;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -743,7 +777,7 @@ static inline void i2c_ll_slave_clr_rx_it(i2c_dev_t *hw)
|
||||
*/
|
||||
static inline void i2c_ll_master_fsm_rst(i2c_dev_t *hw)
|
||||
{
|
||||
;//ESP32 do not support
|
||||
hw->ctr.fsm_rst = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -758,7 +792,10 @@ static inline void i2c_ll_master_fsm_rst(i2c_dev_t *hw)
|
||||
*/
|
||||
static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw)
|
||||
{
|
||||
;//ESP32 do not support
|
||||
hw->scl_sp_conf.scl_rst_slv_num = 9;
|
||||
hw->scl_sp_conf.scl_rst_slv_en = 0;
|
||||
hw->ctr.conf_upgate = 1;
|
||||
hw->scl_sp_conf.scl_rst_slv_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -771,7 +808,7 @@ static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw)
|
||||
*/
|
||||
static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_sclk_t src_clk)
|
||||
{
|
||||
;//Not support on ESP32
|
||||
hw->clk_conf.sclk_sel = (src_clk == I2C_SCLK_RTC) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -787,7 +824,7 @@ static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *even
|
||||
typeof(hw->int_status) int_sts = hw->int_status;
|
||||
if (int_sts.arbitration_lost) {
|
||||
*event = I2C_INTR_EVENT_ARBIT_LOST;
|
||||
} else if (int_sts.ack_err) {
|
||||
} else if (int_sts.nack) {
|
||||
*event = I2C_INTR_EVENT_NACK;
|
||||
} else if (int_sts.time_out) {
|
||||
*event = I2C_INTR_EVENT_TOUT;
|
||||
@ -811,11 +848,11 @@ static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *even
|
||||
static inline void i2c_ll_slave_get_event(i2c_dev_t *hw, i2c_intr_event_t *event)
|
||||
{
|
||||
typeof(hw->int_status) int_sts = hw->int_status;
|
||||
if (int_sts.tx_fifo_empty) {
|
||||
if (int_sts.tx_fifo_wm) {
|
||||
*event = I2C_INTR_EVENT_TXFIFO_EMPTY;
|
||||
} else if (int_sts.trans_complete) {
|
||||
*event = I2C_INTR_EVENT_TRANS_DONE;
|
||||
} else if (int_sts.rx_fifo_full) {
|
||||
} else if (int_sts.rx_fifo_wm) {
|
||||
*event = I2C_INTR_EVENT_RXFIFO_FULL;
|
||||
} else {
|
||||
*event = I2C_INTR_EVENT_ERR;
|
||||
@ -834,6 +871,7 @@ static inline void i2c_ll_master_init(i2c_dev_t *hw)
|
||||
typeof(hw->ctr) ctrl_reg;
|
||||
ctrl_reg.val = 0;
|
||||
ctrl_reg.ms_mode = 1;
|
||||
ctrl_reg.clk_en = 1;
|
||||
ctrl_reg.sda_force_out = 1;
|
||||
ctrl_reg.scl_force_out = 1;
|
||||
hw->ctr.val = ctrl_reg.val;
|
||||
|
@ -176,9 +176,11 @@ void i2c_hal_disable_slave_rx_it(i2c_hal_context_t *hal)
|
||||
|
||||
void i2c_hal_set_bus_timing(i2c_hal_context_t *hal, uint32_t scl_freq, i2c_sclk_t src_clk)
|
||||
{
|
||||
uint32_t sclk = (src_clk == I2C_SCLK_REF_TICK) ? 1000000 : 80000000;
|
||||
i2c_ll_set_source_clk(hal->dev, src_clk);
|
||||
uint32_t sclk = I2C_LL_CLK_SRC_FREQ(src_clk);
|
||||
i2c_clk_cal_t clk_cal = {0};
|
||||
i2c_ll_cal_bus_clk(sclk, scl_freq, &clk_cal);
|
||||
uint32_t scl_hw_freq = (scl_freq == I2C_CLK_FREQ_MAX) ? (src_clk / 20) : scl_freq; // FREQ_MAX use the highest freq of the chosen clk.
|
||||
i2c_ll_cal_bus_clk(sclk, scl_hw_freq, &clk_cal);
|
||||
i2c_ll_set_bus_timing(hal->dev, &clk_cal);
|
||||
}
|
||||
|
||||
@ -216,3 +218,8 @@ void i2c_hal_master_init(i2c_hal_context_t *hal, int i2c_num)
|
||||
i2c_ll_txfifo_rst(hal->dev);
|
||||
i2c_ll_rxfifo_rst(hal->dev);
|
||||
}
|
||||
|
||||
void i2c_hal_update_config(i2c_hal_context_t *hal)
|
||||
{
|
||||
i2c_ll_update(hal->dev);
|
||||
}
|
||||
|
@ -522,3 +522,13 @@ void i2c_hal_master_handle_rx_event(i2c_hal_context_t *hal, i2c_intr_event_t *ev
|
||||
* @return None
|
||||
*/
|
||||
void i2c_hal_slave_handle_event(i2c_hal_context_t *hal, i2c_intr_event_t *event);
|
||||
|
||||
/**
|
||||
* @brief Synchronize I2C status
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
void i2c_hal_update_config(i2c_hal_context_t *hal);
|
||||
|
@ -38,14 +38,6 @@ typedef enum {
|
||||
I2C_MASTER_READ, /*!< I2C read data */
|
||||
} i2c_rw_t;
|
||||
|
||||
typedef enum{
|
||||
I2C_CMD_RESTART = 0, /*!<I2C restart command */
|
||||
I2C_CMD_WRITE, /*!<I2C write command */
|
||||
I2C_CMD_READ, /*!<I2C read command */
|
||||
I2C_CMD_STOP, /*!<I2C stop command */
|
||||
I2C_CMD_END /*!<I2C end command */
|
||||
} i2c_opmode_t;
|
||||
|
||||
typedef enum {
|
||||
I2C_DATA_MODE_MSB_FIRST = 0, /*!< I2C data msb first */
|
||||
I2C_DATA_MODE_LSB_FIRST = 1, /*!< I2C data lsb first */
|
||||
@ -65,11 +57,36 @@ typedef enum {
|
||||
I2C_MASTER_ACK_MAX,
|
||||
} i2c_ack_type_t;
|
||||
|
||||
/**
|
||||
* @brief I2C clock source, sorting from smallest to largest,
|
||||
* place them in order.
|
||||
* This can be expanded in the future use.
|
||||
*/
|
||||
typedef enum {
|
||||
I2C_SCLK_REF_TICK, /*!< I2C source clock from REF_TICK */
|
||||
I2C_SCLK_APB, /*!< I2C source clock from APB */
|
||||
I2C_SCLK_DEFAULT = 0, /*!< I2C source clock not selected*/
|
||||
#if SOC_I2C_SUPPORT_APB
|
||||
I2C_SCLK_APB, /*!< I2C source clock from APB, 80M*/
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_XTAL
|
||||
I2C_SCLK_XTAL, /*!< I2C source clock from XTAL, 40M */
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_RTC
|
||||
I2C_SCLK_RTC, /*!< I2C source clock from 8M RTC, 8M */
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_REF_TICK
|
||||
I2C_SCLK_REF_TICK, /*!< I2C source clock from REF_TICK, 1M */
|
||||
#endif
|
||||
I2C_SCLK_MAX,
|
||||
} i2c_sclk_t;
|
||||
|
||||
// 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.*/
|
||||
#define I2C_SCLK_SRC_FLAG_LIGHT_SLEEP (1 << 1) /*!< For light sleep mode.*/
|
||||
|
||||
/// Use the highest speed that is available for the clock source picked by clk_flags
|
||||
#define I2C_CLK_FREQ_MAX (-1)
|
||||
|
||||
/**
|
||||
* @brief I2C initialization parameters
|
||||
*/
|
||||
@ -89,8 +106,19 @@ typedef struct{
|
||||
uint16_t slave_addr; /*!< I2C address for slave mode */
|
||||
} slave; /*!< I2C slave config */
|
||||
};
|
||||
uint32_t clk_flags; /*!< Bitwise of ``I2C_SCLK_SRC_FLAG_**FOR_DFS**`` for clk source choice*/
|
||||
} i2c_config_t;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
typedef enum{
|
||||
I2C_CMD_RESTART = 0, /*!<I2C restart command */
|
||||
I2C_CMD_WRITE, /*!<I2C write command */
|
||||
I2C_CMD_READ, /*!<I2C read command */
|
||||
I2C_CMD_STOP, /*!<I2C stop command */
|
||||
I2C_CMD_END /*!<I2C end command */
|
||||
} i2c_opmode_t __attribute__((deprecated));
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -120,6 +120,8 @@
|
||||
|
||||
#define SOC_I2C_FIFO_LEN (32) /*!< I2C hardware FIFO depth */
|
||||
|
||||
#define SOC_I2C_SUPPORT_APB (1)
|
||||
|
||||
/*-------------------------- I2S CAPS ----------------------------------------*/
|
||||
// ESP32 have 2 I2S
|
||||
#define SOC_I2S_NUM (2)
|
||||
|
@ -113,6 +113,9 @@
|
||||
//ESP32-S2 support hardware clear bus
|
||||
#define SOC_I2C_SUPPORT_HW_CLR_BUS (1)
|
||||
|
||||
#define SOC_I2C_SUPPORT_REF_TICK (1)
|
||||
#define SOC_I2C_SUPPORT_APB (1)
|
||||
|
||||
/*-------------------------- I2S CAPS ----------------------------------------*/
|
||||
// ESP32-S2 have 2 I2S
|
||||
#define SOC_I2S_NUM (1)
|
||||
|
@ -28,6 +28,9 @@ extern "C" {
|
||||
//ESP32-S3 support hardware clear bus
|
||||
#define SOC_I2C_SUPPORT_HW_CLR_BUS (1)
|
||||
|
||||
#define SOC_I2C_SUPPORT_XTAL (1)
|
||||
#define SOC_I2C_SUPPORT_RTC (1)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
// Copyright 2017-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
// 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.
|
||||
@ -22,41 +22,43 @@ extern "C" {
|
||||
typedef volatile struct {
|
||||
union {
|
||||
struct {
|
||||
uint32_t period: 14;
|
||||
uint32_t reserved14: 18;
|
||||
uint32_t period: 9;
|
||||
uint32_t reserved9: 23;
|
||||
};
|
||||
uint32_t val;
|
||||
} scl_low_period;
|
||||
union {
|
||||
struct {
|
||||
uint32_t sda_force_out: 1;
|
||||
uint32_t scl_force_out: 1;
|
||||
uint32_t sample_scl_level: 1;
|
||||
uint32_t ack_level: 1;
|
||||
uint32_t ms_mode: 1;
|
||||
uint32_t trans_start: 1;
|
||||
uint32_t tx_lsb_first: 1;
|
||||
uint32_t rx_lsb_first: 1;
|
||||
uint32_t clk_en: 1;
|
||||
uint32_t arbitration_en: 1;
|
||||
uint32_t fsm_rst: 1;
|
||||
uint32_t ref_always_on: 1;
|
||||
uint32_t reserved12: 20;
|
||||
uint32_t sda_force_out: 1;
|
||||
uint32_t scl_force_out: 1;
|
||||
uint32_t sample_scl_level: 1;
|
||||
uint32_t rx_full_ack_level: 1;
|
||||
uint32_t ms_mode: 1;
|
||||
uint32_t trans_start: 1;
|
||||
uint32_t tx_lsb_first: 1;
|
||||
uint32_t rx_lsb_first: 1;
|
||||
uint32_t clk_en: 1;
|
||||
uint32_t arbitration_en: 1;
|
||||
uint32_t fsm_rst: 1;
|
||||
uint32_t conf_upgate: 1;
|
||||
uint32_t slv_tx_auto_start_en: 1;
|
||||
uint32_t reserved13: 19;
|
||||
};
|
||||
uint32_t val;
|
||||
} ctr;
|
||||
union {
|
||||
struct {
|
||||
uint32_t ack_rec: 1;
|
||||
uint32_t resp_rec: 1;
|
||||
uint32_t slave_rw: 1;
|
||||
uint32_t time_out: 1;
|
||||
uint32_t reserved2: 1;
|
||||
uint32_t arb_lost: 1;
|
||||
uint32_t bus_busy: 1;
|
||||
uint32_t slave_addressed: 1;
|
||||
uint32_t byte_trans: 1;
|
||||
uint32_t reserved6: 1;
|
||||
uint32_t reserved7: 1;
|
||||
uint32_t rx_fifo_cnt: 6;
|
||||
uint32_t reserved14: 4;
|
||||
uint32_t stretch_cause: 2;
|
||||
uint32_t reserved16: 2;
|
||||
uint32_t tx_fifo_cnt: 6;
|
||||
uint32_t scl_main_state_last: 3;
|
||||
uint32_t reserved27: 1;
|
||||
@ -67,9 +69,9 @@ typedef volatile struct {
|
||||
} status_reg;
|
||||
union {
|
||||
struct {
|
||||
uint32_t tout: 24;
|
||||
uint32_t time_out_en: 1;
|
||||
uint32_t reserved25: 7;
|
||||
uint32_t time_out_value: 5;
|
||||
uint32_t time_out_en: 1;
|
||||
uint32_t reserved6: 26;
|
||||
};
|
||||
uint32_t val;
|
||||
} timeout;
|
||||
@ -83,216 +85,222 @@ typedef volatile struct {
|
||||
} slave_addr;
|
||||
union {
|
||||
struct {
|
||||
uint32_t rx_fifo_start_addr: 5;
|
||||
uint32_t rx_fifo_end_addr: 5;
|
||||
uint32_t tx_fifo_start_addr: 5;
|
||||
uint32_t tx_fifo_end_addr: 5;
|
||||
uint32_t rx_update: 1;
|
||||
uint32_t tx_update: 1;
|
||||
uint32_t tx_fifo_init_raddr: 5;
|
||||
uint32_t rx_fifo_init_waddr: 5;
|
||||
uint32_t rx_fifo_raddr: 5;
|
||||
uint32_t rx_fifo_waddr: 5;
|
||||
uint32_t tx_fifo_raddr: 5;
|
||||
uint32_t tx_fifo_waddr: 5;
|
||||
uint32_t reserved20: 1;
|
||||
uint32_t reserved21: 1;
|
||||
uint32_t slave_rw_point: 8;
|
||||
uint32_t reserved30: 2;
|
||||
};
|
||||
uint32_t val;
|
||||
} fifo_st;
|
||||
union {
|
||||
struct {
|
||||
uint32_t rx_fifo_full_thrhd: 5;
|
||||
uint32_t tx_fifo_empty_thrhd: 5;
|
||||
uint32_t nonfifo_en: 1;
|
||||
uint32_t fifo_addr_cfg_en: 1;
|
||||
uint32_t rx_fifo_rst: 1;
|
||||
uint32_t tx_fifo_rst: 1;
|
||||
uint32_t nonfifo_rx_thres: 6;
|
||||
uint32_t nonfifo_tx_thres: 6;
|
||||
uint32_t reserved26: 6;
|
||||
uint32_t rx_fifo_wm_thrhd: 5;
|
||||
uint32_t tx_fifo_wm_thrhd: 5;
|
||||
uint32_t nonfifo_en: 1;
|
||||
uint32_t fifo_addr_cfg_en: 1;
|
||||
uint32_t rx_fifo_rst: 1;
|
||||
uint32_t tx_fifo_rst: 1;
|
||||
uint32_t fifo_prt_en: 1;
|
||||
uint32_t reserved15: 5;
|
||||
uint32_t reserved20: 6;
|
||||
uint32_t reserved26: 1;
|
||||
uint32_t reserved27: 5;
|
||||
};
|
||||
uint32_t val;
|
||||
} fifo_conf;
|
||||
union {
|
||||
struct {
|
||||
uint8_t data;
|
||||
uint8_t reserved[3];
|
||||
uint32_t data;
|
||||
};
|
||||
uint32_t val;
|
||||
} fifo_data;
|
||||
union {
|
||||
struct {
|
||||
uint32_t rx_fifo_full: 1;
|
||||
uint32_t tx_fifo_empty: 1;
|
||||
uint32_t rx_fifo_wm: 1;
|
||||
uint32_t tx_fifo_wm: 1;
|
||||
uint32_t rx_fifo_ovf: 1;
|
||||
uint32_t end_detect: 1;
|
||||
uint32_t slave_tran_comp: 1;
|
||||
uint32_t byte_trans_done: 1;
|
||||
uint32_t arbitration_lost: 1;
|
||||
uint32_t master_tran_comp: 1;
|
||||
uint32_t mst_tx_fifo_udf: 1;
|
||||
uint32_t trans_complete: 1;
|
||||
uint32_t time_out: 1;
|
||||
uint32_t trans_start: 1;
|
||||
uint32_t ack_err: 1;
|
||||
uint32_t rx_rec_full: 1;
|
||||
uint32_t tx_send_empty: 1;
|
||||
uint32_t nack: 1;
|
||||
uint32_t tx_fifo_ovf: 1;
|
||||
uint32_t rx_fifo_udf: 1;
|
||||
uint32_t scl_st_to: 1;
|
||||
uint32_t scl_main_st_to: 1;
|
||||
uint32_t det_start: 1;
|
||||
uint32_t reserved16: 16;
|
||||
uint32_t slave_stretch: 1;
|
||||
uint32_t reserved17: 15;
|
||||
};
|
||||
uint32_t val;
|
||||
} int_raw;
|
||||
union {
|
||||
struct {
|
||||
uint32_t rx_fifo_full: 1;
|
||||
uint32_t tx_fifo_empty: 1;
|
||||
uint32_t rx_fifo_wm: 1;
|
||||
uint32_t tx_fifo_wm: 1;
|
||||
uint32_t rx_fifo_ovf: 1;
|
||||
uint32_t end_detect: 1;
|
||||
uint32_t slave_tran_comp: 1;
|
||||
uint32_t byte_trans_done: 1;
|
||||
uint32_t arbitration_lost: 1;
|
||||
uint32_t master_tran_comp: 1;
|
||||
uint32_t mst_tx_fifo_udf: 1;
|
||||
uint32_t trans_complete: 1;
|
||||
uint32_t time_out: 1;
|
||||
uint32_t trans_start: 1;
|
||||
uint32_t ack_err: 1;
|
||||
uint32_t rx_rec_full: 1;
|
||||
uint32_t tx_send_empty: 1;
|
||||
uint32_t nack: 1;
|
||||
uint32_t tx_fifo_ovf: 1;
|
||||
uint32_t rx_fifo_udf: 1;
|
||||
uint32_t scl_st_to: 1;
|
||||
uint32_t scl_main_st_to: 1;
|
||||
uint32_t det_start: 1;
|
||||
uint32_t reserved16: 16;
|
||||
uint32_t slave_stretch: 1;
|
||||
uint32_t reserved17: 15;
|
||||
};
|
||||
uint32_t val;
|
||||
} int_clr;
|
||||
union {
|
||||
struct {
|
||||
uint32_t rx_fifo_full: 1;
|
||||
uint32_t tx_fifo_empty: 1;
|
||||
uint32_t rx_fifo_wm: 1;
|
||||
uint32_t tx_fifo_wm: 1;
|
||||
uint32_t rx_fifo_ovf: 1;
|
||||
uint32_t end_detect: 1;
|
||||
uint32_t slave_tran_comp: 1;
|
||||
uint32_t byte_trans_done: 1;
|
||||
uint32_t arbitration_lost: 1;
|
||||
uint32_t master_tran_comp: 1;
|
||||
uint32_t mst_tx_fifo_udf: 1;
|
||||
uint32_t trans_complete: 1;
|
||||
uint32_t time_out: 1;
|
||||
uint32_t trans_start: 1;
|
||||
uint32_t ack_err: 1;
|
||||
uint32_t rx_rec_full: 1;
|
||||
uint32_t tx_send_empty: 1;
|
||||
uint32_t nack: 1;
|
||||
uint32_t tx_fifo_ovf: 1;
|
||||
uint32_t rx_fifo_udf: 1;
|
||||
uint32_t scl_st_to: 1;
|
||||
uint32_t scl_main_st_to: 1;
|
||||
uint32_t det_start: 1;
|
||||
uint32_t reserved16: 16;
|
||||
uint32_t slave_stretch: 1;
|
||||
uint32_t reserved17: 15;
|
||||
};
|
||||
uint32_t val;
|
||||
} int_ena;
|
||||
union {
|
||||
struct {
|
||||
uint32_t rx_fifo_full: 1;
|
||||
uint32_t tx_fifo_empty: 1;
|
||||
uint32_t rx_fifo_wm: 1;
|
||||
uint32_t tx_fifo_wm: 1;
|
||||
uint32_t rx_fifo_ovf: 1;
|
||||
uint32_t end_detect: 1;
|
||||
uint32_t slave_tran_comp: 1;
|
||||
uint32_t byte_trans_done: 1;
|
||||
uint32_t arbitration_lost: 1;
|
||||
uint32_t master_tran_comp: 1;
|
||||
uint32_t mst_tx_fifo_udf: 1;
|
||||
uint32_t trans_complete: 1;
|
||||
uint32_t time_out: 1;
|
||||
uint32_t trans_start: 1;
|
||||
uint32_t ack_err: 1;
|
||||
uint32_t rx_rec_full: 1;
|
||||
uint32_t tx_send_empty: 1;
|
||||
uint32_t nack: 1;
|
||||
uint32_t tx_fifo_ovf: 1;
|
||||
uint32_t rx_fifo_udf: 1;
|
||||
uint32_t scl_st_to: 1;
|
||||
uint32_t scl_main_st_to: 1;
|
||||
uint32_t det_start: 1;
|
||||
uint32_t reserved16: 16;
|
||||
uint32_t slave_stretch: 1;
|
||||
uint32_t reserved17: 15;
|
||||
};
|
||||
uint32_t val;
|
||||
} int_status;
|
||||
union {
|
||||
struct {
|
||||
uint32_t time: 10;
|
||||
uint32_t reserved10: 22;
|
||||
uint32_t time: 9;
|
||||
uint32_t reserved9: 23;
|
||||
};
|
||||
uint32_t val;
|
||||
} sda_hold;
|
||||
union {
|
||||
struct {
|
||||
uint32_t time: 10;
|
||||
uint32_t reserved10: 22;
|
||||
uint32_t time: 9;
|
||||
uint32_t reserved9: 23;
|
||||
};
|
||||
uint32_t val;
|
||||
} sda_sample;
|
||||
union {
|
||||
struct {
|
||||
uint32_t period: 14;
|
||||
uint32_t scl_wait_high_period: 14;
|
||||
uint32_t reserved28: 4;
|
||||
uint32_t period: 9;
|
||||
uint32_t scl_wait_high_period: 7;
|
||||
uint32_t reserved16: 16;
|
||||
};
|
||||
uint32_t val;
|
||||
} scl_high_period;
|
||||
uint32_t reserved_3c;
|
||||
union {
|
||||
struct {
|
||||
uint32_t time: 10;
|
||||
uint32_t reserved10: 22;
|
||||
uint32_t time: 9;
|
||||
uint32_t reserved9: 23;
|
||||
};
|
||||
uint32_t val;
|
||||
} scl_start_hold;
|
||||
union {
|
||||
struct {
|
||||
uint32_t time: 10;
|
||||
uint32_t reserved10: 22;
|
||||
uint32_t time: 9;
|
||||
uint32_t reserved9: 23;
|
||||
};
|
||||
uint32_t val;
|
||||
} scl_rstart_setup;
|
||||
union {
|
||||
struct {
|
||||
uint32_t time: 14;
|
||||
uint32_t reserved14: 18;
|
||||
uint32_t time: 9;
|
||||
uint32_t reserved9: 23;
|
||||
};
|
||||
uint32_t val;
|
||||
} scl_stop_hold;
|
||||
union {
|
||||
struct {
|
||||
uint32_t time: 10;
|
||||
uint32_t reserved10: 22;
|
||||
uint32_t time: 9;
|
||||
uint32_t reserved9: 23;
|
||||
};
|
||||
uint32_t val;
|
||||
} scl_stop_setup;
|
||||
union {
|
||||
struct {
|
||||
uint32_t thres: 3;
|
||||
uint32_t en: 1;
|
||||
uint32_t reserved4: 28;
|
||||
uint32_t scl_thres: 4;
|
||||
uint32_t sda_thres: 4;
|
||||
uint32_t scl_en: 1;
|
||||
uint32_t sda_en: 1;
|
||||
uint32_t reserved10: 22;
|
||||
};
|
||||
uint32_t val;
|
||||
} scl_filter_cfg;
|
||||
} filter_cfg;
|
||||
union {
|
||||
struct {
|
||||
uint32_t thres: 3;
|
||||
uint32_t en: 1;
|
||||
uint32_t reserved4: 28;
|
||||
uint32_t sclk_div_num: 8;
|
||||
uint32_t sclk_div_a: 6;
|
||||
uint32_t sclk_div_b: 6;
|
||||
uint32_t sclk_sel: 1;
|
||||
uint32_t sclk_active: 1;
|
||||
uint32_t reserved22: 10;
|
||||
};
|
||||
uint32_t val;
|
||||
} sda_filter_cfg;
|
||||
} clk_conf;
|
||||
union {
|
||||
struct {
|
||||
uint32_t byte_num: 8; /*Byte_num represent the number of data need to be send or data need to be received.*/
|
||||
uint32_t ack_en: 1; /*ack_check_en ack_exp and ack value are used to control the ack bit.*/
|
||||
uint32_t ack_exp: 1; /*ack_check_en ack_exp and ack value are used to control the ack bit.*/
|
||||
uint32_t ack_val: 1; /*ack_check_en ack_exp and ack value are used to control the ack bit.*/
|
||||
uint32_t op_code: 3; /*op_code is the command 0:RSTART 1:WRITE 2:READ 3:STOP . 4:END.*/
|
||||
uint32_t command0: 14;
|
||||
uint32_t reserved14: 17;
|
||||
uint32_t done: 1;
|
||||
};
|
||||
uint32_t val;
|
||||
} command[16];
|
||||
} command[8];
|
||||
union {
|
||||
struct {
|
||||
uint32_t scl_st_to: 24;
|
||||
uint32_t reserved24: 8;
|
||||
uint32_t scl_st_to: 5; /*no more than 23*/
|
||||
uint32_t reserved5: 27;
|
||||
};
|
||||
uint32_t val;
|
||||
} scl_st_time_out;
|
||||
union {
|
||||
struct {
|
||||
uint32_t scl_main_st_to: 24;
|
||||
uint32_t reserved24: 8;
|
||||
uint32_t scl_main_st_to: 5; /*no more than 23*/
|
||||
uint32_t reserved5: 27;
|
||||
};
|
||||
uint32_t val;
|
||||
} scl_main_st_time_out;
|
||||
@ -306,6 +314,22 @@ typedef volatile struct {
|
||||
};
|
||||
uint32_t val;
|
||||
} scl_sp_conf;
|
||||
union {
|
||||
struct {
|
||||
uint32_t stretch_protect_num: 10;
|
||||
uint32_t slave_scl_stretch_en: 1;
|
||||
uint32_t slave_scl_stretch_clr: 1;
|
||||
uint32_t reserved12: 20;
|
||||
};
|
||||
uint32_t val;
|
||||
} scl_stretch_conf;
|
||||
uint32_t reserved_88;
|
||||
uint32_t reserved_8c;
|
||||
uint32_t reserved_90;
|
||||
uint32_t reserved_94;
|
||||
uint32_t reserved_98;
|
||||
uint32_t reserved_9c;
|
||||
uint32_t reserved_a0;
|
||||
uint32_t reserved_a4;
|
||||
uint32_t reserved_a8;
|
||||
uint32_t reserved_ac;
|
||||
@ -329,7 +353,39 @@ typedef volatile struct {
|
||||
uint32_t reserved_f4;
|
||||
uint32_t date; /**/
|
||||
uint32_t reserved_fc;
|
||||
uint32_t ram_data[32]; /**/
|
||||
uint32_t txfifo_start_addr; /**/
|
||||
uint32_t reserved_104;
|
||||
uint32_t reserved_108;
|
||||
uint32_t reserved_10c;
|
||||
uint32_t reserved_110;
|
||||
uint32_t reserved_114;
|
||||
uint32_t reserved_118;
|
||||
uint32_t reserved_11c;
|
||||
uint32_t reserved_120;
|
||||
uint32_t reserved_124;
|
||||
uint32_t reserved_128;
|
||||
uint32_t reserved_12c;
|
||||
uint32_t reserved_130;
|
||||
uint32_t reserved_134;
|
||||
uint32_t reserved_138;
|
||||
uint32_t reserved_13c;
|
||||
uint32_t reserved_140;
|
||||
uint32_t reserved_144;
|
||||
uint32_t reserved_148;
|
||||
uint32_t reserved_14c;
|
||||
uint32_t reserved_150;
|
||||
uint32_t reserved_154;
|
||||
uint32_t reserved_158;
|
||||
uint32_t reserved_15c;
|
||||
uint32_t reserved_160;
|
||||
uint32_t reserved_164;
|
||||
uint32_t reserved_168;
|
||||
uint32_t reserved_16c;
|
||||
uint32_t reserved_170;
|
||||
uint32_t reserved_174;
|
||||
uint32_t reserved_178;
|
||||
uint32_t reserved_17c;
|
||||
uint32_t fifo_start_addr; /**/
|
||||
} i2c_dev_t;
|
||||
|
||||
extern i2c_dev_t I2C0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user