5#include <driver/gpio.h>
18static constexpr size_t I2C_MAX_LOG_BYTES = 32;
21 static i2c_port_t next_hp_port = I2C_NUM_0;
22#if SOC_LP_I2C_SUPPORTED
23 static i2c_port_t next_lp_port = LP_I2C_NUM_0;
27 ESP_LOGW(TAG,
"Using max allowed timeout: 13 ms");
33 i2c_master_bus_config_t bus_conf{};
34 memset(&bus_conf, 0,
sizeof(bus_conf));
35 bus_conf.sda_io_num = gpio_num_t(this->
sda_pin_);
36 bus_conf.scl_io_num = gpio_num_t(this->
scl_pin_);
37 bus_conf.glitch_ignore_cnt = 7;
38#if SOC_LP_I2C_SUPPORTED
40 if ((next_lp_port - LP_I2C_NUM_0) == SOC_LP_I2C_NUM) {
41 ESP_LOGE(TAG,
"No more than %u LP buses supported", SOC_LP_I2C_NUM);
45 this->
port_ = next_lp_port;
46 next_lp_port = (i2c_port_t) (next_lp_port + 1);
47 bus_conf.lp_source_clk = LP_I2C_SCLK_DEFAULT;
50 if (next_hp_port == SOC_HP_I2C_NUM) {
51 ESP_LOGE(TAG,
"No more than %u HP buses supported", SOC_HP_I2C_NUM);
55 this->
port_ = next_hp_port;
56 next_hp_port = (i2c_port_t) (next_hp_port + 1);
57 bus_conf.clk_source = I2C_CLK_SRC_DEFAULT;
58#if SOC_LP_I2C_SUPPORTED
61 bus_conf.i2c_port = this->
port_;
63 esp_err_t err = i2c_new_master_bus(&bus_conf, &this->
bus_);
65 ESP_LOGW(TAG,
"i2c_new_master_bus failed: %s", esp_err_to_name(err));
71 if (this->
dev_ ==
nullptr) {
75#ifdef I2C_PORT_FREQUENCY_COUNT
77 for (
auto &device : this->
devices_) {
78 device.dev = device.frequency == this->
frequency_ ? this->
dev_ : this->add_device_(device.frequency);
79 if (device.dev ==
nullptr) {
89 ESP_LOGV(TAG,
"Scanning for devices");
95 i2c_device_config_t dev_conf{};
96 dev_conf.dev_addr_length = I2C_ADDR_BIT_LEN_7;
97 dev_conf.device_address = I2C_DEVICE_ADDRESS_NOT_USED;
99 dev_conf.scl_wait_us = this->
timeout_;
100 i2c_master_dev_handle_t dev{};
101 const esp_err_t err = i2c_master_bus_add_device(this->
bus_, &dev_conf, &dev);
103 ESP_LOGW(TAG,
"i2c_master_bus_add_device failed: %s", esp_err_to_name(err));
110 ESP_LOGCONFIG(TAG,
"I2C Bus:");
114 " Frequency: %" PRIu32
" Hz",
117 ESP_LOGCONFIG(TAG,
" Timeout: %" PRIu32
"us", this->
timeout_);
119 switch (this->recovery_result_) {
121 ESP_LOGCONFIG(TAG,
" Recovery: bus successfully recovered");
124 ESP_LOGCONFIG(TAG,
" Recovery: failed, SCL is held low on the bus");
127 ESP_LOGCONFIG(TAG,
" Recovery: failed, SDA is held low on the bus");
131 ESP_LOGCONFIG(TAG,
"Results from bus scan:");
133 ESP_LOGCONFIG(TAG,
"Found no devices");
137 ESP_LOGCONFIG(TAG,
"Found device at address 0x%02X", s.first);
139 ESP_LOGE(TAG,
"Unknown error at address 0x%02X", s.first);
151 ESP_LOGW(TAG,
"i2c bus not initialized!");
155 i2c_operation_job_t jobs[8]{};
157 uint8_t write_addr = (
address << 1) | I2C_MASTER_WRITE;
158 uint8_t read_addr = (
address << 1) | I2C_MASTER_READ;
159 ESP_LOGV(TAG,
"Writing %zu bytes, reading %zu bytes", write_count, read_count);
160 if (read_count == 0 && write_count == 0) {
162 ESP_LOGV(TAG,
"0x%02X BUS PROBE",
address);
163 jobs[num_jobs++].command = I2C_MASTER_CMD_START;
164 jobs[num_jobs].command = I2C_MASTER_CMD_WRITE;
165 jobs[num_jobs].write.ack_check =
true;
166 jobs[num_jobs].write.data = &write_addr;
167 jobs[num_jobs++].write.total_bytes = 1;
169 if (write_count != 0) {
170 ESP_LOGV_HEX(TAG, write_buffer, write_count, I2C_MAX_LOG_BYTES,
"0x%02X TX %s",
address);
171 jobs[num_jobs++].command = I2C_MASTER_CMD_START;
172 jobs[num_jobs].command = I2C_MASTER_CMD_WRITE;
173 jobs[num_jobs].write.ack_check =
true;
174 jobs[num_jobs].write.data = &write_addr;
175 jobs[num_jobs++].write.total_bytes = 1;
176 jobs[num_jobs].command = I2C_MASTER_CMD_WRITE;
177 jobs[num_jobs].write.ack_check =
true;
178 jobs[num_jobs].write.data = (uint8_t *) write_buffer;
179 jobs[num_jobs++].write.total_bytes = write_count;
181 if (read_count != 0) {
182 ESP_LOGV(TAG,
"0x%02X RX bytes %zu",
address, read_count);
183 jobs[num_jobs++].command = I2C_MASTER_CMD_START;
184 jobs[num_jobs].command = I2C_MASTER_CMD_WRITE;
185 jobs[num_jobs].write.ack_check =
true;
186 jobs[num_jobs].write.data = &read_addr;
187 jobs[num_jobs++].write.total_bytes = 1;
188 if (read_count > 1) {
189 jobs[num_jobs].command = I2C_MASTER_CMD_READ;
190 jobs[num_jobs].read.ack_value = I2C_ACK_VAL;
191 jobs[num_jobs].read.data = read_buffer;
192 jobs[num_jobs++].read.total_bytes = read_count - 1;
194 jobs[num_jobs].command = I2C_MASTER_CMD_READ;
195 jobs[num_jobs].read.ack_value = I2C_NACK_VAL;
196 jobs[num_jobs].read.data = read_buffer + read_count - 1;
197 jobs[num_jobs++].read.total_bytes = 1;
200 jobs[num_jobs++].command = I2C_MASTER_CMD_STOP;
201 ESP_LOGV(TAG,
"Sending %zu jobs", num_jobs);
202 esp_err_t err = i2c_master_execute_defined_operations(this->
dev_, jobs, num_jobs, 100);
203 if (err == ESP_ERR_INVALID_STATE || err == ESP_ERR_INVALID_RESPONSE) {
204 ESP_LOGV(TAG,
"TX to %02X failed: not acked",
address);
206 }
else if (err == ESP_ERR_TIMEOUT) {
207 ESP_LOGV(TAG,
"TX to %02X failed: timeout",
address);
209 }
else if (err != ESP_OK) {
210 ESP_LOGV(TAG,
"TX to %02X failed: %s",
address, esp_err_to_name(err));
216#ifdef I2C_PORT_FREQUENCY_COUNT
218 for (
const auto &device : this->
devices_) {
223 this->devices_.push_back({
frequency,
nullptr});
235 for (
const auto &device : this->
devices_) {
237 this->
dev_ = device.dev;
249void IDFI2CBus::recover_() {
250 ESP_LOGI(TAG,
"Performing bus recovery");
252 const auto scl_pin =
static_cast<gpio_num_t
>(this->
scl_pin_);
253 const auto sda_pin =
static_cast<gpio_num_t
>(this->
sda_pin_);
261 const auto half_period_usec = 7;
264 gpio_set_level(scl_pin, 1);
265 gpio_config_t scl_config{};
266 scl_config.pin_bit_mask = 1ULL << this->
scl_pin_;
267 scl_config.mode = GPIO_MODE_INPUT_OUTPUT_OD;
268 scl_config.pull_up_en = GPIO_PULLUP_ENABLE;
269 scl_config.pull_down_en = GPIO_PULLDOWN_DISABLE;
270 scl_config.intr_type = GPIO_INTR_DISABLE;
271 gpio_config(&scl_config);
274 gpio_set_level(sda_pin, 1);
275 gpio_config_t sda_conf{};
276 sda_conf.pin_bit_mask = 1ULL << this->
sda_pin_;
277 sda_conf.mode = GPIO_MODE_INPUT_OUTPUT_OD;
278 sda_conf.pull_up_en = GPIO_PULLUP_ENABLE;
279 sda_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
280 sda_conf.intr_type = GPIO_INTR_DISABLE;
281 gpio_config(&sda_conf);
286 if (gpio_get_level(scl_pin) == 0) {
287 ESP_LOGE(TAG,
"Recovery failed: SCL is held LOW on the bus");
299 for (
auto i = 0; i < 9; i++) {
300 gpio_set_level(scl_pin, 0);
302 gpio_set_level(scl_pin, 1);
313 while (wait-- && gpio_get_level(scl_pin) == 0) {
317 if (gpio_get_level(scl_pin) == 0) {
318 ESP_LOGE(TAG,
"Recovery failed: SCL is held LOW during clock pulse cycle");
327 if (gpio_get_level(sda_pin) == 0) {
328 ESP_LOGE(TAG,
"Recovery failed: SDA is held LOW after clock pulse cycle");
345 gpio_set_level(sda_pin, 0);
354 gpio_set_level(sda_pin, 1);
void feed_wdt()
Feed the task watchdog.
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
void i2c_scan_()
Scans the I2C bus for devices.
ErrorCode switch_frequency(uint32_t frequency) override
StaticVector< FrequencyDevice, I2C_PORT_FREQUENCY_COUNT+1 > devices_
i2c_master_bus_handle_t bus_
void add_frequency(uint32_t frequency)
Register a frequency used on the bus so setup() creates its device handle.
void dump_config() override
i2c_master_dev_handle_t dev_
ErrorCode write_readv(uint8_t address, const uint8_t *write_buffer, size_t write_count, uint8_t *read_buffer, size_t read_count) override
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
ESPHOME_LOG_TAG(TAG, "i2c")
void IRAM_ATTR HOT delayMicroseconds(uint32_t us)
Application App
Global storage of Application pointer - only one Application can exist.