mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/ulp_i2c_timeout_config' into 'master'
ulp-riscv-i2c: Add ULP RISC-V I2C read/write timeout config option Closes IDFGH-9822 See merge request espressif/esp-idf!23470
This commit is contained in:
commit
02d473615d
@ -49,6 +49,19 @@ menu "Ultra Low Power (ULP) Co-processor"
|
||||
help
|
||||
The accuracy of the bitbanged UART driver is limited, it is not
|
||||
recommend to increase the value above 19200.
|
||||
|
||||
config ULP_RISCV_I2C_RW_TIMEOUT
|
||||
int
|
||||
prompt "Set timeout for ULP RISC-V I2C transaction timeout in ticks."
|
||||
default 500
|
||||
range -1 4294967295
|
||||
help
|
||||
Set the ULP RISC-V I2C read/write timeout. Set this value to -1
|
||||
if the ULP RISC-V I2C read and write APIs should wait forever.
|
||||
Please note that the tick rate of the ULP co-processor would be
|
||||
different than the OS tick rate of the main core and therefore
|
||||
can have different timeout value depending on which core the API
|
||||
is invoked on.
|
||||
endmenu
|
||||
|
||||
|
||||
|
@ -52,6 +52,7 @@ typedef struct {
|
||||
.i2c_pin_cfg.sda_pullup_en = true, \
|
||||
.i2c_pin_cfg.scl_pullup_en = true, \
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
/* Nominal I2C bus timing parameters for I2C fast mode. Max SCL freq of 400 KHz. */
|
||||
#define ULP_RISCV_I2C_FAST_MODE_CONFIG() \
|
||||
.i2c_timing_cfg.scl_low_period = 1.4, \
|
||||
@ -59,7 +60,17 @@ typedef struct {
|
||||
.i2c_timing_cfg.sda_duty_period = 1, \
|
||||
.i2c_timing_cfg.scl_start_period = 2, \
|
||||
.i2c_timing_cfg.scl_stop_period = 1.3, \
|
||||
.i2c_timing_cfg.i2c_trans_timeout = 20, \
|
||||
.i2c_timing_cfg.i2c_trans_timeout = 20,
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
/* Nominal I2C bus timing parameters for I2C fast mode. Max SCL freq on S2 is about 233 KHz due to timing constraints. */
|
||||
#define ULP_RISCV_I2C_FAST_MODE_CONFIG() \
|
||||
.i2c_timing_cfg.scl_low_period = 2, \
|
||||
.i2c_timing_cfg.scl_high_period = 0.7, \
|
||||
.i2c_timing_cfg.sda_duty_period = 1.7, \
|
||||
.i2c_timing_cfg.scl_start_period = 2.4, \
|
||||
.i2c_timing_cfg.scl_stop_period = 1.3, \
|
||||
.i2c_timing_cfg.i2c_trans_timeout = 20,
|
||||
#endif
|
||||
|
||||
/* Nominal I2C bus timing parameters for I2C standard mode. Max SCL freq of 100 KHz. */
|
||||
#define ULP_RISCV_I2C_STANDARD_MODE_CONFIG() \
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "soc/rtc_io_reg.h"
|
||||
#include "soc/sens_reg.h"
|
||||
#include "hal/i2c_ll.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define I2C_CTRL_SLAVE_ADDR_MASK (0xFF << 0)
|
||||
#define I2C_CTRL_SLAVE_REG_ADDR_MASK (0xFF << 11)
|
||||
@ -30,7 +31,7 @@
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S3
|
||||
|
||||
/* Read/Write timeout (number of iterationis) */
|
||||
#define ULP_RISCV_I2C_RW_TIMEOUT 500
|
||||
#define ULP_RISCV_I2C_RW_TIMEOUT CONFIG_ULP_RISCV_I2C_RW_TIMEOUT
|
||||
|
||||
/*
|
||||
* The RTC I2C controller follows the I2C command registers to perform read/write operations.
|
||||
@ -65,19 +66,19 @@ static void ulp_riscv_i2c_format_cmd(uint32_t cmd_idx, uint8_t op_code, uint8_t
|
||||
((byte_num & 0xFF) << 0)); // Byte Num
|
||||
}
|
||||
|
||||
static inline int32_t ulp_riscv_i2c_wait_for_interrupt(uint32_t timeout)
|
||||
static inline int32_t ulp_riscv_i2c_wait_for_interrupt(int32_t ticks_to_wait)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
uint32_t to = 0;
|
||||
|
||||
while (to < timeout) {
|
||||
while (1) {
|
||||
status = READ_PERI_REG(RTC_I2C_INT_ST_REG);
|
||||
|
||||
/* Return 0 if Tx or Rx data interrupt bits are set. -1 otherwise */
|
||||
/* Return 0 if Tx or Rx data interrupt bits are set. */
|
||||
if ((status & RTC_I2C_TX_DATA_INT_ST) ||
|
||||
(status & RTC_I2C_RX_DATA_INT_ST)) {
|
||||
return 0;
|
||||
/* In case of errors return immidiately */
|
||||
/* In case of error status, break and return -1 */
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
} else if ((status & RTC_I2C_TIMEOUT_INT_ST) ||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
@ -88,13 +89,18 @@ static inline int32_t ulp_riscv_i2c_wait_for_interrupt(uint32_t timeout)
|
||||
return -1;
|
||||
}
|
||||
|
||||
ulp_riscv_delay_cycles(ULP_RISCV_CYCLES_PER_MS);
|
||||
if (ticks_to_wait > -1) {
|
||||
/* If the ticks_to_wait value is not -1, keep track of ticks and
|
||||
* break from the loop once the timeout is reached.
|
||||
*/
|
||||
ulp_riscv_delay_cycles(1);
|
||||
to++;
|
||||
}
|
||||
|
||||
/* If we reach here, it is a timeout error */
|
||||
if (to >= ticks_to_wait) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ulp_riscv_i2c_master_set_slave_addr(uint8_t slave_addr)
|
||||
{
|
||||
@ -169,10 +175,7 @@ void ulp_riscv_i2c_master_read_from_device(uint8_t *data_rd, size_t size)
|
||||
SET_PERI_REG_MASK(SENS_SAR_I2C_CTRL_REG, SENS_SAR_I2C_START);
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
/* Poll for RTC I2C Rx Data interrupt bit to be set.
|
||||
* Set a loop timeout of 500 msec to bail in case of any driver
|
||||
* and/or hardware errors.
|
||||
*/
|
||||
/* Poll for RTC I2C Rx Data interrupt bit to be set */
|
||||
if(!ulp_riscv_i2c_wait_for_interrupt(ULP_RISCV_I2C_RW_TIMEOUT)) {
|
||||
/* Read the data
|
||||
*
|
||||
@ -253,10 +256,7 @@ void ulp_riscv_i2c_master_write_to_device(uint8_t *data_wr, size_t size)
|
||||
SET_PERI_REG_MASK(SENS_SAR_I2C_CTRL_REG, SENS_SAR_I2C_START);
|
||||
}
|
||||
|
||||
/* Poll for RTC I2C Tx Data interrupt bit to be set.
|
||||
* Set a loop timeout of 500 msec to bail in case of any driver
|
||||
* and/or hardware errors.
|
||||
*/
|
||||
/* Poll for RTC I2C Tx Data interrupt bit to be set */
|
||||
if (!ulp_riscv_i2c_wait_for_interrupt(ULP_RISCV_I2C_RW_TIMEOUT)) {
|
||||
/* Clear the Tx data interrupt bit */
|
||||
SET_PERI_REG_MASK(RTC_I2C_INT_CLR_REG, RTC_I2C_TX_DATA_INT_CLR);
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "driver/rtc_io.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
static const char *RTCI2C_TAG = "ulp_riscv_i2c";
|
||||
|
||||
@ -43,7 +44,7 @@ rtc_io_dev_t *rtc_io_dev = &RTCIO;
|
||||
#define MICROSEC_TO_RTC_FAST_CLK(period) (period) * ((float)(SOC_CLK_RC_FAST_FREQ_APPROX) / (1000000.0))
|
||||
|
||||
/* Read/Write timeout (number of iterations)*/
|
||||
#define ULP_RISCV_I2C_RW_TIMEOUT 500
|
||||
#define ULP_RISCV_I2C_RW_TIMEOUT CONFIG_ULP_RISCV_I2C_RW_TIMEOUT
|
||||
|
||||
static esp_err_t i2c_gpio_is_cfg_valid(gpio_num_t sda_io_num, gpio_num_t scl_io_num)
|
||||
{
|
||||
@ -233,13 +234,13 @@ static void ulp_riscv_i2c_format_cmd(uint32_t cmd_idx, uint8_t op_code, uint8_t
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S2
|
||||
}
|
||||
|
||||
static inline esp_err_t ulp_riscv_i2c_wait_for_interrupt(uint32_t timeout)
|
||||
static inline esp_err_t ulp_riscv_i2c_wait_for_interrupt(int32_t ticks_to_wait)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
uint32_t to = 0;
|
||||
esp_err_t ret = ESP_ERR_TIMEOUT;
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
while (to < timeout) {
|
||||
while (1) {
|
||||
status = READ_PERI_REG(RTC_I2C_INT_ST_REG);
|
||||
|
||||
/* Return ESP_OK if Tx or Rx data interrupt bits are set. */
|
||||
@ -259,10 +260,17 @@ static inline esp_err_t ulp_riscv_i2c_wait_for_interrupt(uint32_t timeout)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ticks_to_wait > -1) {
|
||||
/* If the ticks_to_wait value is not -1, keep track of ticks and
|
||||
* break from the loop once the timeout is reached.
|
||||
*/
|
||||
vTaskDelay(1);
|
||||
|
||||
/* Loop timeout. If this expires, we return ESP_ERR_TIMEOUT */
|
||||
to++;
|
||||
if (to >= ticks_to_wait) {
|
||||
ret = ESP_ERR_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -339,10 +347,7 @@ void ulp_riscv_i2c_master_read_from_device(uint8_t *data_rd, size_t size)
|
||||
SET_PERI_REG_MASK(SENS_SAR_I2C_CTRL_REG, SENS_SAR_I2C_START);
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
/* Poll for RTC I2C Rx Data interrupt bit to be set.
|
||||
* Set a loop timeout of 500 iterations to bail in case of any driver
|
||||
* and/or hardware errors.
|
||||
*/
|
||||
/* Poll for RTC I2C Rx Data interrupt bit to be set */
|
||||
ret = ulp_riscv_i2c_wait_for_interrupt(ULP_RISCV_I2C_RW_TIMEOUT);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
@ -426,10 +431,7 @@ void ulp_riscv_i2c_master_write_to_device(uint8_t *data_wr, size_t size)
|
||||
SET_PERI_REG_MASK(SENS_SAR_I2C_CTRL_REG, SENS_SAR_I2C_START);
|
||||
}
|
||||
|
||||
/* Poll for RTC I2C Tx Data interrupt bit to be set.
|
||||
* Set a loop timeout of 500 iterations to bail in case of any driver
|
||||
* and/or hardware errors.
|
||||
*/
|
||||
/* Poll for RTC I2C Tx Data interrupt bit to be set */
|
||||
ret = ulp_riscv_i2c_wait_for_interrupt(ULP_RISCV_I2C_RW_TIMEOUT);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
|
Loading…
Reference in New Issue
Block a user