11#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 3, 0)
12#define SOC_HP_I2C_NUM SOC_I2C_NUM
18static const char *
const TAG =
"i2c.idf";
21 ESP_LOGCONFIG(TAG,
"Running setup");
22 static i2c_port_t next_port = I2C_NUM_0;
25 next_port = (next_port == I2C_NUM_0) ? I2C_NUM_1 : I2C_NUM_MAX;
27 next_port = I2C_NUM_MAX;
30 if (
port_ == I2C_NUM_MAX) {
31 ESP_LOGE(TAG,
"No more than %u buses supported", SOC_HP_I2C_NUM);
39 memset(&conf, 0,
sizeof(conf));
40 conf.mode = I2C_MODE_MASTER;
46#ifdef USE_ESP32_VARIANT_ESP32S2
48 conf.clk_flags = I2C_SCLK_SRC_FLAG_AWARE_DFS;
50 esp_err_t err = i2c_param_config(
port_, &conf);
52 ESP_LOGW(TAG,
"i2c_param_config failed: %s", esp_err_to_name(err));
58 ESP_LOGW(TAG,
"i2c timeout of %" PRIu32
"us greater than max of 13ms on esp-idf, setting to max",
timeout_);
63 ESP_LOGW(TAG,
"i2c_set_timeout failed: %s", esp_err_to_name(err));
67 ESP_LOGV(TAG,
"i2c_timeout set to %" PRIu32
" ticks (%" PRIu32
" us)",
timeout_ * 80,
timeout_);
70 err = i2c_driver_install(
port_, I2C_MODE_MASTER, 0, 0, 0);
72 ESP_LOGW(TAG,
"i2c_driver_install failed: %s", esp_err_to_name(err));
78 ESP_LOGV(TAG,
"Scanning bus for active devices");
83 ESP_LOGCONFIG(TAG,
"I2C Bus:");
87 " Frequency: %" PRIu32
" Hz",
90 ESP_LOGCONFIG(TAG,
" Timeout: %" PRIu32
"us", this->
timeout_);
92 switch (this->recovery_result_) {
94 ESP_LOGCONFIG(TAG,
" Recovery: bus successfully recovered");
97 ESP_LOGCONFIG(TAG,
" Recovery: failed, SCL is held low on the bus");
100 ESP_LOGCONFIG(TAG,
" Recovery: failed, SDA is held low on the bus");
104 ESP_LOGI(TAG,
"Results from bus scan:");
106 ESP_LOGI(TAG,
"Found no devices");
110 ESP_LOGI(TAG,
"Found device at address 0x%02X", s.first);
112 ESP_LOGE(TAG,
"Unknown error at address 0x%02X", s.first);
123 ESP_LOGVV(TAG,
"i2c bus not initialized!");
126 i2c_cmd_handle_t cmd = i2c_cmd_link_create();
127 esp_err_t err = i2c_master_start(cmd);
129 ESP_LOGVV(TAG,
"RX from %02X master start failed: %s",
address, esp_err_to_name(err));
130 i2c_cmd_link_delete(cmd);
133 err = i2c_master_write_byte(cmd, (
address << 1) | I2C_MASTER_READ,
true);
135 ESP_LOGVV(TAG,
"RX from %02X address write failed: %s",
address, esp_err_to_name(err));
136 i2c_cmd_link_delete(cmd);
139 for (
size_t i = 0; i < cnt; i++) {
140 const auto &buf = buffers[i];
143 err = i2c_master_read(cmd, buf.data, buf.len, i == cnt - 1 ? I2C_MASTER_LAST_NACK : I2C_MASTER_ACK);
145 ESP_LOGVV(TAG,
"RX from %02X data read failed: %s",
address, esp_err_to_name(err));
146 i2c_cmd_link_delete(cmd);
150 err = i2c_master_stop(cmd);
152 ESP_LOGVV(TAG,
"RX from %02X stop failed: %s",
address, esp_err_to_name(err));
153 i2c_cmd_link_delete(cmd);
156 err = i2c_master_cmd_begin(
port_, cmd, 20 / portTICK_PERIOD_MS);
159 i2c_cmd_link_delete(cmd);
160 if (err == ESP_FAIL) {
162 ESP_LOGVV(TAG,
"RX from %02X failed: not acked",
address);
164 }
else if (err == ESP_ERR_TIMEOUT) {
165 ESP_LOGVV(TAG,
"RX from %02X failed: timeout",
address);
167 }
else if (err != ESP_OK) {
168 ESP_LOGVV(TAG,
"RX from %02X failed: %s",
address, esp_err_to_name(err));
172#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
174 std::string debug_hex;
176 for (
size_t i = 0; i < cnt; i++) {
177 const auto &buf = buffers[i];
178 for (
size_t j = 0; j < buf.len; j++) {
179 snprintf(debug_buf,
sizeof(debug_buf),
"%02X", buf.data[j]);
180 debug_hex += debug_buf;
183 ESP_LOGVV(TAG,
"0x%02X RX %s",
address, debug_hex.c_str());
192 ESP_LOGVV(TAG,
"i2c bus not initialized!");
196#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
198 std::string debug_hex;
200 for (
size_t i = 0; i < cnt; i++) {
201 const auto &buf = buffers[i];
202 for (
size_t j = 0; j < buf.len; j++) {
203 snprintf(debug_buf,
sizeof(debug_buf),
"%02X", buf.data[j]);
204 debug_hex += debug_buf;
207 ESP_LOGVV(TAG,
"0x%02X TX %s",
address, debug_hex.c_str());
210 i2c_cmd_handle_t cmd = i2c_cmd_link_create();
211 esp_err_t err = i2c_master_start(cmd);
213 ESP_LOGVV(TAG,
"TX to %02X master start failed: %s",
address, esp_err_to_name(err));
214 i2c_cmd_link_delete(cmd);
217 err = i2c_master_write_byte(cmd, (
address << 1) | I2C_MASTER_WRITE,
true);
219 ESP_LOGVV(TAG,
"TX to %02X address write failed: %s",
address, esp_err_to_name(err));
220 i2c_cmd_link_delete(cmd);
223 for (
size_t i = 0; i < cnt; i++) {
224 const auto &buf = buffers[i];
227 err = i2c_master_write(cmd, buf.data, buf.len,
true);
229 ESP_LOGVV(TAG,
"TX to %02X data write failed: %s",
address, esp_err_to_name(err));
230 i2c_cmd_link_delete(cmd);
235 err = i2c_master_stop(cmd);
237 ESP_LOGVV(TAG,
"TX to %02X master stop failed: %s",
address, esp_err_to_name(err));
238 i2c_cmd_link_delete(cmd);
242 err = i2c_master_cmd_begin(
port_, cmd, 20 / portTICK_PERIOD_MS);
243 i2c_cmd_link_delete(cmd);
244 if (err == ESP_FAIL) {
246 ESP_LOGVV(TAG,
"TX to %02X failed: not acked",
address);
248 }
else if (err == ESP_ERR_TIMEOUT) {
249 ESP_LOGVV(TAG,
"TX to %02X failed: timeout",
address);
251 }
else if (err != ESP_OK) {
252 ESP_LOGVV(TAG,
"TX to %02X failed: %s",
address, esp_err_to_name(err));
261void IDFI2CBus::recover_() {
262 ESP_LOGI(TAG,
"Performing bus recovery");
264 const gpio_num_t scl_pin =
static_cast<gpio_num_t
>(
scl_pin_);
265 const gpio_num_t sda_pin =
static_cast<gpio_num_t
>(
sda_pin_);
273 const auto half_period_usec = 7;
276 gpio_set_level(scl_pin, 1);
277 gpio_config_t scl_config{};
278 scl_config.pin_bit_mask = 1ULL <<
scl_pin_;
279 scl_config.mode = GPIO_MODE_INPUT_OUTPUT_OD;
280 scl_config.pull_up_en = GPIO_PULLUP_ENABLE;
281 scl_config.pull_down_en = GPIO_PULLDOWN_DISABLE;
282 scl_config.intr_type = GPIO_INTR_DISABLE;
283 gpio_config(&scl_config);
286 gpio_set_level(sda_pin, 1);
287 gpio_config_t sda_conf{};
288 sda_conf.pin_bit_mask = 1ULL <<
sda_pin_;
289 sda_conf.mode = GPIO_MODE_INPUT_OUTPUT_OD;
290 sda_conf.pull_up_en = GPIO_PULLUP_ENABLE;
291 sda_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
292 sda_conf.intr_type = GPIO_INTR_DISABLE;
293 gpio_config(&sda_conf);
298 if (gpio_get_level(scl_pin) == 0) {
299 ESP_LOGE(TAG,
"Recovery failed: SCL is held LOW on the bus");
311 for (
auto i = 0; i < 9; i++) {
312 gpio_set_level(scl_pin, 0);
314 gpio_set_level(scl_pin, 1);
325 while (wait-- && gpio_get_level(scl_pin) == 0) {
329 if (gpio_get_level(scl_pin) == 0) {
330 ESP_LOGE(TAG,
"Recovery failed: SCL is held LOW during clock pulse cycle");
339 if (gpio_get_level(sda_pin) == 0) {
340 ESP_LOGE(TAG,
"Recovery failed: SDA is held LOW after clock pulse cycle");
357 gpio_set_level(sda_pin, 0);
366 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
void i2c_scan_()
Scans the I2C bus for devices.
ErrorCode readv(uint8_t address, ReadBuffer *buffers, size_t cnt) override
void dump_config() override
ErrorCode writev(uint8_t address, WriteBuffer *buffers, size_t cnt, bool stop) 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
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