mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-30 19:19:21 +00:00
i2c: Add supports on esp32s3
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user