Have you tinkered with I2C on 96Boards Carbon - IoT Edition of our 96Boards family through Zephyr RTOS? If yes, then this blog will give you a quick update on the latest change made for I2C. If you haven’t used then this blog will serve you as a good introduction to I2C on Carbon.


Carbon board is the first board to be certified as 96Boards IoT edition compatible. The heart of the Carbon board is STM32F401RE which is a Cortex M4 based microcontroller. For any IoT project, communication is a must have feature. For aiding this purpose another Co- processor is embedded onto the Carbon board which is nRF51822. This is used to provide BLE support for communicating the host, thus making Carbon as a best bet for doing IoT projects. On the software side, this board has Zephyr RTOS support. This blog post will clarify few misconceptions on Zephyr I2C support for Carbon and also provides a quick update over I2C_2 interface.

I2C on Carbon

I2C-Inter Intergrated Circuit is a serial communication protocol for sharing data between master and slave seamlessly. I2C supports multiple bus speed with the below standard ones:

  1. Low speed mode - 10 Kbits/s
  2. Standard mode - 100 Kbits/s
  3. Fast mode - 400 Kbits/s
  4. High speed mode - 3.4 Mbits/s

But the I2C controller can be designed to operate at wide number of frequencies. For the detailed information on I2C, take a look at the official website

Carbon board supports 2 I2C interfaces on-board, I2C_1 and I2C_2 operating at Standard and Fast modes. Both are exposed on the Low Speed expansion header, allowing easy interfacing to the external world. Although the microcontroller supports 3rd I2C interface, it is not exposed on carbon as it got wired to nRF51822 for BLE support.

Ambiguity on I2C pinout

When you look at the Carbon’s Zephyr documentation, you can see two sets of I2C interfaces as below:

  • I2C1_SCL - PB6
  • I2C1_SDA - PB7

  • I2C1_SCL - PB8
  • I2C1_SDA - PB9

Users often gets confused by this (as like me on first time :P) and fails to see the default pinmux section for I2C on the same document. This confusion can lead to connecting the I2C devices to wrong pins. But the Pinmux section clearly says that the Pinmux has been configured for I2C1 on PB6/PB7.

Connecting to the wrong I2C pins often causes the device to hang at Wait for Slave Ack as Carbon will try to establish I2C communcation via PB6/PB7 where no I2C slave device is hooked up.

Okay, now I got the correct pinmap for I2C1 but what should I do for using another I2C1 interface?

Answer to the above question is to modify the default Pinmux code. It can be changed as like the following code:

#ifdef CONFIG_I2C_1
#endif /* CONFIG_I2C_1 */

This will allow the I2C controller present in STM32F401RE to use PB8/PB9 for SCL/SDA.

I2C_2 Update

Since, Carbon supports I2C_2 interface you might want to leverage that also. But, the previous code base would error out while trying to build Zephyr with I2C_2 support enabled for Carbon. Reason for that is the absence of Kconfig mapping for I2C_2 in Zephyr I2C driver. Zephyr expects to have the mapping between Kconfig definitons and driver definitions for using any driver. This mapping is provided by the DTS fixup file for now. Since, there was no mapping for I2C_2 on Carbon before, I’ve added the mapping in this Pull Request.

So now you can build Zephyr for Carbon with I2C_2 support and communicate any slave devices easily :-)

Note: PR has been merged into arm branch of Zephyr, it will be merged into master only during the next release. Please use arm branch for now.


I hope this post has cleared few doubts and provided some information over the Zephyr I2C support for Carbon board. TBH all of the information is supplied with the document itself, we just have to read it thoroughly before working on it :-)