RTC_I2C SDA sampling

feuerrot
Posts: 2
Joined: Wed Feb 07, 2018 5:22 pm

RTC_I2C SDA sampling

Postby feuerrot » Wed Feb 07, 2018 6:39 pm

Hi everyone,

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
As you can see in the screenshot, this results in an I2C transaction:Image

However R0 doesn't contain the expected data afterwards. According to the note in TRM 29.6.2.1, this should be expected:
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
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:
Image

However, this behaviour does not seem to be I2C compliant, as the specification only guarantees SDA to be valid while SCL is high:
3.1.3: The data on the SDA line must be stable during the HIGH period of the clock
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.

WiFive
Posts: 3529
Joined: Tue Dec 01, 2015 7:35 am

Re: RTC_I2C SDA sampling

Postby WiFive » Thu Feb 08, 2018 8:33 pm

Probably not, you could try the SW i2c https://github.com/tomtor/ulp-i2c or maybe a delay line?

ESP_Sprite
Posts: 9711
Joined: Thu Nov 26, 2015 4:08 am

Re: RTC_I2C SDA sampling

Postby ESP_Sprite » Fri Feb 09, 2018 3:41 am

WiFive unfortunately is correct: the I2C hardware in the ULP samples at the wrong edge. Either using a delay element or software I2C is a possible solution.

ramvij30
Posts: 2
Joined: Fri Aug 31, 2018 9:39 am

Re: RTC_I2C SDA sampling

Postby ramvij30 » Fri Mar 29, 2019 9:43 am

Is it possible to get a complete example of this project for me to try as it's not published as part of the ESP-IDF example?

ESP_Sprite
Posts: 9711
Joined: Thu Nov 26, 2015 4:08 am

Re: RTC_I2C SDA sampling

Postby ESP_Sprite » Sat Mar 30, 2019 7:56 am

I have successfully built off this example before: https://github.com/tomtor/ulp-i2c
Edit: Just saw Wifive also mentioned this.

fededim
Posts: 15
Joined: Sat Apr 11, 2020 8:11 am

Re: RTC_I2C SDA sampling

Postby fededim » Thu Apr 23, 2020 2:46 pm

ESP_Sprite wrote:
Fri Feb 09, 2018 3:41 am
WiFive unfortunately is correct: the I2C hardware in the ULP samples at the wrong edge. Either using a delay element or software I2C is a possible solution.
I do have the same problem with BME280, it reads bad values. What do you mean by using a delay element ?

Who is online

Users browsing this forum: No registered users and 9 guests