I2C: Refactor i2c hal and ll

This commit is contained in:
Cao Sen Miao 2022-08-24 16:29:00 +08:00
parent 5e47c7ce13
commit 31b88a4c88
13 changed files with 1669 additions and 2238 deletions

View File

@ -34,8 +34,6 @@
#include "clk_ctrl_os.h"
#endif
static const char *I2C_TAG = "i2c";
/* DRAM_ATTR is required to avoid I2C array placed in flash, due to accessed from ISR */
@ -376,8 +374,8 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
}
i2c_hw_enable(i2c_num);
//Disable I2C interrupt.
i2c_hal_disable_intr_mask(&(i2c_context[i2c_num].hal), I2C_LL_INTR_MASK);
i2c_hal_clr_intsts_mask(&(i2c_context[i2c_num].hal), I2C_LL_INTR_MASK);
i2c_ll_disable_intr_mask(i2c_context[i2c_num].hal.dev, I2C_LL_INTR_MASK);
i2c_ll_clear_intr_mask(i2c_context[i2c_num].hal.dev, I2C_LL_INTR_MASK);
//hook isr handler
ret = esp_intr_alloc(i2c_periph_signal[i2c_num].irq, intr_alloc_flags,
i2c_isr_handler_default, p_i2c_obj[i2c_num],
@ -386,7 +384,7 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
#if SOC_I2C_SUPPORT_SLAVE
//Enable I2C slave rx interrupt
if (mode == I2C_MODE_SLAVE) {
i2c_hal_enable_slave_rx_it(&(i2c_context[i2c_num].hal));
i2c_ll_slave_enable_rx_it(i2c_context[i2c_num].hal.dev);
}
#endif // SOC_I2C_SUPPORT_SLAVE
return ESP_OK;
@ -443,7 +441,7 @@ esp_err_t i2c_driver_delete(i2c_port_t i2c_num)
ESP_RETURN_ON_FALSE(p_i2c_obj[i2c_num] != NULL, ESP_FAIL, I2C_TAG, I2C_DRIVER_ERR_STR);
i2c_obj_t *p_i2c = p_i2c_obj[i2c_num];
i2c_hal_disable_intr_mask(&(i2c_context[i2c_num].hal), I2C_LL_INTR_MASK);
i2c_ll_disable_intr_mask(i2c_context[i2c_num].hal.dev, I2C_LL_INTR_MASK);
esp_intr_free(p_i2c->intr_handle);
p_i2c->intr_handle = NULL;
@ -500,7 +498,7 @@ esp_err_t i2c_reset_tx_fifo(i2c_port_t i2c_num)
{
ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_NUM_ERROR_STR);
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_txfifo_rst(&(i2c_context[i2c_num].hal));
i2c_ll_txfifo_rst(i2c_context[i2c_num].hal.dev);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
return ESP_OK;
}
@ -509,7 +507,7 @@ esp_err_t i2c_reset_rx_fifo(i2c_port_t i2c_num)
{
ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_NUM_ERROR_STR);
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_rxfifo_rst(&(i2c_context[i2c_num].hal));
i2c_ll_rxfifo_rst(i2c_context[i2c_num].hal.dev);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
return ESP_OK;
}
@ -522,7 +520,7 @@ static void IRAM_ATTR i2c_isr_handler_default(void *arg)
// On C3 and S3 targets, the I2C may trigger a spurious interrupt,
// in order to detect these false positive, check the I2C's hardware interrupt mask
uint32_t int_mask;
i2c_hal_get_intsts_mask(&(i2c_context[i2c_num].hal), &int_mask);
i2c_ll_get_intr_mask(i2c_context[i2c_num].hal.dev, &int_mask);
if (int_mask == 0) {
return;
}
@ -561,25 +559,25 @@ static void IRAM_ATTR i2c_isr_handler_default(void *arg)
}
#if SOC_I2C_SUPPORT_SLAVE
else {
i2c_hal_slave_handle_event(&(i2c_context[i2c_num].hal), &evt_type);
i2c_ll_slave_get_event(i2c_context[i2c_num].hal.dev, &evt_type);
if (evt_type == I2C_INTR_EVENT_TRANS_DONE || evt_type == I2C_INTR_EVENT_RXFIFO_FULL) {
uint32_t rx_fifo_cnt;
i2c_hal_get_rxfifo_cnt(&(i2c_context[i2c_num].hal), &rx_fifo_cnt);
i2c_hal_read_rxfifo(&(i2c_context[i2c_num].hal), p_i2c->data_buf, rx_fifo_cnt);
i2c_ll_get_rxfifo_cnt(i2c_context[i2c_num].hal.dev, &rx_fifo_cnt);
i2c_ll_read_rxfifo(i2c_context[i2c_num].hal.dev, p_i2c->data_buf, rx_fifo_cnt);
xRingbufferSendFromISR(p_i2c->rx_ring_buf, p_i2c->data_buf, rx_fifo_cnt, &HPTaskAwoken);
i2c_hal_slave_clr_rx_it(&(i2c_context[i2c_num].hal));
i2c_ll_clear_intr_mask(i2c_context[i2c_num].hal.dev, int_mask);
} else if (evt_type == I2C_INTR_EVENT_TXFIFO_EMPTY) {
uint32_t tx_fifo_rem;
i2c_hal_get_txfifo_cnt(&(i2c_context[i2c_num].hal), &tx_fifo_rem);
i2c_ll_get_txfifo_len(i2c_context[i2c_num].hal.dev, &tx_fifo_rem);
size_t size = 0;
uint8_t *data = (uint8_t *) xRingbufferReceiveUpToFromISR(p_i2c->tx_ring_buf, &size, tx_fifo_rem);
if (data) {
i2c_hal_write_txfifo(&(i2c_context[i2c_num].hal), data, size);
i2c_ll_write_txfifo(i2c_context[i2c_num].hal.dev, data, size);
vRingbufferReturnItemFromISR(p_i2c->tx_ring_buf, data, &HPTaskAwoken);
} else {
i2c_hal_disable_slave_tx_it(&(i2c_context[i2c_num].hal));
i2c_ll_slave_disable_tx_it(i2c_context[i2c_num].hal.dev);
}
i2c_hal_slave_clr_tx_it(&(i2c_context[i2c_num].hal));
i2c_ll_clear_intr_mask(i2c_context[i2c_num].hal.dev, int_mask);
}
}
#endif // SOC_I2C_SUPPORT_SLAVE
@ -595,8 +593,8 @@ esp_err_t i2c_set_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t tx_trans_mode,
ESP_RETURN_ON_FALSE(tx_trans_mode < I2C_DATA_MODE_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_TRANS_MODE_ERR_STR);
ESP_RETURN_ON_FALSE(rx_trans_mode < I2C_DATA_MODE_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_TRANS_MODE_ERR_STR);
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_set_data_mode(&(i2c_context[i2c_num].hal), tx_trans_mode, rx_trans_mode);
i2c_hal_update_config(&(i2c_context[i2c_num].hal));
i2c_ll_set_data_mode(i2c_context[i2c_num].hal.dev, tx_trans_mode, rx_trans_mode);
i2c_ll_update(i2c_context[i2c_num].hal.dev);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
return ESP_OK;
}
@ -604,7 +602,7 @@ esp_err_t i2c_set_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t tx_trans_mode,
esp_err_t i2c_get_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t *tx_trans_mode, i2c_trans_mode_t *rx_trans_mode)
{
ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_NUM_ERROR_STR);
i2c_hal_get_data_mode(&(i2c_context[i2c_num].hal), tx_trans_mode, rx_trans_mode);
i2c_ll_get_data_mode(i2c_context[i2c_num].hal.dev, tx_trans_mode, rx_trans_mode);
return ESP_OK;
}
@ -642,7 +640,7 @@ static esp_err_t i2c_master_clear_bus(i2c_port_t i2c_num)
gpio_set_level(sda_io, 1); // STOP, SDA low -> high while SCL is HIGH
i2c_set_pin(i2c_num, sda_io, scl_io, 1, 1, I2C_MODE_MASTER);
#else
i2c_hal_master_clr_bus(&(i2c_context[i2c_num].hal));
i2c_ll_master_clr_bus(i2c_context[i2c_num].hal.dev);
#endif
return ESP_OK;
}
@ -656,36 +654,24 @@ static esp_err_t i2c_hw_fsm_reset(i2c_port_t i2c_num)
// A workaround for avoiding cause timeout issue when using
// hardware reset.
#if !SOC_I2C_SUPPORT_HW_FSM_RST
int scl_low_period, scl_high_period, scl_wait_high_period;
int scl_start_hold, scl_rstart_setup;
int scl_stop_hold, scl_stop_setup;
int sda_hold, sda_sample;
int timeout;
i2c_hal_timing_config_t timing_config;
uint8_t filter_cfg;
i2c_hal_get_scl_clk_timing(&(i2c_context[i2c_num].hal), &scl_high_period, &scl_low_period, &scl_wait_high_period);
i2c_hal_get_start_timing(&(i2c_context[i2c_num].hal), &scl_rstart_setup, &scl_start_hold);
i2c_hal_get_stop_timing(&(i2c_context[i2c_num].hal), &scl_stop_setup, &scl_stop_hold);
i2c_hal_get_sda_timing(&(i2c_context[i2c_num].hal), &sda_sample, &sda_hold);
i2c_hal_get_tout(&(i2c_context[i2c_num].hal), &timeout);
i2c_hal_get_filter(&(i2c_context[i2c_num].hal), &filter_cfg);
i2c_hal_get_timing_config(&i2c_context[i2c_num].hal, &timing_config);
i2c_ll_get_filter(i2c_context[i2c_num].hal.dev, &filter_cfg);
//to reset the I2C hw module, we need re-enable the hw
i2c_hw_disable(i2c_num);
i2c_master_clear_bus(i2c_num);
i2c_hw_enable(i2c_num);
i2c_hal_master_init(&(i2c_context[i2c_num].hal), i2c_num);
i2c_hal_disable_intr_mask(&(i2c_context[i2c_num].hal), I2C_LL_INTR_MASK);
i2c_hal_clr_intsts_mask(&(i2c_context[i2c_num].hal), I2C_LL_INTR_MASK);
i2c_hal_set_scl_clk_timing(&(i2c_context[i2c_num].hal), scl_high_period, scl_low_period, scl_wait_high_period);
i2c_hal_set_start_timing(&(i2c_context[i2c_num].hal), scl_rstart_setup, scl_start_hold);
i2c_hal_set_stop_timing(&(i2c_context[i2c_num].hal), scl_stop_setup, scl_stop_hold);
i2c_hal_set_sda_timing(&(i2c_context[i2c_num].hal), sda_sample, sda_hold);
i2c_hal_set_tout(&(i2c_context[i2c_num].hal), timeout);
i2c_hal_set_filter(&(i2c_context[i2c_num].hal), filter_cfg);
i2c_hal_master_init(&(i2c_context[i2c_num].hal));
i2c_ll_disable_intr_mask(i2c_context[i2c_num].hal.dev, I2C_LL_INTR_MASK);
i2c_ll_clear_intr_mask(i2c_context[i2c_num].hal.dev, I2C_LL_INTR_MASK);
i2c_hal_set_timing_config(&i2c_context[i2c_num].hal, &timing_config);
i2c_ll_set_filter(i2c_context[i2c_num].hal.dev, filter_cfg);
#else
i2c_hal_master_fsm_rst(&(i2c_context[i2c_num].hal));
i2c_ll_master_fsm_rst(i2c_context[i2c_num].hal.dev);
i2c_master_clear_bus(i2c_num);
#endif
return ESP_OK;
@ -769,28 +755,29 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf)
}
i2c_hw_enable(i2c_num);
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_disable_intr_mask(&(i2c_context[i2c_num].hal), I2C_LL_INTR_MASK);
i2c_hal_clr_intsts_mask(&(i2c_context[i2c_num].hal), I2C_LL_INTR_MASK);
i2c_ll_disable_intr_mask(i2c_context[i2c_num].hal.dev, I2C_LL_INTR_MASK);
i2c_ll_clear_intr_mask(i2c_context[i2c_num].hal.dev, I2C_LL_INTR_MASK);
#if SOC_I2C_SUPPORT_SLAVE
if (i2c_conf->mode == I2C_MODE_SLAVE) { //slave mode
i2c_hal_slave_init(&(i2c_context[i2c_num].hal), i2c_num);
i2c_hal_set_source_clk(&(i2c_context[i2c_num].hal), src_clk);
i2c_hal_set_slave_addr(&(i2c_context[i2c_num].hal), i2c_conf->slave.slave_addr, i2c_conf->slave.addr_10bit_en);
i2c_hal_set_rxfifo_full_thr(&(i2c_context[i2c_num].hal), I2C_FIFO_FULL_THRESH_VAL);
i2c_hal_set_txfifo_empty_thr(&(i2c_context[i2c_num].hal), I2C_FIFO_EMPTY_THRESH_VAL);
i2c_hal_slave_init(&(i2c_context[i2c_num].hal));
i2c_ll_slave_tx_auto_start_en(i2c_context[i2c_num].hal.dev, true);
i2c_ll_set_source_clk(i2c_context[i2c_num].hal.dev, src_clk);
i2c_ll_set_slave_addr(i2c_context[i2c_num].hal.dev, i2c_conf->slave.slave_addr, i2c_conf->slave.addr_10bit_en);
i2c_ll_set_rxfifo_full_thr(i2c_context[i2c_num].hal.dev, I2C_FIFO_FULL_THRESH_VAL);
i2c_ll_set_txfifo_empty_thr(i2c_context[i2c_num].hal.dev, I2C_FIFO_EMPTY_THRESH_VAL);
//set timing for data
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_ll_set_sda_timing(i2c_context[i2c_num].hal.dev, I2C_SLAVE_SDA_SAMPLE_DEFAULT, I2C_SLAVE_SDA_HOLD_DEFAULT);
i2c_ll_set_tout(i2c_context[i2c_num].hal.dev, I2C_SLAVE_TIMEOUT_DEFAULT);
i2c_ll_slave_enable_rx_it(i2c_context[i2c_num].hal.dev);
} else
#endif // SOC_I2C_SUPPORT_SLAVE
{
i2c_hal_master_init(&(i2c_context[i2c_num].hal), i2c_num);
i2c_hal_master_init(&(i2c_context[i2c_num].hal));
//Default, we enable hardware filter
i2c_hal_set_filter(&(i2c_context[i2c_num].hal), I2C_FILTER_CYC_NUM_DEF);
i2c_ll_set_filter(i2c_context[i2c_num].hal.dev, I2C_FILTER_CYC_NUM_DEF);
i2c_hal_set_bus_timing(&(i2c_context[i2c_num].hal), i2c_conf->master.clk_speed, src_clk, s_get_src_clk_freq(src_clk));
}
i2c_hal_update_config(&(i2c_context[i2c_num].hal));
i2c_ll_update(i2c_context[i2c_num].hal.dev);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
return ESP_OK;
}
@ -802,8 +789,8 @@ esp_err_t i2c_set_period(i2c_port_t i2c_num, int high_period, int low_period)
ESP_RETURN_ON_FALSE((low_period <= I2C_SCL_LOW_PERIOD_V) && (low_period > 0), ESP_ERR_INVALID_ARG, I2C_TAG, I2C_TIMING_VAL_ERR_STR);
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_set_scl_timing(&(i2c_context[i2c_num].hal), high_period, low_period);
i2c_hal_update_config(&(i2c_context[i2c_num].hal));
i2c_ll_set_scl_timing(i2c_context[i2c_num].hal.dev, high_period, low_period);
i2c_ll_update(i2c_context[i2c_num].hal.dev);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
return ESP_OK;
}
@ -812,7 +799,7 @@ esp_err_t i2c_get_period(i2c_port_t i2c_num, int *high_period, int *low_period)
{
ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX && high_period != NULL && low_period != NULL, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_NUM_ERROR_STR);
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_get_scl_timing(&(i2c_context[i2c_num].hal), high_period, low_period);
i2c_ll_get_scl_timing(i2c_context[i2c_num].hal.dev, high_period, low_period);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
return ESP_OK;
}
@ -822,8 +809,8 @@ esp_err_t i2c_filter_enable(i2c_port_t i2c_num, uint8_t cyc_num)
ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_NUM_ERROR_STR);
ESP_RETURN_ON_FALSE(p_i2c_obj[i2c_num] != NULL, ESP_FAIL, I2C_TAG, I2C_DRIVER_ERR_STR);
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_set_filter(&(i2c_context[i2c_num].hal), cyc_num);
i2c_hal_update_config(&(i2c_context[i2c_num].hal));
i2c_ll_set_filter(i2c_context[i2c_num].hal.dev, cyc_num);
i2c_ll_update(i2c_context[i2c_num].hal.dev);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
return ESP_OK;
}
@ -832,8 +819,8 @@ esp_err_t i2c_filter_disable(i2c_port_t i2c_num)
{
ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_NUM_ERROR_STR);
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_set_filter(&(i2c_context[i2c_num].hal), 0);
i2c_hal_update_config(&(i2c_context[i2c_num].hal));
i2c_ll_set_filter(i2c_context[i2c_num].hal.dev, 0);
i2c_ll_update(i2c_context[i2c_num].hal.dev);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
return ESP_OK;
}
@ -845,8 +832,8 @@ esp_err_t i2c_set_start_timing(i2c_port_t i2c_num, int setup_time, int hold_time
ESP_RETURN_ON_FALSE((setup_time <= I2C_SCL_RSTART_SETUP_TIME_V) && (setup_time > 0), ESP_ERR_INVALID_ARG, I2C_TAG, I2C_TIMING_VAL_ERR_STR);
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_set_start_timing(&(i2c_context[i2c_num].hal), setup_time, hold_time);
i2c_hal_update_config(&(i2c_context[i2c_num].hal));
i2c_ll_set_start_timing(i2c_context[i2c_num].hal.dev, setup_time, hold_time);
i2c_ll_update(i2c_context[i2c_num].hal.dev);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
return ESP_OK;
}
@ -855,7 +842,7 @@ esp_err_t i2c_get_start_timing(i2c_port_t i2c_num, int *setup_time, int *hold_ti
{
ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX && setup_time != NULL && hold_time != NULL, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_NUM_ERROR_STR);
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_get_start_timing(&(i2c_context[i2c_num].hal), setup_time, hold_time);
i2c_ll_get_start_timing(i2c_context[i2c_num].hal.dev, setup_time, hold_time);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
return ESP_OK;
}
@ -867,8 +854,8 @@ esp_err_t i2c_set_stop_timing(i2c_port_t i2c_num, int setup_time, int hold_time)
ESP_RETURN_ON_FALSE((hold_time <= I2C_SCL_STOP_HOLD_TIME_V) && (hold_time > 0), ESP_ERR_INVALID_ARG, I2C_TAG, I2C_TIMING_VAL_ERR_STR);
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_set_stop_timing(&(i2c_context[i2c_num].hal), setup_time, hold_time);
i2c_hal_update_config(&(i2c_context[i2c_num].hal));
i2c_ll_set_stop_timing(i2c_context[i2c_num].hal.dev, setup_time, hold_time);
i2c_ll_update(i2c_context[i2c_num].hal.dev);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
return ESP_OK;
}
@ -877,7 +864,7 @@ esp_err_t i2c_get_stop_timing(i2c_port_t i2c_num, int *setup_time, int *hold_tim
{
ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX && setup_time != NULL && hold_time != NULL, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_NUM_ERROR_STR);
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_get_stop_timing(&(i2c_context[i2c_num].hal), setup_time, hold_time);
i2c_ll_get_stop_timing(i2c_context[i2c_num].hal.dev, setup_time, hold_time);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
return ESP_OK;
}
@ -889,8 +876,8 @@ esp_err_t i2c_set_data_timing(i2c_port_t i2c_num, int sample_time, int hold_time
ESP_RETURN_ON_FALSE((hold_time <= I2C_SDA_HOLD_TIME_V) && (hold_time > 0), ESP_ERR_INVALID_ARG, I2C_TAG, I2C_TIMING_VAL_ERR_STR);
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_set_sda_timing(&(i2c_context[i2c_num].hal), sample_time, hold_time);
i2c_hal_update_config(&(i2c_context[i2c_num].hal));
i2c_ll_set_sda_timing(i2c_context[i2c_num].hal.dev, sample_time, hold_time);
i2c_ll_update(i2c_context[i2c_num].hal.dev);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
return ESP_OK;
}
@ -899,7 +886,7 @@ esp_err_t i2c_get_data_timing(i2c_port_t i2c_num, int *sample_time, int *hold_ti
{
ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX && sample_time != NULL && hold_time != NULL, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_NUM_ERROR_STR);
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_get_sda_timing(&(i2c_context[i2c_num].hal), sample_time, hold_time);
i2c_ll_get_sda_timing(i2c_context[i2c_num].hal.dev, sample_time, hold_time);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
return ESP_OK;
}
@ -910,7 +897,7 @@ esp_err_t i2c_set_timeout(i2c_port_t i2c_num, int timeout)
ESP_RETURN_ON_FALSE((timeout <= I2C_LL_MAX_TIMEOUT) && (timeout > 0), ESP_ERR_INVALID_ARG, I2C_TAG, I2C_TIMING_VAL_ERR_STR);
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_set_tout(&(i2c_context[i2c_num].hal), timeout);
i2c_ll_set_tout(i2c_context[i2c_num].hal.dev, timeout);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
return ESP_OK;
}
@ -918,7 +905,7 @@ esp_err_t i2c_set_timeout(i2c_port_t i2c_num, int timeout)
esp_err_t i2c_get_timeout(i2c_port_t i2c_num, int *timeout)
{
ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX && timeout != NULL, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_NUM_ERROR_STR);
i2c_hal_get_tout(&(i2c_context[i2c_num].hal), timeout);
i2c_ll_get_tout(i2c_context[i2c_num].hal.dev, timeout);
return ESP_OK;
}
@ -1363,7 +1350,7 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num, portBASE_T
i2c_cmd_evt_t evt = { 0 };
if (p_i2c->cmd_link.head != NULL && p_i2c->status == I2C_STATUS_READ) {
i2c_cmd_t *cmd = &p_i2c->cmd_link.head->cmd;
i2c_hal_read_rxfifo(&(i2c_context[i2c_num].hal), cmd->data + cmd->bytes_used, p_i2c->rx_cnt);
i2c_ll_read_rxfifo(i2c_context[i2c_num].hal.dev, cmd->data + cmd->bytes_used, p_i2c->rx_cnt);
/* rx_cnt bytes have just been read, increment the number of bytes used from the buffer */
cmd->bytes_used += p_i2c->rx_cnt;
@ -1425,10 +1412,10 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num, portBASE_T
write_pr = (uint8_t*) &cmd->data_byte;
}
hw_cmd.byte_num = fifo_fill;
i2c_hal_write_txfifo(&(i2c_context[i2c_num].hal), write_pr, fifo_fill);
i2c_hal_write_cmd_reg(&(i2c_context[i2c_num].hal), hw_cmd, p_i2c->cmd_idx);
i2c_hal_write_cmd_reg(&(i2c_context[i2c_num].hal), hw_end_cmd, p_i2c->cmd_idx + 1);
i2c_hal_enable_master_tx_it(&(i2c_context[i2c_num].hal));
i2c_ll_write_txfifo(i2c_context[i2c_num].hal.dev, write_pr, fifo_fill);
i2c_ll_write_cmd_reg(i2c_context[i2c_num].hal.dev, hw_cmd, p_i2c->cmd_idx);
i2c_ll_write_cmd_reg(i2c_context[i2c_num].hal.dev, hw_end_cmd, p_i2c->cmd_idx + 1);
i2c_ll_master_enable_tx_it(i2c_context[i2c_num].hal.dev);
p_i2c->cmd_idx = 0;
if (i2c_cmd_is_single_byte(cmd) || cmd->total_bytes == cmd->bytes_used) {
p_i2c->cmd_link.head = p_i2c->cmd_link.head->next;
@ -1443,13 +1430,13 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num, portBASE_T
fifo_fill = MIN(remaining_bytes, SOC_I2C_FIFO_LEN);
p_i2c->rx_cnt = fifo_fill;
hw_cmd.byte_num = fifo_fill;
i2c_hal_write_cmd_reg(&(i2c_context[i2c_num].hal), hw_cmd, p_i2c->cmd_idx);
i2c_hal_write_cmd_reg(&(i2c_context[i2c_num].hal), hw_end_cmd, p_i2c->cmd_idx + 1);
i2c_hal_enable_master_rx_it(&(i2c_context[i2c_num].hal));
i2c_ll_write_cmd_reg(i2c_context[i2c_num].hal.dev, hw_cmd, p_i2c->cmd_idx);
i2c_ll_write_cmd_reg(i2c_context[i2c_num].hal.dev, hw_end_cmd, p_i2c->cmd_idx + 1);
i2c_ll_master_enable_rx_it(i2c_context[i2c_num].hal.dev);
p_i2c->status = I2C_STATUS_READ;
break;
} else {
i2c_hal_write_cmd_reg(&(i2c_context[i2c_num].hal), hw_cmd, p_i2c->cmd_idx);
i2c_ll_write_cmd_reg(i2c_context[i2c_num].hal.dev, hw_cmd, p_i2c->cmd_idx);
}
p_i2c->cmd_idx++;
p_i2c->cmd_link.head = p_i2c->cmd_link.head->next;
@ -1458,8 +1445,8 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num, portBASE_T
break;
}
}
i2c_hal_update_config(&(i2c_context[i2c_num].hal));
i2c_hal_trans_start(&(i2c_context[i2c_num].hal));
i2c_ll_update(i2c_context[i2c_num].hal.dev);
i2c_ll_trans_start(i2c_context[i2c_num].hal.dev);
return;
}
@ -1513,7 +1500,7 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle,
#endif
xQueueReset(p_i2c->cmd_evt_queue);
if (p_i2c->status == I2C_STATUS_TIMEOUT
|| i2c_hal_is_bus_busy(&(i2c_context[i2c_num].hal))) {
|| i2c_ll_is_bus_busy(i2c_context[i2c_num].hal.dev)) {
i2c_hw_fsm_reset(i2c_num);
clear_bus_cnt[i2c_num] = 0;
}
@ -1534,8 +1521,8 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle,
i2c_reset_rx_fifo(i2c_num);
// These two interrupts some times can not be cleared when the FSM gets stuck.
// so we disable them when these two interrupt occurs and re-enable them here.
i2c_hal_disable_intr_mask(&(i2c_context[i2c_num].hal), I2C_LL_INTR_MASK);
i2c_hal_clr_intsts_mask(&(i2c_context[i2c_num].hal), I2C_LL_INTR_MASK);
i2c_ll_disable_intr_mask(i2c_context[i2c_num].hal.dev, I2C_LL_INTR_MASK);
i2c_ll_clear_intr_mask(i2c_context[i2c_num].hal.dev, I2C_LL_INTR_MASK);
//start send commands, at most 32 bytes one time, isr handler will process the remaining commands.
i2c_master_cmd_begin_static(i2c_num, NULL);
@ -1616,7 +1603,7 @@ int i2c_slave_write_buffer(i2c_port_t i2c_num, const uint8_t *data, int size, Ti
cnt = 0;
} else {
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_enable_slave_tx_it(&(i2c_context[i2c_num].hal));
i2c_ll_slave_enable_tx_it(i2c_context[i2c_num].hal.dev);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
cnt = size;
}
@ -1640,7 +1627,7 @@ int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t *data, size_t max_size, Ti
TickType_t ticks_rem = ticks_to_wait;
TickType_t ticks_end = xTaskGetTickCount() + ticks_to_wait;
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
i2c_hal_enable_slave_rx_it(&(i2c_context[i2c_num].hal));
i2c_ll_slave_enable_rx_it(i2c_context[i2c_num].hal.dev);
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
while (size_rem && ticks_rem <= ticks_to_wait) {
uint8_t *pdata = (uint8_t *) xRingbufferReceiveUpTo(p_i2c->rx_ring_buf, &size, ticks_to_wait, size_rem);

View File

@ -8,18 +8,18 @@
#pragma once
#include <stdbool.h>
#include "hal/misc.h"
#include "soc/i2c_periph.h"
#include "soc/i2c_struct.h"
#include "soc/clk_tree_defs.h"
#include "hal/i2c_types.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */
/**
* @brief I2C hardware cmd register fields.
*/
@ -36,33 +36,6 @@ typedef union {
uint32_t val;
} i2c_hw_cmd_t;
/**
* @brief I2C interrupt event
*/
typedef enum {
I2C_INTR_EVENT_ERR,
I2C_INTR_EVENT_ARBIT_LOST, /*!< I2C arbition lost event */
I2C_INTR_EVENT_NACK, /*!< I2C NACK event */
I2C_INTR_EVENT_TOUT, /*!< I2C time out event */
I2C_INTR_EVENT_END_DET, /*!< I2C end detected event */
I2C_INTR_EVENT_TRANS_DONE, /*!< I2C trans done event */
I2C_INTR_EVENT_RXFIFO_FULL, /*!< I2C rxfifo full event */
I2C_INTR_EVENT_TXFIFO_EMPTY, /*!< I2C txfifo empty event */
} i2c_intr_event_t;
/**
* @brief Data structure for calculating I2C bus timing.
*/
typedef struct {
uint16_t scl_low; /*!< I2C scl low period */
uint16_t scl_high; /*!< I2C scl hight 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 */
uint16_t hold; /*!< I2C start and stop condition hold period */
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 */
@ -70,20 +43,25 @@ typedef struct {
#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
#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)
// 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)
// I2C slave RX interrupt bitmap
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_FULL_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
// I2C max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_REG_V
typedef enum {
I2C_INTR_NACK = (1 << 10),
I2C_INTR_TIMEOUT = (1 << 8),
I2C_INTR_MST_COMPLETE = (1 << 7),
I2C_INTR_ARBITRATION = (1 << 5),
I2C_INTR_END_DETECT = (1 << 3),
I2C_INTR_ST_TO = (1 << 13),
} i2c_ll_master_intr_t;
typedef enum {
I2C_INTR_TXFIFO_WM = (1 << 1),
I2C_INTR_RXFIFO_WM = (1 << 0),
I2C_INTR_SLV_COMPLETE = (1 << 7),
I2C_INTR_START = (1 << 15),
} i2c_ll_slave_intr_t;
#define I2C_LL_MASTER_EVENT_INTR (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_SLAVE_EVENT_INTR (I2C_RXFIFO_FULL_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_TXFIFO_EMPTY_INT_ENA_M)
/**
* @brief Calculate I2C bus frequency
@ -94,7 +72,7 @@ typedef struct {
*
* @return None
*/
static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2c_clk_cal_t *clk_cal)
static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2c_hal_clk_config_t *clk_cal)
{
uint32_t half_cycle = source_clk / bus_freq / 2;
clk_cal->scl_low = half_cycle;
@ -114,7 +92,7 @@ static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2
*
* @return None
*/
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg)
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_hal_clk_config_t *bus_cfg)
{
/* SCL period. According to the TRM, we should always subtract 1 to SCL low period */
assert(bus_cfg->scl_low > 0);
@ -199,7 +177,8 @@ static inline void i2c_ll_set_scl_timing(i2c_dev_t *hw, int hight_period, int lo
*
* @return None
*/
static inline void i2c_ll_clr_intsts_mask(i2c_dev_t *hw, uint32_t mask)
__attribute__((always_inline))
static inline void i2c_ll_clear_intr_mask(i2c_dev_t *hw, uint32_t mask)
{
hw->int_clr.val = mask;
}
@ -225,6 +204,7 @@ static inline void i2c_ll_enable_intr_mask(i2c_dev_t *hw, uint32_t mask)
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_disable_intr_mask(i2c_dev_t *hw, uint32_t mask)
{
hw->int_ena.val &= (~mask);
@ -237,9 +217,10 @@ static inline void i2c_ll_disable_intr_mask(i2c_dev_t *hw, uint32_t mask)
*
* @return I2C interrupt status
*/
static inline uint32_t i2c_ll_get_intsts_mask(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_intr_mask(i2c_dev_t *hw, uint32_t *intr_status)
{
return hw->int_status.val;
*intr_status = hw->int_status.val;
}
/**
@ -413,17 +394,6 @@ static inline void i2c_ll_get_sda_timing(i2c_dev_t *hw, int *sda_sample, int *sd
*sda_sample = hw->sda_sample.time;
}
/**
* @brief Get the I2C hardware version
*
* @param hw Beginning address of the peripheral registers
*
* @return The I2C hardware version
*/
static inline uint32_t i2c_ll_get_hw_version(i2c_dev_t *hw)
{
return hw->date;
}
/**
* @brief Check if the I2C bus is busy
@ -437,18 +407,6 @@ static inline bool i2c_ll_is_bus_busy(i2c_dev_t *hw)
return hw->status_reg.bus_busy;
}
/**
* @brief Check if I2C is master mode
*
* @param hw Beginning address of the peripheral registers
*
* @return True if I2C is master mode, else false will be returned
*/
static inline bool i2c_ll_is_master_mode(i2c_dev_t *hw)
{
return hw->ctr.ms_mode;
}
/**
* @brief Get the rxFIFO readable length
*
@ -456,9 +414,10 @@ static inline bool i2c_ll_is_master_mode(i2c_dev_t *hw)
*
* @return RxFIFO readable length
*/
static inline uint32_t i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw, uint32_t *length)
{
return hw->status_reg.rx_fifo_cnt;
*length = hw->status_reg.rx_fifo_cnt;
}
/**
@ -468,9 +427,10 @@ static inline uint32_t i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw)
*
* @return TxFIFO writable length
*/
static inline uint32_t i2c_ll_get_txfifo_len(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_txfifo_len(i2c_dev_t *hw, uint32_t *length)
{
return SOC_I2C_FIFO_LEN - hw->status_reg.tx_fifo_cnt;
*length = SOC_I2C_FIFO_LEN - hw->status_reg.tx_fifo_cnt;
}
/**
@ -480,9 +440,9 @@ static inline uint32_t i2c_ll_get_txfifo_len(i2c_dev_t *hw)
*
* @return The I2C timeout value
*/
static inline uint32_t i2c_ll_get_tout(i2c_dev_t *hw)
static inline void i2c_ll_get_tout(i2c_dev_t *hw, int *timeout)
{
return hw->timeout.tout;
*timeout = hw->timeout.tout;
}
/**
@ -551,7 +511,8 @@ static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *l
*
* @return None.
*/
static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
__attribute__((always_inline))
static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, const uint8_t *ptr, uint8_t len)
{
uint32_t fifo_addr = (hw == &I2C0) ? 0x6001301c : 0x6002701c;
for(int i = 0; i < len; i++) {
@ -568,6 +529,7 @@ static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
{
for(int i = 0; i < len; i++) {
@ -604,155 +566,9 @@ static inline void i2c_ll_set_filter(i2c_dev_t *hw, uint8_t filter_num)
*
* @return The hardware filter configuration
*/
static inline uint8_t i2c_ll_get_filter(i2c_dev_t *hw)
static inline void i2c_ll_get_filter(i2c_dev_t *hw, uint8_t *filter_conf)
{
return hw->sda_filter_cfg.thres;
}
/**
* @brief Enable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = ~0;
hw->int_ena.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Enable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = ~0;
hw->int_ena.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief Disable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_TX_INT);
}
/**
* @brief Disable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_RX_INT);
}
/**
* @brief Clear I2C master TX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_clr_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Clear I2C master RX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_clr_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_TX_INT;
}
/**
* @brief Enable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_RX_INT;
}
/**
* @brief Disable I2C slave TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_TX_INT);
}
/**
* @brief Disable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_RX_INT);
}
/**
* @brief Clear I2C slave TX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_clr_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_SLAVE_TX_INT;
}
/**
* @brief Clear I2C slave RX interrupt status register.
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_clr_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_SLAVE_RX_INT;
*filter_conf = hw->sda_filter_cfg.thres;
}
/**
@ -795,54 +611,6 @@ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_c
;//Not support on ESP32
}
/**
* @brief Get I2C master interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *event)
{
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) {
*event = I2C_INTR_EVENT_NACK;
} else if (int_sts.time_out) {
*event = I2C_INTR_EVENT_TOUT;
} else if (int_sts.end_detect) {
*event = I2C_INTR_EVENT_END_DET;
} else if (int_sts.trans_complete) {
*event = I2C_INTR_EVENT_TRANS_DONE;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Get I2C slave interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
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) {
*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) {
*event = I2C_INTR_EVENT_RXFIFO_FULL;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Init I2C master
*
@ -890,22 +658,60 @@ static inline void i2c_ll_update(i2c_dev_t *hw)
}
/**
* @brief Configure I2C SCL timing
* @brief Set whether slave should auto start, or only start with start signal from master
*
* @param hw Beginning address of the peripheral registers
* @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)
* @param wait_high_period The I2C SCL wait rising edge period.
*
* @return None.
* @param hw Beginning address of the peripheral registers
* @param slv_ex_auto_en 1 if slave auto start data transaction, otherwise, 0.
*/
static inline void i2c_ll_set_scl_clk_timing(i2c_dev_t *hw, int high_period, int low_period, int wait_high_period)
static inline void i2c_ll_slave_tx_auto_start_en(i2c_dev_t *hw, bool slv_ex_auto_en)
{
(void)wait_high_period;
hw->scl_low_period.period = low_period;
hw->scl_high_period.period = high_period;
;// ESP32 do not support
}
/**
* @brief Get I2C interrupt status register address
*/
static inline volatile void *i2c_ll_get_interrupt_status_reg(i2c_dev_t *dev)
{
return &dev->int_status;
}
//////////////////////////////////////////Deprecated Functions//////////////////////////////////////////////////////////
/////////////////////////////The following functions are only used by the legacy driver/////////////////////////////////
/////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)//////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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)
// 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)
// I2C slave RX interrupt bitmap
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_FULL_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
// I2C max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_REG_V
#define I2C_LL_INTR_MASK (0xffff) /*!< I2C all interrupt bitmap */
/**
* @brief I2C interrupt event
*/
typedef enum {
I2C_INTR_EVENT_ERR,
I2C_INTR_EVENT_ARBIT_LOST, /*!< I2C arbition lost event */
I2C_INTR_EVENT_NACK, /*!< I2C NACK event */
I2C_INTR_EVENT_TOUT, /*!< I2C time out event */
I2C_INTR_EVENT_END_DET, /*!< I2C end detected event */
I2C_INTR_EVENT_TRANS_DONE, /*!< I2C trans done event */
I2C_INTR_EVENT_RXFIFO_FULL, /*!< I2C rxfifo full event */
I2C_INTR_EVENT_TXFIFO_EMPTY, /*!< I2C txfifo empty event */
} i2c_intr_event_t;
/**
* @brief Get I2C SCL timing configuration
*
@ -922,6 +728,186 @@ static inline void i2c_ll_get_scl_clk_timing(i2c_dev_t *hw, int *high_period, in
*low_period = hw->scl_low_period.period;
}
/**
* @brief Configure I2C SCL timing
*
* @param hw Beginning address of the peripheral registers
* @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)
* @param wait_high_period The I2C SCL wait rising edge period.
*
* @return None.
*/
static inline void i2c_ll_set_scl_clk_timing(i2c_dev_t *hw, int high_period, int low_period, int wait_high_period)
{
(void)wait_high_period;
hw->scl_low_period.period = low_period;
hw->scl_high_period.period = high_period;
}
/**
* @brief Get I2C slave interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
__attribute__((always_inline))
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) {
*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) {
*event = I2C_INTR_EVENT_RXFIFO_FULL;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Get I2C master interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *event)
{
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) {
*event = I2C_INTR_EVENT_NACK;
} else if (int_sts.time_out) {
*event = I2C_INTR_EVENT_TOUT;
} else if (int_sts.end_detect) {
*event = I2C_INTR_EVENT_END_DET;
} else if (int_sts.trans_complete) {
*event = I2C_INTR_EVENT_TRANS_DONE;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_TX_INT;
}
/**
* @brief Enable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_RX_INT;
}
/**
* @brief Disable I2C slave TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_slave_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_TX_INT);
}
/**
* @brief Disable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_RX_INT);
}
/**
* @brief Enable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = UINT32_MAX;
hw->int_ena.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Enable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = UINT32_MAX;
hw->int_ena.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief Disable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_TX_INT);
}
/**
* @brief Disable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_master_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_RX_INT);
}
/**
* @brief Get the I2C hardware version
*
* @param hw Beginning address of the peripheral registers
*
* @return The I2C hardware version
*/
static inline uint32_t i2c_ll_get_hw_version(i2c_dev_t *hw)
{
return hw->date;
}
#ifdef __cplusplus
}
#endif

View File

@ -8,6 +8,7 @@
#pragma once
#include <stdbool.h>
#include "hal/misc.h"
#include "soc/i2c_periph.h"
#include "soc/soc_caps.h"
@ -16,13 +17,12 @@
#include "soc/rtc_cntl_reg.h"
#include "soc/clk_tree_defs.h"
#include "esp_rom_sys.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */
/**
* @brief I2C hardware cmd register fields.
*/
@ -39,35 +39,6 @@ typedef union {
uint32_t val;
} i2c_hw_cmd_t;
/**
* @brief I2C interrupt event
*/
typedef enum {
I2C_INTR_EVENT_ERR,
I2C_INTR_EVENT_ARBIT_LOST, /*!< I2C arbition lost event */
I2C_INTR_EVENT_NACK, /*!< I2C NACK event */
I2C_INTR_EVENT_TOUT, /*!< I2C time out event */
I2C_INTR_EVENT_END_DET, /*!< I2C end detected event */
I2C_INTR_EVENT_TRANS_DONE, /*!< I2C trans done event */
I2C_INTR_EVENT_RXFIFO_FULL, /*!< I2C rxfifo full event */
I2C_INTR_EVENT_TXFIFO_EMPTY, /*!< I2C txfifo empty event */
} i2c_intr_event_t;
/**
* @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 */
uint16_t hold; /*!< I2C start and stop condition hold period */
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 */
@ -75,18 +46,24 @@ typedef struct {
#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) (&I2C0)
// 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_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)
// delay time after rtc_clk swiching on
#define DELAY_RTC_CLK_SWITCH (5)
// I2C max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_VALUE
typedef enum {
I2C_INTR_NACK = (1 << 10),
I2C_INTR_TIMEOUT = (1 << 8),
I2C_INTR_MST_COMPLETE = (1 << 7),
I2C_INTR_ARBITRATION = (1 << 5),
I2C_INTR_END_DETECT = (1 << 3),
I2C_INTR_ST_TO = (1 << 13),
} i2c_ll_master_intr_t;
typedef enum {
I2C_INTR_TXFIFO_WM = (1 << 1),
I2C_INTR_RXFIFO_WM = (1 << 0),
I2C_INTR_SLV_COMPLETE = (1 << 7),
I2C_INTR_START = (1 << 15),
} i2c_ll_slave_intr_t;
#define I2C_LL_MASTER_EVENT_INTR (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)
#define I2C_LL_SLAVE_EVENT_INTR (I2C_RXFIFO_WM_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_TXFIFO_WM_INT_ENA_M)
/**
* @brief Calculate I2C bus frequency
@ -100,7 +77,7 @@ typedef struct {
*
* @return None
*/
static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2c_clk_cal_t *clk_cal)
static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2c_hal_clk_config_t *clk_cal)
{
uint32_t clkm_div = source_clk / (bus_freq * 1024) +1;
uint32_t sclk_freq = source_clk / clkm_div;
@ -129,6 +106,7 @@ static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_update(i2c_dev_t *hw)
{
hw->ctr.conf_upgate = 1;
@ -142,7 +120,7 @@ static inline void i2c_ll_update(i2c_dev_t *hw)
*
* @return None
*/
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg)
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_hal_clk_config_t *bus_cfg)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, bus_cfg->clkm_div - 1);
/* According to the Technical Reference Manual, the following timings must be subtracted by 1.
@ -216,7 +194,8 @@ static inline void i2c_ll_set_scl_timing(i2c_dev_t *hw, int hight_period, int lo
*
* @return None
*/
static inline void i2c_ll_clr_intsts_mask(i2c_dev_t *hw, uint32_t mask)
__attribute__((always_inline))
static inline void i2c_ll_clear_intr_mask(i2c_dev_t *hw, uint32_t mask)
{
hw->int_clr.val = mask;
}
@ -242,6 +221,7 @@ static inline void i2c_ll_enable_intr_mask(i2c_dev_t *hw, uint32_t mask)
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_disable_intr_mask(i2c_dev_t *hw, uint32_t mask)
{
hw->int_ena.val &= (~mask);
@ -254,9 +234,10 @@ static inline void i2c_ll_disable_intr_mask(i2c_dev_t *hw, uint32_t mask)
*
* @return I2C interrupt status
*/
static inline uint32_t i2c_ll_get_intsts_mask(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_intr_mask(i2c_dev_t *hw, uint32_t *intr_status)
{
return hw->int_status.val;
*intr_status = hw->int_status.val;
}
/**
@ -458,9 +439,10 @@ static inline bool i2c_ll_is_master_mode(i2c_dev_t *hw)
*
* @return RxFIFO readable length
*/
static inline uint32_t i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw, uint32_t *length)
{
return hw->sr.rxfifo_cnt;
*length = hw->sr.rxfifo_cnt;
}
/**
@ -470,9 +452,10 @@ static inline uint32_t i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw)
*
* @return TxFIFO writable length
*/
static inline uint32_t i2c_ll_get_txfifo_len(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_txfifo_len(i2c_dev_t *hw, uint32_t *length)
{
return SOC_I2C_FIFO_LEN - hw->sr.txfifo_cnt;
*length = SOC_I2C_FIFO_LEN - hw->sr.txfifo_cnt;
}
/**
@ -482,9 +465,9 @@ static inline uint32_t i2c_ll_get_txfifo_len(i2c_dev_t *hw)
*
* @return The I2C timeout value
*/
static inline uint32_t i2c_ll_get_tout(i2c_dev_t *hw)
static inline void i2c_ll_get_tout(i2c_dev_t *hw, int *timeout)
{
return hw->to.time_out_value;
*timeout = hw->to.time_out_value;
}
/**
@ -553,7 +536,8 @@ static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *l
*
* @return None.
*/
static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
__attribute__((always_inline))
static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, const uint8_t *ptr, uint8_t len)
{
for (int i = 0; i< len; i++) {
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->data, fifo_rdata, ptr[i]);
@ -569,6 +553,7 @@ static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
{
for(int i = 0; i < len; i++) {
@ -605,83 +590,9 @@ static inline void i2c_ll_set_filter(i2c_dev_t *hw, uint8_t filter_num)
*
* @return The hardware filter configuration
*/
static inline uint8_t i2c_ll_get_filter(i2c_dev_t *hw)
static inline void i2c_ll_get_filter(i2c_dev_t *hw, uint8_t *filter_conf)
{
return hw->filter_cfg.scl_filter_thres;
}
/**
* @brief Enable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = ~0;
hw->int_ena.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Enable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = ~0;
hw->int_ena.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief Disable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_TX_INT);
}
/**
* @brief Disable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_RX_INT);
}
/**
* @brief Clear I2C master TX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_clr_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Clear I2C master RX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_clr_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_MASTER_RX_INT;
*filter_conf = hw->filter_cfg.scl_filter_thres;
}
/**
@ -693,6 +604,7 @@ static inline void i2c_ll_master_clr_rx_it(i2c_dev_t *hw)
*/
static inline void i2c_ll_master_fsm_rst(i2c_dev_t *hw)
{
// fsm_rst is a self cleared bit.
hw->ctr.fsm_rst = 1;
}
@ -731,32 +643,6 @@ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_c
hw->clk_conf.sclk_sel = (src_clk == I2C_CLK_SRC_RC_FAST) ? 1 : 0;
}
/**
* @brief Get I2C master interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *event)
{
i2c_int_status_reg_t int_sts = hw->int_status;
if (int_sts.arbitration_lost_int_st) {
*event = I2C_INTR_EVENT_ARBIT_LOST;
} else if (int_sts.nack_int_st) {
*event = I2C_INTR_EVENT_NACK;
} else if (int_sts.time_out_int_st) {
*event = I2C_INTR_EVENT_TOUT;
} else if (int_sts.end_detect_int_st) {
*event = I2C_INTR_EVENT_END_DET;
} else if (int_sts.trans_complete_int_st) {
*event = I2C_INTR_EVENT_TRANS_DONE;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Init I2C master
*
@ -775,6 +661,48 @@ static inline void i2c_ll_master_init(i2c_dev_t *hw)
hw->ctr.val = ctrl_reg.val;
}
/**
* @brief Get I2C interrupt status register address
*/
static inline volatile void *i2c_ll_get_interrupt_status_reg(i2c_dev_t *dev)
{
return &dev->int_status;
}
//////////////////////////////////////////Deprecated Functions//////////////////////////////////////////////////////////
/////////////////////////////The following functions are only used by the legacy driver/////////////////////////////////
/////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)//////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Get the I2C hardware instance
#define I2C_LL_GET_HW(i2c_num) (&I2C0)
// 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_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)
// delay time after rtc_clk swiching on
#define DELAY_RTC_CLK_SWITCH (5)
// I2C max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_VALUE
#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */
/**
* @brief I2C interrupt event
*/
typedef enum {
I2C_INTR_EVENT_ERR,
I2C_INTR_EVENT_ARBIT_LOST, /*!< I2C arbition lost event */
I2C_INTR_EVENT_NACK, /*!< I2C NACK event */
I2C_INTR_EVENT_TOUT, /*!< I2C time out event */
I2C_INTR_EVENT_END_DET, /*!< I2C end detected event */
I2C_INTR_EVENT_TRANS_DONE, /*!< I2C trans done event */
I2C_INTR_EVENT_RXFIFO_FULL, /*!< I2C rxfifo full event */
I2C_INTR_EVENT_TXFIFO_EMPTY, /*!< I2C txfifo empty event */
} i2c_intr_event_t;
/**
* @brief Configure I2C SCL timing
*
@ -808,6 +736,84 @@ static inline void i2c_ll_get_scl_clk_timing(i2c_dev_t *hw, int *high_period, in
*low_period = hw->scl_low_period.scl_low_period;
}
/**
* @brief Get I2C master interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *event)
{
i2c_int_status_reg_t int_sts = hw->int_status;
if (int_sts.arbitration_lost_int_st) {
*event = I2C_INTR_EVENT_ARBIT_LOST;
} else if (int_sts.nack_int_st) {
*event = I2C_INTR_EVENT_NACK;
} else if (int_sts.time_out_int_st) {
*event = I2C_INTR_EVENT_TOUT;
} else if (int_sts.end_detect_int_st) {
*event = I2C_INTR_EVENT_END_DET;
} else if (int_sts.trans_complete_int_st) {
*event = I2C_INTR_EVENT_TRANS_DONE;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Enable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = UINT32_MAX;
hw->int_ena.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Enable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = UINT32_MAX;
hw->int_ena.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief Disable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_TX_INT);
}
/**
* @brief Disable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_master_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_RX_INT);
}
#ifdef __cplusplus
}
#endif

View File

@ -8,6 +8,7 @@
#pragma once
#include "stdbool.h"
#include "hal/misc.h"
#include "soc/i2c_periph.h"
#include "soc/soc_caps.h"
@ -16,12 +17,12 @@
#include "soc/rtc_cntl_reg.h"
#include "soc/clk_tree_defs.h"
#include "esp_rom_sys.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */
/**
* @brief I2C hardware cmd register fields.
@ -39,35 +40,6 @@ typedef union {
uint32_t val;
} i2c_hw_cmd_t;
/**
* @brief I2C interrupt event
*/
typedef enum {
I2C_INTR_EVENT_ERR,
I2C_INTR_EVENT_ARBIT_LOST, /*!< I2C arbition lost event */
I2C_INTR_EVENT_NACK, /*!< I2C NACK event */
I2C_INTR_EVENT_TOUT, /*!< I2C time out event */
I2C_INTR_EVENT_END_DET, /*!< I2C end detected event */
I2C_INTR_EVENT_TRANS_DONE, /*!< I2C trans done event */
I2C_INTR_EVENT_RXFIFO_FULL, /*!< I2C rxfifo full event */
I2C_INTR_EVENT_TXFIFO_EMPTY, /*!< I2C txfifo empty event */
} i2c_intr_event_t;
/**
* @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 */
uint16_t hold; /*!< I2C start and stop condition hold period */
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 */
@ -75,22 +47,25 @@ typedef struct {
#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) (&I2C0)
// 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_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_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)
// delay time after rtc_clk swiching on
#define DELAY_RTC_CLK_SWITCH (5)
// I2C max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_REG_V
typedef enum {
I2C_INTR_NACK = (1 << 10),
I2C_INTR_TIMEOUT = (1 << 8),
I2C_INTR_MST_COMPLETE = (1 << 7),
I2C_INTR_ARBITRATION = (1 << 5),
I2C_INTR_END_DETECT = (1 << 3),
I2C_INTR_ST_TO = (1 << 13),
} i2c_ll_master_intr_t;
typedef enum {
I2C_INTR_TXFIFO_WM = (1 << 1),
I2C_INTR_RXFIFO_WM = (1 << 0),
I2C_INTR_SLV_COMPLETE = (1 << 7),
I2C_INTR_START = (1 << 15),
} i2c_ll_slave_intr_t;
#define I2C_LL_MASTER_EVENT_INTR (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)
#define I2C_LL_SLAVE_EVENT_INTR (I2C_RXFIFO_WM_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_TXFIFO_WM_INT_ENA_M)
/**
* @brief Calculate I2C bus frequency
@ -104,7 +79,7 @@ typedef struct {
*
* @return None
*/
static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2c_clk_cal_t *clk_cal)
static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2c_hal_clk_config_t *clk_cal)
{
uint32_t clkm_div = source_clk / (bus_freq * 1024) +1;
uint32_t sclk_freq = source_clk / clkm_div;
@ -133,6 +108,7 @@ static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_update(i2c_dev_t *hw)
{
hw->ctr.conf_upgate = 1;
@ -146,7 +122,7 @@ static inline void i2c_ll_update(i2c_dev_t *hw)
*
* @return None
*/
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg)
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_hal_clk_config_t *bus_cfg)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, bus_cfg->clkm_div - 1);
/* According to the Technical Reference Manual, the following timings must be subtracted by 1.
@ -220,7 +196,8 @@ static inline void i2c_ll_set_scl_timing(i2c_dev_t *hw, int hight_period, int lo
*
* @return None
*/
static inline void i2c_ll_clr_intsts_mask(i2c_dev_t *hw, uint32_t mask)
__attribute__((always_inline))
static inline void i2c_ll_clear_intr_mask(i2c_dev_t *hw, uint32_t mask)
{
hw->int_clr.val = mask;
}
@ -246,6 +223,7 @@ static inline void i2c_ll_enable_intr_mask(i2c_dev_t *hw, uint32_t mask)
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_disable_intr_mask(i2c_dev_t *hw, uint32_t mask)
{
hw->int_ena.val &= (~mask);
@ -258,9 +236,10 @@ static inline void i2c_ll_disable_intr_mask(i2c_dev_t *hw, uint32_t mask)
*
* @return I2C interrupt status
*/
static inline uint32_t i2c_ll_get_intsts_mask(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_intr_mask(i2c_dev_t *hw, uint32_t *intr_status)
{
return hw->int_status.val;
*intr_status = hw->int_status.val;
}
/**
@ -477,9 +456,10 @@ static inline bool i2c_ll_is_master_mode(i2c_dev_t *hw)
*
* @return RxFIFO readable length
*/
static inline uint32_t i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw, uint32_t *length)
{
return hw->sr.rx_fifo_cnt;
*length = hw->sr.rx_fifo_cnt;
}
/**
@ -489,9 +469,10 @@ static inline uint32_t i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw)
*
* @return TxFIFO writable length
*/
static inline uint32_t i2c_ll_get_txfifo_len(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_txfifo_len(i2c_dev_t *hw, uint32_t *length)
{
return SOC_I2C_FIFO_LEN - hw->sr.tx_fifo_cnt;
*length = SOC_I2C_FIFO_LEN - hw->sr.tx_fifo_cnt;
}
/**
@ -501,9 +482,9 @@ static inline uint32_t i2c_ll_get_txfifo_len(i2c_dev_t *hw)
*
* @return The I2C timeout value
*/
static inline uint32_t i2c_ll_get_tout(i2c_dev_t *hw)
static inline void i2c_ll_get_tout(i2c_dev_t *hw, int *timeout)
{
return hw->timeout.time_out_value;
*timeout = hw->timeout.time_out_value;
}
/**
@ -572,7 +553,8 @@ static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *l
*
* @return None.
*/
static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
__attribute__((always_inline))
static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, const uint8_t *ptr, uint8_t len)
{
for (int i = 0; i< len; i++) {
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->fifo_data, data, ptr[i]);
@ -588,6 +570,7 @@ static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
{
for(int i = 0; i < len; i++) {
@ -624,156 +607,12 @@ static inline void i2c_ll_set_filter(i2c_dev_t *hw, uint8_t filter_num)
*
* @return The hardware filter configuration
*/
static inline uint8_t i2c_ll_get_filter(i2c_dev_t *hw)
static inline void i2c_ll_get_filter(i2c_dev_t *hw, uint8_t *filter_conf)
{
return hw->filter_cfg.scl_thres;
*filter_conf = hw->filter_cfg.scl_thres;
}
/**
* @brief Enable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = ~0;
hw->int_ena.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Enable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = ~0;
hw->int_ena.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief Disable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_TX_INT);
}
/**
* @brief Disable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_RX_INT);
}
/**
* @brief Clear I2C master TX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_clr_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Clear I2C master RX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_clr_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_TX_INT;
}
/**
* @brief Enable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_RX_INT;
}
/**
* @brief Disable I2C slave TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_TX_INT);
}
/**
* @brief Disable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_RX_INT);
}
/**
* @brief Clear I2C slave TX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_clr_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_SLAVE_TX_INT;
}
/**
* @brief Clear I2C slave RX interrupt status register.
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_clr_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_SLAVE_RX_INT;
}
/**
* @brief Reste I2C master FSM. When the master FSM is stuck, call this function to reset the FSM
@ -784,6 +623,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)
{
// fsm_rst is a self cleared bit.
hw->ctr.fsm_rst = 1;
}
@ -822,53 +662,7 @@ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_c
hw->clk_conf.sclk_sel = (src_clk == I2C_CLK_SRC_RC_FAST) ? 1 : 0;
}
/**
* @brief Get I2C master interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *event)
{
typeof(hw->int_status) int_sts = hw->int_status;
if (int_sts.arbitration_lost) {
*event = I2C_INTR_EVENT_ARBIT_LOST;
} else if (int_sts.nack) {
*event = I2C_INTR_EVENT_NACK;
} else if (int_sts.time_out) {
*event = I2C_INTR_EVENT_TOUT;
} else if (int_sts.end_detect) {
*event = I2C_INTR_EVENT_END_DET;
} else if (int_sts.trans_complete) {
*event = I2C_INTR_EVENT_TRANS_DONE;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Get I2C slave interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
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_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_wm) {
*event = I2C_INTR_EVENT_RXFIFO_FULL;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Init I2C master
@ -902,10 +696,64 @@ static inline void i2c_ll_slave_init(i2c_dev_t *hw)
ctrl_reg.sda_force_out = 1;
ctrl_reg.scl_force_out = 1;
hw->ctr.val = ctrl_reg.val;
hw->ctr.slv_tx_auto_start_en = 1;
hw->fifo_conf.fifo_addr_cfg_en = 0;
}
/**
* @brief Set whether slave should auto start, or only start with start signal from master
*
* @param hw Beginning address of the peripheral registers
* @param slv_ex_auto_en 1 if slave auto start data transaction, otherwise, 0.
*/
static inline void i2c_ll_slave_tx_auto_start_en(i2c_dev_t *hw, bool slv_ex_auto_en)
{
hw->ctr.slv_tx_auto_start_en = slv_ex_auto_en;
}
/**
* @brief Get I2C interrupt status register address
*/
static inline volatile void *i2c_ll_get_interrupt_status_reg(i2c_dev_t *dev)
{
return &dev->int_status;
}
//////////////////////////////////////////Deprecated Functions//////////////////////////////////////////////////////////
/////////////////////////////The following functions are only used by the legacy driver/////////////////////////////////
/////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)//////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Get the I2C hardware instance
#define I2C_LL_GET_HW(i2c_num) (&I2C0)
// 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_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_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 max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_REG_V
#define I2C_LL_INTR_MASK (0xffff) /*!< I2C all interrupt bitmap */
/**
* @brief I2C interrupt event
*/
typedef enum {
I2C_INTR_EVENT_ERR,
I2C_INTR_EVENT_ARBIT_LOST, /*!< I2C arbition lost event */
I2C_INTR_EVENT_NACK, /*!< I2C NACK event */
I2C_INTR_EVENT_TOUT, /*!< I2C time out event */
I2C_INTR_EVENT_END_DET, /*!< I2C end detected event */
I2C_INTR_EVENT_TRANS_DONE, /*!< I2C trans done event */
I2C_INTR_EVENT_RXFIFO_FULL, /*!< I2C rxfifo full event */
I2C_INTR_EVENT_TXFIFO_EMPTY, /*!< I2C txfifo empty event */
} i2c_intr_event_t;
/**
* @brief Configure I2C SCL timing
*
@ -939,6 +787,157 @@ static inline void i2c_ll_get_scl_clk_timing(i2c_dev_t *hw, int *high_period, in
*low_period = hw->scl_low_period.period;
}
/**
* @brief Get I2C master interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *event)
{
typeof(hw->int_status) int_sts = hw->int_status;
if (int_sts.arbitration_lost) {
*event = I2C_INTR_EVENT_ARBIT_LOST;
} else if (int_sts.nack) {
*event = I2C_INTR_EVENT_NACK;
} else if (int_sts.time_out||int_sts.scl_st_to||int_sts.scl_main_st_to) {
*event = I2C_INTR_EVENT_TOUT;
} else if (int_sts.end_detect) {
*event = I2C_INTR_EVENT_END_DET;
} else if (int_sts.trans_complete) {
*event = I2C_INTR_EVENT_TRANS_DONE;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Get I2C slave interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
__attribute__((always_inline))
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_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_wm) {
*event = I2C_INTR_EVENT_RXFIFO_FULL;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Enable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = UINT32_MAX;
hw->int_ena.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Enable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = UINT32_MAX;
hw->int_ena.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief Disable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_TX_INT);
}
/**
* @brief Disable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_master_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_RX_INT);
}
/**
* @brief
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_TX_INT;
}
/**
* @brief Enable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_RX_INT;
}
/**
* @brief Disable I2C slave TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_slave_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_TX_INT);
}
/**
* @brief Disable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_RX_INT);
}
#ifdef __cplusplus
}
#endif

View File

@ -8,6 +8,7 @@
#pragma once
#include "stdbool.h"
#include "hal/misc.h"
#include "soc/i2c_periph.h"
#include "soc/soc_caps.h"
@ -16,15 +17,14 @@
#include "soc/rtc_cntl_reg.h"
#include "soc/clk_tree_defs.h"
#include "esp_rom_sys.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */
/**
* @brief I2C hardware cmd register filed.
* @brief I2C hardware cmd register fields.
*/
typedef union {
struct {
@ -39,35 +39,6 @@ typedef union {
uint32_t val;
} i2c_hw_cmd_t;
/**
* @brief I2C interrupt event
*/
typedef enum {
I2C_INTR_EVENT_ERR,
I2C_INTR_EVENT_ARBIT_LOST, /*!< I2C arbition lost event */
I2C_INTR_EVENT_NACK, /*!< I2C NACK event */
I2C_INTR_EVENT_TOUT, /*!< I2C time out event */
I2C_INTR_EVENT_END_DET, /*!< I2C end detected event */
I2C_INTR_EVENT_TRANS_DONE, /*!< I2C trans done event */
I2C_INTR_EVENT_RXFIFO_FULL, /*!< I2C rxfifo full event */
I2C_INTR_EVENT_TXFIFO_EMPTY, /*!< I2C txfifo empty event */
} i2c_intr_event_t;
/**
* @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 */
uint16_t hold; /*!< I2C start and stop condition hold period */
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 */
@ -75,22 +46,26 @@ typedef struct {
#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) (&I2C0)
// 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_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_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)
// delay time after rtc_clk swiching on
#define DELAY_RTC_CLK_SWITCH (5)
// I2C max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_REG_V
typedef enum {
I2C_INTR_NACK = (1 << 10),
I2C_INTR_TIMEOUT = (1 << 8),
I2C_INTR_MST_COMPLETE = (1 << 7),
I2C_INTR_ARBITRATION = (1 << 5),
I2C_INTR_END_DETECT = (1 << 3),
I2C_INTR_ST_TO = (1 << 13),
} i2c_ll_master_intr_t;
typedef enum {
I2C_INTR_TXFIFO_WM = (1 << 1),
I2C_INTR_RXFIFO_WM = (1 << 0),
I2C_INTR_SLV_COMPLETE = (1 << 7),
I2C_INTR_START = (1 << 15),
} i2c_ll_slave_intr_t;
#define I2C_LL_MASTER_EVENT_INTR (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_SCL_ST_TO_INT_ENA)
#define I2C_LL_SLAVE_EVENT_INTR (I2C_RXFIFO_WM_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_TXFIFO_WM_INT_ENA_M)
/**
* @brief Calculate I2C bus frequency
@ -104,7 +79,7 @@ typedef struct {
*
* @return None
*/
static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2c_clk_cal_t *clk_cal)
static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2c_hal_clk_config_t *clk_cal)
{
uint32_t clkm_div = source_clk / (bus_freq * 1024) +1;
uint32_t sclk_freq = source_clk / clkm_div;
@ -133,6 +108,7 @@ static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_update(i2c_dev_t *hw)
{
hw->ctr.conf_upgate = 1;
@ -146,7 +122,7 @@ static inline void i2c_ll_update(i2c_dev_t *hw)
*
* @return None
*/
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg)
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_hal_clk_config_t *bus_cfg)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, bus_cfg->clkm_div - 1);
/* According to the Technical Reference Manual, the following timings must be subtracted by 1.
@ -220,7 +196,8 @@ static inline void i2c_ll_set_scl_timing(i2c_dev_t *hw, int hight_period, int lo
*
* @return None
*/
static inline void i2c_ll_clr_intsts_mask(i2c_dev_t *hw, uint32_t mask)
__attribute__((always_inline))
static inline void i2c_ll_clear_intr_mask(i2c_dev_t *hw, uint32_t mask)
{
hw->int_clr.val = mask;
}
@ -246,6 +223,7 @@ static inline void i2c_ll_enable_intr_mask(i2c_dev_t *hw, uint32_t mask)
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_disable_intr_mask(i2c_dev_t *hw, uint32_t mask)
{
hw->int_ena.val &= (~mask);
@ -258,9 +236,10 @@ static inline void i2c_ll_disable_intr_mask(i2c_dev_t *hw, uint32_t mask)
*
* @return I2C interrupt status
*/
static inline uint32_t i2c_ll_get_intsts_mask(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_intr_mask(i2c_dev_t *hw, uint32_t *intr_status)
{
return hw->int_status.val;
*intr_status = hw->int_status.val;
}
/**
@ -477,9 +456,10 @@ static inline bool i2c_ll_is_master_mode(i2c_dev_t *hw)
*
* @return RxFIFO readable length
*/
static inline uint32_t i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw, uint32_t *length)
{
return hw->sr.rx_fifo_cnt;
*length = hw->sr.rx_fifo_cnt;
}
/**
@ -489,9 +469,10 @@ static inline uint32_t i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw)
*
* @return TxFIFO writable length
*/
static inline uint32_t i2c_ll_get_txfifo_len(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_txfifo_len(i2c_dev_t *hw, uint32_t *length)
{
return SOC_I2C_FIFO_LEN - hw->sr.tx_fifo_cnt;
*length = SOC_I2C_FIFO_LEN - hw->sr.tx_fifo_cnt;
}
/**
@ -501,9 +482,9 @@ static inline uint32_t i2c_ll_get_txfifo_len(i2c_dev_t *hw)
*
* @return The I2C timeout value
*/
static inline uint32_t i2c_ll_get_tout(i2c_dev_t *hw)
static inline void i2c_ll_get_tout(i2c_dev_t *hw, int *timeout)
{
return hw->timeout.time_out_value;
*timeout = hw->timeout.time_out_value;
}
/**
@ -572,7 +553,8 @@ static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *l
*
* @return None.
*/
static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
__attribute__((always_inline))
static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, const uint8_t *ptr, uint8_t len)
{
for (int i = 0; i< len; i++) {
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->fifo_data, data, ptr[i]);
@ -588,6 +570,7 @@ static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
{
for(int i = 0; i < len; i++) {
@ -624,155 +607,9 @@ static inline void i2c_ll_set_filter(i2c_dev_t *hw, uint8_t filter_num)
*
* @return The hardware filter configuration
*/
static inline uint8_t i2c_ll_get_filter(i2c_dev_t *hw)
static inline void i2c_ll_get_filter(i2c_dev_t *hw, uint8_t *filter_conf)
{
return hw->filter_cfg.scl_thres;
}
/**
* @brief Enable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = ~0;
hw->int_ena.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Enable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = ~0;
hw->int_ena.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief Disable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_TX_INT);
}
/**
* @brief Disable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_RX_INT);
}
/**
* @brief Clear I2C master TX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_clr_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Clear I2C master RX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_clr_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_TX_INT;
}
/**
* @brief Enable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_RX_INT;
}
/**
* @brief Disable I2C slave TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_TX_INT);
}
/**
* @brief Disable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_RX_INT);
}
/**
* @brief Clear I2C slave TX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_clr_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_SLAVE_TX_INT;
}
/**
* @brief Clear I2C slave RX interrupt status register.
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_clr_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_SLAVE_RX_INT;
*filter_conf = hw->filter_cfg.scl_thres;
}
/**
@ -800,9 +637,12 @@ static inline void i2c_ll_master_fsm_rst(i2c_dev_t *hw)
static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw)
{
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;
hw->ctr.conf_upgate = 1;
// hardward will clear scl_rst_slv_en after sending SCL pulses,
// and we should set conf_upgate bit to synchronize register value.
while (hw->scl_sp_conf.scl_rst_slv_en);
hw->ctr.conf_upgate = 1;
}
/**
@ -819,54 +659,6 @@ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_c
hw->clk_conf.sclk_sel = (src_clk == I2C_CLK_SRC_RC_FAST) ? 1 : 0;
}
/**
* @brief Get I2C master interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *event)
{
typeof(hw->int_status) int_sts = hw->int_status;
if (int_sts.arbitration_lost) {
*event = I2C_INTR_EVENT_ARBIT_LOST;
} else if (int_sts.nack) {
*event = I2C_INTR_EVENT_NACK;
} else if (int_sts.time_out) {
*event = I2C_INTR_EVENT_TOUT;
} else if (int_sts.end_detect) {
*event = I2C_INTR_EVENT_END_DET;
} else if (int_sts.trans_complete) {
*event = I2C_INTR_EVENT_TRANS_DONE;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Get I2C slave interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
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_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_wm) {
*event = I2C_INTR_EVENT_RXFIFO_FULL;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Init I2C master
*
@ -899,10 +691,64 @@ static inline void i2c_ll_slave_init(i2c_dev_t *hw)
ctrl_reg.sda_force_out = 1;
ctrl_reg.scl_force_out = 1;
hw->ctr.val = ctrl_reg.val;
hw->ctr.slv_tx_auto_start_en = 1;
hw->fifo_conf.fifo_addr_cfg_en = 0;
}
/**
* @brief Set whether slave should auto start, or only start with start signal from master
*
* @param hw Beginning address of the peripheral registers
* @param slv_ex_auto_en 1 if slave auto start data transaction, otherwise, 0.
*/
static inline void i2c_ll_slave_tx_auto_start_en(i2c_dev_t *hw, bool slv_ex_auto_en)
{
hw->ctr.slv_tx_auto_start_en = slv_ex_auto_en;
}
/**
* @brief Get I2C interrupt status register address
*/
static inline volatile void *i2c_ll_get_interrupt_status_reg(i2c_dev_t *dev)
{
return &dev->int_status;
}
//////////////////////////////////////////Deprecated Functions//////////////////////////////////////////////////////////
/////////////////////////////The following functions are only used by the legacy driver/////////////////////////////////
/////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)//////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Get the I2C hardware instance
#define I2C_LL_GET_HW(i2c_num) (&I2C0)
// 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_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_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 max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_REG_V
#define I2C_LL_INTR_MASK (0xffff) /*!< I2C all interrupt bitmap */
/**
* @brief I2C interrupt event
*/
typedef enum {
I2C_INTR_EVENT_ERR,
I2C_INTR_EVENT_ARBIT_LOST, /*!< I2C arbition lost event */
I2C_INTR_EVENT_NACK, /*!< I2C NACK event */
I2C_INTR_EVENT_TOUT, /*!< I2C time out event */
I2C_INTR_EVENT_END_DET, /*!< I2C end detected event */
I2C_INTR_EVENT_TRANS_DONE, /*!< I2C trans done event */
I2C_INTR_EVENT_RXFIFO_FULL, /*!< I2C rxfifo full event */
I2C_INTR_EVENT_TXFIFO_EMPTY, /*!< I2C txfifo empty event */
} i2c_intr_event_t;
/**
* @brief Configure I2C SCL timing
*
@ -936,6 +782,156 @@ static inline void i2c_ll_get_scl_clk_timing(i2c_dev_t *hw, int *high_period, in
*low_period = hw->scl_low_period.period;
}
/**
* @brief Get I2C master interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *event)
{
typeof(hw->int_status) int_sts = hw->int_status;
if (int_sts.arbitration_lost) {
*event = I2C_INTR_EVENT_ARBIT_LOST;
} else if (int_sts.nack) {
*event = I2C_INTR_EVENT_NACK;
} else if (int_sts.time_out) {
*event = I2C_INTR_EVENT_TOUT;
} else if (int_sts.end_detect) {
*event = I2C_INTR_EVENT_END_DET;
} else if (int_sts.trans_complete) {
*event = I2C_INTR_EVENT_TRANS_DONE;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Get I2C slave interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
__attribute__((always_inline))
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_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_wm) {
*event = I2C_INTR_EVENT_RXFIFO_FULL;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Enable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = UINT32_MAX;
hw->int_ena.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Enable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = UINT32_MAX;
hw->int_ena.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief Disable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_TX_INT);
}
/**
* @brief Disable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_master_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_RX_INT);
}
/**
* @brief
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_TX_INT;
}
/**
* @brief Enable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_RX_INT;
}
/**
* @brief Disable I2C slave TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_slave_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_TX_INT);
}
/**
* @brief Disable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_RX_INT);
}
#ifdef __cplusplus
}
#endif

View File

@ -7,16 +7,18 @@
// The LL layer for I2C register operations
#pragma once
#include <stdbool.h>
#include "soc/i2c_periph.h"
#include "soc/i2c_struct.h"
#include "soc/clk_tree_defs.h"
#include "hal/i2c_types.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
#define I2C_LL_INTR_MASK (0x1ffff) /*!< I2C all interrupt bitmap */
/**
* @brief I2C hardware cmd register fields.
@ -34,34 +36,6 @@ typedef union {
uint32_t val;
} i2c_hw_cmd_t;
/**
* @brief I2C interrupt event
*/
typedef enum {
I2C_INTR_EVENT_ERR,
I2C_INTR_EVENT_ARBIT_LOST, /*!< I2C arbition lost event */
I2C_INTR_EVENT_NACK, /*!< I2C NACK event */
I2C_INTR_EVENT_TOUT, /*!< I2C time out event */
I2C_INTR_EVENT_END_DET, /*!< I2C end detected event */
I2C_INTR_EVENT_TRANS_DONE, /*!< I2C trans done event */
I2C_INTR_EVENT_RXFIFO_FULL, /*!< I2C rxfifo full event */
I2C_INTR_EVENT_TXFIFO_EMPTY, /*!< I2C txfifo empty event */
} i2c_intr_event_t;
/**
* @brief Data structure for calculating I2C bus timing.
*/
typedef struct {
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 */
uint16_t hold; /*!< I2C start and stop condition hold period */
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 */
@ -69,20 +43,26 @@ typedef struct {
#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
#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_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_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 max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_REG_V
typedef enum {
I2C_INTR_NACK = (1 << 10),
I2C_INTR_TIMEOUT = (1 << 8),
I2C_INTR_MST_COMPLETE = (1 << 7),
I2C_INTR_ARBITRATION = (1 << 5),
I2C_INTR_END_DETECT = (1 << 3),
I2C_INTR_ST_TO = (1 << 13),
} i2c_ll_master_intr_t;
typedef enum {
I2C_INTR_TXFIFO_WM = (1 << 1),
I2C_INTR_RXFIFO_WM = (1 << 0),
I2C_INTR_SLV_COMPLETE = (1 << 7),
I2C_INTR_START = (1 << 15),
} i2c_ll_slave_intr_t;
#define I2C_LL_MASTER_EVENT_INTR (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)
#define I2C_LL_SLAVE_EVENT_INTR (I2C_RXFIFO_WM_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_TXFIFO_WM_INT_ENA_M)
/**
* @brief Calculate I2C bus frequency
*
@ -92,7 +72,7 @@ typedef struct {
*
* @return None
*/
static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2c_clk_cal_t *clk_cal)
static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2c_hal_clk_config_t *clk_cal)
{
uint32_t half_cycle = source_clk / bus_freq / 2;
//SCL
@ -117,7 +97,7 @@ static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2
*
* @return None
*/
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg)
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_hal_clk_config_t *bus_cfg)
{
//scl period
hw->scl_low_period.period = bus_cfg->scl_low - 1;
@ -185,7 +165,8 @@ static inline void i2c_ll_set_scl_timing(i2c_dev_t *hw, int hight_period, int lo
*
* @return None
*/
static inline void i2c_ll_clr_intsts_mask(i2c_dev_t *hw, uint32_t mask)
__attribute__((always_inline))
static inline void i2c_ll_clear_intr_mask(i2c_dev_t *hw, uint32_t mask)
{
hw->int_clr.val = mask;
}
@ -211,6 +192,7 @@ static inline void i2c_ll_enable_intr_mask(i2c_dev_t *hw, uint32_t mask)
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_disable_intr_mask(i2c_dev_t *hw, uint32_t mask)
{
hw->int_ena.val &= (~mask);
@ -223,9 +205,10 @@ static inline void i2c_ll_disable_intr_mask(i2c_dev_t *hw, uint32_t mask)
*
* @return I2C interrupt status
*/
static inline uint32_t i2c_ll_get_intsts_mask(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_intr_mask(i2c_dev_t *hw, uint32_t *intr_status)
{
return hw->int_status.val;
*intr_status = hw->int_status.val;
}
/**
@ -443,9 +426,10 @@ static inline bool i2c_ll_is_master_mode(i2c_dev_t *hw)
*
* @return RxFIFO readable length
*/
static inline uint32_t i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw, uint32_t *length)
{
return hw->status_reg.rx_fifo_cnt;
*length = hw->status_reg.rx_fifo_cnt;
}
/**
@ -455,9 +439,10 @@ static inline uint32_t i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw)
*
* @return TxFIFO writable length
*/
static inline uint32_t i2c_ll_get_txfifo_len(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_txfifo_len(i2c_dev_t *hw, uint32_t *length)
{
return SOC_I2C_FIFO_LEN - hw->status_reg.tx_fifo_cnt;
*length = SOC_I2C_FIFO_LEN - hw->status_reg.tx_fifo_cnt;
}
/**
@ -467,9 +452,9 @@ static inline uint32_t i2c_ll_get_txfifo_len(i2c_dev_t *hw)
*
* @return The I2C timeout value
*/
static inline uint32_t i2c_ll_get_tout(i2c_dev_t *hw)
static inline void i2c_ll_get_tout(i2c_dev_t *hw, int *timeout)
{
return hw->timeout.tout;
*timeout = hw->timeout.tout;
}
/**
@ -538,7 +523,8 @@ static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *l
*
* @return None.
*/
static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
__attribute__((always_inline))
static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, const uint8_t *ptr, uint8_t len)
{
uint32_t fifo_addr = (hw == &I2C0) ? 0x6001301c : 0x6002701c;
for(int i = 0; i < len; i++) {
@ -555,6 +541,7 @@ static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
{
uint32_t fifo_addr = (hw == &I2C0) ? 0x6001301c : 0x6002701c;
@ -592,155 +579,9 @@ static inline void i2c_ll_set_filter(i2c_dev_t *hw, uint8_t filter_num)
*
* @return The hardware filter configuration
*/
static inline uint8_t i2c_ll_get_filter(i2c_dev_t *hw)
static inline void i2c_ll_get_filter(i2c_dev_t *hw, uint8_t *filter_conf)
{
return hw->sda_filter_cfg.thres;
}
/**
* @brief Enable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = ~0;
hw->int_ena.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Enable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = ~0;
hw->int_ena.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief Disable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_TX_INT);
}
/**
* @brief Disable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_RX_INT);
}
/**
* @brief Clear I2C master TX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_clr_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Clear I2C master RX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_clr_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief Enable I2C slave TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_TX_INT;
}
/**
* @brief Enable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_RX_INT;
}
/**
* @brief Disable I2C slave TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_TX_INT);
}
/**
* @brief Disable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_RX_INT);
}
/**
* @brief Clear I2C slave TX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_clr_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_SLAVE_TX_INT;
}
/**
* @brief Clear I2C slave RX interrupt status register.
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_clr_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_SLAVE_RX_INT;
*filter_conf = hw->sda_filter_cfg.thres;
}
/**
@ -786,53 +627,6 @@ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_c
hw->ctr.ref_always_on = (src_clk == I2C_CLK_SRC_REF_TICK) ? 0 : 1;
}
/**
* @brief Get I2C master interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *event)
{
typeof(hw->int_status) int_sts = hw->int_status;
if (int_sts.arbitration_lost) {
*event = I2C_INTR_EVENT_ARBIT_LOST;
} else if (int_sts.nack) {
*event = I2C_INTR_EVENT_NACK;
} else if (int_sts.time_out) {
*event = I2C_INTR_EVENT_TOUT;
} else if (int_sts.end_detect) {
*event = I2C_INTR_EVENT_END_DET;
} else if (int_sts.trans_complete) {
*event = I2C_INTR_EVENT_TRANS_DONE;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Get I2C slave interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
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_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_wm) {
*event = I2C_INTR_EVENT_RXFIFO_FULL;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Init I2C master
@ -893,11 +687,67 @@ static inline void i2c_ll_slave_init(i2c_dev_t *hw)
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_update(i2c_dev_t *hw)
{
;// ESP32S2 do not support
}
/**
* @brief Set whether slave should auto start, or only start with start signal from master
*
* @param hw Beginning address of the peripheral registers
* @param slv_ex_auto_en 1 if slave auto start data transaction, otherwise, 0.
*/
static inline void i2c_ll_slave_tx_auto_start_en(i2c_dev_t *hw, bool slv_ex_auto_en)
{
;// ESP32-S2 do not support
}
/**
* @brief Get I2C interrupt status register address
*/
static inline volatile void *i2c_ll_get_interrupt_status_reg(i2c_dev_t *dev)
{
return &dev->int_status;
}
//////////////////////////////////////////Deprecated Functions//////////////////////////////////////////////////////////
/////////////////////////////The following functions are only used by the legacy driver/////////////////////////////////
/////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)//////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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_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_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 max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_REG_V
#define I2C_LL_INTR_MASK (0x1ffff) /*!< I2C all interrupt bitmap */
/**
* @brief I2C interrupt event
*/
typedef enum {
I2C_INTR_EVENT_ERR,
I2C_INTR_EVENT_ARBIT_LOST, /*!< I2C arbition lost event */
I2C_INTR_EVENT_NACK, /*!< I2C NACK event */
I2C_INTR_EVENT_TOUT, /*!< I2C time out event */
I2C_INTR_EVENT_END_DET, /*!< I2C end detected event */
I2C_INTR_EVENT_TRANS_DONE, /*!< I2C trans done event */
I2C_INTR_EVENT_RXFIFO_FULL, /*!< I2C rxfifo full event */
I2C_INTR_EVENT_TXFIFO_EMPTY, /*!< I2C txfifo empty event */
} i2c_intr_event_t;
/**
* @brief Configure I2C SCL timing
*
@ -931,6 +781,157 @@ static inline void i2c_ll_get_scl_clk_timing(i2c_dev_t *hw, int *high_period, in
*low_period = hw->scl_low_period.period;
}
/**
* @brief Get I2C master interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *event)
{
typeof(hw->int_status) int_sts = hw->int_status;
if (int_sts.arbitration_lost) {
*event = I2C_INTR_EVENT_ARBIT_LOST;
} else if (int_sts.nack) {
*event = I2C_INTR_EVENT_NACK;
} else if (int_sts.time_out) {
*event = I2C_INTR_EVENT_TOUT;
} else if (int_sts.end_detect) {
*event = I2C_INTR_EVENT_END_DET;
} else if (int_sts.trans_complete) {
*event = I2C_INTR_EVENT_TRANS_DONE;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Get I2C slave interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
__attribute__((always_inline))
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_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_wm) {
*event = I2C_INTR_EVENT_RXFIFO_FULL;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Enable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = UINT32_MAX;
hw->int_ena.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Enable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = UINT32_MAX;
hw->int_ena.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief Disable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_TX_INT);
}
/**
* @brief Disable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_master_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_RX_INT);
}
/**
* @brief Enable I2C slave TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_TX_INT;
}
/**
* @brief Enable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_RX_INT;
}
/**
* @brief Disable I2C slave TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_slave_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_TX_INT);
}
/**
* @brief Disable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_RX_INT);
}
#ifdef __cplusplus
}
#endif

View File

@ -8,18 +8,19 @@
#pragma once
#include "stdbool.h"
#include "hal/misc.h"
#include "soc/i2c_periph.h"
#include "soc/soc_caps.h"
#include "soc/i2c_struct.h"
#include "soc/clk_tree_defs.h"
#include "hal/i2c_types.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */
/**
* @brief I2C hardware cmd register fields.
*/
@ -36,35 +37,6 @@ typedef union {
uint32_t val;
} i2c_hw_cmd_t;
/**
* @brief I2C interrupt event
*/
typedef enum {
I2C_INTR_EVENT_ERR,
I2C_INTR_EVENT_ARBIT_LOST, /*!< I2C arbition lost event */
I2C_INTR_EVENT_NACK, /*!< I2C NACK event */
I2C_INTR_EVENT_TOUT, /*!< I2C time out event */
I2C_INTR_EVENT_END_DET, /*!< I2C end detected event */
I2C_INTR_EVENT_TRANS_DONE, /*!< I2C trans done event */
I2C_INTR_EVENT_RXFIFO_FULL, /*!< I2C rxfifo full event */
I2C_INTR_EVENT_TXFIFO_EMPTY, /*!< I2C txfifo empty event */
} i2c_intr_event_t;
/**
* @brief Data structure for calculating I2C bus timing.
*/
typedef struct {
uint16_t clkm_div; /*!< I2C core clock divider */
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 */
uint16_t hold; /*!< I2C start and stop condition hold period */
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 */
@ -72,20 +44,24 @@ typedef struct {
#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_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_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 max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_VALUE_V
typedef enum {
I2C_INTR_NACK = (1 << 10),
I2C_INTR_TIMEOUT = (1 << 8),
I2C_INTR_MST_COMPLETE = (1 << 7),
I2C_INTR_ARBITRATION = (1 << 5),
I2C_INTR_END_DETECT = (1 << 3),
I2C_INTR_ST_TO = (1 << 13),
} i2c_ll_master_intr_t;
typedef enum {
I2C_INTR_TXFIFO_WM = (1 << 1),
I2C_INTR_RXFIFO_WM = (1 << 0),
I2C_INTR_SLV_COMPLETE = (1 << 7),
I2C_INTR_START = (1 << 15),
} i2c_ll_slave_intr_t;
#define I2C_LL_MASTER_EVENT_INTR (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)
#define I2C_LL_SLAVE_EVENT_INTR (I2C_RXFIFO_WM_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_TXFIFO_WM_INT_ENA_M)
/**
* @brief Calculate I2C bus frequency
@ -99,7 +75,7 @@ typedef struct {
*
* @return None
*/
static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2c_clk_cal_t *clk_cal)
static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2c_hal_clk_config_t *clk_cal)
{
uint32_t clkm_div = source_clk / (bus_freq * 1024) +1;
uint32_t sclk_freq = source_clk / clkm_div;
@ -128,6 +104,7 @@ static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_update(i2c_dev_t *hw)
{
hw->ctr.conf_upgate = 1;
@ -141,7 +118,7 @@ static inline void i2c_ll_update(i2c_dev_t *hw)
*
* @return None
*/
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg)
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_hal_clk_config_t *bus_cfg)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, bus_cfg->clkm_div - 1);
/* According to the Technical Reference Manual, the following timings must be subtracted by 1.
@ -208,23 +185,6 @@ static inline void i2c_ll_set_scl_timing(i2c_dev_t *hw, int high_period, int low
hw->scl_high_period.scl_wait_high_period = high_period - high_period_output;
}
/**
* @brief Configure I2C SCL timing
*
* @param hw Beginning address of the peripheral registers
* @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)
* @param wait_high_period The I2C SCL wait rising edge period.
*
* @return None.
*/
static inline void i2c_ll_set_scl_clk_timing(i2c_dev_t *hw, int high_period, int low_period, int wait_high_period)
{
hw->scl_low_period.scl_low_period = low_period;
hw->scl_high_period.scl_high_period = high_period;
hw->scl_high_period.scl_wait_high_period = wait_high_period;
}
/**
* @brief Clear I2C interrupt status
*
@ -233,7 +193,8 @@ static inline void i2c_ll_set_scl_clk_timing(i2c_dev_t *hw, int high_period, int
*
* @return None
*/
static inline void i2c_ll_clr_intsts_mask(i2c_dev_t *hw, uint32_t mask)
__attribute__((always_inline))
static inline void i2c_ll_clear_intr_mask(i2c_dev_t *hw, uint32_t mask)
{
hw->int_clr.val = mask;
}
@ -259,6 +220,7 @@ static inline void i2c_ll_enable_intr_mask(i2c_dev_t *hw, uint32_t mask)
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_disable_intr_mask(i2c_dev_t *hw, uint32_t mask)
{
hw->int_ena.val &= (~mask);
@ -271,9 +233,10 @@ static inline void i2c_ll_disable_intr_mask(i2c_dev_t *hw, uint32_t mask)
*
* @return I2C interrupt status
*/
static inline uint32_t i2c_ll_get_intsts_mask(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_intr_mask(i2c_dev_t *hw, uint32_t *intr_status)
{
return hw->int_status.val;
*intr_status = hw->int_status.val;
}
/**
@ -493,9 +456,10 @@ static inline bool i2c_ll_is_master_mode(i2c_dev_t *hw)
*
* @return RxFIFO readable length
*/
static inline uint32_t i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw, uint32_t *length)
{
return hw->sr.rxfifo_cnt;
*length = hw->sr.rxfifo_cnt;
}
/**
@ -505,9 +469,10 @@ static inline uint32_t i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw)
*
* @return TxFIFO writable length
*/
static inline uint32_t i2c_ll_get_txfifo_len(i2c_dev_t *hw)
__attribute__((always_inline))
static inline void i2c_ll_get_txfifo_len(i2c_dev_t *hw, uint32_t *length)
{
return SOC_I2C_FIFO_LEN - hw->sr.txfifo_cnt;
*length = SOC_I2C_FIFO_LEN - hw->sr.txfifo_cnt;
}
/**
@ -517,9 +482,9 @@ static inline uint32_t i2c_ll_get_txfifo_len(i2c_dev_t *hw)
*
* @return The I2C timeout value
*/
static inline uint32_t i2c_ll_get_tout(i2c_dev_t *hw)
static inline void i2c_ll_get_tout(i2c_dev_t *hw, int *timeout)
{
return hw->to.time_out_value;
*timeout = hw->to.time_out_value;
}
/**
@ -579,22 +544,6 @@ static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *l
*low_period = hw->scl_low_period.scl_low_period + 1;
}
/**
* @brief Get I2C SCL timing configuration
*
* @param hw Beginning address of the peripheral registers
* @param high_period Pointer to accept the SCL high period
* @param low_period Pointer to accept the SCL low period
*
* @return None
*/
static inline void i2c_ll_get_scl_clk_timing(i2c_dev_t *hw, int *high_period, int *low_period, int *wait_high_period)
{
*high_period = hw->scl_high_period.scl_high_period;
*wait_high_period = hw->scl_high_period.scl_wait_high_period;
*low_period = hw->scl_low_period.scl_low_period;
}
/**
* @brief Write the I2C hardware txFIFO
*
@ -604,7 +553,8 @@ static inline void i2c_ll_get_scl_clk_timing(i2c_dev_t *hw, int *high_period, in
*
* @return None.
*/
static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
__attribute__((always_inline))
static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, const uint8_t *ptr, uint8_t len)
{
for (int i = 0; i< len; i++) {
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->data, fifo_rdata, ptr[i]);
@ -620,6 +570,7 @@ static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
{
for(int i = 0; i < len; i++) {
@ -656,155 +607,9 @@ static inline void i2c_ll_set_filter(i2c_dev_t *hw, uint8_t filter_num)
*
* @return The hardware filter configuration
*/
static inline uint8_t i2c_ll_get_filter(i2c_dev_t *hw)
static inline void i2c_ll_get_filter(i2c_dev_t *hw, uint8_t *filter_conf)
{
return hw->filter_cfg.scl_filter_thres;
}
/**
* @brief Enable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = ~0;
hw->int_ena.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Enable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = ~0;
hw->int_ena.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief Disable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_TX_INT);
}
/**
* @brief Disable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_RX_INT);
}
/**
* @brief Clear I2C master TX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_clr_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Clear I2C master RX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_clr_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_TX_INT;
}
/**
* @brief Enable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_RX_INT;
}
/**
* @brief Disable I2C slave TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_TX_INT);
}
/**
* @brief Disable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_RX_INT);
}
/**
* @brief Clear I2C slave TX interrupt status register
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_clr_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_SLAVE_TX_INT;
}
/**
* @brief Clear I2C slave RX interrupt status register.
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_clr_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = I2C_LL_SLAVE_RX_INT;
*filter_conf = hw->filter_cfg.scl_filter_thres;
}
/**
@ -832,9 +637,8 @@ static inline void i2c_ll_master_fsm_rst(i2c_dev_t *hw)
static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw)
{
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;
hw->ctr.conf_upgate = 1;
}
/**
@ -850,54 +654,6 @@ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_c
hw->clk_conf.sclk_sel = (src_clk == I2C_CLK_SRC_RC_FAST) ? 1 : 0;
}
/**
* @brief Get I2C master interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *event)
{
typeof(hw->int_status) int_sts = hw->int_status;
if (int_sts.arbitration_lost_int_st) {
*event = I2C_INTR_EVENT_ARBIT_LOST;
} else if (int_sts.nack_int_st) {
*event = I2C_INTR_EVENT_NACK;
} else if (int_sts.time_out_int_st) {
*event = I2C_INTR_EVENT_TOUT;
} else if (int_sts.end_detect_int_st) {
*event = I2C_INTR_EVENT_END_DET;
} else if (int_sts.trans_complete_int_st) {
*event = I2C_INTR_EVENT_TRANS_DONE;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Get I2C slave interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
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.txfifo_wm_int_st) {
*event = I2C_INTR_EVENT_TXFIFO_EMPTY;
} else if (int_sts.trans_complete_int_st) {
*event = I2C_INTR_EVENT_TRANS_DONE;
} else if (int_sts.rxfifo_wm_int_st) {
*event = I2C_INTR_EVENT_RXFIFO_FULL;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Init I2C master
*
@ -930,10 +686,247 @@ static inline void i2c_ll_slave_init(i2c_dev_t *hw)
ctrl_reg.sda_force_out = 1;
ctrl_reg.scl_force_out = 1;
hw->ctr.val = ctrl_reg.val;
hw->ctr.slv_tx_auto_start_en = 1;
hw->fifo_conf.fifo_addr_cfg_en = 0;
}
/**
* @brief Set whether slave should auto start, or only start with start signal from master
*
* @param hw Beginning address of the peripheral registers
* @param slv_ex_auto_en 1 if slave auto start data transaction, otherwise, 0.
*/
static inline void i2c_ll_slave_tx_auto_start_en(i2c_dev_t *hw, bool slv_ex_auto_en)
{
hw->ctr.slv_tx_auto_start_en = slv_ex_auto_en;
}
/**
* @brief Get I2C interrupt status register address
*/
static inline volatile void *i2c_ll_get_interrupt_status_reg(i2c_dev_t *dev)
{
return &dev->int_status;
}
//////////////////////////////////////////Deprecated Functions//////////////////////////////////////////////////////////
/////////////////////////////The following functions are only used by the legacy driver/////////////////////////////////
/////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)//////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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_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_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 max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_VALUE_V
#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */
/**
* @brief I2C interrupt event
*/
typedef enum {
I2C_INTR_EVENT_ERR,
I2C_INTR_EVENT_ARBIT_LOST, /*!< I2C arbition lost event */
I2C_INTR_EVENT_NACK, /*!< I2C NACK event */
I2C_INTR_EVENT_TOUT, /*!< I2C time out event */
I2C_INTR_EVENT_END_DET, /*!< I2C end detected event */
I2C_INTR_EVENT_TRANS_DONE, /*!< I2C trans done event */
I2C_INTR_EVENT_RXFIFO_FULL, /*!< I2C rxfifo full event */
I2C_INTR_EVENT_TXFIFO_EMPTY, /*!< I2C txfifo empty event */
} i2c_intr_event_t;
/**
* @brief Get I2C SCL timing configuration
*
* @param hw Beginning address of the peripheral registers
* @param high_period Pointer to accept the SCL high period
* @param low_period Pointer to accept the SCL low period
*
* @return None
*/
static inline void i2c_ll_get_scl_clk_timing(i2c_dev_t *hw, int *high_period, int *low_period, int *wait_high_period)
{
*high_period = hw->scl_high_period.scl_high_period;
*wait_high_period = hw->scl_high_period.scl_wait_high_period;
*low_period = hw->scl_low_period.scl_low_period;
}
/**
* @brief Configure I2C SCL timing
*
* @param hw Beginning address of the peripheral registers
* @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)
* @param wait_high_period The I2C SCL wait rising edge period.
*
* @return None.
*/
static inline void i2c_ll_set_scl_clk_timing(i2c_dev_t *hw, int high_period, int low_period, int wait_high_period)
{
hw->scl_low_period.scl_low_period = low_period;
hw->scl_high_period.scl_high_period = high_period;
hw->scl_high_period.scl_wait_high_period = wait_high_period;
}
/**
* @brief Get I2C master interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *event)
{
typeof(hw->int_status) int_sts = hw->int_status;
if (int_sts.arbitration_lost_int_st) {
*event = I2C_INTR_EVENT_ARBIT_LOST;
} else if (int_sts.nack_int_st) {
*event = I2C_INTR_EVENT_NACK;
} else if (int_sts.time_out_int_st) {
*event = I2C_INTR_EVENT_TOUT;
} else if (int_sts.end_detect_int_st) {
*event = I2C_INTR_EVENT_END_DET;
} else if (int_sts.trans_complete_int_st) {
*event = I2C_INTR_EVENT_TRANS_DONE;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Get I2C slave interrupt event
*
* @param hw Beginning address of the peripheral registers
* @param event Pointer to accept the interrupt event
*
* @return None
*/
__attribute__((always_inline))
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.txfifo_wm_int_st) {
*event = I2C_INTR_EVENT_TXFIFO_EMPTY;
} else if (int_sts.trans_complete_int_st) {
*event = I2C_INTR_EVENT_TRANS_DONE;
} else if (int_sts.rxfifo_wm_int_st) {
*event = I2C_INTR_EVENT_RXFIFO_FULL;
} else {
*event = I2C_INTR_EVENT_ERR;
}
}
/**
* @brief Enable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_tx_it(i2c_dev_t *hw)
{
hw->int_clr.val = UINT32_MAX;
hw->int_ena.val = I2C_LL_MASTER_TX_INT;
}
/**
* @brief Enable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_enable_rx_it(i2c_dev_t *hw)
{
hw->int_clr.val = UINT32_MAX;
hw->int_ena.val = I2C_LL_MASTER_RX_INT;
}
/**
* @brief Disable I2C master TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_master_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_TX_INT);
}
/**
* @brief Disable I2C master RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_master_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_MASTER_RX_INT);
}
/**
* @brief
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= 0x2;
}
/**
* @brief Enable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_enable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val |= I2C_LL_SLAVE_RX_INT;
}
/**
* @brief Disable I2C slave TX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
__attribute__((always_inline))
static inline void i2c_ll_slave_disable_tx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_TX_INT);
}
/**
* @brief Disable I2C slave RX interrupt
*
* @param hw Beginning address of the peripheral registers
*
* @return None
*/
static inline void i2c_ll_slave_disable_rx_it(i2c_dev_t *hw)
{
hw->int_ena.val &= (~I2C_LL_SLAVE_RX_INT);
}
#ifdef __cplusplus
}
#endif

View File

@ -5,154 +5,12 @@
*/
#include "hal/i2c_hal.h"
void i2c_hal_txfifo_rst(i2c_hal_context_t *hal)
{
i2c_ll_txfifo_rst(hal->dev);
}
void i2c_hal_rxfifo_rst(i2c_hal_context_t *hal)
{
i2c_ll_rxfifo_rst(hal->dev);
}
void i2c_hal_set_data_mode(i2c_hal_context_t *hal, i2c_trans_mode_t tx_mode, i2c_trans_mode_t rx_mode)
{
i2c_ll_set_data_mode(hal->dev, tx_mode, rx_mode);
}
void i2c_hal_get_data_mode(i2c_hal_context_t *hal, i2c_trans_mode_t *tx_mode, i2c_trans_mode_t *rx_mode)
{
i2c_ll_get_data_mode(hal->dev, tx_mode, rx_mode);
}
void i2c_hal_set_filter(i2c_hal_context_t *hal, uint8_t filter_num)
{
i2c_ll_set_filter(hal->dev, filter_num);
}
void i2c_hal_get_filter(i2c_hal_context_t *hal, uint8_t *filter_num)
{
*filter_num = i2c_ll_get_filter(hal->dev);
}
void i2c_hal_set_scl_timing(i2c_hal_context_t *hal, int hight_period, int low_period)
{
i2c_ll_set_scl_timing(hal->dev, hight_period, low_period);
}
void i2c_hal_clr_intsts_mask(i2c_hal_context_t *hal, uint32_t mask)
{
i2c_ll_clr_intsts_mask(hal->dev, mask);
}
void i2c_hal_enable_intr_mask(i2c_hal_context_t *hal, uint32_t mask)
{
i2c_ll_enable_intr_mask(hal->dev, mask);
}
void i2c_hal_disable_intr_mask(i2c_hal_context_t *hal, uint32_t mask)
{
i2c_ll_disable_intr_mask(hal->dev, mask);
}
void i2c_hal_get_intsts_mask(i2c_hal_context_t *hal, uint32_t *mask)
{
*mask = i2c_ll_get_intsts_mask(hal->dev);
}
void i2c_hal_set_fifo_mode(i2c_hal_context_t *hal, bool fifo_mode_en)
{
i2c_ll_set_fifo_mode(hal->dev, fifo_mode_en);
}
void i2c_hal_set_tout(i2c_hal_context_t *hal, int tout_num)
{
i2c_ll_set_tout(hal->dev, tout_num);
}
void i2c_hal_set_stop_timing(i2c_hal_context_t *hal, int stop_setup, int stop_hold)
{
i2c_ll_set_stop_timing(hal->dev, stop_setup, stop_hold);
}
void i2c_hal_set_start_timing(i2c_hal_context_t *hal, int start_setup, int start_hold)
{
i2c_ll_set_start_timing(hal->dev, start_setup, start_hold);
}
void i2c_hal_set_sda_timing(i2c_hal_context_t *hal, int sda_sample, int sda_hold)
{
i2c_ll_set_sda_timing(hal->dev, sda_sample, sda_hold);
}
void i2c_hal_set_txfifo_empty_thr(i2c_hal_context_t *hal, uint8_t empty_thr)
{
i2c_ll_set_txfifo_empty_thr(hal->dev, empty_thr);
}
void i2c_hal_set_rxfifo_full_thr(i2c_hal_context_t *hal, uint8_t full_thr)
{
i2c_ll_set_rxfifo_full_thr(hal->dev, full_thr);
}
bool i2c_hal_is_bus_busy(i2c_hal_context_t *hal)
{
return i2c_ll_is_bus_busy(hal->dev);
}
void i2c_hal_get_sda_timing(i2c_hal_context_t *hal, int *sample_time, int *hold_time)
{
i2c_ll_get_sda_timing(hal->dev, sample_time, hold_time);
}
void i2c_hal_get_tout(i2c_hal_context_t *hal, int *tout_val)
{
*tout_val = i2c_ll_get_tout(hal->dev);
}
void i2c_hal_get_start_timing(i2c_hal_context_t *hal, int *setup_time, int *hold_time)
{
i2c_ll_get_start_timing(hal->dev, setup_time, hold_time);
}
void i2c_hal_get_stop_timing(i2c_hal_context_t *hal, int *setup_time, int *hold_time)
{
i2c_ll_get_stop_timing(hal->dev, setup_time, hold_time);
}
void i2c_hal_get_scl_timing(i2c_hal_context_t *hal, int *high_period, int *low_period)
{
i2c_ll_get_scl_timing(hal->dev, high_period, low_period);
}
bool i2c_hal_is_master_mode(i2c_hal_context_t *hal)
{
return i2c_ll_is_master_mode(hal->dev);
}
#include "hal/i2c_ll.h"
#include "hal/i2c_types.h"
#if SOC_I2C_SUPPORT_SLAVE
void i2c_hal_set_slave_addr(i2c_hal_context_t *hal, uint16_t slave_addr, bool addr_10bit_en)
{
i2c_ll_set_slave_addr(hal->dev, slave_addr, addr_10bit_en);
}
void i2c_hal_enable_slave_tx_it(i2c_hal_context_t *hal)
{
i2c_ll_slave_enable_tx_it(hal->dev);
}
void i2c_hal_enable_slave_rx_it(i2c_hal_context_t *hal)
{
i2c_ll_slave_enable_rx_it(hal->dev);
}
void i2c_hal_disable_slave_rx_it(i2c_hal_context_t *hal)
{
i2c_ll_slave_disable_rx_it(hal->dev);
}
void i2c_hal_slave_init(i2c_hal_context_t *hal, i2c_port_t i2c_num)
void i2c_hal_slave_init(i2c_hal_context_t *hal)
{
i2c_ll_slave_init(hal->dev);
//Use fifo mode
@ -168,24 +26,18 @@ void i2c_hal_slave_init(i2c_hal_context_t *hal, i2c_port_t i2c_num)
void i2c_hal_set_bus_timing(i2c_hal_context_t *hal, int scl_freq, i2c_clock_source_t src_clk, int source_freq)
{
i2c_ll_set_source_clk(hal->dev, src_clk);
i2c_clk_cal_t clk_cal = {0};
i2c_hal_clk_config_t clk_cal = {0};
i2c_ll_cal_bus_clk(source_freq, scl_freq, &clk_cal);
i2c_ll_set_bus_timing(hal->dev, &clk_cal);
}
void i2c_hal_master_clr_bus(i2c_hal_context_t *hal)
{
i2c_ll_master_clr_bus(hal->dev);
}
void i2c_hal_master_fsm_rst(i2c_hal_context_t *hal)
{
i2c_ll_master_fsm_rst(hal->dev);
}
void i2c_hal_master_init(i2c_hal_context_t *hal, i2c_port_t i2c_num)
void i2c_hal_master_init(i2c_hal_context_t *hal)
{
hal->version = i2c_ll_get_hw_version(hal->dev);
i2c_ll_master_init(hal->dev);
//Use fifo mode
i2c_ll_set_fifo_mode(hal->dev, true);
@ -195,3 +47,32 @@ void i2c_hal_master_init(i2c_hal_context_t *hal, i2c_port_t i2c_num)
i2c_ll_txfifo_rst(hal->dev);
i2c_ll_rxfifo_rst(hal->dev);
}
void i2c_hal_init(i2c_hal_context_t *hal, int i2c_port)
{
hal->dev = I2C_LL_GET_HW(i2c_port);
}
void i2c_hal_master_trans_start(i2c_hal_context_t *hal)
{
i2c_ll_update(hal->dev);
i2c_ll_trans_start(hal->dev);
}
void i2c_hal_get_timing_config(i2c_hal_context_t *hal, i2c_hal_timing_config_t *timing_config)
{
i2c_ll_get_scl_clk_timing(hal->dev, &timing_config->high_period, &timing_config->low_period, &timing_config->wait_high_period);
i2c_ll_get_start_timing(hal->dev, &timing_config->rstart_setup, &timing_config->start_hold);
i2c_ll_get_stop_timing(hal->dev, &timing_config->stop_setup, &timing_config->stop_hold);
i2c_ll_get_sda_timing(hal->dev, &timing_config->sda_sample, &timing_config->sda_hold);
i2c_ll_get_tout(hal->dev, &timing_config->timeout);
}
void i2c_hal_set_timing_config(i2c_hal_context_t *hal, i2c_hal_timing_config_t *timing_config)
{
i2c_ll_set_scl_clk_timing(hal->dev, timing_config->high_period, timing_config->low_period, timing_config->wait_high_period);
i2c_ll_set_start_timing(hal->dev, timing_config->rstart_setup, timing_config->start_hold);
i2c_ll_set_stop_timing(hal->dev, timing_config->stop_setup, timing_config->stop_hold);
i2c_ll_set_sda_timing(hal->dev, timing_config->sda_sample, timing_config->sda_hold);
i2c_ll_set_tout(hal->dev, timing_config->timeout);
}

View File

@ -6,57 +6,41 @@
#include "hal/i2c_hal.h"
//////////////////////////////////////////Deprecated Functions//////////////////////////////////////////////////////////
/////////////////////////////The following functions are only used by the legacy driver/////////////////////////////////
/////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)//////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void i2c_hal_master_handle_tx_event(i2c_hal_context_t *hal, i2c_intr_event_t *event)
{
if (i2c_ll_get_intsts_mask(hal->dev) != 0) {
uint32_t intr_status = 0;
i2c_ll_get_intr_mask(hal->dev, &intr_status);
if (intr_status != 0) {
// If intr status is 0, no need to handle it.
i2c_ll_master_get_event(hal->dev, event);
if ((*event < I2C_INTR_EVENT_END_DET) ||
(*event == I2C_INTR_EVENT_TRANS_DONE)) {
i2c_ll_master_disable_tx_it(hal->dev);
i2c_ll_master_clr_tx_it(hal->dev);
i2c_ll_clear_intr_mask(hal->dev, intr_status);
} else if (*event == I2C_INTR_EVENT_END_DET) {
i2c_ll_master_clr_tx_it(hal->dev);
i2c_ll_clear_intr_mask(hal->dev, intr_status);
}
}
}
void i2c_hal_master_handle_rx_event(i2c_hal_context_t *hal, i2c_intr_event_t *event)
{
if (i2c_ll_get_intsts_mask(hal->dev) != 0) {
uint32_t intr_status = 0;
i2c_ll_get_intr_mask(hal->dev, &intr_status);
if (intr_status != 0) {
i2c_ll_master_get_event(hal->dev, event);
if ((*event < I2C_INTR_EVENT_END_DET) ||
(*event == I2C_INTR_EVENT_TRANS_DONE)) {
i2c_ll_master_disable_rx_it(hal->dev);
i2c_ll_master_clr_rx_it(hal->dev);
i2c_ll_clear_intr_mask(hal->dev, intr_status);
} else if (*event == I2C_INTR_EVENT_END_DET) {
i2c_ll_master_clr_rx_it(hal->dev);
i2c_ll_clear_intr_mask(hal->dev, intr_status);
}
}
}
#if SOC_I2C_SUPPORT_SLAVE
void i2c_hal_slave_handle_event(i2c_hal_context_t *hal, i2c_intr_event_t *event)
{
i2c_ll_slave_get_event(hal->dev, event);
}
void i2c_hal_disable_slave_tx_it(i2c_hal_context_t *hal)
{
i2c_ll_slave_disable_tx_it(hal->dev);
}
#endif // SOC_I2C_SUPPORT_SLAVE
void i2c_hal_update_config(i2c_hal_context_t *hal)
{
i2c_ll_update(hal->dev);
}
void i2c_hal_get_rxfifo_cnt(i2c_hal_context_t *hal, uint32_t *len)
{
*len = i2c_ll_get_rxfifo_cnt(hal->dev);
}
void i2c_hal_get_txfifo_cnt(i2c_hal_context_t *hal, uint32_t *len)
{
*len = i2c_ll_get_txfifo_len(hal->dev);
}

View File

@ -13,95 +13,22 @@
// The HAL layer for I2C
#pragma once
#include "hal/i2c_ll.h"
#include "hal/i2c_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief I2C hal Context definition
*/
typedef struct {
i2c_dev_t *dev;
uint32_t version;
} i2c_hal_context_t;
/**
* @brief Write the I2C rxfifo with the given length
*
* @param hal Context of the HAL layer
* @param wr_data Pointer to data buffer
* @param wr_size Amount of data needs write
*
* @return None
*/
#define i2c_hal_write_txfifo(hal,wr_data,wr_size) i2c_ll_write_txfifo((hal)->dev,wr_data,wr_size)
/**
* @brief Read the I2C rxfifo with the given length
*
* @param hal Context of the HAL layer
* @param buf Pointer to data buffer
* @param rd_size Amount of data needs read
*
* @return None
*/
#define i2c_hal_read_rxfifo(hal,buf,rd_size) i2c_ll_read_rxfifo((hal)->dev,buf,rd_size)
/**
* @brief Write I2C cmd register
*
* @param hal Context of the HAL layer
* @param cmd I2C hardware command
* @param cmd_idx The index of the command register, should be less than 16
*
* @return None
*/
#define i2c_hal_write_cmd_reg(hal,cmd, cmd_idx) i2c_ll_write_cmd_reg((hal)->dev,cmd,cmd_idx)
/**
* @brief Configure the I2C to triger a transaction
*
* @param hal Context of the HAL layer
*
* @return None
*/
#define i2c_hal_trans_start(hal) i2c_ll_trans_start((hal)->dev)
/**
* @brief Enable I2C master RX interrupt
*
* @param hal Context of the HAL layer
*
* @return None
*/
#define i2c_hal_enable_master_rx_it(hal) i2c_ll_master_enable_rx_it((hal)->dev)
/**
* @brief Enable I2C master TX interrupt
*
* @param hal Context of the HAL layer
*
* @return None
*/
#define i2c_hal_enable_master_tx_it(hal) i2c_ll_master_enable_tx_it((hal)->dev)
#if SOC_I2C_SUPPORT_SLAVE
/**
* @brief Clear I2C slave TX interrupt
*
* @param hal Context of the HAL layer
*
* @return None
*/
#define i2c_hal_slave_clr_tx_it(hal) i2c_ll_slave_clr_tx_it((hal)->dev)
/**
* @brief Clear I2C slave RX interrupt
*
* @param hal Context of the HAL layer
*
* @return None
*/
#define i2c_hal_slave_clr_rx_it(hal) i2c_ll_slave_clr_rx_it((hal)->dev)
/**
* @brief Init the I2C slave.
@ -111,100 +38,10 @@ typedef struct {
*
* @return None
*/
void i2c_hal_slave_init(i2c_hal_context_t *hal, i2c_port_t i2c_num);
void i2c_hal_slave_init(i2c_hal_context_t *hal);
/**
* @brief Configure the I2C slave address
*
* @param hal Context of the HAL layer
* @param slave_addr Slave address
* @param addr_10bit_en Set true to enable 10-bit slave address mode, Set false to enable 7-bit address mode
*
* @return None
*/
void i2c_hal_set_slave_addr(i2c_hal_context_t *hal, uint16_t slave_addr, bool addr_10bit_en);
/**
* @brief Enable I2C slave TX interrupt
*
* @param hal Context of the HAL layer
*
* @return None
*/
void i2c_hal_enable_slave_tx_it(i2c_hal_context_t *hal);
/**
* @brief Disable I2C slave TX interrupt
*
* @param hal Context of the HAL layer
*
* @return None
*/
void i2c_hal_disable_slave_tx_it(i2c_hal_context_t *hal);
/**
* @brief Enable I2C slave RX interrupt
*
* @param hal Context of the HAL layer
*
* @return None
*/
void i2c_hal_enable_slave_rx_it(i2c_hal_context_t *hal);
/**
* @brief Disable I2C slave RX interrupt
*
* @param hal Context of the HAL layer
*
* @return None
*/
void i2c_hal_disable_slave_rx_it(i2c_hal_context_t *hal);
/**
* @brief I2C slave handle interrupt event
*
* @param hal Context of the HAL layer
* @param event Pointer to accept the interrupt event
*
* @return None
*/
void i2c_hal_slave_handle_event(i2c_hal_context_t *hal, i2c_intr_event_t *event);
#endif // SOC_I2C_SUPPORT_SLAVE
/**
* @brief Set the source clock. This function is meant to be used in
* slave mode, in order to select a source clock abe to handle
* the expected SCL frequency.
*
* @param hal Context of the HAL layer
* @param src_clk Source clock to use choosen from `i2c_clock_source_t` type
*/
#define i2c_hal_set_source_clk(hal, src_clk) i2c_ll_set_source_clk((hal)->dev, src_clk)
/**
* @brief Configure I2C SCL timing
*
* @param hw Beginning address of the peripheral registers
* @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)
* @param wait_high_period The I2C SCL wait rising edge period.
*
* @return None.
*/
#define i2c_hal_set_scl_clk_timing(hal, high_period, low_period, wait_high_period) i2c_ll_set_scl_clk_timing((hal)->dev, high_period, low_period, wait_high_period)
/**
* @brief Get I2C SCL timing configuration
*
* @param hw Beginning address of the peripheral registers
* @param high_period Pointer to accept the SCL high period
* @param low_period Pointer to accept the SCL low period
*
* @return None
*/
#define i2c_hal_get_scl_clk_timing(hal, high_period, low_period, wait_high_period) i2c_ll_get_scl_clk_timing((hal)->dev, high_period, low_period, wait_high_period)
/**
* @brief Init the I2C master.
*
@ -213,273 +50,7 @@ void i2c_hal_slave_handle_event(i2c_hal_context_t *hal, i2c_intr_event_t *event)
*
* @return None
*/
void i2c_hal_master_init(i2c_hal_context_t *hal, i2c_port_t i2c_num);
/**
* @brief Reset the I2C hw txfifo
*
* @param hal Context of the HAL layer
*
* @return None
*/
void i2c_hal_txfifo_rst(i2c_hal_context_t *hal);
/**
* @brief Reset the I2C hw rxfifo
*
* @param hal Context of the HAL layer
*
* @return None
*/
void i2c_hal_rxfifo_rst(i2c_hal_context_t *hal);
/**
* @brief Configure the I2C data MSB bit shifted first or LSB bit shifted first.
*
* @param hal Context of the HAL layer
* @param tx_mode Data format of TX
* @param rx_mode Data format of RX
*
* @return None
*/
void i2c_hal_set_data_mode(i2c_hal_context_t *hal, i2c_trans_mode_t tx_mode, i2c_trans_mode_t rx_mode);
/**
* @brief Configure the I2C hardware filter function.
*
* @param hal Context of the HAL layer
* @param filter_num If the glitch period on the line is less than this value(in APB cycle), it will be filtered out
* If `filter_num == 0`, the filter will be disabled
*
* @return None
*/
void i2c_hal_set_filter(i2c_hal_context_t *hal, uint8_t filter_num);
/**
* @brief Get the I2C hardware filter configuration
*
* @param hal Context of the HAL layer
* @param filter_num Pointer to accept the hardware filter configuration
*
* @return None
*/
void i2c_hal_get_filter(i2c_hal_context_t *hal, uint8_t *filter_num);
/**
* @brief Configure the I2C SCL timing
*
* @param hal Context of the HAL layer
* @param hight_period SCL high period
* @param low_period SCL low period
*
* @return None
*/
void i2c_hal_set_scl_timing(i2c_hal_context_t *hal, int hight_period, int low_period);
/**
* @brief Configure the I2C master SCL frequency
*
* @param hal Context of the HAL layer
* @param src_clk The I2C Source clock frequency
* @param scl_freq The SCL frequency to be set
*
* @return None
*/
void i2c_hal_set_scl_freq(i2c_hal_context_t *hal, uint32_t src_clk, uint32_t scl_freq);
/**
* @brief Clear the I2C interrupt status with the given mask
*
* @param hal Context of the HAL layer
* @param mask The interrupt bitmap needs to be clearned
*
* @return None
*/
void i2c_hal_clr_intsts_mask(i2c_hal_context_t *hal, uint32_t mask);
/**
* @brief Enable the I2C interrupt with the given mask
*
* @param hal Context of the HAL layer
* @param mask The interrupt bitmap needs to be enabled
*
* @return None
*/
void i2c_hal_enable_intr_mask(i2c_hal_context_t *hal, uint32_t mask);
/**
* @brief Disable the I2C interrupt with the given mask
*
* @param hal Context of the HAL layer
* @param mask The interrupt bitmap needs to be disabled
*
* @return None
*/
void i2c_hal_disable_intr_mask(i2c_hal_context_t *hal, uint32_t mask);
/**
* @brief Configure the I2C memory access mode, FIFO mode or none FIFO mode
*
* @param hal Context of the HAL layer
* @param fifo_mode_en Set true to enable FIFO access mode, else set it false
*
* @return None
*/
void i2c_hal_set_fifo_mode(i2c_hal_context_t *hal, bool fifo_mode_en);
/**
* @brief Configure the I2C timeout value
*
* @param hal Context of the HAL layer
* @param tout_val the timeout value to be set
*
* @return None
*/
void i2c_hal_set_tout(i2c_hal_context_t *hal, int tout_val);
/**
* @brief Get the I2C time out configuration
*
* @param tout_val Pointer to accept the timeout configuration
*
* @return None
*/
void i2c_hal_get_tout(i2c_hal_context_t *hal, int *tout_val);
/**
* @brief Configure the I2C stop timing
*
* @param hal Context of the HAL layer
* @param stop_setup The stop condition setup period (in APB cycle)
* @param stop_hold The stop condition hold period (in APB cycle)
*
* @return None
*/
void i2c_hal_set_stop_timing(i2c_hal_context_t *hal, int stop_setup, int stop_hold);
/**
* @brief Configure the I2C start timing
*
* @param hal Context of the HAL layer
* @param start_setup The start condition setup period (in APB cycle)
* @param start_hold The start condition hold period (in APB cycle)
*
* @return None
*/
void i2c_hal_set_start_timing(i2c_hal_context_t *hal, int start_setup, int start_hold);
/**
* @brief Configure the I2C sda sample timing
*
* @param hal Context of the HAL layer
* @param sda_sample The SDA sample time (in APB cycle)
* @param sda_hold The SDA hold time (in APB cycle)
*
* @return None
*/
void i2c_hal_set_sda_timing(i2c_hal_context_t *hal, int sda_sample, int sda_hold);
/**
* @brief Configure the I2C txfifo empty threshold value
*
* @param hal Context of the HAL layer.
* @param empty_thr TxFIFO empty threshold value
*
* @return None
*/
void i2c_hal_set_txfifo_empty_thr(i2c_hal_context_t *hal, uint8_t empty_thr);
/**
* @brief Configure the I2C rxfifo full threshold value
*
* @param hal Context of the HAL layer
* @param full_thr RxFIFO full threshold value
*
* @return None
*/
void i2c_hal_set_rxfifo_full_thr(i2c_hal_context_t *hal, uint8_t full_thr);
/**
* @brief Get the I2C interrupt status
*
* @param hal Context of the HAL layer
* @param mask Pointer to accept the interrupt status
*
* @return None
*/
void i2c_hal_get_intsts_mask(i2c_hal_context_t *hal, uint32_t *mask);
/**
* @brief Check if the I2C bus is busy
*
* @param hal Context of the HAL layer
*
* @return True if the bus is busy, otherwise, fale will be returned
*/
bool i2c_hal_is_bus_busy(i2c_hal_context_t *hal);
/**
* @brief Get the I2C sda sample timing configuration
*
* @param hal Context of the HAL layer
* @param sample_time Pointer to accept the SDA sample time
* @param hold_time Pointer to accept the SDA hold time
*
* @return None
*/
void i2c_hal_get_sda_timing(i2c_hal_context_t *hal, int *sample_time, int *hold_time);
/**
* @brief Get the I2C stop timing configuration
*
* @param hal Context of the HAL layer
* @param setup_time Pointer to accept the stop condition setup period
* @param hold_time Pointer to accept the stop condition hold period
*
* @return None
*/
void i2c_hal_get_stop_timing(i2c_hal_context_t *hal, int *setup_time, int *hold_time);
/**
* @brief Get the I2C scl timing configuration
*
* @param hal Context of the HAL layer
* @param high_period Pointer to accept the scl high period
* @param low_period Pointer to accept the scl low period
*
* @return None
*/
void i2c_hal_get_scl_timing(i2c_hal_context_t *hal, int *high_period, int *low_period);
/**
* @brief Get the I2C start timing configuration
*
* @param hal Context of the HAL layer
* @param setup_time Pointer to accept the start condition setup period
* @param hold_time Pointer to accept the start condition hold period
*
* @return None
*/
void i2c_hal_get_start_timing(i2c_hal_context_t *hal, int *setup_time, int *hold_time);
/**
* @brief Check if the I2C is master mode
*
* @param hal Context of the HAL layer
*
* @return True if in master mode, otherwise, false will be returned
*/
bool i2c_hal_is_master_mode(i2c_hal_context_t *hal);
/**
* @brief Get the rxFIFO readable length
*
* @param hal Context of the HAL layer
* @param len Pointer to accept the rxFIFO readable length
*
* @return None
*/
void i2c_hal_get_rxfifo_cnt(i2c_hal_context_t *hal, uint32_t *len);
void i2c_hal_master_init(i2c_hal_context_t *hal);
/**
* @brief Set I2C bus timing with the given frequency
@ -493,27 +64,6 @@ void i2c_hal_get_rxfifo_cnt(i2c_hal_context_t *hal, uint32_t *len);
*/
void i2c_hal_set_bus_timing(i2c_hal_context_t *hal, int scl_freq, i2c_clock_source_t src_clk, int source_freq);
/**
* @brief Get I2C txFIFO writeable length
*
* @param hal Context of the HAL layer
* @param len Pointer to accept the txFIFO writeable length
*
* @return None
*/
void i2c_hal_get_txfifo_cnt(i2c_hal_context_t *hal, uint32_t *len);
/**
* @brief Check if the I2C is master mode
*
* @param hal Context of the HAL layer
* @param tx_mode Pointer to accept the TX data mode
* @param rx_mode Pointer to accept the RX data mode
*
* @return None
*/
void i2c_hal_get_data_mode(i2c_hal_context_t *hal, i2c_trans_mode_t *tx_mode, i2c_trans_mode_t *rx_mode);
/**
* @brief I2C hardware FSM reset
*
@ -523,15 +73,6 @@ void i2c_hal_get_data_mode(i2c_hal_context_t *hal, i2c_trans_mode_t *tx_mode, i2
*/
void i2c_hal_master_fsm_rst(i2c_hal_context_t *hal);
/**
* @brief @brief Clear I2C bus
*
* @param hal Context of the HAL layer
*
* @return None
*/
void i2c_hal_master_clr_bus(i2c_hal_context_t *hal);
/**
* @brief I2C master handle tx interrupt event
*
@ -553,11 +94,36 @@ void i2c_hal_master_handle_tx_event(i2c_hal_context_t *hal, i2c_intr_event_t *ev
void i2c_hal_master_handle_rx_event(i2c_hal_context_t *hal, i2c_intr_event_t *event);
/**
* @brief Synchronize I2C status
*
* @param hal Context of the HAL layer
*
* @return None
* @brief Init I2C hal layer
*
* @param hal Context of the HAL
* @param i2c_port I2C port number.
*/
void i2c_hal_update_config(i2c_hal_context_t *hal);
void i2c_hal_init(i2c_hal_context_t *hal, int i2c_port);
/**
* @brief Start I2C master transaction
*
* @param hal Context of the HAL
*/
void i2c_hal_master_trans_start(i2c_hal_context_t *hal);
/**
* @brief Get timing configuration
*
* @param hal Context of the HAL
* @param timing_config Pointer to timing config structure.
*/
void i2c_hal_get_timing_config(i2c_hal_context_t *hal, i2c_hal_timing_config_t *timing_config);
/**
* @brief Set timing configuration
*
* @param hal Context of the HAL
* @param timing_config Timing config structure.
*/
void i2c_hal_set_timing_config(i2c_hal_context_t *hal, i2c_hal_timing_config_t *timing_config);
#ifdef __cplusplus
}
#endif

View File

@ -26,6 +26,21 @@ typedef enum {
I2C_NUM_MAX, /*!< I2C port max */
} i2c_port_t;
/**
* @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 */
uint16_t hold; /*!< I2C start and stop condition hold period */
uint16_t tout; /*!< I2C bus timeout period */
} i2c_hal_clk_config_t;
typedef enum{
#if SOC_I2C_SUPPORT_SLAVE
I2C_MODE_SLAVE = 0, /*!< I2C slave mode */
@ -58,6 +73,23 @@ typedef enum {
I2C_MASTER_ACK_MAX,
} i2c_ack_type_t;
/**
* @brief Timing configuration structure. Used for I2C reset internally.
*/
typedef struct {
int high_period; /*!< high_period time */
int low_period; /*!< low_period time */
int wait_high_period; /*!< wait_high_period time */
int rstart_setup; /*!< restart setup */
int start_hold; /*!< start hold time */
int stop_setup; /*!< stop setup */
int stop_hold; /*!< stop hold time */
int sda_sample; /*!< high_period time */
int sda_hold; /*!< sda hold time */
int timeout; /*!< timeout value */
} i2c_hal_timing_config_t;
/**
* @brief I2C group clock source
*/

View File

@ -241,7 +241,7 @@ config SOC_I2C_NUM
config SOC_I2C_FIFO_LEN
int
default 32
default 16
config SOC_I2C_SUPPORT_HW_CLR_BUS
bool

View File

@ -124,7 +124,7 @@
// ESP32-C2 has 1 I2C
#define SOC_I2C_NUM (1U)
#define SOC_I2C_FIFO_LEN (32) /*!< I2C hardware FIFO depth */
#define SOC_I2C_FIFO_LEN (16) /*!< I2C hardware FIFO depth */
// FSM_RST only resets the FSM, not using it. So SOC_I2C_SUPPORT_HW_FSM_RST not defined.
#define SOC_I2C_SUPPORT_HW_CLR_BUS (1)