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
|
help
|
||||||
The accuracy of the bitbanged UART driver is limited, it is not
|
The accuracy of the bitbanged UART driver is limited, it is not
|
||||||
recommend to increase the value above 19200.
|
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
|
endmenu
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ typedef struct {
|
|||||||
.i2c_pin_cfg.sda_pullup_en = true, \
|
.i2c_pin_cfg.sda_pullup_en = true, \
|
||||||
.i2c_pin_cfg.scl_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. */
|
/* Nominal I2C bus timing parameters for I2C fast mode. Max SCL freq of 400 KHz. */
|
||||||
#define ULP_RISCV_I2C_FAST_MODE_CONFIG() \
|
#define ULP_RISCV_I2C_FAST_MODE_CONFIG() \
|
||||||
.i2c_timing_cfg.scl_low_period = 1.4, \
|
.i2c_timing_cfg.scl_low_period = 1.4, \
|
||||||
@ -59,7 +60,17 @@ typedef struct {
|
|||||||
.i2c_timing_cfg.sda_duty_period = 1, \
|
.i2c_timing_cfg.sda_duty_period = 1, \
|
||||||
.i2c_timing_cfg.scl_start_period = 2, \
|
.i2c_timing_cfg.scl_start_period = 2, \
|
||||||
.i2c_timing_cfg.scl_stop_period = 1.3, \
|
.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. */
|
/* Nominal I2C bus timing parameters for I2C standard mode. Max SCL freq of 100 KHz. */
|
||||||
#define ULP_RISCV_I2C_STANDARD_MODE_CONFIG() \
|
#define ULP_RISCV_I2C_STANDARD_MODE_CONFIG() \
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "soc/rtc_io_reg.h"
|
#include "soc/rtc_io_reg.h"
|
||||||
#include "soc/sens_reg.h"
|
#include "soc/sens_reg.h"
|
||||||
#include "hal/i2c_ll.h"
|
#include "hal/i2c_ll.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#define I2C_CTRL_SLAVE_ADDR_MASK (0xFF << 0)
|
#define I2C_CTRL_SLAVE_ADDR_MASK (0xFF << 0)
|
||||||
#define I2C_CTRL_SLAVE_REG_ADDR_MASK (0xFF << 11)
|
#define I2C_CTRL_SLAVE_REG_ADDR_MASK (0xFF << 11)
|
||||||
@ -30,7 +31,7 @@
|
|||||||
#endif // CONFIG_IDF_TARGET_ESP32S3
|
#endif // CONFIG_IDF_TARGET_ESP32S3
|
||||||
|
|
||||||
/* Read/Write timeout (number of iterationis) */
|
/* 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.
|
* 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
|
((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 status = 0;
|
||||||
uint32_t to = 0;
|
uint32_t to = 0;
|
||||||
|
|
||||||
while (to < timeout) {
|
while (1) {
|
||||||
status = READ_PERI_REG(RTC_I2C_INT_ST_REG);
|
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) ||
|
if ((status & RTC_I2C_TX_DATA_INT_ST) ||
|
||||||
(status & RTC_I2C_RX_DATA_INT_ST)) {
|
(status & RTC_I2C_RX_DATA_INT_ST)) {
|
||||||
return 0;
|
return 0;
|
||||||
/* In case of errors return immidiately */
|
/* In case of error status, break and return -1 */
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
} else if ((status & RTC_I2C_TIMEOUT_INT_ST) ||
|
} else if ((status & RTC_I2C_TIMEOUT_INT_ST) ||
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
@ -88,12 +89,17 @@ static inline int32_t ulp_riscv_i2c_wait_for_interrupt(uint32_t timeout)
|
|||||||
return -1;
|
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++;
|
to++;
|
||||||
}
|
if (to >= ticks_to_wait) {
|
||||||
|
|
||||||
/* If we reach here, it is a timeout error */
|
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ulp_riscv_i2c_master_set_slave_addr(uint8_t slave_addr)
|
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);
|
SET_PERI_REG_MASK(SENS_SAR_I2C_CTRL_REG, SENS_SAR_I2C_START);
|
||||||
|
|
||||||
for (i = 0; i < size; i++) {
|
for (i = 0; i < size; i++) {
|
||||||
/* Poll for RTC I2C Rx Data interrupt bit to be set.
|
/* 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.
|
|
||||||
*/
|
|
||||||
if(!ulp_riscv_i2c_wait_for_interrupt(ULP_RISCV_I2C_RW_TIMEOUT)) {
|
if(!ulp_riscv_i2c_wait_for_interrupt(ULP_RISCV_I2C_RW_TIMEOUT)) {
|
||||||
/* Read the data
|
/* 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);
|
SET_PERI_REG_MASK(SENS_SAR_I2C_CTRL_REG, SENS_SAR_I2C_START);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Poll for RTC I2C Tx Data interrupt bit to be set.
|
/* 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.
|
|
||||||
*/
|
|
||||||
if (!ulp_riscv_i2c_wait_for_interrupt(ULP_RISCV_I2C_RW_TIMEOUT)) {
|
if (!ulp_riscv_i2c_wait_for_interrupt(ULP_RISCV_I2C_RW_TIMEOUT)) {
|
||||||
/* Clear the Tx data interrupt bit */
|
/* Clear the Tx data interrupt bit */
|
||||||
SET_PERI_REG_MASK(RTC_I2C_INT_CLR_REG, RTC_I2C_TX_DATA_INT_CLR);
|
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 "driver/rtc_io.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
static const char *RTCI2C_TAG = "ulp_riscv_i2c";
|
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))
|
#define MICROSEC_TO_RTC_FAST_CLK(period) (period) * ((float)(SOC_CLK_RC_FAST_FREQ_APPROX) / (1000000.0))
|
||||||
|
|
||||||
/* Read/Write timeout (number of iterations)*/
|
/* 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)
|
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
|
#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 status = 0;
|
||||||
uint32_t to = 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);
|
status = READ_PERI_REG(RTC_I2C_INT_ST_REG);
|
||||||
|
|
||||||
/* Return ESP_OK if Tx or Rx data interrupt bits are set. */
|
/* 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;
|
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);
|
vTaskDelay(1);
|
||||||
|
|
||||||
/* Loop timeout. If this expires, we return ESP_ERR_TIMEOUT */
|
|
||||||
to++;
|
to++;
|
||||||
|
if (to >= ticks_to_wait) {
|
||||||
|
ret = ESP_ERR_TIMEOUT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
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);
|
SET_PERI_REG_MASK(SENS_SAR_I2C_CTRL_REG, SENS_SAR_I2C_START);
|
||||||
|
|
||||||
for (i = 0; i < size; i++) {
|
for (i = 0; i < size; i++) {
|
||||||
/* Poll for RTC I2C Rx Data interrupt bit to be set.
|
/* 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.
|
|
||||||
*/
|
|
||||||
ret = ulp_riscv_i2c_wait_for_interrupt(ULP_RISCV_I2C_RW_TIMEOUT);
|
ret = ulp_riscv_i2c_wait_for_interrupt(ULP_RISCV_I2C_RW_TIMEOUT);
|
||||||
|
|
||||||
if (ret == ESP_OK) {
|
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);
|
SET_PERI_REG_MASK(SENS_SAR_I2C_CTRL_REG, SENS_SAR_I2C_START);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Poll for RTC I2C Tx Data interrupt bit to be set.
|
/* 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.
|
|
||||||
*/
|
|
||||||
ret = ulp_riscv_i2c_wait_for_interrupt(ULP_RISCV_I2C_RW_TIMEOUT);
|
ret = ulp_riscv_i2c_wait_for_interrupt(ULP_RISCV_I2C_RW_TIMEOUT);
|
||||||
|
|
||||||
if (ret == ESP_OK) {
|
if (ret == ESP_OK) {
|
||||||
|
Loading…
Reference in New Issue
Block a user