Merge branch 'feature/bringup_i2c_for_s3' into 'master'

I2C:  Add support for esp32s3 and add source clock allocator

Closes IDF-2011

See merge request espressif/esp-idf!10923
This commit is contained in:
Michael (XIAO Xufeng) 2020-11-12 22:12:58 +08:00
commit caf83b88ba
14 changed files with 1365 additions and 1212 deletions

View File

@ -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;
}

View File

@ -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.

View File

@ -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)
{

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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);

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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 0RSTART 1WRITE 2READ 3STOP . 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;