4#include <driver/gpio.h>
12#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 3, 0)
13#define SOC_HP_I2C_NUM SOC_I2C_NUM
19static const char *
const TAG =
"i2c.idf";
22 static i2c_port_t next_port = I2C_NUM_0;
23 this->
port_ = next_port;
24 if (this->
port_ == I2C_NUM_MAX) {
25 ESP_LOGE(TAG,
"No more than %u buses supported", I2C_NUM_MAX);
31 ESP_LOGW(TAG,
"Using max allowed timeout: 13 ms");
37#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2)
38 next_port = (i2c_port_t) (next_port + 1);
40 i2c_master_bus_config_t bus_conf{};
41 memset(&bus_conf, 0,
sizeof(bus_conf));
42 bus_conf.sda_io_num = gpio_num_t(
sda_pin_);
43 bus_conf.scl_io_num = gpio_num_t(
scl_pin_);
44 bus_conf.i2c_port = this->
port_;
45 bus_conf.glitch_ignore_cnt = 7;
46#if SOC_LP_I2C_SUPPORTED
47 if (this->
port_ < SOC_HP_I2C_NUM) {
48 bus_conf.clk_source = I2C_CLK_SRC_DEFAULT;
50 bus_conf.lp_source_clk = LP_I2C_SCLK_DEFAULT;
53 bus_conf.clk_source = I2C_CLK_SRC_DEFAULT;
56 esp_err_t err = i2c_new_master_bus(&bus_conf, &this->
bus_);
58 ESP_LOGW(TAG,
"i2c_new_master_bus failed: %s", esp_err_to_name(err));
63 i2c_device_config_t dev_conf{};
64 memset(&dev_conf, 0,
sizeof(dev_conf));
65 dev_conf.dev_addr_length = I2C_ADDR_BIT_LEN_7;
66 dev_conf.device_address = I2C_DEVICE_ADDRESS_NOT_USED;
68 dev_conf.scl_wait_us = this->
timeout_;
69 err = i2c_master_bus_add_device(this->
bus_, &dev_conf, &this->
dev_);
71 ESP_LOGW(TAG,
"i2c_master_bus_add_device failed: %s", esp_err_to_name(err));
79 ESP_LOGV(TAG,
"Scanning for devices");
84 next_port = (next_port == I2C_NUM_0) ? I2C_NUM_1 : I2C_NUM_MAX;
86 next_port = I2C_NUM_MAX;
90 memset(&conf, 0,
sizeof(conf));
91 conf.mode = I2C_MODE_MASTER;
97#ifdef USE_ESP32_VARIANT_ESP32S2
99 conf.clk_flags = I2C_SCLK_SRC_FLAG_AWARE_DFS;
101 esp_err_t err = i2c_param_config(
port_, &conf);
103 ESP_LOGW(TAG,
"i2c_param_config failed: %s", esp_err_to_name(err));
110 ESP_LOGW(TAG,
"i2c_set_timeout failed: %s", esp_err_to_name(err));
114 ESP_LOGV(TAG,
"i2c_timeout set to %" PRIu32
" ticks (%" PRIu32
" us)",
timeout_ * 80,
timeout_);
117 err = i2c_driver_install(
port_, I2C_MODE_MASTER, 0, 0, 0);
119 ESP_LOGW(TAG,
"i2c_driver_install failed: %s", esp_err_to_name(err));
126 ESP_LOGV(TAG,
"Scanning bus for active devices");
133 ESP_LOGCONFIG(TAG,
"I2C Bus:");
137 " Frequency: %" PRIu32
" Hz",
140 ESP_LOGCONFIG(TAG,
" Timeout: %" PRIu32
"us", this->
timeout_);
142 switch (this->recovery_result_) {
144 ESP_LOGCONFIG(TAG,
" Recovery: bus successfully recovered");
147 ESP_LOGCONFIG(TAG,
" Recovery: failed, SCL is held low on the bus");
150 ESP_LOGCONFIG(TAG,
" Recovery: failed, SDA is held low on the bus");
154 ESP_LOGCONFIG(TAG,
"Results from bus scan:");
156 ESP_LOGCONFIG(TAG,
"Found no devices");
160 ESP_LOGCONFIG(TAG,
"Found device at address 0x%02X", s.first);
162 ESP_LOGE(TAG,
"Unknown error at address 0x%02X", s.first);
169#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2)
172 auto err = i2c_master_probe(this->
bus_,
address, 20);
184 ESP_LOGVV(TAG,
"i2c bus not initialized!");
188#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2)
189 i2c_operation_job_t jobs[cnt + 4];
191 size_t last = 0, num = 0;
193 jobs[num].command = I2C_MASTER_CMD_START;
196 jobs[num].command = I2C_MASTER_CMD_WRITE;
197 jobs[num].write.ack_check =
true;
198 jobs[num].write.data = &
read;
199 jobs[num].write.total_bytes = 1;
203 for (
size_t i = 0; i < cnt; i++) {
204 const auto &buf = buffers[i];
211 for (
size_t i = 0; i < cnt; i++) {
212 const auto &buf = buffers[i];
220 jobs[num].command = I2C_MASTER_CMD_READ;
221 jobs[num].read.ack_value = I2C_ACK_VAL;
222 jobs[num].read.data = (uint8_t *) buf.data;
223 jobs[num].read.total_bytes = buf.len - 1;
226 jobs[num].command = I2C_MASTER_CMD_READ;
227 jobs[num].read.ack_value = I2C_NACK_VAL;
228 jobs[num].read.data = (uint8_t *) buf.data + buf.len - 1;
229 jobs[num].read.total_bytes = 1;
232 jobs[num].command = I2C_MASTER_CMD_READ;
233 jobs[num].read.ack_value = I2C_ACK_VAL;
234 jobs[num].read.data = (uint8_t *) buf.data;
235 jobs[num].read.total_bytes = buf.len;
240 jobs[num].command = I2C_MASTER_CMD_STOP;
243 esp_err_t err = i2c_master_execute_defined_operations(this->
dev_, jobs, num, 20);
244 if (err == ESP_ERR_INVALID_STATE) {
245 ESP_LOGVV(TAG,
"RX from %02X failed: not acked",
address);
247 }
else if (err == ESP_ERR_TIMEOUT) {
248 ESP_LOGVV(TAG,
"RX from %02X failed: timeout",
address);
250 }
else if (err != ESP_OK) {
251 ESP_LOGVV(TAG,
"RX from %02X failed: %s",
address, esp_err_to_name(err));
255 i2c_cmd_handle_t cmd = i2c_cmd_link_create();
256 esp_err_t err = i2c_master_start(cmd);
258 ESP_LOGVV(TAG,
"RX from %02X master start failed: %s",
address, esp_err_to_name(err));
259 i2c_cmd_link_delete(cmd);
262 err = i2c_master_write_byte(cmd, (
address << 1) | I2C_MASTER_READ,
true);
264 ESP_LOGVV(TAG,
"RX from %02X address write failed: %s",
address, esp_err_to_name(err));
265 i2c_cmd_link_delete(cmd);
268 for (
size_t i = 0; i < cnt; i++) {
269 const auto &buf = buffers[i];
272 err = i2c_master_read(cmd, buf.data, buf.len, i == cnt - 1 ? I2C_MASTER_LAST_NACK : I2C_MASTER_ACK);
274 ESP_LOGVV(TAG,
"RX from %02X data read failed: %s",
address, esp_err_to_name(err));
275 i2c_cmd_link_delete(cmd);
279 err = i2c_master_stop(cmd);
281 ESP_LOGVV(TAG,
"RX from %02X stop failed: %s",
address, esp_err_to_name(err));
282 i2c_cmd_link_delete(cmd);
285 err = i2c_master_cmd_begin(
port_, cmd, 20 / portTICK_PERIOD_MS);
288 i2c_cmd_link_delete(cmd);
289 if (err == ESP_FAIL) {
291 ESP_LOGVV(TAG,
"RX from %02X failed: not acked",
address);
293 }
else if (err == ESP_ERR_TIMEOUT) {
294 ESP_LOGVV(TAG,
"RX from %02X failed: timeout",
address);
296 }
else if (err != ESP_OK) {
297 ESP_LOGVV(TAG,
"RX from %02X failed: %s",
address, esp_err_to_name(err));
302#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
304 std::string debug_hex;
306 for (
size_t i = 0; i < cnt; i++) {
307 const auto &buf = buffers[i];
308 for (
size_t j = 0; j < buf.len; j++) {
309 snprintf(debug_buf,
sizeof(debug_buf),
"%02X", buf.data[j]);
310 debug_hex += debug_buf;
313 ESP_LOGVV(TAG,
"0x%02X RX %s",
address, debug_hex.c_str());
323 ESP_LOGVV(TAG,
"i2c bus not initialized!");
327#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
329 std::string debug_hex;
331 for (
size_t i = 0; i < cnt; i++) {
332 const auto &buf = buffers[i];
333 for (
size_t j = 0; j < buf.len; j++) {
334 snprintf(debug_buf,
sizeof(debug_buf),
"%02X", buf.data[j]);
335 debug_hex += debug_buf;
338 ESP_LOGVV(TAG,
"0x%02X TX %s",
address, debug_hex.c_str());
341#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2)
342 i2c_operation_job_t jobs[cnt + 3];
346 jobs[num].command = I2C_MASTER_CMD_START;
349 jobs[num].command = I2C_MASTER_CMD_WRITE;
350 jobs[num].write.ack_check =
true;
351 jobs[num].write.data = &
write;
352 jobs[num].write.total_bytes = 1;
355 for (
size_t i = 0; i < cnt; i++) {
356 const auto &buf = buffers[i];
360 jobs[num].command = I2C_MASTER_CMD_WRITE;
361 jobs[num].write.ack_check =
true;
362 jobs[num].write.
data = (uint8_t *) buf.data;
363 jobs[num].write.total_bytes = buf.len;
368 jobs[num].command = I2C_MASTER_CMD_STOP;
372 esp_err_t err = i2c_master_execute_defined_operations(this->
dev_, jobs, num, 20);
373 if (err == ESP_ERR_INVALID_STATE) {
374 ESP_LOGVV(TAG,
"TX to %02X failed: not acked",
address);
376 }
else if (err == ESP_ERR_TIMEOUT) {
377 ESP_LOGVV(TAG,
"TX to %02X failed: timeout",
address);
379 }
else if (err != ESP_OK) {
380 ESP_LOGVV(TAG,
"TX to %02X failed: %s",
address, esp_err_to_name(err));
384 i2c_cmd_handle_t cmd = i2c_cmd_link_create();
385 esp_err_t err = i2c_master_start(cmd);
387 ESP_LOGVV(TAG,
"TX to %02X master start failed: %s",
address, esp_err_to_name(err));
388 i2c_cmd_link_delete(cmd);
391 err = i2c_master_write_byte(cmd, (
address << 1) | I2C_MASTER_WRITE,
true);
393 ESP_LOGVV(TAG,
"TX to %02X address write failed: %s",
address, esp_err_to_name(err));
394 i2c_cmd_link_delete(cmd);
397 for (
size_t i = 0; i < cnt; i++) {
398 const auto &buf = buffers[i];
401 err = i2c_master_write(cmd, buf.data, buf.len,
true);
403 ESP_LOGVV(TAG,
"TX to %02X data write failed: %s",
address, esp_err_to_name(err));
404 i2c_cmd_link_delete(cmd);
409 err = i2c_master_stop(cmd);
411 ESP_LOGVV(TAG,
"TX to %02X master stop failed: %s",
address, esp_err_to_name(err));
412 i2c_cmd_link_delete(cmd);
416 err = i2c_master_cmd_begin(
port_, cmd, 20 / portTICK_PERIOD_MS);
417 i2c_cmd_link_delete(cmd);
418 if (err == ESP_FAIL) {
420 ESP_LOGVV(TAG,
"TX to %02X failed: not acked",
address);
422 }
else if (err == ESP_ERR_TIMEOUT) {
423 ESP_LOGVV(TAG,
"TX to %02X failed: timeout",
address);
425 }
else if (err != ESP_OK) {
426 ESP_LOGVV(TAG,
"TX to %02X failed: %s",
address, esp_err_to_name(err));
436void IDFI2CBus::recover_() {
437 ESP_LOGI(TAG,
"Performing bus recovery");
439 const gpio_num_t scl_pin =
static_cast<gpio_num_t
>(
scl_pin_);
440 const gpio_num_t sda_pin =
static_cast<gpio_num_t
>(
sda_pin_);
448 const auto half_period_usec = 7;
451 gpio_set_level(scl_pin, 1);
452 gpio_config_t scl_config{};
453 scl_config.pin_bit_mask = 1ULL <<
scl_pin_;
454 scl_config.mode = GPIO_MODE_INPUT_OUTPUT_OD;
455 scl_config.pull_up_en = GPIO_PULLUP_ENABLE;
456 scl_config.pull_down_en = GPIO_PULLDOWN_DISABLE;
457 scl_config.intr_type = GPIO_INTR_DISABLE;
458 gpio_config(&scl_config);
461 gpio_set_level(sda_pin, 1);
462 gpio_config_t sda_conf{};
463 sda_conf.pin_bit_mask = 1ULL <<
sda_pin_;
464 sda_conf.mode = GPIO_MODE_INPUT_OUTPUT_OD;
465 sda_conf.pull_up_en = GPIO_PULLUP_ENABLE;
466 sda_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
467 sda_conf.intr_type = GPIO_INTR_DISABLE;
468 gpio_config(&sda_conf);
473 if (gpio_get_level(scl_pin) == 0) {
474 ESP_LOGE(TAG,
"Recovery failed: SCL is held LOW on the bus");
486 for (
auto i = 0; i < 9; i++) {
487 gpio_set_level(scl_pin, 0);
489 gpio_set_level(scl_pin, 1);
500 while (wait-- && gpio_get_level(scl_pin) == 0) {
504 if (gpio_get_level(scl_pin) == 0) {
505 ESP_LOGE(TAG,
"Recovery failed: SCL is held LOW during clock pulse cycle");
514 if (gpio_get_level(sda_pin) == 0) {
515 ESP_LOGE(TAG,
"Recovery failed: SDA is held LOW after clock pulse cycle");
532 gpio_set_level(sda_pin, 0);
541 gpio_set_level(sda_pin, 1);
void feed_wdt(uint32_t time=0)
virtual void mark_failed()
Mark this component as failed.
bool scan_
Should we scan ? Can be set in the yaml.
std::vector< std::pair< uint8_t, bool > > scan_results_
array containing scan results
virtual ErrorCode read(uint8_t address, uint8_t *buffer, size_t len)
Creates a ReadBuffer and calls the virtual readv() method to read bytes into this buffer.
virtual ErrorCode write(uint8_t address, const uint8_t *buffer, size_t len)
ErrorCode readv(uint8_t address, ReadBuffer *buffers, size_t cnt) override
i2c_master_bus_handle_t bus_
void dump_config() override
ErrorCode writev(uint8_t address, WriteBuffer *buffers, size_t cnt, bool stop) override
i2c_master_dev_handle_t dev_
ErrorCode
Error codes returned by I2CBus and I2CDevice methods.
@ ERROR_OK
No error found during execution of method.
@ ERROR_TIMEOUT
timeout while waiting to receive bytes
@ ERROR_NOT_ACKNOWLEDGED
I2C bus acknowledgment not received.
@ ERROR_NOT_INITIALIZED
call method to a not initialized bus
@ ERROR_UNKNOWN
miscellaneous I2C error during execution
@ RECOVERY_FAILED_SDA_LOW
@ RECOVERY_FAILED_SCL_LOW
Providing packet encoding functions for exchanging data with a remote host.
void IRAM_ATTR HOT delayMicroseconds(uint32_t us)
Application App
Global storage of Application pointer - only one Application can exist.
the ReadBuffer structure stores a pointer to a read buffer and its length
the WriteBuffer structure stores a pointer to a write buffer and its length
const uint8_t * data
pointer to the write buffer