Zephyr OS and I2C - bus speed for FAST (400kHz) is actually STANDARD (100kHz)

Hello all, I’ve been using the i2c interface on the hifive1_revb with the zephyr OS (recently synced from master zephyr-v2.2.0-844-g6c2451c5c0a6).

Configuring as I2C_SPEED_FAST - the default in i2c_sifive_init:
i2c_map_dt_bitrate(config->f_bus) returns 2 which is the I2C_SPEED_FAST constant


My understanding of the zephyr os mappings are:

Further, I understand 400kHz is the max for the hifive1_revb. (SiFive please correct if I’m mistaken).

When I capture the SCL (at the default of FAST) I observe ~100kHz.

I have not yet root caused the issue (hoping to get some guidance here), but I have experimented with
i2c_sifive_configure, in particular the line:

from: prescale = (config->f_sys / (i2c_speed * 5U)) - 1;
to: prescale = (config->f_sys / (i2c_speed * 17U)) - 1;

I verified with the oscilloscope that the clock is ~400kHz with the change.


I have seen the FE310-G002, -G003 running much faster than 400 kHz. Good luck.

Good to know it can go faster. The issue with Zephyr is the sifive driver only accepts STANDARD or FAST (rejecting other speeds) and only works at 100kHz when passed the configuration of FAST.


I2C_MODE_MASTER | I2C_SPEED_STANDARD <-- what I was doing wrong

OMFG! I hate getting caught by stuff like this. Silly me for assuming (and quickly skimming and missing the detail in the docs) since MASTER’s field mask didn’t need shifting neither did SPEED.

Nothing to do with FE310 (or the zephyr i2c driver), and totally me stubbing my toe on Zephyr’s inconsistent field macros. IMHO, there should be I2C_*_SET/GET for all the fields, rather than the current situation.

I hope my foolishness helps someone else.


PS: I’ll poke around raising the maximum frequency (as the driver’s maximum is FAST) based on deadcommon’s comment.

I created https://github.com/zephyrproject-rtos/zephyr/pull/23971 if anyone is interested.