Can not get I2C (SDA) working on mbedOS 6.x with custom nrf52840 board

Hello all,

I am totally lost and desperate with solving an issue that I could not solve in weeks now. Here is how it looks like:

  • custom nrf52840 board (Ebyte E72) with external 32khz crystal
  • no Softdevice used (using mbed Cordio Stack)
  • programmed using P20 of an attached nrf52_DK
  • I2C connected to Port 0 Pin 12 (SDA) and Port 0 Pin 7 (CLK)

On mbedOS5 (up to 5.15.4) all is working perfectly fine. I can connect to the I2C devices attached and communicate properly without any issues. On the logic analyzer the data line as well as the clock are looking nice and clean.

If I now compile the same code for mbedOS 6 (tested all versions .0, .1, .2, .2.1, .3, .4) the code is buidling without any errors but when I am trying to communicate with the I2C devices I can not see any proper signal on the data line.
I have even removed all code related to I2C and started with a very clean I2C example again with the same result - data line does not seem to work on mbedOS6 while on mbedOS5 all is fine.

If anyone of you has any tip what I can try to make it work - I highly appreciate any tip.

THANK YOU!!! (even for reading)

Here is what I have tested so far without success:

  • enabled TWIM in sdkconfig (in mbedOS6 it is disabled)
  • added “device_has”: [“I2C”] to custom_target.json
  • replaced the whole I2C code with the example from mbedOS
  • tried to write/read a single byte from a device without the use of any additional library
  • switching to single-byte API read/write (tip from MultipleMonomials)
  • removing mbedOS 6 and setting up a new project

Here are screenshots from the LA:
mbedOS 6:

mbedOS 6:

mbedOS 5:

Are you using the single byte I2C API (e.g. i2c.start(), i2c.write(data), i2c.stop()), or the entire-transfer (i2c.write(addr, data, len)) API? Whichever one you’re using, try the other one. I ran into a somewhat similar issue once where the single byte i2c API works fine but the transfer API was giving strange behavior similar to what you’re seeing.

1 Like

Hi Jamie,

thank you very much for your response. Indeed I am using the “entire-transfer” API as I need multibyte read/writes for at least two of the connected devices. Anyway I have tried your approach just to see if there is anything on the data line but it seems to be not reacting at all. Not even with single byte write/read.
As mentioned earlier - If I try mbedOS 5 with the same source and same PINs all is fine. Open for any other ideas :slight_smile:

I have found one thing that I could replicated on two devices:

When resetting the device and immediately resetting it again the I2C works for a moment:

  • double reset -> I2C working
  • single reset -> I2C not working

I wonder why a double reset / double pin reset is showing a different behaviour? As far as I remember there is only one reset. Also this still does not explain why the same code compiled with mbedOS5 works well. :slightly_frowning_face: It seems like I2C is somehow in an unknown state.

When I2C seems to work for a moment it also appears to be super slow (debugging printouts from I2C appear very slow). I am currently testing with a frequency of 100khz

Answering my own question/problem:

I was comparing the I2C drivers specific to the nrf52840 in both, mbedOS 5 and 6 and it turned out that mbedOS 6 is introducing an additional check of the I2C pins (line 360 f):

    /* To secure correct signal levels on the pins used by the TWI
    master when the system is in OFF mode, and when the TWI master is
    disabled, these pins must be configured in the GPIO peripheral.

These changes are actually doing a great job in identifying weaknesses of an existing I2C connection. It turned out that on both of my test devices that I usually use to recheck certain behaviors had (rather very minor) issues on the I2C bus. After fixing those hardware issues mbedOS 6.4 is now running nicely!

Hope this helps anyone in the future dealing with similar problems.