I have a problem regarding the usage of I2C from ULP. I'm trying to read from a Bosch BMI160 using the following code:
Code: Select all
init_i2c:
// Use TOUCH3/RTC_GPIO13/GPIO15 as SDA
WRITE_RTC_FIELD(RTC_IO_SAR_I2C_IO_REG, RTC_IO_SAR_I2C_SDA_SEL, 1)
// Use TOUCH2/RTC_GPIO12/GPIO2 as SCL
WRITE_RTC_FIELD(RTC_IO_SAR_I2C_IO_REG, RTC_IO_SAR_I2C_SCL_SEL, 1)
// rtc_gpio_init(GPIO_NUM_2)
WRITE_RTC_FIELD(RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_MUX_SEL, 1)
WRITE_RTC_FIELD(RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_FUN_SEL, 0)
// rtc_gpio_init(GPIO_NUM_15)
WRITE_RTC_FIELD(RTC_IO_TOUCH_PAD3_REG, RTC_IO_TOUCH_PAD3_MUX_SEL, 1)
WRITE_RTC_FIELD(RTC_IO_TOUCH_PAD3_REG, RTC_IO_TOUCH_PAD3_FUN_SEL, 0)
// rtc_gpio_set_level(GPIO_NUM_2, 1);
// RTCIO_GPIO2_CHANNEL == 12, 4096 == 1<<12
WRITE_RTC_FIELD(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS, 4096)
// rtc_gpio_set_level(GPIO_NUM_15, 1);
// RTCIO_GPIO15_CHANNEL == 13, 8192 == 1<<13
WRITE_RTC_FIELD(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS, 8192)
// rtc_gpio_set_direction(GPIO_NUM_2, RTC_GPIO_MODE_INPUT_OUTUT);
// rtc_gpio_output_enable(GPIO_NUM_2)
// RTCIO_GPIO2_CHANNEL == 12, 4096 == 1<<12
WRITE_RTC_FIELD(RTC_GPIO_ENABLE_W1TS_REG, RTC_GPIO_ENABLE_W1TS, 4096)
// rtc_gpio_input_enable(GPIO_NUM_2)
WRITE_RTC_FIELD(RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_FUN_IE, 1)
// rtc_gpio_set_direction(GPIO_NUM_15, RTC_GPIO_MODE_INPUT_OUTUT);
// rtc_gpio_output_enable(GPIO_NUM_15)
// RTCIO_GPIO15_CHANNEL == 13, 8192 == 1<<13
WRITE_RTC_FIELD(RTC_GPIO_ENABLE_W1TS_REG, RTC_GPIO_ENABLE_W1TS, 8192)
// rtc_gpio_input_enable(GPIO_NUM_15)
WRITE_RTC_FIELD(RTC_IO_TOUCH_PAD3_REG, RTC_IO_TOUCH_PAD3_FUN_IE, 1)
// magic???
WRITE_RTC_FIELD(RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_FUN_SEL, 3)
WRITE_RTC_FIELD(RTC_IO_TOUCH_PAD3_REG, RTC_IO_TOUCH_PAD3_FUN_SEL, 3)
// Disable Pulldown on Touch2 and Touch3
WRITE_RTC_FIELD(RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_RDE, 0)
WRITE_RTC_FIELD(RTC_IO_TOUCH_PAD3_REG, RTC_IO_TOUCH_PAD3_RDE, 0)
// Enable Pullup on Touch2 and Touch3
WRITE_RTC_FIELD(RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_RUE, 1)
WRITE_RTC_FIELD(RTC_IO_TOUCH_PAD3_REG, RTC_IO_TOUCH_PAD3_RUE, 1)
// Set slave address 0
WRITE_RTC_FIELD(SENS_SAR_SLAVE_ADDR1_REG, SENS_I2C_SLAVE_ADDR0, 0x69)
// initialization as described in TRM 29.6.1
// Set SCL low/high period
WRITE_RTC_FIELD(RTC_I2C_SCL_LOW_PERIOD_REG, RTC_I2C_SCL_LOW_PERIOD, 40)
WRITE_RTC_FIELD(RTC_I2C_SCL_HIGH_PERIOD_REG, RTC_I2C_SCL_HIGH_PERIOD, 40)
// Set cycles between SDA switch and SCL falling edge
WRITE_RTC_FIELD(RTC_I2C_SDA_DUTY_REG, RTC_I2C_SDA_DUTY, 16)
// Set waiting time after start condition
WRITE_RTC_FIELD(RTC_I2C_SCL_START_PERIOD_REG, RTC_I2C_SCL_START_PERIOD, 30)
// Set waiting time before end condition
WRITE_RTC_FIELD(RTC_I2C_SCL_STOP_PERIOD_REG, RTC_I2C_SCL_STOP_PERIOD, 44)
// Set transaction timeout
WRITE_RTC_FIELD(RTC_I2C_TIMEOUT_REG, RTC_I2C_TIMEOUT, 200)
// Enable master mode
WRITE_RTC_FIELD(RTC_I2C_CTRL_REG, RTC_I2C_MS_MODE, 1)
init_imu:
I2C_RD 0x00, 7, 0, 0
However R0 doesn't contain the expected data afterwards. According to the note in TRM 29.6.2.1, this should be expected:
Zooming into the trace reveals that the BMI160 changes SDA at most 0.2μs after the falling edge of SCL, which is likely the reason why R0 contains incorrect data:The RTC_I2C peripheral samples the SDA signals on the falling edge of SCL. If the slave changes SDA in less
than 0.38 microseconds, the master will receive incorrect data
However, this behaviour does not seem to be I2C compliant, as the specification only guarantees SDA to be valid while SCL is high:
Is it possible to change the RTC_I2C behaviour so that it only samples between the rising and falling edge of SCL? If it isn't this seems to be a bug in the RTC I2C implementation.3.1.3: The data on the SDA line must be stable during the HIGH period of the clock