#include "freertos/xtensa_api.h"\r
#include "freertos/task.h"\r
#include "freertos/ringbuf.h"\r
+#include "freertos/event_groups.h"\r
#include "soc/dport_reg.h"\r
#include "soc/i2c_struct.h"\r
#include "soc/i2c_reg.h"\r
\r
#define I2C_ENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux)\r
#define I2C_EXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux)\r
-#define I2C_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux)\r
-#define I2C_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux)\r
+#define I2C_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux)\r
+#define I2C_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux)\r
\r
#define I2C_DRIVER_ERR_STR "i2c driver install error"\r
#define I2C_DRIVER_MALLOC_ERR_STR "i2c driver malloc error"\r
#define I2C_NUM_ERROR_STR "i2c number error"\r
+#define I2C_TIMEING_VAL_ERR_STR "i2c timing value error"\r
#define I2C_ADDR_ERROR_STR "i2c null address error"\r
#define I2C_DRIVER_NOT_INSTALL_ERR_STR "i2c driver not installed"\r
#define I2C_SLAVE_BUFFER_LEN_ERR_STR "i2c buffer size too short for slave mode"\r
#define I2C_CMD_MALLOC_ERR_STR "i2c command link malloc error"\r
#define I2C_TRANS_MODE_ERR_STR "i2c trans mode error"\r
#define I2C_MODE_ERR_STR "i2c mode error"\r
-#define I2C_SDA_IO_ERR_STR "sda gpio number error"\r
-#define I2C_SCL_IO_ERR_STR "scl gpio number error"\r
-#define I2C_CMD_LINK_INIT_ERR_STR "i2c command link error"\r
-#define I2C_GPIO_PULLUP_ERR_STR "this i2c pin do not support internal pull-up"\r
-#define I2C_FIFO_FULL_THRESH_VAL (28)\r
-#define I2C_FIFO_EMPTY_THRESH_VAL (5)\r
-#define I2C_IO_INIT_LEVEL (1)\r
+#define I2C_SDA_IO_ERR_STR "sda gpio number error"\r
+#define I2C_SCL_IO_ERR_STR "scl gpio number error"\r
+#define I2C_CMD_LINK_INIT_ERR_STR "i2c command link error"\r
+#define I2C_GPIO_PULLUP_ERR_STR "this i2c pin do not support internal pull-up"\r
+#define I2C_FIFO_FULL_THRESH_VAL (28)\r
+#define I2C_FIFO_EMPTY_THRESH_VAL (5)\r
+#define I2C_IO_INIT_LEVEL (1)\r
+#define I2C_CMD_ALIVE_INTERVAL_TICK (1000 / portTICK_PERIOD_MS)\r
+#define I2C_CMD_EVT_ALIVE (BIT0)\r
+#define I2C_CMD_EVT_DONE (BIT1)\r
+#define I2C_SLAVE_TIMEOUT_DEFAULT (32000) /* I2C slave timeout value, APB clock cycle number */\r
+#define I2C_SLAVE_SDA_SAMPLE_DEFAULT (10) /* I2C slave sample time after scl positive edge default value */\r
+#define I2C_SLAVE_SDA_HOLD_DEFAULT (10) /* I2C slave hold time after scl negative edge default value */\r
+#define I2C_MASTER_TOUT_CNUM_DEFAULT (8) /* I2C master timeout cycle number of I2C clock, after which the timeout interrupt will be triggered */\r
\r
typedef struct {\r
uint8_t byte_num; /*!< cmd byte number */\r
I2C_STATUS_IDLE, /*!< idle status for current master command */\r
I2C_STATUS_ACK_ERROR, /*!< ack error status for current master command */\r
I2C_STATUS_DONE, /*!< I2C command done */\r
+ I2C_STATUS_TIMEOUT, /*!< I2C bus status error, and operation timeout */\r
} i2c_status_t;\r
\r
typedef struct {\r
int i2c_num; /*!< I2C port number */\r
int mode; /*!< I2C mode, master or slave */\r
intr_handle_t intr_handle; /*!< I2C interrupt handle*/\r
-\r
int cmd_idx; /*!< record current command index, for master mode */\r
int status; /*!< record current command status, for master mode */\r
int rx_cnt; /*!< record current read index, for master mode */\r
uint8_t data_buf[I2C_FIFO_LEN]; /*!< a buffer to store i2c fifo data */\r
+\r
i2c_cmd_desc_t cmd_link; /*!< I2C command link */\r
- xSemaphoreHandle cmd_sem; /*!< semaphore to sync command status */\r
+ EventGroupHandle_t cmd_evt; /*!< I2C command event bits */\r
xSemaphoreHandle cmd_mux; /*!< semaphore to lock command process */\r
size_t tx_fifo_remain; /*!< tx fifo remain length, for master mode */\r
size_t rx_fifo_remain; /*!< rx fifo remain length, for master mode */\r
static i2c_obj_t *p_i2c_obj[I2C_NUM_MAX] = {0};\r
static void i2c_isr_handler_default(void* arg);\r
static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num);\r
+static esp_err_t IRAM_ATTR i2c_hw_fsm_reset(i2c_port_t i2c_num);\r
\r
/*\r
For i2c master mode, we don't need to use a buffer for the data, the APIs will execute the master commands\r
For i2c slave mode, we need a data buffer to stash the sending and receiving data, because the hardware fifo\r
has only 32 bytes.\r
*/\r
-\r
esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_buf_len, size_t slv_tx_buf_len,\r
int intr_alloc_flags)\r
{\r
ESP_LOGE(I2C_TAG, I2C_SEM_ERR_STR);\r
goto err;\r
}\r
- intr_mask |= ( I2C_RXFIFO_FULL_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M );\r
+ intr_mask |= ( I2C_RXFIFO_FULL_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M);\r
} else {\r
//semaphore to sync sending process, because we only have 32 bytes for hardware fifo.\r
- p_i2c->cmd_sem = xSemaphoreCreateBinary();\r
p_i2c->cmd_mux = xSemaphoreCreateMutex();\r
- if (p_i2c->cmd_sem == NULL || p_i2c->cmd_mux == NULL) {\r
+ p_i2c->cmd_evt = xEventGroupCreate();\r
+ if (p_i2c->cmd_mux == NULL || p_i2c->cmd_evt == NULL) {\r
ESP_LOGE(I2C_TAG, I2C_SEM_ERR_STR);\r
goto err;\r
}\r
p_i2c->rx_buf_length = 0;\r
p_i2c->tx_ring_buf = NULL;\r
p_i2c->tx_buf_length = 0;\r
+ intr_mask |= I2C_ARBITRATION_LOST_INT_ENA_M | I2C_TIME_OUT_INT_ST_M;\r
}\r
} else {\r
ESP_LOGE(I2C_TAG, I2C_DRIVER_ERR_STR);\r
i2c_isr_register(i2c_num, i2c_isr_handler_default, p_i2c_obj[i2c_num], intr_alloc_flags, &p_i2c_obj[i2c_num]->intr_handle);\r
intr_mask |= ( I2C_TRANS_COMPLETE_INT_ENA_M |\r
I2C_TRANS_START_INT_ENA_M |\r
- I2C_ARBITRATION_LOST_INT_ENA_M |\r
I2C_ACK_ERR_INT_ENA_M |\r
I2C_RXFIFO_OVF_INT_ENA_M |\r
- I2C_SLAVE_TRAN_COMP_INT_ENA_M );\r
- SET_PERI_REG_MASK(I2C_INT_ENA_REG(i2c_num), intr_mask);\r
+ I2C_SLAVE_TRAN_COMP_INT_ENA_M);\r
+ I2C[i2c_num]->int_clr.val = intr_mask;\r
+ I2C[i2c_num]->int_ena.val = intr_mask;\r
return ESP_OK;\r
\r
err:\r
p_i2c_obj[i2c_num]->tx_ring_buf = NULL;\r
p_i2c_obj[i2c_num]->tx_buf_length = 0;\r
}\r
- if (p_i2c_obj[i2c_num]->cmd_sem) {\r
- vSemaphoreDelete(p_i2c_obj[i2c_num]->cmd_sem);\r
+ if (p_i2c_obj[i2c_num]->cmd_evt) {\r
+ vEventGroupDelete(p_i2c_obj[i2c_num]->cmd_evt);\r
+ p_i2c_obj[i2c_num]->cmd_evt = NULL;\r
}\r
if (p_i2c_obj[i2c_num]->cmd_mux) {\r
vSemaphoreDelete(p_i2c_obj[i2c_num]->cmd_mux);\r
return ESP_FAIL;\r
}\r
\r
+static esp_err_t i2c_hw_enable(i2c_port_t i2c_num)\r
+{\r
+ if (i2c_num == I2C_NUM_0) {\r
+ periph_module_enable(PERIPH_I2C0_MODULE);\r
+ } else if (i2c_num == I2C_NUM_1) {\r
+ periph_module_enable(PERIPH_I2C1_MODULE);\r
+ }\r
+ return ESP_OK;\r
+}\r
+\r
+static esp_err_t i2c_hw_disable(i2c_port_t i2c_num)\r
+{\r
+ if (i2c_num == I2C_NUM_0) {\r
+ periph_module_disable(PERIPH_I2C0_MODULE);\r
+ } else if (i2c_num == I2C_NUM_1) {\r
+ periph_module_disable(PERIPH_I2C1_MODULE);\r
+ }\r
+ return ESP_OK;\r
+}\r
+\r
esp_err_t i2c_driver_delete(i2c_port_t i2c_num)\r
{\r
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);\r
\r
i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];\r
\r
- uint32_t intr_mask = I2C_MASTER_TRAN_COMP_INT_ENA_M |\r
- I2C_TIME_OUT_INT_ENA_M |\r
- I2C_TRANS_COMPLETE_INT_ENA_M |\r
- I2C_TRANS_START_INT_ENA_M |\r
- I2C_TX_SEND_EMPTY_INT_ENA_M |\r
- I2C_ARBITRATION_LOST_INT_ENA_M |\r
- I2C_ACK_ERR_INT_ENA_M |\r
- I2C_RXFIFO_OVF_INT_ENA_M |\r
- I2C_RX_REC_FULL_INT_ENA_M |\r
- I2C_SLAVE_TRAN_COMP_INT_ENA_M;\r
- CLEAR_PERI_REG_MASK(I2C_INT_ENA_REG(i2c_num), intr_mask);\r
+ I2C[i2c_num]->int_ena.val = 0;\r
esp_intr_free(p_i2c->intr_handle);\r
p_i2c->intr_handle = NULL;\r
\r
xSemaphoreTake(p_i2c->cmd_mux, portMAX_DELAY);\r
vSemaphoreDelete(p_i2c->cmd_mux);\r
}\r
- if (p_i2c->cmd_sem) {\r
- vSemaphoreDelete(p_i2c->cmd_sem);\r
+ if (p_i2c_obj[i2c_num]->cmd_evt) {\r
+ vEventGroupDelete(p_i2c_obj[i2c_num]->cmd_evt);\r
+ p_i2c_obj[i2c_num]->cmd_evt = NULL;\r
}\r
if (p_i2c->slv_rx_mux) {\r
vSemaphoreDelete(p_i2c->slv_rx_mux);\r
\r
free(p_i2c_obj[i2c_num]);\r
p_i2c_obj[i2c_num] = NULL;\r
+\r
+ i2c_hw_disable(i2c_num);\r
return ESP_OK;\r
}\r
\r
return ESP_OK;\r
}\r
\r
-static void i2c_isr_handler_default(void* arg)\r
+static void IRAM_ATTR i2c_isr_handler_default(void* arg)\r
{\r
i2c_obj_t* p_i2c = (i2c_obj_t*) arg;\r
int i2c_num = p_i2c->i2c_num;\r
uint32_t status = I2C[i2c_num]->int_status.val;\r
int idx = 0;\r
+\r
portBASE_TYPE HPTaskAwoken = pdFALSE;\r
while (status != 0) {\r
status = I2C[i2c_num]->int_status.val;\r
I2C[i2c_num]->int_clr.trans_start = 1;\r
} else if (status & I2C_TIME_OUT_INT_ST_M) {\r
I2C[i2c_num]->int_clr.time_out = 1;\r
+ p_i2c_obj[i2c_num]->status = I2C_STATUS_TIMEOUT;\r
+ i2c_master_cmd_begin_static(i2c_num);\r
} else if (status & I2C_TRANS_COMPLETE_INT_ST_M) {\r
I2C[i2c_num]->int_clr.trans_complete = 1;\r
if (p_i2c->mode == I2C_MODE_SLAVE) {\r
I2C[i2c_num]->int_clr.master_tran_comp = 1;\r
} else if (status & I2C_ARBITRATION_LOST_INT_ST_M) {\r
I2C[i2c_num]->int_clr.arbitration_lost = 1;\r
+ p_i2c_obj[i2c_num]->status = I2C_STATUS_TIMEOUT;\r
+ i2c_master_cmd_begin_static(i2c_num);\r
} else if (status & I2C_SLAVE_TRAN_COMP_INT_ST_M) {\r
I2C[i2c_num]->int_clr.slave_tran_comp = 1;\r
} else if (status & I2C_END_DETECT_INT_ST_M) {\r
I2C[i2c_num]->int_clr.val = status;\r
}\r
}\r
+ if (p_i2c->mode == I2C_MODE_MASTER) {\r
+ xEventGroupSetBitsFromISR(p_i2c->cmd_evt, I2C_CMD_EVT_ALIVE, &HPTaskAwoken);\r
+ if (HPTaskAwoken == pdTRUE) {\r
+ portYIELD_FROM_ISR();\r
+ }\r
+ }\r
}\r
\r
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)\r
return ESP_OK;\r
}\r
\r
+/* Some slave device will die by accident and keep the SDA in low level,\r
+ * in this case, master should send several clock to make the slave release the bus.\r
+ * Slave mode of ESP32 might also get in wrong state that held the SDA low,\r
+ * in this case, master device could send a stop signal to make esp32 slave release the bus.\r
+ **/\r
+static esp_err_t i2c_master_clear_bus(i2c_port_t i2c_num)\r
+{\r
+ I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);\r
+ int sda_in_sig = 0, scl_in_sig = 0;\r
+ if (i2c_num == I2C_NUM_0) {\r
+ sda_in_sig = I2CEXT0_SDA_IN_IDX;\r
+ scl_in_sig = I2CEXT0_SCL_IN_IDX;\r
+ } else if (i2c_num == I2C_NUM_1) {\r
+ sda_in_sig = I2CEXT1_SDA_IN_IDX;\r
+ scl_in_sig = I2CEXT1_SCL_IN_IDX;\r
+ }\r
+ int scl_io = GPIO.func_in_sel_cfg[scl_in_sig].func_sel;\r
+ int sda_io = GPIO.func_in_sel_cfg[sda_in_sig].func_sel;\r
+ I2C_CHECK((GPIO_IS_VALID_OUTPUT_GPIO(scl_io)), I2C_SCL_IO_ERR_STR, ESP_ERR_INVALID_ARG);\r
+ I2C_CHECK((GPIO_IS_VALID_GPIO(sda_io)), I2C_SDA_IO_ERR_STR, ESP_ERR_INVALID_ARG);\r
+\r
+ if (gpio_get_level(sda_io) == 1) {\r
+ return ESP_OK;\r
+ }\r
+ gpio_set_direction(scl_io, GPIO_MODE_OUTPUT_OD);\r
+ gpio_set_direction(sda_io, GPIO_MODE_OUTPUT_OD);\r
+ gpio_set_level(scl_io, 0);\r
+ gpio_set_level(sda_io, 0);\r
+ for (int i = 0; i < 9; i++) {\r
+ gpio_set_level(scl_io, 1);\r
+ gpio_set_level(scl_io, 0);\r
+ }\r
+ gpio_set_level(scl_io, 1);\r
+ gpio_set_level(sda_io, 1);\r
+ i2c_set_pin(i2c_num, sda_io, scl_io, 1, 1, I2C_MODE_MASTER);\r
+ return ESP_OK;\r
+}\r
+\r
+/**if the power and SDA/SCL wires are in proper condition, everything works find with reading the slave.\r
+ * If we remove the power supply for the slave during I2C is reading, or directly connect SDA or SCL to ground,\r
+ * this would cause the I2C FSM get stuck in wrong state, all we can do is to reset the I2C hardware in this case.\r
+ **/\r
+static esp_err_t i2c_hw_fsm_reset(i2c_port_t i2c_num)\r
+{\r
+ I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);\r
+ uint32_t ctr = I2C[i2c_num]->ctr.val;\r
+ uint32_t fifo_conf = I2C[i2c_num]->fifo_conf.val;\r
+ uint32_t scl_low_period = I2C[i2c_num]->scl_low_period.val;\r
+ uint32_t scl_high_period = I2C[i2c_num]->scl_high_period.val;\r
+ uint32_t scl_start_hold = I2C[i2c_num]->scl_start_hold.val;\r
+ uint32_t scl_rstart_setup = I2C[i2c_num]->scl_rstart_setup.val;\r
+ uint32_t scl_stop_hold = I2C[i2c_num]->scl_stop_hold.val;\r
+ uint32_t scl_stop_setup = I2C[i2c_num]->scl_stop_setup.val;\r
+ uint32_t sda_hold = I2C[i2c_num]->sda_hold.val;\r
+ uint32_t sda_sample = I2C[i2c_num]->sda_sample.val;\r
+ uint32_t timeout = I2C[i2c_num]->timeout.val;\r
+ uint32_t scl_filter_cfg = I2C[i2c_num]->scl_filter_cfg.val;\r
+ uint32_t sda_filter_cfg = I2C[i2c_num]->sda_filter_cfg.val;\r
+ uint32_t slave_addr = I2C[i2c_num]->slave_addr.val;\r
+\r
+ //to reset the I2C hw module, we need re-enable the hw\r
+ i2c_hw_disable(i2c_num);\r
+ i2c_master_clear_bus(i2c_num);\r
+ i2c_hw_enable(i2c_num);\r
+ I2C[i2c_num]->int_ena.val = 0;\r
+ I2C[i2c_num]->ctr.val = ctr & (~I2C_TRANS_START_M);\r
+ I2C[i2c_num]->fifo_conf.val = fifo_conf;\r
+ I2C[i2c_num]->scl_low_period.val = scl_low_period;\r
+ I2C[i2c_num]->scl_high_period.val = scl_high_period;\r
+ I2C[i2c_num]->scl_start_hold.val = scl_start_hold;\r
+ I2C[i2c_num]->scl_rstart_setup.val = scl_rstart_setup;\r
+ I2C[i2c_num]->scl_stop_hold.val = scl_stop_hold;\r
+ I2C[i2c_num]->scl_stop_setup.val = scl_stop_setup;\r
+ I2C[i2c_num]->sda_hold.val = sda_hold;\r
+ I2C[i2c_num]->sda_sample.val = sda_sample;\r
+ I2C[i2c_num]->timeout.val = timeout;\r
+ I2C[i2c_num]->scl_filter_cfg.val = scl_filter_cfg;\r
+ I2C[i2c_num]->sda_filter_cfg.val = sda_filter_cfg;\r
+ uint32_t intr_mask = ( I2C_TRANS_COMPLETE_INT_ENA_M\r
+ | I2C_TRANS_START_INT_ENA_M\r
+ | I2C_ACK_ERR_INT_ENA_M\r
+ | I2C_RXFIFO_OVF_INT_ENA_M\r
+ | I2C_SLAVE_TRAN_COMP_INT_ENA_M\r
+ | I2C_TIME_OUT_INT_ENA_M);\r
+ if (I2C[i2c_num]->ctr.ms_mode == I2C_MODE_SLAVE) {\r
+ I2C[i2c_num]->slave_addr.val = slave_addr;\r
+ intr_mask |= ( I2C_RXFIFO_FULL_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M);\r
+ } else {\r
+ intr_mask |= I2C_ARBITRATION_LOST_INT_ENA_M;\r
+ }\r
+ I2C[i2c_num]->int_clr.val = intr_mask;\r
+ I2C[i2c_num]->int_ena.val = intr_mask;\r
+ return ESP_OK;\r
+}\r
+\r
esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t* i2c_conf)\r
{\r
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);\r
if (ret != ESP_OK) {\r
return ret;\r
}\r
- if (i2c_num == I2C_NUM_0) {\r
- periph_module_enable(PERIPH_I2C0_MODULE);\r
- } else if (i2c_num == I2C_NUM_1) {\r
- periph_module_enable(PERIPH_I2C1_MODULE);\r
- }\r
-\r
+ i2c_hw_enable(i2c_num);\r
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);\r
I2C[i2c_num]->ctr.rx_lsb_first = I2C_DATA_MODE_MSB_FIRST; //set rx data msb first\r
I2C[i2c_num]->ctr.tx_lsb_first = I2C_DATA_MODE_MSB_FIRST; //set tx data msb first\r
I2C[i2c_num]->fifo_conf.fifo_addr_cfg_en = 0;\r
I2C[i2c_num]->fifo_conf.rx_fifo_full_thrhd = I2C_FIFO_FULL_THRESH_VAL;\r
I2C[i2c_num]->fifo_conf.tx_fifo_empty_thrhd = I2C_FIFO_EMPTY_THRESH_VAL;\r
- I2C[i2c_num]->int_ena.rx_fifo_full = 1;\r
I2C[i2c_num]->ctr.trans_start = 0;\r
+ I2C[i2c_num]->timeout.tout = I2C_SLAVE_TIMEOUT_DEFAULT;\r
+ //set timing for data\r
+ I2C[i2c_num]->sda_hold.time = I2C_SLAVE_SDA_HOLD_DEFAULT;\r
+ I2C[i2c_num]->sda_sample.time = I2C_SLAVE_SDA_SAMPLE_DEFAULT;\r
} else {\r
I2C[i2c_num]->fifo_conf.nonfifo_en = 0;\r
+ int cycle = (I2C_APB_CLK_FREQ / i2c_conf->master.clk_speed);\r
+ int half_cycle = cycle / 2;\r
+ I2C[i2c_num]->timeout.tout = cycle * I2C_MASTER_TOUT_CNUM_DEFAULT;\r
+ //set timing for data\r
+ I2C[i2c_num]->sda_hold.time = half_cycle / 2;\r
+ I2C[i2c_num]->sda_sample.time = half_cycle / 2;\r
+\r
+ I2C[i2c_num]->scl_low_period.period = half_cycle;\r
+ I2C[i2c_num]->scl_high_period.period = half_cycle;\r
+ //set timing for start signal\r
+ I2C[i2c_num]->scl_start_hold.time = half_cycle;\r
+ I2C[i2c_num]->scl_rstart_setup.time = half_cycle;\r
+ //set timing for stop signal\r
+ I2C[i2c_num]->scl_stop_hold.time = half_cycle;\r
+ I2C[i2c_num]->scl_stop_setup.time = half_cycle;\r
}\r
- //set frequency\r
- int half_cycle = ( I2C_APB_CLK_FREQ / i2c_conf->master.clk_speed ) / 2;\r
- I2C[i2c_num]->scl_low_period.period = half_cycle - 1;\r
- I2C[i2c_num]->scl_high_period.period = ( I2C_APB_CLK_FREQ / i2c_conf->master.clk_speed ) - half_cycle - 1;\r
- //set timing for start signal\r
- I2C[i2c_num]->scl_start_hold.time = half_cycle;\r
- I2C[i2c_num]->scl_rstart_setup.time = half_cycle;\r
- //set timing for stop signal\r
- I2C[i2c_num]->scl_stop_hold.time = half_cycle;\r
- I2C[i2c_num]->scl_stop_setup.time = half_cycle;\r
- //set timing for data\r
- I2C[i2c_num]->sda_hold.time = half_cycle / 2;\r
- I2C[i2c_num]->sda_sample.time = half_cycle / 2;\r
- //set timeout of receving data\r
- I2C[i2c_num]->timeout.tout = 200000;\r
+\r
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);\r
return ESP_OK;\r
}\r
esp_err_t i2c_set_period(i2c_port_t i2c_num, int high_period, int low_period)\r
{\r
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);\r
+ I2C_CHECK((high_period <= I2C_SCL_HIGH_PERIOD_V) && (high_period > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);\r
+ I2C_CHECK((low_period <= I2C_SCL_LOW_PERIOD_V) && (low_period > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);\r
+\r
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);\r
I2C[i2c_num]->scl_high_period.period = high_period;\r
I2C[i2c_num]->scl_low_period.period = low_period;\r
esp_err_t i2c_set_start_timing(i2c_port_t i2c_num, int setup_time, int hold_time)\r
{\r
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);\r
+ I2C_CHECK((hold_time <= I2C_SCL_START_HOLD_TIME_V) && (hold_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);\r
+ I2C_CHECK((setup_time <= I2C_SCL_RSTART_SETUP_TIME_V) && (setup_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);\r
+\r
I2C[i2c_num]->scl_start_hold.time = hold_time;\r
I2C[i2c_num]->scl_rstart_setup.time = setup_time;\r
return ESP_OK;\r
esp_err_t i2c_set_stop_timing(i2c_port_t i2c_num, int setup_time, int hold_time)\r
{\r
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);\r
+ I2C_CHECK((setup_time <= I2C_SCL_STOP_SETUP_TIME_V) && (setup_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);\r
+ I2C_CHECK((hold_time <= I2C_SCL_STOP_HOLD_TIME_V) && (hold_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);\r
+\r
I2C[i2c_num]->scl_stop_hold.time = hold_time;\r
I2C[i2c_num]->scl_stop_setup.time = setup_time;\r
return ESP_OK;\r
esp_err_t i2c_set_data_timing(i2c_port_t i2c_num, int sample_time, int hold_time)\r
{\r
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);\r
+ I2C_CHECK((sample_time <= I2C_SDA_SAMPLE_TIME_V) && (sample_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);\r
+ I2C_CHECK((hold_time <= I2C_SDA_HOLD_TIME_V) && (hold_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);\r
+\r
I2C[i2c_num]->sda_hold.time = hold_time;\r
I2C[i2c_num]->sda_sample.time = sample_time;\r
return ESP_OK;\r
return ESP_OK;\r
}\r
\r
+esp_err_t i2c_set_timeout(i2c_port_t i2c_num, int timeout)\r
+{\r
+ I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);\r
+ I2C_CHECK((timeout <= I2C_SDA_SAMPLE_TIME_V) && (timeout > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);\r
+\r
+ I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);\r
+ I2C[i2c_num]->timeout.tout = timeout;\r
+ I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);\r
+ return ESP_OK;\r
+}\r
+\r
+esp_err_t i2c_get_timeout(i2c_port_t i2c_num, int* timeout)\r
+{\r
+ I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);\r
+ if (timeout) {\r
+ *timeout = I2C[i2c_num]->timeout.tout;\r
+ }\r
+ return ESP_OK;\r
+}\r
+\r
esp_err_t i2c_isr_register(i2c_port_t i2c_num, void (*fn)(void*), void * arg, int intr_alloc_flags, intr_handle_t *handle)\r
{\r
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);\r
return esp_intr_free(handle);\r
}\r
\r
-esp_err_t i2c_set_pin(i2c_port_t i2c_num, gpio_num_t sda_io_num, gpio_num_t scl_io_num, gpio_pullup_t sda_pullup_en, gpio_pullup_t scl_pullup_en, i2c_mode_t mode)\r
+esp_err_t i2c_set_pin(i2c_port_t i2c_num, int sda_io_num, int scl_io_num, gpio_pullup_t sda_pullup_en, gpio_pullup_t scl_pullup_en, i2c_mode_t mode)\r
{\r
I2C_CHECK(( i2c_num < I2C_NUM_MAX ), I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);\r
- I2C_CHECK(((GPIO_IS_VALID_OUTPUT_GPIO(sda_io_num))), I2C_SDA_IO_ERR_STR, ESP_ERR_INVALID_ARG);\r
- I2C_CHECK((GPIO_IS_VALID_OUTPUT_GPIO(scl_io_num)) ||\r
+ I2C_CHECK(((sda_io_num < 0) || ((GPIO_IS_VALID_OUTPUT_GPIO(sda_io_num)))), I2C_SDA_IO_ERR_STR, ESP_ERR_INVALID_ARG);\r
+ I2C_CHECK(scl_io_num < 0 ||\r
+ (GPIO_IS_VALID_OUTPUT_GPIO(scl_io_num)) ||\r
(GPIO_IS_VALID_GPIO(scl_io_num) && mode == I2C_MODE_SLAVE),\r
I2C_SCL_IO_ERR_STR,\r
ESP_ERR_INVALID_ARG);\r
- I2C_CHECK((sda_pullup_en == GPIO_PULLUP_ENABLE && GPIO_IS_VALID_OUTPUT_GPIO(sda_io_num)) ||\r
+ I2C_CHECK(sda_io_num < 0 ||\r
+ (sda_pullup_en == GPIO_PULLUP_ENABLE && GPIO_IS_VALID_OUTPUT_GPIO(sda_io_num)) ||\r
sda_pullup_en == GPIO_PULLUP_DISABLE, I2C_GPIO_PULLUP_ERR_STR, ESP_ERR_INVALID_ARG);\r
- I2C_CHECK((scl_pullup_en == GPIO_PULLUP_ENABLE && GPIO_IS_VALID_OUTPUT_GPIO(scl_io_num)) ||\r
+ I2C_CHECK(scl_io_num < 0 ||\r
+ (scl_pullup_en == GPIO_PULLUP_ENABLE && GPIO_IS_VALID_OUTPUT_GPIO(scl_io_num)) ||\r
scl_pullup_en == GPIO_PULLUP_DISABLE, I2C_GPIO_PULLUP_ERR_STR, ESP_ERR_INVALID_ARG);\r
\r
int sda_in_sig, sda_out_sig, scl_in_sig, scl_out_sig;\r
gpio_set_level(sda_io_num, I2C_IO_INIT_LEVEL);\r
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[sda_io_num], PIN_FUNC_GPIO);\r
gpio_set_direction(sda_io_num, GPIO_MODE_INPUT_OUTPUT_OD);\r
+\r
if (sda_pullup_en == GPIO_PULLUP_ENABLE) {\r
gpio_set_pull_mode(sda_io_num, GPIO_PULLUP_ONLY);\r
} else {\r
{\r
i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];\r
portBASE_TYPE HPTaskAwoken = pdFALSE;\r
+\r
//This should never happen\r
if (p_i2c->mode == I2C_MODE_SLAVE) {\r
return;\r
}\r
if (p_i2c->status == I2C_STATUS_DONE) {\r
return;\r
- } else if (p_i2c->status == I2C_STATUS_ACK_ERROR) {\r
+ } else if ((p_i2c->status == I2C_STATUS_ACK_ERROR)\r
+ || (p_i2c->status == I2C_STATUS_TIMEOUT)) {\r
I2C[i2c_num]->int_ena.end_detect = 0;\r
I2C[i2c_num]->int_clr.end_detect = 1;\r
- I2C[i2c_num]->int_ena.master_tran_comp = 0;\r
- xSemaphoreGiveFromISR(p_i2c->cmd_sem, &HPTaskAwoken);\r
+ if(p_i2c->status == I2C_STATUS_TIMEOUT) {\r
+ I2C[i2c_num]->int_clr.time_out = 1;\r
+ I2C[i2c_num]->int_ena.val = 0;\r
+ }\r
+ xEventGroupSetBitsFromISR(p_i2c->cmd_evt, I2C_CMD_EVT_DONE, &HPTaskAwoken);\r
if (HPTaskAwoken == pdTRUE) {\r
portYIELD_FROM_ISR();\r
}\r
}\r
if (p_i2c->cmd_link.head == NULL) {\r
p_i2c->cmd_link.cur = NULL;\r
- xSemaphoreGiveFromISR(p_i2c->cmd_sem, &HPTaskAwoken);\r
+ xEventGroupSetBitsFromISR(p_i2c->cmd_evt, I2C_CMD_EVT_DONE, &HPTaskAwoken);\r
if (HPTaskAwoken == pdTRUE) {\r
portYIELD_FROM_ISR();\r
}\r
}\r
}\r
I2C[i2c_num]->int_clr.end_detect = 1;\r
- I2C[i2c_num]->int_clr.master_tran_comp = 1;\r
I2C[i2c_num]->int_ena.end_detect = 1;\r
- I2C[i2c_num]->int_ena.master_tran_comp = 1;\r
I2C[i2c_num]->ctr.trans_start = 0;\r
I2C[i2c_num]->ctr.trans_start = 1;\r
return;\r
}\r
\r
-esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, portBASE_TYPE ticks_to_wait)\r
+esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, TickType_t ticks_to_wait)\r
{\r
I2C_CHECK(( i2c_num < I2C_NUM_MAX ), I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);\r
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_NOT_INSTALL_ERR_STR, ESP_ERR_INVALID_STATE);\r
I2C_CHECK(p_i2c_obj[i2c_num]->mode == I2C_MODE_MASTER, I2C_MASTER_MODE_ERR_STR, ESP_ERR_INVALID_STATE);\r
I2C_CHECK(cmd_handle != NULL, I2C_CMD_LINK_INIT_ERR_STR, ESP_ERR_INVALID_ARG);\r
\r
- esp_err_t ret;\r
+ esp_err_t ret = ESP_FAIL;\r
i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];\r
portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait;\r
portBASE_TYPE res = xSemaphoreTake(p_i2c->cmd_mux, ticks_to_wait);\r
if (res == pdFALSE) {\r
return ESP_ERR_TIMEOUT;\r
}\r
- xSemaphoreTake(p_i2c->cmd_sem, 0);\r
+ xEventGroupClearBits(p_i2c->cmd_evt, I2C_CMD_EVT_DONE | I2C_CMD_EVT_ALIVE);\r
+ if (p_i2c->status == I2C_STATUS_TIMEOUT\r
+ || I2C[i2c_num]->status_reg.bus_busy == 1) {\r
+ i2c_hw_fsm_reset(i2c_num);\r
+ }\r
i2c_reset_tx_fifo(i2c_num);\r
i2c_reset_rx_fifo(i2c_num);\r
i2c_cmd_desc_t* cmd = (i2c_cmd_desc_t*) cmd_handle;\r
\r
//start send commands, at most 32 bytes one time, isr handler will process the remaining commands.\r
i2c_master_cmd_begin_static(i2c_num);\r
- ticks_to_wait = ticks_end - xTaskGetTickCount();\r
- res = xSemaphoreTake(p_i2c->cmd_sem, ticks_to_wait);\r
- if (res == pdFALSE) {\r
- ret = ESP_ERR_TIMEOUT;\r
- } else if (p_i2c->status == I2C_STATUS_ACK_ERROR) {\r
- ret = ESP_FAIL;\r
+ if (ticks_to_wait == portMAX_DELAY) {\r
+\r
+ } else if (ticks_to_wait == 0) {\r
+\r
} else {\r
- ret = ESP_OK;\r
+ ticks_to_wait = ticks_end - xTaskGetTickCount();\r
+ }\r
+ // Wait event bits\r
+ EventBits_t uxBits;\r
+ while (1) {\r
+ TickType_t wait_time = (ticks_to_wait < (I2C_CMD_ALIVE_INTERVAL_TICK) ? ticks_to_wait : (I2C_CMD_ALIVE_INTERVAL_TICK));\r
+ // In master mode, since we don't have an interrupt to detective bus error or FSM state, what we do here is to make\r
+ // sure the interrupt mechanism for master mode is still working.\r
+ // If the command sending is not finished and there is no interrupt any more, the bus is probably dead caused by external noise.\r
+ uxBits = xEventGroupWaitBits(p_i2c->cmd_evt, I2C_CMD_EVT_ALIVE | I2C_CMD_EVT_DONE, false, false, wait_time);\r
+ if (uxBits) {\r
+ if (uxBits & I2C_CMD_EVT_DONE) {\r
+ xEventGroupClearBits(p_i2c->cmd_evt, I2C_CMD_EVT_DONE);\r
+ if (p_i2c->status == I2C_STATUS_TIMEOUT) {\r
+ // If the I2C slave are powered off or the SDA/SCL are connected to ground, for example,\r
+ // I2C hw FSM would get stuck in wrong state, we have to reset the I2C module in this case.\r
+ i2c_hw_fsm_reset(i2c_num);\r
+ ret = ESP_ERR_TIMEOUT;\r
+ } else if (p_i2c->status == I2C_STATUS_ACK_ERROR) {\r
+ ret = ESP_FAIL;\r
+ } else {\r
+ ret = ESP_OK;\r
+ }\r
+ break;\r
+ }\r
+ if (uxBits & I2C_CMD_EVT_ALIVE) {\r
+ xEventGroupClearBits(p_i2c->cmd_evt, I2C_CMD_EVT_ALIVE);\r
+ }\r
+ } else {\r
+ ret = ESP_ERR_TIMEOUT;\r
+ // If the I2C slave are powered off or the SDA/SCL are connected to ground, for example,\r
+ // I2C hw FSM would get stuck in wrong state, we have to reset the I2C module in this case.\r
+ i2c_hw_fsm_reset(i2c_num);\r
+ break;\r
+ }\r
+ if (ticks_to_wait == portMAX_DELAY) {\r
+\r
+ } else {\r
+ TickType_t now = xTaskGetTickCount();\r
+ ticks_to_wait = ticks_end > now ? (ticks_end - now) : 0;\r
+ }\r
}\r
p_i2c->status = I2C_STATUS_DONE;\r
xSemaphoreGive(p_i2c->cmd_mux);\r
return ret;\r
}\r
\r
-int i2c_slave_write_buffer(i2c_port_t i2c_num, uint8_t* data, int size, portBASE_TYPE ticks_to_wait)\r
+int i2c_slave_write_buffer(i2c_port_t i2c_num, uint8_t* data, int size, TickType_t ticks_to_wait)\r
{\r
I2C_CHECK(( i2c_num < I2C_NUM_MAX ), I2C_NUM_ERROR_STR, ESP_FAIL);\r
I2C_CHECK((data != NULL), I2C_ADDR_ERROR_STR, ESP_FAIL);\r
return cnt;\r
}\r
\r
-static int i2c_slave_read(i2c_port_t i2c_num, uint8_t* data, size_t max_size, portBASE_TYPE ticks_to_wait)\r
+static int i2c_slave_read(i2c_port_t i2c_num, uint8_t* data, size_t max_size, TickType_t ticks_to_wait)\r
{\r
i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];\r
size_t size = 0;\r
return size;\r
}\r
\r
-int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t* data, size_t max_size, portBASE_TYPE ticks_to_wait)\r
+int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t* data, size_t max_size, TickType_t ticks_to_wait)\r
{\r
I2C_CHECK(( i2c_num < I2C_NUM_MAX ), I2C_NUM_ERROR_STR, ESP_FAIL);\r
I2C_CHECK((data != NULL), I2C_ADDR_ERROR_STR, ESP_FAIL);\r
\r
\r
\r
-\r
* - i2c master(ESP32) will read data from i2c slave(ESP32).
*/
-#define DATA_LENGTH 512 /*!<Data buffer length for test buffer*/
-#define RW_TEST_LENGTH 129 /*!<Data length for r/w test, any value from 0-DATA_LENGTH*/
-#define DELAY_TIME_BETWEEN_ITEMS_MS 1234 /*!< delay time between different test items */
+#define DATA_LENGTH 512 /*!<Data buffer length for test buffer*/
+#define RW_TEST_LENGTH 129 /*!<Data length for r/w test, any value from 0-DATA_LENGTH*/
+#define DELAY_TIME_BETWEEN_ITEMS_MS 1234 /*!< delay time between different test items */
-#define I2C_EXAMPLE_SLAVE_SCL_IO 26 /*!<gpio number for i2c slave clock */
-#define I2C_EXAMPLE_SLAVE_SDA_IO 25 /*!<gpio number for i2c slave data */
-#define I2C_EXAMPLE_SLAVE_NUM I2C_NUM_0 /*!<I2C port number for slave dev */
-#define I2C_EXAMPLE_SLAVE_TX_BUF_LEN (2*DATA_LENGTH) /*!<I2C slave tx buffer size */
-#define I2C_EXAMPLE_SLAVE_RX_BUF_LEN (2*DATA_LENGTH) /*!<I2C slave rx buffer size */
+#define I2C_EXAMPLE_SLAVE_SCL_IO 26 /*!<gpio number for i2c slave clock */
+#define I2C_EXAMPLE_SLAVE_SDA_IO 25 /*!<gpio number for i2c slave data */
+#define I2C_EXAMPLE_SLAVE_NUM I2C_NUM_0 /*!<I2C port number for slave dev */
+#define I2C_EXAMPLE_SLAVE_TX_BUF_LEN (2*DATA_LENGTH) /*!<I2C slave tx buffer size */
+#define I2C_EXAMPLE_SLAVE_RX_BUF_LEN (2*DATA_LENGTH) /*!<I2C slave rx buffer size */
-#define I2C_EXAMPLE_MASTER_SCL_IO 19 /*!< gpio number for I2C master clock */
-#define I2C_EXAMPLE_MASTER_SDA_IO 18 /*!< gpio number for I2C master data */
-#define I2C_EXAMPLE_MASTER_NUM I2C_NUM_1 /*!< I2C port number for master dev */
-#define I2C_EXAMPLE_MASTER_TX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
-#define I2C_EXAMPLE_MASTER_RX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
-#define I2C_EXAMPLE_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */
+#define I2C_EXAMPLE_MASTER_SCL_IO 19 /*!< gpio number for I2C master clock */
+#define I2C_EXAMPLE_MASTER_SDA_IO 18 /*!< gpio number for I2C master data */
+#define I2C_EXAMPLE_MASTER_NUM I2C_NUM_1 /*!< I2C port number for master dev */
+#define I2C_EXAMPLE_MASTER_TX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
+#define I2C_EXAMPLE_MASTER_RX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
+#define I2C_EXAMPLE_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */
-#define BH1750_SENSOR_ADDR 0x23 /*!< slave address for BH1750 sensor */
-#define BH1750_CMD_START 0x23 /*!< Command to set measure mode */
-#define ESP_SLAVE_ADDR 0x28 /*!< ESP32 slave address, you can set any 7bit value */
-#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
-#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
-#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
-#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
-#define ACK_VAL 0x0 /*!< I2C ack value */
-#define NACK_VAL 0x1 /*!< I2C nack value */
+#define BH1750_SENSOR_ADDR 0x23 /*!< slave address for BH1750 sensor */
+#define BH1750_CMD_START 0x23 /*!< Command to set measure mode */
+#define ESP_SLAVE_ADDR 0x28 /*!< ESP32 slave address, you can set any 7bit value */
+#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
+#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
+#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
+#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
+#define ACK_VAL 0x0 /*!< I2C ack value */
+#define NACK_VAL 0x1 /*!< I2C nack value */
-xSemaphoreHandle print_mux;
+SemaphoreHandle_t print_mux = NULL;
/**
* @brief test code to read esp-i2c-slave
*/
static esp_err_t i2c_example_master_sensor_test(i2c_port_t i2c_num, uint8_t* data_h, uint8_t* data_l)
{
+ int ret;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, BH1750_SENSOR_ADDR << 1 | WRITE_BIT, ACK_CHECK_EN);
i2c_master_write_byte(cmd, BH1750_CMD_START, ACK_CHECK_EN);
i2c_master_stop(cmd);
- int ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
+ ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
- if (ret == ESP_FAIL) {
+ if (ret != ESP_OK) {
return ret;
}
vTaskDelay(30 / portTICK_RATE_MS);
-
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, BH1750_SENSOR_ADDR << 1 | READ_BIT, ACK_CHECK_EN);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
- if (ret == ESP_FAIL) {
- return ESP_FAIL;
- }
- return ESP_OK;
+ return ret;
}
/**
uint8_t* data_wr = (uint8_t*) malloc(DATA_LENGTH);
uint8_t* data_rd = (uint8_t*) malloc(DATA_LENGTH);
uint8_t sensor_data_h, sensor_data_l;
-
+ int cnt = 0;
while (1) {
+ printf("test cnt: %d\n", cnt++);
ret = i2c_example_master_sensor_test( I2C_EXAMPLE_MASTER_NUM, &sensor_data_h, &sensor_data_l);
xSemaphoreTake(print_mux, portMAX_DELAY);
- printf("*******************\n");
- printf("TASK[%d] MASTER READ SENSOR( BH1750 )\n", task_idx);
- printf("*******************\n");
- if (ret == ESP_OK) {
+ if(ret == ESP_ERR_TIMEOUT) {
+ printf("I2C timeout\n");
+ } else if(ret == ESP_OK) {
+ printf("*******************\n");
+ printf("TASK[%d] MASTER READ SENSOR( BH1750 )\n", task_idx);
+ printf("*******************\n");
printf("data_h: %02x\n", sensor_data_h);
printf("data_l: %02x\n", sensor_data_l);
- printf("sensor val: %f\n", ( sensor_data_h << 8 | sensor_data_l ) / 1.2);
+ printf("sensor val: %f\n", (sensor_data_h << 8 | sensor_data_l) / 1.2);
} else {
printf("No ack, sensor not connected...skip...\n");
}
xSemaphoreGive(print_mux);
vTaskDelay(( DELAY_TIME_BETWEEN_ITEMS_MS * ( task_idx + 1 ) ) / portTICK_RATE_MS);
-
//---------------------------------------------------
for (i = 0; i < DATA_LENGTH; i++) {
data[i] = i;
}
+ xSemaphoreTake(print_mux, portMAX_DELAY);
size_t d_size = i2c_slave_write_buffer(I2C_EXAMPLE_SLAVE_NUM, data, RW_TEST_LENGTH, 1000 / portTICK_RATE_MS);
if (d_size == 0) {
printf("i2c slave tx buffer full\n");
} else {
ret = i2c_example_master_read_slave(I2C_EXAMPLE_MASTER_NUM, data_rd, RW_TEST_LENGTH);
}
- xSemaphoreTake(print_mux, portMAX_DELAY);
- printf("*******************\n");
- printf("TASK[%d] MASTER READ FROM SLAVE\n", task_idx);
- printf("*******************\n");
- printf("====TASK[%d] Slave buffer data ====\n", task_idx);
- disp_buf(data, d_size);
- if (ret == ESP_OK) {
+
+ if (ret == ESP_ERR_TIMEOUT) {
+ printf("I2C timeout\n");
+ printf("*********\n");
+ } else if (ret == ESP_OK) {
+ printf("*******************\n");
+ printf("TASK[%d] MASTER READ FROM SLAVE\n", task_idx);
+ printf("*******************\n");
+ printf("====TASK[%d] Slave buffer data ====\n", task_idx);
+ disp_buf(data, d_size);
printf("====TASK[%d] Master read ====\n", task_idx);
disp_buf(data_rd, d_size);
} else {
for (i = 0; i < DATA_LENGTH; i++) {
data_wr[i] = i + 10;
}
+ xSemaphoreTake(print_mux, portMAX_DELAY);
//we need to fill the slave buffer so that master can read later
ret = i2c_example_master_write_slave( I2C_EXAMPLE_MASTER_NUM, data_wr, RW_TEST_LENGTH);
if (ret == ESP_OK) {
size = i2c_slave_read_buffer( I2C_EXAMPLE_SLAVE_NUM, data, RW_TEST_LENGTH, 1000 / portTICK_RATE_MS);
}
- xSemaphoreTake(print_mux, portMAX_DELAY);
- printf("*******************\n");
- printf("TASK[%d] MASTER WRITE TO SLAVE\n", task_idx);
- printf("*******************\n");
- printf("----TASK[%d] Master write ----\n", task_idx);
- disp_buf(data_wr, RW_TEST_LENGTH);
- if (ret == ESP_OK) {
+ if (ret == ESP_ERR_TIMEOUT) {
+ printf("I2C timeout\n");
+ } else if (ret == ESP_OK) {
+ printf("*******************\n");
+ printf("TASK[%d] MASTER WRITE TO SLAVE\n", task_idx);
+ printf("*******************\n");
+ printf("----TASK[%d] Master write ----\n", task_idx);
+ disp_buf(data_wr, RW_TEST_LENGTH);
printf("----TASK[%d] Slave read: [%d] bytes ----\n", task_idx, size);
disp_buf(data, size);
} else {
print_mux = xSemaphoreCreateMutex();
i2c_example_slave_init();
i2c_example_master_init();
-
xTaskCreate(i2c_test_task, "i2c_test_task_0", 1024 * 2, (void* ) 0, 10, NULL);
xTaskCreate(i2c_test_task, "i2c_test_task_1", 1024 * 2, (void* ) 1, 10, NULL);
+
}