Re: I²C clock problem
Posted: Thu Jan 24, 2019 10:50 pm
Have you enabled Power Management? The DFS might be the cause of the issue as your i2c_master_read_slave doesnt include pm locks.
Hi,Have you enabled Power Management? The DFS might be the cause of the issue as your i2c_master_read_slave doesnt include pm locks.
Code: Select all
void Initialize_pm_lock()
{
esp_err_t ret;
if((ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 1, "CPU_FREQ_MAX", &pm_lock_handle)) != ESP_OK) {
printf("pm config error %s\n", \
ret == ESP_ERR_INVALID_ARG ? "ESP_ERR_INVALID_ARG" : \
(ret == ESP_ERR_NOT_SUPPORTED ? "ESP_ERR_NOT_SUPPORTED" :\
"ESP_ERR_NO_MEM"));
}
}
esp_err_t i2c_master_read_slave(i2c_port_t i2c_num, uint8_t slave_address, uint8_t registerAddress, uint8_t* data_rd, size_t size)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, slave_address << 1 | I2C_MASTER_WRITE, I2C_ACK_CHECK_EN);
i2c_master_write_byte(cmd, registerAddress, I2C_ACK_CHECK_EN);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, slave_address << 1 | I2C_READ_BIT, I2C_ACK_CHECK_EN);
if (size > 1) {
i2c_master_read(cmd, data_rd, size - 1, I2C_ACK_VAL);
}
i2c_master_read_byte(cmd, data_rd + size - 1, I2C_NACK_VAL);
i2c_master_stop(cmd);
esp_pm_lock_acquire(pm_lock_handle);
esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 100000 / portTICK_RATE_MS);
esp_pm_lock_release(pm_lock_handle);
i2c_cmd_link_delete(cmd);
if(ret != ESP_OK)
ESP_LOGE(TAG, "i2c error: %s", esp_err_to_name(ret));
return ret;
}
The last recordings where made using the modefied i2c_master_clear_bus function. Here is a recording using the orginal master branch:Hi,Have you enabled Power Management? The DFS might be the cause of the issue as your i2c_master_read_slave doesnt include pm locks.
Thanks for your reply!
I have tried your suggestion, both using pm locks and disabled DFS in menuconfig:
The clock looks better now but it still behaves strange and do not communicate with the gauge IC with this frequency.DFS turned on with power locksCode: Select all
void Initialize_pm_lock() { esp_err_t ret; if((ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 1, "CPU_FREQ_MAX", &pm_lock_handle)) != ESP_OK) { printf("pm config error %s\n", \ ret == ESP_ERR_INVALID_ARG ? "ESP_ERR_INVALID_ARG" : \ (ret == ESP_ERR_NOT_SUPPORTED ? "ESP_ERR_NOT_SUPPORTED" :\ "ESP_ERR_NO_MEM")); } } esp_err_t i2c_master_read_slave(i2c_port_t i2c_num, uint8_t slave_address, uint8_t registerAddress, uint8_t* data_rd, size_t size) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, slave_address << 1 | I2C_MASTER_WRITE, I2C_ACK_CHECK_EN); i2c_master_write_byte(cmd, registerAddress, I2C_ACK_CHECK_EN); i2c_master_start(cmd); i2c_master_write_byte(cmd, slave_address << 1 | I2C_READ_BIT, I2C_ACK_CHECK_EN); if (size > 1) { i2c_master_read(cmd, data_rd, size - 1, I2C_ACK_VAL); } i2c_master_read_byte(cmd, data_rd + size - 1, I2C_NACK_VAL); i2c_master_stop(cmd); esp_pm_lock_acquire(pm_lock_handle); esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 100000 / portTICK_RATE_MS); esp_pm_lock_release(pm_lock_handle); i2c_cmd_link_delete(cmd); if(ret != ESP_OK) ESP_LOGE(TAG, "i2c error: %s", esp_err_to_name(ret)); return ret; }
DFS on with power locks 100KHz.png
DFS turned off and without power locks.
DFS off 100KHz.png
If you disabled DFS, you dont need the locks but Ive found DFS saves quite a bit of power, so its best to leave it on in the future (the PM lock should prevent further scl-messing-up-ness when DFS is turned on). I cant tell without a bit more information on the actual timing of your I2C transaction, but it looks like youre encountering the same issue I had talking to a BQ27621 (another TI battery monitor from the BQ35100 you are using). You should try adding this to right after you initialize I2C master:The last recordings where made using the modefied i2c_master_clear_bus function. Here is a recording using the orginal master branch:Hi,Have you enabled Power Management? The DFS might be the cause of the issue as your i2c_master_read_slave doesnt include pm locks.
Thanks for your reply!
I have tried your suggestion, both using pm locks and disabled DFS in menuconfig:
The clock looks better now but it still behaves strange and do not communicate with the gauge IC with this frequency.DFS turned on with power locksCode: Select all
void Initialize_pm_lock() { esp_err_t ret; if((ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 1, "CPU_FREQ_MAX", &pm_lock_handle)) != ESP_OK) { printf("pm config error %s\n", \ ret == ESP_ERR_INVALID_ARG ? "ESP_ERR_INVALID_ARG" : \ (ret == ESP_ERR_NOT_SUPPORTED ? "ESP_ERR_NOT_SUPPORTED" :\ "ESP_ERR_NO_MEM")); } } esp_err_t i2c_master_read_slave(i2c_port_t i2c_num, uint8_t slave_address, uint8_t registerAddress, uint8_t* data_rd, size_t size) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, slave_address << 1 | I2C_MASTER_WRITE, I2C_ACK_CHECK_EN); i2c_master_write_byte(cmd, registerAddress, I2C_ACK_CHECK_EN); i2c_master_start(cmd); i2c_master_write_byte(cmd, slave_address << 1 | I2C_READ_BIT, I2C_ACK_CHECK_EN); if (size > 1) { i2c_master_read(cmd, data_rd, size - 1, I2C_ACK_VAL); } i2c_master_read_byte(cmd, data_rd + size - 1, I2C_NACK_VAL); i2c_master_stop(cmd); esp_pm_lock_acquire(pm_lock_handle); esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 100000 / portTICK_RATE_MS); esp_pm_lock_release(pm_lock_handle); i2c_cmd_link_delete(cmd); if(ret != ESP_OK) ESP_LOGE(TAG, "i2c error: %s", esp_err_to_name(ret)); return ret; }
DFS on with power locks 100KHz.png
DFS turned off and without power locks.
DFS off 100KHz.png
Org master i2c_master_clear_bus DFS on with power locks 100KHz.png
Code: Select all
#define I2C_MASTER_TRANSACTION_TIMEOUT_MS (10)
...
i2c_set_timeout(I2C_MASTER_PORT, I2C_APB_CLK_FREQ * I2C_MASTER_TRANSACTION_TIMEOUT_MS / 1000)Thank you for your reply!If you disabled DFS, you dont need the locks but Ive found DFS saves quite a bit of power, so its best to leave it on in the future (the PM lock should prevent further scl-messing-up-ness when DFS is turned on). I cant tell without a bit more information on the actual timing of your I2C transaction, but it looks like youre encountering the same issue I had talking to a BQ27621 (another TI battery monitor from the BQ35100 you are using). You should try adding this to right after you initialize I2C master:The last recordings where made using the modefied i2c_master_clear_bus function. Here is a recording using the orginal master branch:
Hi,
Thanks for your reply!
I have tried your suggestion, both using pm locks and disabled DFS in menuconfig:
The clock looks better now but it still behaves strange and do not communicate with the gauge IC with this frequency.DFS turned on with power locksCode: Select all
void Initialize_pm_lock() { esp_err_t ret; if((ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 1, "CPU_FREQ_MAX", &pm_lock_handle)) != ESP_OK) { printf("pm config error %s\n", \ ret == ESP_ERR_INVALID_ARG ? "ESP_ERR_INVALID_ARG" : \ (ret == ESP_ERR_NOT_SUPPORTED ? "ESP_ERR_NOT_SUPPORTED" :\ "ESP_ERR_NO_MEM")); } } esp_err_t i2c_master_read_slave(i2c_port_t i2c_num, uint8_t slave_address, uint8_t registerAddress, uint8_t* data_rd, size_t size) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, slave_address << 1 | I2C_MASTER_WRITE, I2C_ACK_CHECK_EN); i2c_master_write_byte(cmd, registerAddress, I2C_ACK_CHECK_EN); i2c_master_start(cmd); i2c_master_write_byte(cmd, slave_address << 1 | I2C_READ_BIT, I2C_ACK_CHECK_EN); if (size > 1) { i2c_master_read(cmd, data_rd, size - 1, I2C_ACK_VAL); } i2c_master_read_byte(cmd, data_rd + size - 1, I2C_NACK_VAL); i2c_master_stop(cmd); esp_pm_lock_acquire(pm_lock_handle); esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 100000 / portTICK_RATE_MS); esp_pm_lock_release(pm_lock_handle); i2c_cmd_link_delete(cmd); if(ret != ESP_OK) ESP_LOGE(TAG, "i2c error: %s", esp_err_to_name(ret)); return ret; }
DFS on with power locks 100KHz.png
DFS turned off and without power locks.
DFS off 100KHz.png
Org master i2c_master_clear_bus DFS on with power locks 100KHz.png
Details can be found here:Code: Select all
#define I2C_MASTER_TRANSACTION_TIMEOUT_MS (10) ... i2c_set_timeout(I2C_MASTER_PORT, I2C_APB_CLK_FREQ * I2C_MASTER_TRANSACTION_TIMEOUT_MS / 1000)
https://www.esp32.com/viewtopic.php?f=13&t=6203#p37174
Hi dragondgold,@persan666 did you find any solution to the problem? I'm using a bq27441 fuel gauge and I'm experiencing the exact same problem, DFS is disabled and I increased the timeout time, I have no errors, just inconsistent clock when using 400 kHz.
