mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
bugfix(i2c): fix I2C driver breaking change issue.
1. Fixed I2C driver breaking change issue. 2. Add I2C UT test case.
This commit is contained in:
parent
70cfd7e24c
commit
aac935ec81
@ -37,7 +37,6 @@ static const char* I2C_TAG = "i2c";
|
||||
return (ret); \
|
||||
}
|
||||
|
||||
static portMUX_TYPE i2c_spinlock[I2C_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED};
|
||||
/* DRAM_ATTR is required to avoid I2C array placed in flash, due to accessed from ISR */
|
||||
|
||||
#define I2C_ENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux)
|
||||
@ -84,6 +83,12 @@ static portMUX_TYPE i2c_spinlock[I2C_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, p
|
||||
#define I2C_CLR_BUS_SCL_NUM (9)
|
||||
#define I2C_CLR_BUS_HALF_PERIOD_US (5)
|
||||
|
||||
#define I2C_CONTEX_INIT_DEF(uart_num) {\
|
||||
.hal.dev = I2C_LL_GET_HW(uart_num),\
|
||||
.spinlock = portMUX_INITIALIZER_UNLOCKED,\
|
||||
.hw_enabled = false,\
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
i2c_hw_cmd_t hw_cmd;
|
||||
uint8_t* data; /*!< data address */
|
||||
@ -115,7 +120,6 @@ typedef struct {
|
||||
} i2c_cmd_evt_t;
|
||||
|
||||
typedef struct {
|
||||
i2c_hal_context_t i2c_hal; /*!< I2C hal context */
|
||||
int i2c_num; /*!< I2C port number */
|
||||
int mode; /*!< I2C mode, master or slave */
|
||||
intr_handle_t intr_handle; /*!< I2C interrupt handle*/
|
||||
@ -142,10 +146,23 @@ typedef struct {
|
||||
RingbufHandle_t rx_ring_buf; /*!< rx ringbuffer handler of slave mode */
|
||||
size_t tx_buf_length; /*!< tx buffer length */
|
||||
RingbufHandle_t tx_ring_buf; /*!< tx ringbuffer handler of slave mode */
|
||||
uint8_t scl_io_num;
|
||||
uint8_t sda_io_num;
|
||||
} i2c_obj_t;
|
||||
|
||||
typedef struct {
|
||||
i2c_hal_context_t hal; /*!< I2C hal context */
|
||||
portMUX_TYPE spinlock;
|
||||
bool hw_enabled;
|
||||
#if !I2C_SUPPORT_HW_CLR_BUS
|
||||
int scl_io_num;
|
||||
int sda_io_num;
|
||||
#endif
|
||||
} i2c_context_t;
|
||||
|
||||
static i2c_context_t i2c_context[I2C_NUM_MAX] = {
|
||||
I2C_CONTEX_INIT_DEF(I2C_NUM_0),
|
||||
I2C_CONTEX_INIT_DEF(I2C_NUM_1),
|
||||
};
|
||||
|
||||
static i2c_obj_t *p_i2c_obj[I2C_NUM_MAX] = {0};
|
||||
static void i2c_isr_handler_default(void* arg);
|
||||
static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num);
|
||||
@ -153,12 +170,22 @@ static esp_err_t IRAM_ATTR i2c_hw_fsm_reset(i2c_port_t i2c_num);
|
||||
|
||||
static void i2c_hw_disable(i2c_port_t i2c_num)
|
||||
{
|
||||
periph_module_disable(i2c_periph_signal[i2c_num].module);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
if (i2c_context[i2c_num].hw_enabled != false){
|
||||
periph_module_disable(i2c_periph_signal[i2c_num].module);
|
||||
i2c_context[i2c_num].hw_enabled = false;
|
||||
}
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
}
|
||||
|
||||
static void i2c_hw_enable(i2c_port_t i2c_num)
|
||||
{
|
||||
periph_module_enable(i2c_periph_signal[i2c_num].module);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
if (i2c_context[i2c_num].hw_enabled != true){
|
||||
periph_module_enable(i2c_periph_signal[i2c_num].module);
|
||||
i2c_context[i2c_num].hw_enabled = true;
|
||||
}
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -176,10 +203,6 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
|
||||
ESP_ERR_INVALID_ARG);
|
||||
if (p_i2c_obj[i2c_num] == NULL) {
|
||||
|
||||
// Reset the I2C hardware in case there is a soft reboot.
|
||||
i2c_hw_disable(i2c_num);
|
||||
i2c_hw_enable(i2c_num);
|
||||
|
||||
#if !CONFIG_SPIRAM_USE_MALLOC
|
||||
p_i2c_obj[i2c_num] = (i2c_obj_t*) calloc(1, sizeof(i2c_obj_t));
|
||||
#else
|
||||
@ -234,7 +257,6 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
|
||||
ESP_LOGE(I2C_TAG, I2C_SEM_ERR_STR);
|
||||
goto err;
|
||||
}
|
||||
i2c_hal_slave_init(&(p_i2c->i2c_hal), i2c_num);
|
||||
} else {
|
||||
//semaphore to sync sending process, because we only have 32 bytes for hardware fifo.
|
||||
p_i2c->cmd_mux = xSemaphoreCreateMutex();
|
||||
@ -272,14 +294,14 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
|
||||
p_i2c->rx_buf_length = 0;
|
||||
p_i2c->tx_ring_buf = NULL;
|
||||
p_i2c->tx_buf_length = 0;
|
||||
i2c_hal_master_init(&(p_i2c->i2c_hal), i2c_num);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(I2C_TAG, I2C_DRIVER_ERR_STR);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
i2c_hw_enable(i2c_num);
|
||||
//Disable I2C interrupt.
|
||||
i2c_hal_disable_intr_mask(&(p_i2c_obj[i2c_num]->i2c_hal), I2C_INTR_MASK);
|
||||
i2c_hal_disable_intr_mask(&(i2c_context[i2c_num].hal), I2C_INTR_MASK);
|
||||
//hook isr handler
|
||||
i2c_isr_register(i2c_num, i2c_isr_handler_default, p_i2c_obj[i2c_num], intr_alloc_flags, &p_i2c_obj[i2c_num]->intr_handle);
|
||||
return ESP_OK;
|
||||
@ -334,7 +356,7 @@ esp_err_t i2c_driver_delete(i2c_port_t i2c_num)
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
|
||||
i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];
|
||||
i2c_hal_disable_intr_mask(&(p_i2c->i2c_hal), I2C_INTR_MASK);
|
||||
i2c_hal_disable_intr_mask(&(i2c_context[i2c_num].hal), I2C_INTR_MASK);
|
||||
esp_intr_free(p_i2c->intr_handle);
|
||||
p_i2c->intr_handle = NULL;
|
||||
|
||||
@ -386,20 +408,18 @@ esp_err_t i2c_driver_delete(i2c_port_t i2c_num)
|
||||
esp_err_t i2c_reset_tx_fifo(i2c_port_t i2c_num)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_txfifo_rst(&(p_i2c_obj[i2c_num]->i2c_hal));
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
i2c_hal_txfifo_rst(&(i2c_context[i2c_num].hal));
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_reset_rx_fifo(i2c_port_t i2c_num)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_rxfifo_rst(&(p_i2c_obj[i2c_num]->i2c_hal));
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
i2c_hal_rxfifo_rst(&(i2c_context[i2c_num].hal));
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -411,9 +431,9 @@ static void IRAM_ATTR i2c_isr_handler_default(void *arg)
|
||||
portBASE_TYPE HPTaskAwoken = pdFALSE;
|
||||
if (p_i2c->mode == I2C_MODE_MASTER) {
|
||||
if (p_i2c->status == I2C_STATUS_WRITE) {
|
||||
i2c_hal_master_handle_tx_event(&(p_i2c->i2c_hal), &evt_type);
|
||||
i2c_hal_master_handle_tx_event(&(i2c_context[i2c_num].hal), &evt_type);
|
||||
} else if (p_i2c->status == I2C_STATUS_READ) {
|
||||
i2c_hal_master_handle_rx_event(&(p_i2c->i2c_hal), &evt_type);
|
||||
i2c_hal_master_handle_rx_event(&(i2c_context[i2c_num].hal), &evt_type);
|
||||
}
|
||||
if (evt_type == I2C_INTR_EVENT_NACK) {
|
||||
p_i2c_obj[i2c_num]->status = I2C_STATUS_ACK_ERROR;
|
||||
@ -436,25 +456,25 @@ static void IRAM_ATTR i2c_isr_handler_default(void *arg)
|
||||
};
|
||||
xQueueSendFromISR(p_i2c->cmd_evt_queue, &evt, &HPTaskAwoken);
|
||||
} else {
|
||||
i2c_hal_slave_handle_event(&(p_i2c->i2c_hal), &evt_type);
|
||||
i2c_hal_slave_handle_event(&(i2c_context[i2c_num].hal), &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(&(p_i2c->i2c_hal), &rx_fifo_cnt);
|
||||
i2c_hal_read_rxfifo(&(p_i2c->i2c_hal), p_i2c->data_buf, 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);
|
||||
xRingbufferSendFromISR(p_i2c->rx_ring_buf, p_i2c->data_buf, rx_fifo_cnt, &HPTaskAwoken);
|
||||
i2c_hal_slave_clr_rx_it(&(p_i2c->i2c_hal));
|
||||
i2c_hal_slave_clr_rx_it(&(i2c_context[i2c_num].hal));
|
||||
} else if (evt_type == I2C_INTR_EVENT_TXFIFO_EMPTY) {
|
||||
uint32_t tx_fifo_rem;
|
||||
i2c_hal_get_txfifo_cnt(&(p_i2c->i2c_hal), &tx_fifo_rem);
|
||||
i2c_hal_get_txfifo_cnt(&(i2c_context[i2c_num].hal), &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(&(p_i2c->i2c_hal), data, size);
|
||||
i2c_hal_write_txfifo(&(i2c_context[i2c_num].hal), data, size);
|
||||
vRingbufferReturnItemFromISR(p_i2c->tx_ring_buf, data, &HPTaskAwoken);
|
||||
} else {
|
||||
i2c_hal_disable_slave_tx_it(&(p_i2c->i2c_hal));
|
||||
i2c_hal_disable_slave_tx_it(&(i2c_context[i2c_num].hal));
|
||||
}
|
||||
i2c_hal_slave_clr_tx_it(&(p_i2c->i2c_hal));
|
||||
i2c_hal_slave_clr_tx_it(&(i2c_context[i2c_num].hal));
|
||||
}
|
||||
}
|
||||
//We only need to check here if there is a high-priority task needs to be switched.
|
||||
@ -466,20 +486,18 @@ static void IRAM_ATTR i2c_isr_handler_default(void *arg)
|
||||
esp_err_t i2c_set_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t tx_trans_mode, i2c_trans_mode_t rx_trans_mode)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
I2C_CHECK(tx_trans_mode < I2C_DATA_MODE_MAX, I2C_TRANS_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(rx_trans_mode < I2C_DATA_MODE_MAX, I2C_TRANS_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_set_data_mode(&(p_i2c_obj[i2c_num]->i2c_hal), tx_trans_mode, rx_trans_mode);
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
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_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
i2c_hal_get_data_mode(&(p_i2c_obj[i2c_num]->i2c_hal), tx_trans_mode, rx_trans_mode);
|
||||
i2c_hal_get_data_mode(&(i2c_context[i2c_num].hal), tx_trans_mode, rx_trans_mode);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -493,8 +511,8 @@ static esp_err_t i2c_master_clear_bus(i2c_port_t i2c_num)
|
||||
#if !I2C_SUPPORT_HW_CLR_BUS
|
||||
const int scl_half_period = I2C_CLR_BUS_HALF_PERIOD_US; // use standard 100kHz data rate
|
||||
int i = 0;
|
||||
int scl_io = p_i2c_obj[i2c_num]->scl_io_num;
|
||||
int sda_io = p_i2c_obj[i2c_num]->sda_io_num;
|
||||
int scl_io = i2c_context[i2c_num].scl_io_num;
|
||||
int sda_io = i2c_context[i2c_num].sda_io_num;
|
||||
gpio_set_direction(scl_io, GPIO_MODE_OUTPUT_OD);
|
||||
gpio_set_direction(sda_io, GPIO_MODE_INPUT_OUTPUT_OD);
|
||||
// If a SLAVE device was in a read operation when the bus was interrupted, the SLAVE device is controlling SDA.
|
||||
@ -517,7 +535,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(&(p_i2c_obj[i2c_num]->i2c_hal));
|
||||
i2c_hal_master_clr_bus(&(i2c_context[i2c_num].hal));
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -536,29 +554,29 @@ static esp_err_t i2c_hw_fsm_reset(i2c_port_t i2c_num)
|
||||
int timeout;
|
||||
uint8_t filter_cfg;
|
||||
|
||||
i2c_hal_get_scl_timing(&(p_i2c_obj[i2c_num]->i2c_hal), &scl_high_period, &scl_low_period);
|
||||
i2c_hal_get_start_timing(&(p_i2c_obj[i2c_num]->i2c_hal), &scl_rstart_setup, &scl_start_hold);
|
||||
i2c_hal_get_stop_timing(&(p_i2c_obj[i2c_num]->i2c_hal), &scl_stop_setup, &scl_stop_hold);
|
||||
i2c_hal_get_sda_timing(&(p_i2c_obj[i2c_num]->i2c_hal), &sda_sample, &sda_hold);
|
||||
i2c_hal_get_tout(&(p_i2c_obj[i2c_num]->i2c_hal), &timeout);
|
||||
i2c_hal_get_filter(&(p_i2c_obj[i2c_num]->i2c_hal), &filter_cfg);
|
||||
i2c_hal_get_scl_timing(&(i2c_context[i2c_num].hal), &scl_high_period, &scl_low_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);
|
||||
|
||||
//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(&(p_i2c_obj[i2c_num]->i2c_hal), i2c_num);
|
||||
i2c_hal_disable_intr_mask(&(p_i2c_obj[i2c_num]->i2c_hal), I2C_INTR_MASK);
|
||||
i2c_hal_clr_intsts_mask(&(p_i2c_obj[i2c_num]->i2c_hal), I2C_INTR_MASK);
|
||||
i2c_hal_set_scl_timing(&(p_i2c_obj[i2c_num]->i2c_hal), scl_high_period, scl_low_period);
|
||||
i2c_hal_set_start_timing(&(p_i2c_obj[i2c_num]->i2c_hal), scl_rstart_setup, scl_start_hold);
|
||||
i2c_hal_set_stop_timing(&(p_i2c_obj[i2c_num]->i2c_hal), scl_stop_setup, scl_stop_hold);
|
||||
i2c_hal_set_sda_timing(&(p_i2c_obj[i2c_num]->i2c_hal), sda_sample, sda_hold);
|
||||
i2c_hal_set_tout(&(p_i2c_obj[i2c_num]->i2c_hal), timeout);
|
||||
i2c_hal_set_filter(&(p_i2c_obj[i2c_num]->i2c_hal), filter_cfg);
|
||||
i2c_hal_master_init(&(i2c_context[i2c_num].hal), i2c_num);
|
||||
i2c_hal_disable_intr_mask(&(i2c_context[i2c_num].hal), I2C_INTR_MASK);
|
||||
i2c_hal_clr_intsts_mask(&(i2c_context[i2c_num].hal), I2C_INTR_MASK);
|
||||
i2c_hal_set_scl_timing(&(i2c_context[i2c_num].hal), scl_high_period, scl_low_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);
|
||||
#else
|
||||
i2c_hal_master_fsm_rst(&(p_i2c_obj[i2c_num]->i2c_hal));
|
||||
i2c_hal_master_fsm_rst(&(i2c_context[i2c_num].hal));
|
||||
i2c_master_clear_bus(i2c_num);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
@ -567,7 +585,6 @@ static esp_err_t i2c_hw_fsm_reset(i2c_port_t i2c_num)
|
||||
esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t* i2c_conf)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
I2C_CHECK(i2c_conf != NULL, I2C_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(i2c_conf->mode < I2C_MODE_MAX, I2C_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
@ -576,48 +593,48 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t* i2c_conf)
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
p_i2c_obj[i2c_num]->mode = i2c_conf->mode;
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_disable_intr_mask(&(p_i2c_obj[i2c_num]->i2c_hal), I2C_INTR_MASK);
|
||||
i2c_hal_clr_intsts_mask(&(p_i2c_obj[i2c_num]->i2c_hal), I2C_INTR_MASK);
|
||||
i2c_hw_enable(i2c_num);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
i2c_hal_disable_intr_mask(&(i2c_context[i2c_num].hal), I2C_INTR_MASK);
|
||||
i2c_hal_clr_intsts_mask(&(i2c_context[i2c_num].hal), I2C_INTR_MASK);
|
||||
if (i2c_conf->mode == I2C_MODE_SLAVE) { //slave mode
|
||||
i2c_hal_set_slave_addr(&(p_i2c_obj[i2c_num]->i2c_hal), i2c_conf->slave.slave_addr, i2c_conf->slave.addr_10bit_en);
|
||||
i2c_hal_set_rxfifo_full_thr(&(p_i2c_obj[i2c_num]->i2c_hal), I2C_FIFO_FULL_THRESH_VAL);
|
||||
i2c_hal_set_txfifo_empty_thr(&(p_i2c_obj[i2c_num]->i2c_hal), I2C_FIFO_EMPTY_THRESH_VAL);
|
||||
i2c_hal_slave_init(&(i2c_context[i2c_num].hal), i2c_num);
|
||||
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);
|
||||
//set timing for data
|
||||
i2c_hal_set_sda_timing(&(p_i2c_obj[i2c_num]->i2c_hal), I2C_SLAVE_SDA_SAMPLE_DEFAULT, I2C_SLAVE_SDA_HOLD_DEFAULT);
|
||||
i2c_hal_set_tout(&(p_i2c_obj[i2c_num]->i2c_hal), I2C_SLAVE_TIMEOUT_DEFAULT);
|
||||
i2c_hal_enable_slave_tx_it(&(p_i2c_obj[i2c_num]->i2c_hal));
|
||||
i2c_hal_enable_slave_rx_it(&(p_i2c_obj[i2c_num]->i2c_hal));
|
||||
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_tx_it(&(i2c_context[i2c_num].hal));
|
||||
i2c_hal_enable_slave_rx_it(&(i2c_context[i2c_num].hal));
|
||||
} else {
|
||||
i2c_hal_master_init(&(i2c_context[i2c_num].hal), i2c_num);
|
||||
//Default, we enable hardware filter
|
||||
i2c_hal_set_filter(&(p_i2c_obj[i2c_num]->i2c_hal), I2C_FILTER_CYC_NUM_DEF);
|
||||
i2c_hal_set_bus_timing(&(p_i2c_obj[i2c_num]->i2c_hal), i2c_conf->master.clk_speed, I2C_SCLK_APB);
|
||||
i2c_hal_set_filter(&(i2c_context[i2c_num].hal), I2C_FILTER_CYC_NUM_DEF);
|
||||
i2c_hal_set_bus_timing(&(i2c_context[i2c_num].hal), i2c_conf->master.clk_speed, I2C_SCLK_APB);
|
||||
}
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_set_period(i2c_port_t i2c_num, int high_period, int low_period)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
I2C_CHECK((high_period <= I2C_SCL_HIGH_PERIOD_V) && (high_period > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((low_period <= I2C_SCL_LOW_PERIOD_V) && (low_period > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_set_scl_timing(&(p_i2c_obj[i2c_num]->i2c_hal), high_period, low_period);
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
i2c_hal_set_scl_timing(&(i2c_context[i2c_num].hal), high_period, low_period);
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_get_period(i2c_port_t i2c_num, int* high_period, int* low_period)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX && high_period != NULL && low_period != NULL, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_get_scl_timing(&(p_i2c_obj[i2c_num]->i2c_hal), high_period, low_period);
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
i2c_hal_get_scl_timing(&(i2c_context[i2c_num].hal), high_period, low_period);
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -625,108 +642,99 @@ esp_err_t i2c_filter_enable(i2c_port_t i2c_num, uint8_t cyc_num)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_set_filter(&(p_i2c_obj[i2c_num]->i2c_hal), cyc_num);
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
i2c_hal_set_filter(&(i2c_context[i2c_num].hal), cyc_num);
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_filter_disable(i2c_port_t i2c_num)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_set_filter(&(p_i2c_obj[i2c_num]->i2c_hal), 0);
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
i2c_hal_set_filter(&(i2c_context[i2c_num].hal), 0);
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_set_start_timing(i2c_port_t i2c_num, int setup_time, int hold_time)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
I2C_CHECK((hold_time <= I2C_SCL_START_HOLD_TIME_V) && (hold_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((setup_time <= I2C_SCL_RSTART_SETUP_TIME_V) && (setup_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_set_start_timing(&(p_i2c_obj[i2c_num]->i2c_hal), setup_time, hold_time);
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
i2c_hal_set_start_timing(&(i2c_context[i2c_num].hal), setup_time, hold_time);
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_get_start_timing(i2c_port_t i2c_num, int* setup_time, int* hold_time)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX && setup_time != NULL && hold_time != NULL, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_get_start_timing(&(p_i2c_obj[i2c_num]->i2c_hal), setup_time, hold_time);
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
i2c_hal_get_start_timing(&(i2c_context[i2c_num].hal), setup_time, hold_time);
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_set_stop_timing(i2c_port_t i2c_num, int setup_time, int hold_time)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
I2C_CHECK((setup_time <= I2C_SCL_STOP_SETUP_TIME_V) && (setup_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((hold_time <= I2C_SCL_STOP_HOLD_TIME_V) && (hold_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_set_stop_timing(&(p_i2c_obj[i2c_num]->i2c_hal), setup_time, hold_time);
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
i2c_hal_set_stop_timing(&(i2c_context[i2c_num].hal), setup_time, hold_time);
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_get_stop_timing(i2c_port_t i2c_num, int* setup_time, int* hold_time)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX && setup_time != NULL && hold_time != NULL, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_get_stop_timing(&(p_i2c_obj[i2c_num]->i2c_hal), setup_time, hold_time);
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
i2c_hal_get_stop_timing(&(i2c_context[i2c_num].hal), setup_time, hold_time);
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_set_data_timing(i2c_port_t i2c_num, int sample_time, int hold_time)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
I2C_CHECK((sample_time <= I2C_SDA_SAMPLE_TIME_V) && (sample_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((hold_time <= I2C_SDA_HOLD_TIME_V) && (hold_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_set_sda_timing(&(p_i2c_obj[i2c_num]->i2c_hal), sample_time, hold_time);
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
i2c_hal_set_sda_timing(&(i2c_context[i2c_num].hal), sample_time, hold_time);
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_get_data_timing(i2c_port_t i2c_num, int* sample_time, int* hold_time)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX && sample_time != NULL && hold_time != NULL, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_get_sda_timing(&(p_i2c_obj[i2c_num]->i2c_hal), sample_time, hold_time);
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
i2c_hal_get_sda_timing(&(i2c_context[i2c_num].hal), sample_time, hold_time);
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_set_timeout(i2c_port_t i2c_num, int timeout)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
I2C_CHECK((timeout <= I2C_TIME_OUT_REG_V) && (timeout > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_set_tout(&(p_i2c_obj[i2c_num]->i2c_hal), timeout);
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
i2c_hal_set_tout(&(i2c_context[i2c_num].hal), timeout);
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_get_timeout(i2c_port_t i2c_num, int* timeout)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX && timeout != NULL, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_ERR_STR, ESP_FAIL);
|
||||
i2c_hal_get_tout(&(p_i2c_obj[i2c_num]->i2c_hal), timeout);
|
||||
i2c_hal_get_tout(&(i2c_context[i2c_num].hal), timeout);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -794,8 +802,10 @@ esp_err_t i2c_set_pin(i2c_port_t i2c_num, int sda_io_num, int scl_io_num, bool s
|
||||
}
|
||||
gpio_matrix_in(scl_io_num, scl_in_sig, 0);
|
||||
}
|
||||
p_i2c_obj[i2c_num]->scl_io_num = scl_io_num;
|
||||
p_i2c_obj[i2c_num]->sda_io_num = sda_io_num;
|
||||
#if !I2C_SUPPORT_HW_CLR_BUS
|
||||
i2c_context[i2c_num].scl_io_num = scl_io_num;
|
||||
i2c_context[i2c_num].sda_io_num = sda_io_num;
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -998,7 +1008,7 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
|
||||
i2c_cmd_evt_t evt;
|
||||
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(&(p_i2c->i2c_hal), cmd->data, p_i2c->rx_cnt);
|
||||
i2c_hal_read_rxfifo(&(i2c_context[i2c_num].hal), cmd->data, p_i2c->rx_cnt);
|
||||
cmd->data += p_i2c->rx_cnt;
|
||||
if (cmd->hw_cmd.byte_num > 0) {
|
||||
p_i2c->cmd_idx = 0;
|
||||
@ -1043,10 +1053,10 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
|
||||
cmd->hw_cmd.byte_num--;
|
||||
}
|
||||
hw_cmd.byte_num = wr_filled;
|
||||
i2c_hal_write_txfifo(&(p_i2c->i2c_hal), write_pr, wr_filled);
|
||||
i2c_hal_write_cmd_reg(&(p_i2c->i2c_hal), hw_cmd, p_i2c->cmd_idx);
|
||||
i2c_hal_write_cmd_reg(&(p_i2c->i2c_hal), hw_end_cmd, p_i2c->cmd_idx + 1);
|
||||
i2c_hal_enable_master_tx_it(&(p_i2c->i2c_hal));
|
||||
i2c_hal_write_txfifo(&(i2c_context[i2c_num].hal), write_pr, wr_filled);
|
||||
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));
|
||||
p_i2c->cmd_idx = 0;
|
||||
if (cmd->hw_cmd.byte_num == 0) {
|
||||
p_i2c->cmd_link.head = p_i2c->cmd_link.head->next;
|
||||
@ -1058,13 +1068,13 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
|
||||
p_i2c->rx_cnt = cmd->hw_cmd.byte_num > SOC_I2C_FIFO_LEN ? SOC_I2C_FIFO_LEN : cmd->hw_cmd.byte_num;
|
||||
cmd->hw_cmd.byte_num -= p_i2c->rx_cnt;
|
||||
hw_cmd.byte_num = p_i2c->rx_cnt;
|
||||
i2c_hal_write_cmd_reg(&(p_i2c->i2c_hal), hw_cmd, p_i2c->cmd_idx);
|
||||
i2c_hal_write_cmd_reg(&(p_i2c->i2c_hal), hw_end_cmd, p_i2c->cmd_idx + 1);
|
||||
i2c_hal_enable_master_rx_it(&(p_i2c->i2c_hal));
|
||||
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));
|
||||
p_i2c->status = I2C_STATUS_READ;
|
||||
break;
|
||||
} else {
|
||||
i2c_hal_write_cmd_reg(&(p_i2c->i2c_hal), hw_cmd, p_i2c->cmd_idx);
|
||||
i2c_hal_write_cmd_reg(&(i2c_context[i2c_num].hal), hw_cmd, p_i2c->cmd_idx);
|
||||
}
|
||||
p_i2c->cmd_idx++;
|
||||
p_i2c->cmd_link.head = p_i2c->cmd_link.head->next;
|
||||
@ -1073,7 +1083,7 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
|
||||
break;
|
||||
}
|
||||
}
|
||||
i2c_hal_trans_start(&(p_i2c->i2c_hal));
|
||||
i2c_hal_trans_start(&(i2c_context[i2c_num].hal));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1125,7 +1135,7 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle,
|
||||
}
|
||||
xQueueReset(p_i2c->cmd_evt_queue);
|
||||
if (p_i2c->status == I2C_STATUS_TIMEOUT
|
||||
|| i2c_hal_is_bus_busy(&(p_i2c->i2c_hal))) {
|
||||
|| i2c_hal_is_bus_busy(&(i2c_context[i2c_num].hal))) {
|
||||
i2c_hw_fsm_reset(i2c_num);
|
||||
clear_bus_cnt = 0;
|
||||
}
|
||||
@ -1142,8 +1152,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(&(p_i2c_obj[i2c_num]->i2c_hal), I2C_INTR_MASK);
|
||||
i2c_hal_clr_intsts_mask(&(p_i2c_obj[i2c_num]->i2c_hal), I2C_INTR_MASK);
|
||||
i2c_hal_disable_intr_mask(&(i2c_context[i2c_num].hal), I2C_INTR_MASK);
|
||||
i2c_hal_clr_intsts_mask(&(i2c_context[i2c_num].hal), I2C_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);
|
||||
|
||||
@ -1222,9 +1232,9 @@ int i2c_slave_write_buffer(i2c_port_t i2c_num, uint8_t* data, int size, TickType
|
||||
if (res == pdFALSE) {
|
||||
cnt = 0;
|
||||
} else {
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_enable_slave_tx_it(&(p_i2c->i2c_hal));
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
i2c_hal_enable_slave_tx_it(&(i2c_context[i2c_num].hal));
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
cnt = size;
|
||||
}
|
||||
xSemaphoreGive(p_i2c->slv_tx_mux);
|
||||
@ -1246,9 +1256,9 @@ int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t* data, size_t max_size, Ti
|
||||
}
|
||||
portTickType ticks_rem = ticks_to_wait;
|
||||
portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait;
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
i2c_hal_enable_slave_rx_it(&(p_i2c->i2c_hal));
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
i2c_hal_enable_slave_rx_it(&(i2c_context[i2c_num].hal));
|
||||
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);
|
||||
if (pdata && size > 0) {
|
||||
@ -1263,4 +1273,4 @@ int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t* data, size_t max_size, Ti
|
||||
}
|
||||
xSemaphoreGive(p_i2c->slv_rx_mux);
|
||||
return max_size - size_rem;
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "soc/i2c_periph.h"
|
||||
#include "esp_system.h"
|
||||
#include "driver/pcnt.h"
|
||||
#include "soc/uart_struct.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
|
||||
|
||||
#define DATA_LENGTH 512 /*!<Data buffer length for test buffer*/
|
||||
@ -66,8 +68,8 @@ static i2c_config_t i2c_master_init(void)
|
||||
{
|
||||
i2c_config_t conf_master = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = I2C_MASTER_FREQ_HZ,
|
||||
.sda_io_num = I2C_MASTER_SDA_IO,
|
||||
.scl_io_num = I2C_MASTER_SCL_IO,
|
||||
@ -81,8 +83,8 @@ static i2c_config_t i2c_slave_init(void)
|
||||
.mode = I2C_MODE_SLAVE,
|
||||
.sda_io_num = I2C_SLAVE_SDA_IO,
|
||||
.scl_io_num = I2C_SLAVE_SCL_IO,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.slave.addr_10bit_en = 0,
|
||||
.slave.slave_addr = ESP_SLAVE_ADDR,
|
||||
};
|
||||
@ -304,3 +306,103 @@ TEST_CASE("test i2c_slave_write_buffer is not blocked when ticks_to_wait=0", "[i
|
||||
}
|
||||
TEST_ESP_OK(i2c_driver_delete(I2C_SLAVE_NUM));
|
||||
}
|
||||
|
||||
TEST_CASE("I2C general API test", "[i2c]")
|
||||
{
|
||||
const int i2c_num = 1;
|
||||
i2c_config_t conf_master = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = I2C_MASTER_FREQ_HZ,
|
||||
.sda_io_num = I2C_MASTER_SDA_IO,
|
||||
.scl_io_num = I2C_MASTER_SCL_IO,
|
||||
};
|
||||
TEST_ESP_OK(i2c_param_config( i2c_num, &conf_master));
|
||||
int time_get0, time_get1;
|
||||
for(int i = 10; i < 0x3ff; i++) {
|
||||
//set period test
|
||||
TEST_ESP_OK(i2c_set_period(i2c_num, i, i));
|
||||
TEST_ESP_OK(i2c_get_period(i2c_num, &time_get0, &time_get1));
|
||||
TEST_ASSERT((time_get0 == i) && (time_get1 == i));
|
||||
//set start timing test
|
||||
TEST_ESP_OK(i2c_set_start_timing(i2c_num, i, i));
|
||||
TEST_ESP_OK(i2c_get_start_timing(i2c_num, &time_get0, &time_get1));
|
||||
TEST_ASSERT((time_get0 == i) && (time_get1 == i));
|
||||
//set stop timing test
|
||||
TEST_ESP_OK(i2c_set_stop_timing(i2c_num, i, i));
|
||||
TEST_ESP_OK(i2c_get_stop_timing(i2c_num, &time_get0, &time_get1));
|
||||
TEST_ASSERT((time_get0 == i) && (time_get1 == i));
|
||||
//set data timing test
|
||||
TEST_ESP_OK(i2c_set_data_timing(i2c_num, i, i));
|
||||
TEST_ESP_OK(i2c_get_data_timing(i2c_num, &time_get0, &time_get1));
|
||||
TEST_ASSERT((time_get0 == i) && (time_get1 == i));
|
||||
//set time out test
|
||||
TEST_ESP_OK(i2c_set_timeout(i2c_num, i));
|
||||
TEST_ESP_OK(i2c_get_timeout(i2c_num, &time_get0));
|
||||
TEST_ASSERT(time_get0 == i);
|
||||
}
|
||||
}
|
||||
|
||||
//Init uart baud rate detection
|
||||
static void uart_aut_baud_det_init(int rxd_io_num)
|
||||
{
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[rxd_io_num], PIN_FUNC_GPIO);
|
||||
gpio_set_direction(rxd_io_num, GPIO_MODE_INPUT_OUTPUT);
|
||||
gpio_matrix_out(rxd_io_num, I2CEXT1_SCL_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(rxd_io_num, U1RXD_IN_IDX, 0);
|
||||
periph_module_enable(PERIPH_UART1_MODULE);
|
||||
UART1.int_ena.val = 0;
|
||||
UART1.int_clr.val = ~0;
|
||||
UART1.auto_baud.en = 1;
|
||||
}
|
||||
|
||||
//Calculate I2C scl freq
|
||||
static void i2c_scl_freq_cal(void)
|
||||
{
|
||||
const int i2c_source_clk_freq = 80000000;
|
||||
const float i2c_cource_clk_period = 0.0125;
|
||||
int edg_cnt = UART1.rxd_cnt.edge_cnt;
|
||||
int pospulse_cnt = UART1.pospulse.min_cnt;
|
||||
int negpulse_cnt = UART1.negpulse.min_cnt;
|
||||
int high_period_cnt = UART1.highpulse.min_cnt;
|
||||
int low_period_cnt = UART1.lowpulse.min_cnt;
|
||||
if(edg_cnt != 542) {
|
||||
printf("\nedg_cnt != 542, test fail\n");
|
||||
return;
|
||||
}
|
||||
printf("\nDetected SCL frequency: %d Hz\n", i2c_source_clk_freq / ((pospulse_cnt + negpulse_cnt) / 2) );
|
||||
|
||||
printf("\nSCL high period %.3f (us), SCL low_period %.3f (us)\n\n", (float)(i2c_cource_clk_period * high_period_cnt), (float)(i2c_cource_clk_period * low_period_cnt));
|
||||
UART1.auto_baud.en = 0;
|
||||
periph_module_disable(PERIPH_UART1_MODULE);
|
||||
}
|
||||
|
||||
TEST_CASE("I2C SCL freq test (local test)", "[i2c][ignore]")
|
||||
{
|
||||
//Use the UART baud rate detection function to detect the I2C SCL frequency.
|
||||
const int i2c_num = 1;
|
||||
const int uart1_rxd_io = 5;
|
||||
i2c_config_t conf_master = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = 400000,
|
||||
.sda_io_num = I2C_MASTER_SDA_IO,
|
||||
.scl_io_num = I2C_MASTER_SCL_IO,
|
||||
};
|
||||
uint8_t *data = (uint8_t *)malloc(30);
|
||||
TEST_ESP_OK(i2c_param_config( i2c_num, &conf_master));
|
||||
TEST_ESP_OK(i2c_driver_install(i2c_num, I2C_MODE_MASTER, 0, 0, 0));
|
||||
memset(data, 0, 0);
|
||||
uart_aut_baud_det_init(uart1_rxd_io);
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write(cmd, data, 30, ACK_CHECK_DIS);
|
||||
i2c_master_stop(cmd);
|
||||
i2c_master_cmd_begin(i2c_num, cmd, 5000 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
i2c_scl_freq_cal();
|
||||
free(data);
|
||||
TEST_ESP_OK(i2c_driver_delete(i2c_num));
|
||||
}
|
@ -48,6 +48,19 @@ typedef enum {
|
||||
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;
|
||||
|
||||
// Get the I2C hardware instance
|
||||
#define I2C_LL_GET_HW(i2c_num) (((i2c_num) == 0) ? &I2C0 : &I2C1)
|
||||
// Get the I2C hardware FIFO address
|
||||
@ -63,6 +76,53 @@ typedef enum {
|
||||
//I2C base clock freq 80M
|
||||
#define I2C_BASE_CLK_FREQ (80000000)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Calculate I2C bus frequency
|
||||
*
|
||||
* @param source_clk I2C source clock
|
||||
* @param bus_freq I2C bus frequency
|
||||
* @param clk_cal Pointer to accept the clock configuration
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2c_clk_cal_t *clk_cal)
|
||||
{
|
||||
uint32_t half_cycle = source_clk / bus_freq / 2;
|
||||
clk_cal->scl_low = half_cycle;
|
||||
clk_cal->scl_high = half_cycle;
|
||||
clk_cal->sda_hold = half_cycle / 2;
|
||||
clk_cal->sda_sample = clk_cal->scl_high / 2;
|
||||
clk_cal->setup = half_cycle;
|
||||
clk_cal->hold = half_cycle;
|
||||
clk_cal->tout = half_cycle * 20; //default we set the timeout value to 10 bus cycles.
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the I2C bus timing related register.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param bus_cfg Pointer to the data structure holding the register configuration.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg)
|
||||
{
|
||||
//scl period
|
||||
hw->scl_low_period.period = bus_cfg->scl_low;
|
||||
hw->scl_high_period.period = bus_cfg->scl_high;
|
||||
//sda sample
|
||||
hw->sda_hold.time = bus_cfg->sda_hold;
|
||||
hw->sda_sample.time = bus_cfg->sda_sample;
|
||||
//setup
|
||||
hw->scl_rstart_setup.time = bus_cfg->setup;
|
||||
hw->scl_stop_setup.time = bus_cfg->setup;
|
||||
//hold
|
||||
hw->scl_start_hold.time = bus_cfg->hold;
|
||||
hw->scl_stop_hold.time = bus_cfg->hold;
|
||||
hw->timeout.tout = bus_cfg->tout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset I2C txFIFO
|
||||
*
|
||||
@ -178,7 +238,7 @@ static inline void i2c_ll_set_fifo_mode(i2c_dev_t *hw, bool fifo_mode_en)
|
||||
*/
|
||||
static inline void i2c_ll_set_tout(i2c_dev_t *hw, int tout)
|
||||
{
|
||||
hw->timeout.tout = tout;
|
||||
hw->timeout.tout = tout;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,6 +48,20 @@ typedef enum {
|
||||
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;
|
||||
|
||||
// Get the I2C hardware instance
|
||||
#define I2C_LL_GET_HW(i2c_num) (((i2c_num) == 0) ? &I2C0 : &I2C1)
|
||||
// Get the I2C hardware FIFO address
|
||||
@ -62,6 +76,58 @@ typedef enum {
|
||||
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_FULL_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Calculate I2C bus frequency
|
||||
*
|
||||
* @param source_clk I2C source clock
|
||||
* @param bus_freq I2C bus frequency
|
||||
* @param clk_cal Pointer to accept the clock configuration
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2c_clk_cal_t *clk_cal)
|
||||
{
|
||||
uint32_t half_cycle = source_clk / bus_freq / 2;
|
||||
//SCL
|
||||
clk_cal->scl_low = half_cycle;
|
||||
// default, scl_wait_high < scl_high
|
||||
clk_cal->scl_high = half_cycle / 2 + 2;
|
||||
clk_cal->scl_wait_high = half_cycle - clk_cal->scl_high;
|
||||
clk_cal->sda_hold = half_cycle / 2;
|
||||
// scl_wait_high < sda_sample <= scl_high
|
||||
clk_cal->sda_sample = half_cycle / 2 - 1;
|
||||
clk_cal->setup = half_cycle;
|
||||
clk_cal->hold = half_cycle;
|
||||
//default we set the timeout value to 10 bus cycles
|
||||
clk_cal->tout = half_cycle * 20;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the I2C bus timing related register.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param bus_cfg Pointer to the data structure holding the register configuration.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg)
|
||||
{
|
||||
//scl period
|
||||
hw->scl_low_period.period = bus_cfg->scl_low - 1;
|
||||
hw->scl_high_period.period = bus_cfg->scl_high;
|
||||
hw->scl_high_period.scl_wait_high_period = bus_cfg->scl_wait_high;
|
||||
//sda sample
|
||||
hw->sda_hold.time = bus_cfg->sda_hold;
|
||||
hw->sda_sample.time = bus_cfg->sda_sample;
|
||||
//setup
|
||||
hw->scl_rstart_setup.time = bus_cfg->setup;
|
||||
hw->scl_stop_setup.time = bus_cfg->setup;
|
||||
//hold
|
||||
hw->scl_start_hold.time = bus_cfg->hold - 1;
|
||||
hw->scl_stop_hold.time = bus_cfg->hold;
|
||||
hw->timeout.tout = bus_cfg->tout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset I2C txFIFO
|
||||
*
|
||||
@ -92,16 +158,16 @@ static inline void i2c_ll_rxfifo_rst(i2c_dev_t *hw)
|
||||
* @brief Configure I2C SCL timing
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param hight_period The I2C SCL hight period (in APB cycle)
|
||||
* @param low_period The I2C SCL low period (in APB cycle)
|
||||
* @param hight_period The I2C SCL hight period (in APB cycle, hight_period > 2)
|
||||
* @param low_period The I2C SCL low period (in APB cycle, low_period > 1)
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void i2c_ll_set_scl_timing(i2c_dev_t *hw, int hight_period, int low_period)
|
||||
{
|
||||
hw->scl_low_period.period = low_period;
|
||||
hw->scl_high_period.period = hight_period;
|
||||
hw->scl_high_period.scl_wait_high_period = 0;
|
||||
hw->scl_low_period.period = low_period-1;
|
||||
hw->scl_high_period.period = hight_period/2+2;
|
||||
hw->scl_high_period.scl_wait_high_period = hight_period - hw->scl_high_period.period;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -222,7 +288,7 @@ static inline void i2c_ll_write_cmd_reg(i2c_dev_t *hw, i2c_hw_cmd_t cmd, int cmd
|
||||
static inline void i2c_ll_set_start_timing(i2c_dev_t *hw, int start_setup, int start_hold)
|
||||
{
|
||||
hw->scl_rstart_setup.time = start_setup;
|
||||
hw->scl_start_hold.time = start_hold;
|
||||
hw->scl_start_hold.time = start_hold-1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -422,7 +488,7 @@ static inline void i2c_ll_trans_start(i2c_dev_t *hw)
|
||||
static inline void i2c_ll_get_start_timing(i2c_dev_t *hw, int *setup_time, int *hold_time)
|
||||
{
|
||||
*setup_time = hw->scl_rstart_setup.time;
|
||||
*hold_time = hw->scl_start_hold.time;
|
||||
*hold_time = hw->scl_start_hold.time+1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -451,8 +517,8 @@ static inline void i2c_ll_get_stop_timing(i2c_dev_t *hw, int *setup_time, int *h
|
||||
*/
|
||||
static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *low_period)
|
||||
{
|
||||
*high_period = hw->scl_high_period.period;
|
||||
*low_period = hw->scl_low_period.period;
|
||||
*high_period = hw->scl_high_period.period + hw->scl_high_period.scl_wait_high_period;
|
||||
*low_period = hw->scl_low_period.period + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -797,4 +863,4 @@ static inline void i2c_ll_slave_init(i2c_dev_t *hw)
|
||||
ctrl_reg.ref_always_on = 1;
|
||||
hw->ctr.val = ctrl_reg.val;
|
||||
hw->fifo_conf.fifo_addr_cfg_en = 0;
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ typedef struct {
|
||||
#define i2c_hal_slave_clr_rx_it(hal) i2c_ll_slave_clr_rx_it((hal)->dev)
|
||||
|
||||
/**
|
||||
* @brief Get the I2C hardware instance and init the I2C master. Note that this function should be called before other hal layer function is called.
|
||||
* @brief Init the I2C master.
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param i2c_num I2C port number
|
||||
@ -121,7 +121,7 @@ typedef struct {
|
||||
void i2c_hal_master_init(i2c_hal_context_t *hal, i2c_port_t i2c_num);
|
||||
|
||||
/**
|
||||
* @brief Get the I2C hardware instance and init the I2C slave. Note that this function should be called before other hal layer function is called.
|
||||
* @brief Init the I2C slave.
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param i2c_num I2C port number
|
||||
|
@ -177,21 +177,13 @@ void i2c_hal_disable_slave_rx_it(i2c_hal_context_t *hal)
|
||||
void i2c_hal_set_bus_timing(i2c_hal_context_t *hal, uint32_t scl_freq, i2c_sclk_t src_clk)
|
||||
{
|
||||
uint32_t sclk = (src_clk == I2C_SCLK_REF_TICK) ? 1000000 : 80000000;
|
||||
uint32_t cycle = sclk / scl_freq;
|
||||
i2c_ll_set_source_clk(hal->dev, src_clk);
|
||||
// Set SDA timing
|
||||
i2c_ll_set_sda_timing(hal->dev, cycle/4, cycle/4);
|
||||
// Set start timing
|
||||
i2c_ll_set_start_timing(hal->dev, cycle/2, cycle/2);
|
||||
i2c_ll_set_scl_timing(hal->dev, cycle/2, cycle/2);
|
||||
i2c_ll_set_stop_timing(hal->dev, cycle/2, cycle/2);
|
||||
//Set time out value
|
||||
i2c_ll_set_tout(hal->dev, cycle * 9);
|
||||
i2c_clk_cal_t clk_cal = {0};
|
||||
i2c_ll_cal_bus_clk(sclk, scl_freq, &clk_cal);
|
||||
i2c_ll_set_bus_timing(hal->dev, &clk_cal);
|
||||
}
|
||||
|
||||
void i2c_hal_slave_init(i2c_hal_context_t *hal, int i2c_num)
|
||||
{
|
||||
hal->dev = I2C_LL_GET_HW(i2c_num);
|
||||
i2c_ll_slave_init(hal->dev);
|
||||
//Use fifo mode
|
||||
i2c_ll_set_fifo_mode(hal->dev, true);
|
||||
@ -214,7 +206,6 @@ void i2c_hal_master_fsm_rst(i2c_hal_context_t *hal)
|
||||
|
||||
void i2c_hal_master_init(i2c_hal_context_t *hal, int i2c_num)
|
||||
{
|
||||
hal->dev = I2C_LL_GET_HW(i2c_num);
|
||||
hal->version = i2c_ll_get_hw_version(hal->dev);
|
||||
i2c_ll_master_init(hal->dev);
|
||||
//Use fifo mode
|
||||
|
@ -151,8 +151,8 @@ static esp_err_t i2c_master_init(void)
|
||||
conf.scl_io_num = I2C_MASTER_SCL_IO;
|
||||
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
|
||||
conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
|
||||
i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
|
||||
return i2c_param_config(i2c_master_port, &conf);
|
||||
i2c_param_config(i2c_master_port, &conf);
|
||||
return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,8 +169,8 @@ static esp_err_t i2c_slave_init(void)
|
||||
conf_slave.mode = I2C_MODE_SLAVE;
|
||||
conf_slave.slave.addr_10bit_en = 0;
|
||||
conf_slave.slave.slave_addr = ESP_SLAVE_ADDR;
|
||||
i2c_driver_install(i2c_slave_port, conf_slave.mode, I2C_SLAVE_RX_BUF_LEN, I2C_SLAVE_TX_BUF_LEN, 0);
|
||||
return i2c_param_config(i2c_slave_port, &conf_slave);
|
||||
i2c_param_config(i2c_slave_port, &conf_slave);
|
||||
return i2c_driver_install(i2c_slave_port, conf_slave.mode, I2C_SLAVE_RX_BUF_LEN, I2C_SLAVE_TX_BUF_LEN, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user