Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions Documentation/components/drivers/special/i2c.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,138 @@ I2C Device Drivers
``arch/z80/src/z8/z8_i2c.c``, etc.


=======================
I2C Bit-Bang Driver
=======================

The I2C bit-bang driver provides a software implementation of the I2C
protocol using GPIO pins. This is useful when hardware I2C peripherals
are not available or when additional I2C buses are needed.

Overview
--------

- ``include/nuttx/i2c/i2c_bitbang.h``
Generic upper-half I2C bit-bang driver interface.

- ``drivers/i2c/i2c_bitbang.c``
Generic upper-half implementation that handles the I2C protocol timing.

- Platform-specific lower-half drivers control the GPIO pins (SDA and SCL).

IO Expander-Based I2C Bit-Bang
-------------------------------

A generic lower-half implementation is provided for systems using IO expanders
to control GPIO pins. This eliminates the need for platform-specific code when
implementing I2C bit-bang via IO expander pins.

Configuration
~~~~~~~~~~~~~

- ``CONFIG_I2C_BITBANG`` - Enable I2C bit-bang driver framework
- ``CONFIG_I2C_BITBANG_IOEXPANDER`` - Enable IO expander-based lower-half
(depends on ``CONFIG_IOEXPANDER``)

Header Files
~~~~~~~~~~~~

- ``include/nuttx/i2c/i2c_bitbang_ioexpander.h``
IO expander-based lower-half driver interface.

API
~~~

.. c:function:: FAR struct i2c_master_s *i2c_bitbang_ioexpander_initialize(FAR struct ioexpander_dev_s *ioe, int scl_pin, int sda_pin, int busnum);

Initialize an I2C bit-bang driver using IO expander pins.

:param ioe: Pointer to the IO expander device
:param scl_pin: IO expander pin number for SCL (clock line)
:param sda_pin: IO expander pin number for SDA (data line)
:param busnum: I2C bus number to register (use negative value to skip registration)

:return: Pointer to ``struct i2c_master_s`` on success, NULL on failure

The pins will be configured as open-drain outputs, which is required
for proper I2C operation. If busnum >= 0, the I2C bus is automatically
registered and accessible via standard I2C APIs.

Usage Example
~~~~~~~~~~~~~

.. code-block:: c

#include <nuttx/ioexpander/ioexpander.h>
#include <nuttx/i2c/i2c_bitbang_ioexpander.h>
#include <nuttx/i2c/i2c_master.h>

/* Assume we have an IO expander device */
FAR struct ioexpander_dev_s *ioe = /* ... get IO expander ... */;
FAR struct i2c_master_s *i2c;

/* Initialize I2C bit-bang using IO expander pins 10 (SCL) and 11 (SDA) */
/* Register as I2C bus 0 */
i2c = i2c_bitbang_ioexpander_initialize(ioe, 10, 11, 0);
if (i2c == NULL)
{
/* Initialization failed */
return -1;
}

/* Now use the I2C master device normally */
/* For example, with I2C character driver or directly */

/* If registered (busnum >= 0), can also access via /dev/i2c0 */

Use Cases
~~~~~~~~~

- **GPIO Expansion**: When using I2C or SPI IO expanders for GPIO expansion,
and need to implement additional I2C buses using those expanded pins.

- **Multi-Master Scenarios**: Software bit-bang can be useful in multi-master
configurations where hardware I2C has limitations.

- **Pin Flexibility**: Implement I2C on any GPIO pins, not limited to
hardware I2C peripheral pins.

- **Testing and Debugging**: Use IO expander pins for I2C communication
during prototyping and debugging.

- **Hardware I2C Unavailable**: When hardware I2C peripherals are exhausted
or not available on specific pins.

Features
~~~~~~~~

- Uses standard IO expander API (``IOEXP_WRITEPIN``, ``IOEXP_READPIN``)
- Automatic open-drain configuration
- Supports clock stretching (via pin reading)
- Platform-independent implementation
- Works with any IO expander that implements the standard interface
- Automatic I2C bus registration

Limitations
~~~~~~~~~~~

- Software timing (slower than hardware I2C)
- Timing accuracy depends on system load and IO expander response time
- Limited to standard I2C speeds (fast-mode and high-speed may not be reliable)

Implementation Details
~~~~~~~~~~~~~~~~~~~~~~

The IO expander-based implementation provides these callbacks:

- ``initialize``: Configures SCL and SDA pins as open-drain outputs
- ``set_scl/set_sda``: Controls pin output values
- ``get_scl/get_sda``: Reads current pin states (for clock stretching detection)

The driver automatically manages the IO expander pin states and handles
the bit-bang protocol timing according to I2C specifications.


========================
I2C Slave Device Drivers
========================
Expand Down
5 changes: 5 additions & 0 deletions drivers/i2c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ if(CONFIG_I2C)

if(CONFIG_I2C_BITBANG)
list(APPEND SRCS i2c_bitbang.c)

if(CONFIG_I2C_BITBANG_IOEXPANDER)
list(APPEND SRCS i2c_bitbang_ioexpander.c)
endif()

endif()

if(CONFIG_I2C_SLAVE_DRIVER)
Expand Down
7 changes: 7 additions & 0 deletions drivers/i2c/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ config I2C_BITBANG_CLOCK_STRETCHING
the pin into open-collector mode (master sets SCL high and waits until
slave stops holding it low).

config I2C_BITBANG_IOEXPANDER
bool "Support the ioexpander lower half of i2c bitbang"
default n
depends on IOEXPANDER
---help---
Using ioexpander to control gpio to implement i2c bitbang function.

endif # I2C_BITBANG

config I2C_DRIVER
Expand Down
5 changes: 5 additions & 0 deletions drivers/i2c/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ endif

ifeq ($(CONFIG_I2C_BITBANG),y)
CSRCS += i2c_bitbang.c

ifeq ($(CONFIG_I2C_BITBANG_IOEXPANDER),y)
CSRCS += i2c_bitbang_ioexpander.c
endif

endif

ifeq ($(CONFIG_I2C_SLAVE_DRIVER),y)
Expand Down
Loading
Loading