I2C frequency in NCS V3.2.0 nrf52833

The device tree configuration rate is inconsistent with the actual rate.
Device Tree Configuration

&i2c0 {

status = "okay";

clock-frequency = <I2C_BITRATE_FAST>; //I2C_BITRATE_STANDARD(100000) 250000 I2C_BITRATE_FAST(400000)

}
Verification via code:

/* Read frequency directly from devicetree properties */

uint32_t freq = DT_PROP(I2C0_NODE, clock_frequency);

LOG_INF("i2c0 ready (freq=%u Hz)", freq);

Output: i2c_drv: i2c0 ready (freq=400000 Hz)
Parents Reply Children
  • You could maybe attach your code (do let me know in case I need to make the case private for this) and I can take a look at it.

    -Priyanka

  • One issue which can cause slower than expected clock rates with i2c is the nRF52833 mistakenly thinking the i2c slave is requesting clock stretching; this can occur by using too-soft drive levels on SCL and SDA (S0D1) particularly at 400kHz. Fix - advisable in any case for i2c at 400kHz - by forcing high-drive (H0D1) and ensuring the pull-up resistance to VDD is low enough, perhaps 4k7 or less. If the i2c slave is on a single bus and never requests a clock stretch, H0H1 can be used.

    The trace waveforms captured are very misleading as they are on a digital logic analyser; using an oscilloscope would show that SCL in particular is very soggy with a slow rise- and fall-time; it is this slow rise & fall which makes the nRF52833 think the clock is being externally held low for a time (which is interpreted as a clock stretch) and sharpening up those clock edges can provide a solution. The longer the i2c SCL connection the worse the problem due to parasitic capacitance.

    /* 重新定义 i2c0_default 和 i2c0_sleep 以覆盖默认引脚 */
    &pinctrl {
    	/* 覆盖默认的 i2c0_default */
    	i2c0_default: i2c0_default {
    		group1 {
    			psels = <NRF_PSEL(TWIM_SDA, 0, 17)>,    /* P0.26 SDA */
    					<NRF_PSEL(TWIM_SCL, 0, 15)>;    /* P0.27 SCL */
    			nordic,drive-mode = <NRF_DRIVE_H0D1>;  // <== add something like this
    		};
    	};
    
    	/* 覆盖默认的 i2c0_sleep */
    	i2c0_sleep: i2c0_sleep {
    		group1 {
    			psels = <NRF_PSEL(TWIM_SDA, 0, 17)>,
    					<NRF_PSEL(TWIM_SCL, 0, 15)>;
    			nordic,drive-mode = <NRF_DRIVE_H0D1>;  // <== add something like this
    			low-power-enable;
    		};
    	};
    };

    Worth checking with a debugger that zephyr stuff doesn't defeat this high-drive setting, and if using 10k pull-ups reduce that to 4k7 or less ..

Related