I2C Clock on the Giga Only Supports 100khz, 400khz and 1mhz. No intermediate frequencies Supported

While testing the BNO086 with the Arduino Giga I noticed that setting the I2C clock at 400khz would cause the BNO086 to not sent any of reports. Tested with a couple of examples.

Did find that Sparkfun recommended running at a I2c Clock of 350khz instead of 400khz for reliable operation: MCU keeps resetting the sensor · Issue #2 · sparkfun/SparkFun_BNO08x_Arduino_Library · GitHub as a work around.

However if I try any other clock > 100khz or <400khz (specifically I tried 200khz and 350Khz) I get the "red blinking LED of doom". So my guess is that nothing but 100 and 400khz is supported by the giga.

Can someone confirm this - will probably make this a github issue as well.

EDIT: Github issue: I2C Clock Speed issues with BNO086 · Issue #798 · arduino/ArduinoCore-mbed (github.com)

Do you have a Logic Analyzer or oscilloscope to measure the signals ?

Which BNO086 module do you use ? I hope there are pullup resistors on the module.
Can you show a photo with your wiring ?

Using the Sparkfun BNO086: SparkFun VR IMU Breakout - BNO086 (Qwiic) - SEN-22857 - SparkFun Electronics

Yes there are pullups based on the schematic. And 2 the wiring is correct since it does run at 100khz.

Only get the red lights of doom when setting the i2c clock to speeds other than 100khz and 400khz.

The LA wouldn;t wouldnt work anyway if the processor is hanging.

It seems a software/timing issue, but I still wan to be sure that your I2C wires are okay.
The Qwiic connector is wrong, and if also the wires are wrong, then the official I2C standard gives you 10 cm for the total length of the I2C bus.
Page 54, paragraph 7.5 of the official I2C standard: https://www.nxp.com/docs/en/user-guide/UM10204.pdf

Sorry for taking long to answer - was off doing chores :slight_smile: Anyway here is a series a pictures so you can see the connections and wires the red light after loading at 350khz:




and red light at 350khz

Now I checked that at 350khz it works on a Teensy Micromod plus according to the reference issue it works on a ESP32. I can check other boards.

@Koepel
Think the issue may in mbedos - from the i2c_api for the stm

#define I2C_SPEED_FREQ_STANDARD                0U    /* 100 kHz */
#define I2C_SPEED_FREQ_FAST                    1U    /* 400 kHz */
#define I2C_SPEED_FREQ_FAST_PLUS               2U    /* 1 MHz */

This is very similar to how the UNO R4 I2C is setup - intermediate frequencies are not supported only standard, fast and fast_plus which I don't know is supported for the H7.

1 Like

Thank you for the photos, there is nothing wrong with the connections.

That smells indeed like your problem with the R4 all over again: I2C setClock Does not appear to be Standard way to setClock

Can you try the 'I2C_SPEED_FREQ_FAST' as parameter. Can you make an Issue on Github ?

Maybe the BNO086 has troubles with the 400kHz, but it should work with any clock frequency between 100 and 400kHz. I think you don't have to check with other Arduino boards.

A Logic Analyzer can measure the clock and a USB Logic Analyzer can analyze and decode the signals on your computer.
A Raspberry Pi Pico can be turned into a Logic Analyzer, but I have not tried that.
I'm very fond of the LHT00SU1 in combination with sigrok/PulseView. It costs 25 euros. The 5 dollar 24MHz 8 channel Logic Analyzers do work, but the usb connector easily breaks.

Its a bit different. With the R4 it would only accept standard or fast. In this case it does accept the frequency as I will show in a bit.

As I said in post #1, the BNO086 does indeed have a problem at 400Khz that is why they recommend setting the I2C clock at 350khz. Unfortunately the Mbedos does not calculate frequencies dynamically, it only support 100Khz (standard) and 400khz (fast).

Using a Salae8, here are the traces at 100Khz and 400Khz


At 100Khz all is normal and it works (note I2C clock is at 112khz)

400Khz (setClock(400000):wink:


Note the clock is at 471khz and the read commands are seeing NAK being returned.

The issue is that if you reduce the i2c clock to 350000 mbedos crashes!

2 Likes

I could have known from the other topic that you have a Logic Analyzer :wink:

The Giga variant for Mbed: https://github.com/arduino/ArduinoCore-mbed/tree/main/variants/GIGA
The Arduino layer can use all three I2C buses. Do they make use of different logic inside the processor ?
You made an Issue on Github and it is too complex for me.

I wonder if there might be a bug :astonished: :laughing:

I wonder if it would actually work at 400K?

That is your request for 400K returned a clock of 471K or off by almost 18%.

As far as I can see from what I saw in MBedos all three buses use the same logic, i.e., you can only use Standard(100K) or Fast(400K).

Yeah setting the I2C clock is not easy and doubt Mbed will change their logic the way they do it since they are supporting so may different processors.

Thought about it but didnt see a way of setting it without compiling the whole core again - not as easy as it was with the R4. Probably should try something like the mpu9250 at 400K but I already know it will work since that is that will work at higher clocks.

@Koepel and @KurtE

Did a bunch more tracing and testing and I just posted this in the issue I created on github. Seems it should be able to calculate intermediate frequencies:

Doing a trace found the following:
In mbed_config.h calculating the I2C timing from the requested frequency is enabled: #define MBED_CONF_TARGET_I2C_TIMING_VALUE_ALGO 1

Tracing that it appears in ArduinoCore-mbed/cores/arduino/mbed/targets/TARGET_STM/TARGET_STM32H7/i2c_device.h

uint32_t i2c_get_pclk(I2CName i2c);
uint32_t i2c_get_timing(I2CName i2c, uint32_t current_timing, int current_hz, int hz);

#if MBED_CONF_TARGET_I2C_TIMING_VALUE_ALGO
uint32_t i2c_compute_timing(uint32_t clock_src_freq, uint32_t i2c_freq);
void i2c_compute_presc_scldel_sdadel(uint32_t clock_src_freq, uint32_t I2C_speed);
uint32_t i2c_compute_scll_sclh(uint32_t clock_src_freq, uint32_t I2C_speed);
#endif // MBED_CONF_TARGET_I2C_TIMING_VALUE_ALGO

in i2c_device.c for the H7 (targets/TARGET_STM/TARGET_STM32H7/i2c_device.c in the mbedos repo you can see the calculation

so technically it should be calculating the setting for frequency at 350khz.

i2c_device.h is referenced in ArduinoCore-mbed/cores/arduino/mbed/targets/TARGET_STM/stm_i2c_api.h

Not sure if this is associated with this issue on the portenta:

Additional info I did attach a jlink for debugging and all that can confirm is that the red lights of doom happen when setClock(350000) is called which happens in Wire.cpp: master->frequency(freq);

don;t think I can do much more.

2 Likes

Please correct the topic title - I2c clock not 100 MHz, but KHz

Well I lied. Did a bit more digging. Found that for the GIGA:

/*  Define IP version */
#define I2C_IP_VERSION_V2

which is used in the i2c_api.c ( mbed-os/targets/TARGET_STM/i2c_api.c at 3636262ae786ae623451985dd40c7a54c40b9ab1 · arduino/mbed-os (github.com) ) shows that only 100Khz, 400khz and 1Mhz is supported:

    /*  Only predefined timing for below frequencies are supported */
    MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));

    /* Derives I2C timing value with respect to I2C input clock source speed
    and I2C bus frequency requested. "Init.Timing" is passed to this function to
    reduce multiple computation of timing value which there by reduces CPU load.
    */
    handle->Init.Timing = i2c_get_timing(obj_s->i2c, handle->Init.Timing, \
                                         obj_s->current_hz, hz);
    /* Only non-zero timing value is supported */
    MBED_ASSERT(handle->Init.Timing != 0);

    /* hz value is stored for computing timing value next time */
    obj_s->current_hz = hz;
#endif // I2C_IP_VERSION_V2
1 Like

That sucks!

Wonder if they ran into some issue, or simply did not want to take the time to make it work...

EDIT: - Personally I believe that putting asserts into the code, that is distributed in a precompiled static library, with debug information removed, which the only debug information you can get is the red blinking led... Is maybe not the best approach!

1 Like

I agree wholeheartedly. No clue what the error really was until I dug into the code. Had a gut feeling but.... In addition debugger is rather useless with the static library as we both found out.

1 Like