I2C Driver for Linux Based Embedded System

Today Linux is the operating system choice for a wide range of special-purpose electronic devices known as embedded systems. An embedded system is specifically designed to perform a set of designated activities, and it generally uses custom, heterogeneous processors. This makes Linux a flexible operating system capable of running on a variety of architectures, such as ARM and many others.

Linux has highly modular architecture and it facilitates the porting and a lot of efforts are required to build new kernel components to fully support the target platform. A big part of these efforts are in developing the low-level interfaces commonly referred to as device drivers. A device driver is a piece of software designed to direct control a specific hardware resource using an hardware-independent well defined interface.

The kernel I2C subsystem is divided into Buses and Devices, and then further buses into Algorithms and Adapters, and devices into Drivers and Clients.

Algorithms
An Algorithm performs the reading and writing of I2C messages to the hardware, this may involve bit banging GPIO lines or writing to an I2C controller chip. An Algorithm is represented by the structure i2c_algorithm and allows you to define function pointers to functions that can write I2C messages (master_xfer) or SMBus messages (smbus_xfer).

Adapters
An Adapter represents a bus which is used to tie up a particular I2C/SMBus with an algorithm and bus number. It is represented by the structure i2c_adapter. If you imagine a system where there are many I2C buses – perhaps two controlled by a controller chip and one bit-banged – then you would expect to see 3 instances of an i2c_adapter and 2 instances of an i2c_algorithm.

Clients
A Client represents a chip (slave) on the I2C/SMBus such as a Touchscreen, RTC or ADC-DAC peripheral and is represented by a structure i2c_client. This includes various members such as chip address, name and pointers to the adapter and driver.

Drivers
A driver, represented by a structure i2c_driver represents the device driver for a particular class of I2C/SMBus slave devices. The structure contains a bunch of function pointers like probe and remove pointers.

linux_i2c_subsystem

Linux I2C Subsystem

The I2C core layer and its attendant benefits is an example of how Linux helps portability. For instance, enabling I2C on a new platform requires only to design the hardware-dependent components, namely the bus driver and the client drivers, whereas the core layer needs not to be changed.

Initializing and probing of I2C Client Driver

During initialization the driver registers itself with the I2C core. This is achieved by populating a structure i2c_driver and passing it as argument to the function i2c_add_driver(), as shown in (Listing-1). The structure i2c_driver holds pointers to the probe and remove functions that are executed respectively on device probing and when the device is removed. The id_table member of the structure i2c_driver informs the I2C framework about which slave devices are supported by the driver. In this case the only chip supported is named lis3lv02d. The names of the supported devices are important for binding, as explained next.

1 /* Device and driver names */
2 # define DEVICE_NAME “lis3lv02d”
3
4/* I2C client structure */
5 static struct i2c_device_id lis3lv02d_idtable [] = {
6 { DEVICE_NAME , 0 },
7 {}
8 };
9 MODULE_DEVICE_TABLE (i2c , lis3lv02d_idtable );
10
11 static struct i2c_driver lis3lv02d_driver = {
12 . driver = {
13 . name = DRIVER_NAME
14 },
15 . probe = lis3lv02d_probe ,
16 . remove = __devexit_p ( lis3lv02d_remove ),
17 . id_table = lis3lv02d_idtable ,
18 };
19
20 /* Module init */
21 static int __init lis3lv02d_init ( void )
22 {
23 return i2c_add_driver (& lis3lv02d_driver );
24 }

Listing-1: Registration of the LIS3LV02DL driver.

The binding process consists of associating a device with a driver that can control it. In embedded systems where the number of the I2C bus and the devices connected to it are known for a fact, it is possible to declare in advance the I2C slaves which live on the bus. This is typically done in the board setup file (Listing-2).

The mysoc_platform_init function is executed on board startup and, among other tasks, registers the I2C slave devices by invoking the i2c_register_board_info function with arguments that specify the number of the bus (zero in this case) and the devices connected with it. This is done through an array of structure i2c_board_info(), each item of which specifies the device name and the device address, with the former that must match with the name registered by the driver in order for binding to succeed. In this case structure i2c_board_info holds only one item which corresponds to the LIS3LV02DL inertial sensor.

Since the sensor’s chip has an interrupt line tied to the cpu, the irq member is also specified with the respective IRQ number. By means of another member called platform_data it is possible to define custom data for the driver.

1 /* I2C devices */
2 static struct i2c_board_info mysoc_i2c_devices [] = {
3 {
4 I2C_BOARD_INFO (” lis3lv02d “, 0 x1D ),
5 . irq = MYSOC_GPIO_TO_IRQ (82) ,
6 /* No platform data : use driver defaults */
7 },
8 };
9
10 static void __init mysoc_platform_init ( void )
11 {
12 …
13 /* Register I2C devices on bus #0 */
14 i2c_register_board_info (0, mysoc_i2c_devices ,
15 ARRAY_SIZE ( mysoc_i2c_devices ));
16 …
17 }

Listing 2: Registration of the I2C devices.

During boot the kernel looks for any I2C driver that has registered a matching device name, that is “lis3lv02d”. Upon finding such a driver, the kernel invokes its probe() function passing a pointer to the LIS3LV02DL device as a parameter. This process is called probing. The probe function is responsible for the per-device initialization, that is initializing hardware, allocating resources, and registering the device with any appropriate subsystem.

More in detail, the LIS3LV02DL probe function takes the following actions:

  1. Allocate memory for lis3lv02d_priv private data structure.
  2. Load the device settings.
  3. Identify the LIS3LV02DL chip.
  4. Configure the device hardware.
  5. Create the per-device sysfs nodes.
  6. If the free-fall feature is enabled, request the interrupt and register the IRQ for the free-fall detection.
  7. If the device polling feature is enabled, register the device with the input subsystem.

On successful completion of all the above steps, meaning a successful probing, the device is bound to the driver.

Initializing and probing of I2C Bus Driver

Initializing and probing the dummy MYSOC I2C bus driver is performed in a similar way as for LIS3LV02DL client driver, with the major difference being that the former uses a platform bus. The platform bus requires that any I2C adapter (or equivalently controller), which is controlled by the bus driver, be registered using a platform_device structure. This structure represents the bus adapter and provides information such as the device name, the device resources and the adapter number, to the bus driver.

Usually the registration of the I2C adapters with the platform bus is performed by the board initialization file, as the information needed are highly board specific. Listing-3 shows the part relevant to this matter.

1 /* first bus : i2c0 */
2 static struct platform_device mysoc_i2c_dev0 = {
3 .name = “mysoc_i2c “,
4 .id = 0,
5 . resource = &mysoc_i2c_resources [0] ,
6 . num_resources = 2,
7 . dev = {
8 . platform_data = &mysoc_i2c_dev0_data ,
9 },
10 };
11
12 /* second bus: i2c1 */
13 static struct platform_device mysoc_i2c_dev1 = {
14 . name = “mysoc_i2c”,
15 .id = 1,
16 . resource = &mysoc_i2c_resources [2] ,
17 . num_resources = 2,
18 /* No platform data : use driver defaults */
19 };
20
21 static int __init mysoc_i2c_init ( void )
22 {
23 …
24 platform_device_register (&mysoc_i2c_dev0 );
25 …
26 platform_device_register (&mysoc_i2c_dev1 );
27 …
28 }
29 arch_initcall ( mysoc_i2c_init );

Listing 3: Registration of the I2C platform device with the platform bus.

On the driver’s side, the registration with the platform bus is achieved by populating a structure platform_driver and passing it to the macro module_platform_driver() as argument (Listing-4). The platform bus simply compares the driver.name member against the name of each device, as defined in the platform_device data structure (Listing 3); if they are the same the device matches the driver.

1 # define DRIVER_NAME “mysoc_i2c”
2
3static struct platform_driver mysoc_i2c_driver = {
4 . probe = mysoc_i2c_probe ,
5 . remove = __devexit_p ( mysoc_i2c_remove ),
6 . driver = {
7 . name = DRIVER_NAME ,
8 . owner = THIS_MODULE ,
9 .pm = &mysoc_i2c_pm_ops ,
10 },
11 };
12 module_platform_driver ( mysoc_i2c_driver );

Listing 4: Registration of the I2C platform driver with the platform bus.

As usual, binding a device to a driver involves calling the driver’s probe() function passing a pointer to the device as a parameter.

The sequence of operations performed on probing are the following:

  1. Get the device resource definitions.
  2. Allocate the appropriate memory and remap it to a virtual address for being accessed by the kernel.
  3. Load the device settings.
  4. Configure the device hardware.
  5. Register with the power management system.
  6. Create the per-device sysfs nodes.
  7. Request the interrupt and register the IRQ.
  8. Set up the struct i2c_adapter and register the adapter with the I2C core.

On successful completion of above steps the driver is bounded to the devices representing the two mysoc I2C controllers.

In the Linux I2C subsystem an I2C bus driver consists of an adapter driver and an algorithm driver. This division is to improve the software reuse and to allow portability. An algorithm driver is intended to contain general code that can be used for a whole class of I2C adapters, while each specific adapter driver either depends on one algorithm driver, or includes its own implementation.

However, while having a generic algorithm that works for multiple adapters is suitable for many cases, in embedded systems, where each I2C bus adapter has its own way of interfacing with the processor and the bus, it is usual to develop the adapter driver together with its corresponding algorithm driver. The bus driver registers with the I2C subsystem by using a structure i2c_adapter that is instantiated and initialized by the I2C platform driver’s probe() function, as shown in Listing 5.

The i2c_adapter structure’s algo member is set up to point to a structure i2c_algorithm which in turn holds two pointers:

  • master_xfer points to the function that implements the actual I2C transmit and receive algorithm.
  • functionality points to a function that returns the features supported by the I2C adapter.

To communicate with a client the I2C subsystem offers two class of functions: one for I2C plain communication which includes i2c_master_send(), i2c_master_recv() and i2c_transfer(), and a second one that uses SMBus commands. However, whichever method is used, the data transfer relies on the bus driver’s function pointed to by master_xfer, as the I2C core ultimately calls this function for the actual transfer to take place.

1 /* I2C algorithm structure */
2 static struct i2c_algorithm mysoc_i2c_algo = {
3 . master_xfer = mysoc_i2c_xfer ,
4 . functionality = mysoc_i2c_func ,
5 };
6
7/* Probe function */
8 static int __devinit mysoc_i2c_probe
9 ( struct platform_device * pdev )
10 {
11 …
12 adap = kzalloc ( sizeof ( struct i2c_adapter ),
13 GFP_KERNEL );
14 …
15 adap -> algo = &mysoc_i2c_algo ;
16 …
17 err = i2c_add_numbered_adapter ( adap );
18 …
19 }

Listing 5: Registration of the I2C adapter.

As shown in listing 5, mysoc_i2c_xfer() is the transfer function installed by the I2C bus driver. This function receives an array of messages as argument and processes them in sequence by calling mysoc_i2c_xfer_rd() or mysoc_i2c_xfer_wr() depending on whether the message being processed is marked for read or write. Once all messages have been sent mysoc_i2c_xfer() successfully returns, otherwise, upon detecting a communication error, aborts the transmission and returns an appropriate error code.

Posted in Technical | Tagged , , , | 5 Comments

SPI Driver for Linux Based Embedded System

Today Linux is the operating system choice for a wide range of special-purpose electronic devices known as embedded systems. An embedded system is specifically designed to perform a set of designated activities, and it generally uses custom, heterogeneous processors. This makes Linux a flexible operating system capable of running on a variety of architectures, such as ARM and many others.

Linux has highly modular architecture and it facilitates the porting and a lot of efforts are required to build new kernel components to fully support the target platform. A big part of these efforts are in developing the low-level interfaces commonly referred to as device drivers. A device driver is a piece of software designed to direct control a specific hardware resource using an hardware-independent well defined interface.

The kernel SPI subsystem is divided into Controller Driver and Protocol Drivers.

Controller Driver
A controller driver is represented by the structure spi_master. The driver for an SPI controller manages access to spi slave devices through a queue of spi_message transactions, copying data between CPU memory and an SPI slave device. For each such message it queues, it calls the message’s completion function when the transaction completes.

Protocol Driver
A Protocol driver is represented by the structure spi_driver, they pass messages through the controller driver to communicate with a Slave or Master device on the other side of an SPI link. For example one protocol driver might talk to the MTD layer to export data to file systems stored on SPI flash like Data Flash; and others might control audio interfaces, present touchscreen sensors as input interfaces, or monitor temperature and voltage levels during industrial processing. And those might all be sharing the same controller driver.

Initializing and probing of SPI Controller Driver

For embedded System-on-Chip (SOC) based boards, SPI master controllers connect to their drivers using some non SPI bus, such as the platform bus. Initializing and probing SPI controller driver is performed using the platform bus. During the initial stage of platform driver registration stage of probe() in that code includes calling spi_alloc_master which allocated the structure spi_master in the kernel and during final stage calling spi_register_master() to hook up to this SPI bus glue.

SPI controller’s will usually be platform devices, and the controller may need some platform_data in order to operate properly. The “struct platform_device” will include resources like the physical address of the controller’s first register and its IRQ.

Platforms will often abstract the “register SPI controller” operation,maybe coupling it with code to initialize pin configurations in the board initialization files. This is because most SOCs have several SPI-capable controllers, and only the ones actually usable on a given board should normally be set up and registered.

1 /* spi bus : spi0 */
2 static struct platform_device mysoc_spi_dev0 = {
3 .name = “mysoc_spi”,
4 .id = 0,
5 . resource = &mysoc_spi_resources [0] ,
6 . num_resources = 2,
7 . dev = {
8 . platform_data = &mysoc_spi_dev0_data ,
9 },
10 };
11
21 static int __init mysoc_spi_init ( void )
22 {
23 …
24 platform_device_register (&mysoc_spi_dev0 );
25 …
28 }
29

Listing 1: Registration of the SPI platform device with the platform bus.

On the driver’s side, the registration with the platform bus is achieved by populating a structure platform_driver and passing it to the macro module_platform_driver() as argument (Listing-2). The platform bus simply compares the driver.name member against the name of each device, as defined in the platform_device data structure (Listing 1); if they are the same the device matches the platform driver.

1 # define DRIVER_NAME “mysoc_spi”
2
3 static struct platform_driver mysoc_spi_driver = {
4 .probe = mysoc_spi_probe ,
5 .remove = mysoc_spi_remove,
6 .driver = {
7 .name = DRIVER_NAME ,
8 .owner = THIS_MODULE ,
9 .pm = &mysoc_spi_pm_ops ,
10 },
11 };
12 module_platform_driver ( mysoc_spi_driver );

Listing 2: Registration of the SPI platform driver with the platform bus.

As usual, binding a device to a driver involves calling the driver’s probe() function passing a pointer to the device as a parameter. The SPI controller driver registers with the SPI subsystem by using a structure spi_master that is instantiated and initialized by the SPI platform driver’s probe() function, as shown in Listing 3.

The sequence of operations performed on probing are the following:

  1. Get the device resource definitions.
  2. Allocate the appropriate memory and remap it to a virtual address for being accessed by the kernel.
  3. Load the device settings.
  4. Configure the device hardware.
  5. Register with the power management system.
  6. Create the per-device sysfs nodes.
  7. Request the interrupt and register the IRQ.
  8. Set up the struct spi_master and register the master controller driver with the SPI core.

On successful completion of above steps the driver is bounded to the devices representing the mysoc SPI controllers.

1 /* Probe function */
2 static int mysoc_spi_probe ( struct platform_device * pdev )
3 {
4 …
5 struct spi_master *master;
6 …
7 /* Allocate master */
8 master = spi_alloc_master(&pdev->dev, sizeof(struct spi_master));
9 …
10 /* Register with the SPI framework */
11 status = spi_register_master(master);
12 …
14 }

Listing 3: Registration of the SPI Controller Driver.

Then it will scan the platform data to find the SPI devices connected to this SPI bus. The function scan_boardinfo() scans the platform data, and call spi_new_device() to create SPI device data structure, and set up struct spi_device based on the platform information. Then it calls the master’s setup() method to further initialize, link the struct spi_device with struct spi_master, and add the SPI device to the system. To this point, the SPI master and SPI device are created and added to the system. But it still can’t communicate with the SPI device as no specific driver is installed yet.

Initializing and probing of SPI Protocol Driver

SPI Protocol driver’s deal with the spi chip attached to the SPI controller. These drivers are responsible to send/receive to/from the device. These device drivers expose user-level API (like spidev does) or kernel-level API that can be used by another subsystem. For example, the touch controller chip ADS7846, which is connected to the SPI bus, provides a touch interface and connects to input subsystem to generate input events.

SPI board information is part of the machine-depended code that performs registration of SPI devices with the SPI subsystem. Because SPI devices are usually hardwired to the board and rarely have an ability to enumerate them, they have to be hardcoded in machine board file in the Linux kernel. The board-dependent code does the registration by calling the function spi_register_board_info. It takes two parameters: list of devices connected and the size of this list (Listing-4).

1 /* SPI Device */
2 static struct ads7846_platform_data ads_info = {
3 .vref_delay_usecs = 100,
4 .x_plate_ohms = 580,
5 .y_plate_ohms = 410,
6 };
7 static struct spi_board_info mysoc_spi_devices [] __initdata = {
8 {
9 .modalias = “ads7846”,
10 .platform_data = &ads_info,
11 .mode = SPI_MODE_0,
12 .irq = GPIO_IRQ(31),
13 .max_speed_hz = 120000,
14 .bus_num = 1,
15 .chip_select = 0,
16 },
17 };
18 static void __init mysoc_platform_init ( void )
19 {
20 …
21 /* Register SPI devices on bus #0 */
22 spi_register_board_info (mysoc_spi_devices, ARRAY_SIZE ( mysoc_spi_devices ));
23 …
24 }

Listing 4: Registration of the SPI devices.

During initialization the driver registers itself with the SPI core. This is achieved by populating a structure spi_driver and passing it as argument to the function spi_register_driver(), as shown in Listing-5.

1 static struct spi_driver ads7846_driver = {
2 . driver = {
3 . name = “ads7846”,
4 .owner=THIS_MODULE,
5 },
6 . probe = ads7846_probe ,
7 . remove = ads7846_remove ),
8 };
9
10 /* Module init */
11 static int __init ads7846_init ( void )
12 {
13 return spi_register_driver (& ads7846_driver );
14 }

Listing-5: Registration of the ADS7846 driver.

The structure spi_driver holds pointers to the probe and remove functions that are executed respectively on device probing and when the device is removed. The names of the supported devices are important for binding.

During boot the kernel looks for any SPI driver that has registered a matching device name, that is “ads7846”. Upon finding such a driver, the kernel invokes its probe() function passing a pointer to the ADS7846 device as a parameter. This process is called probing. The probe function is responsible for the per-device initialization, that is initializing hardware, allocating resources, and registering the device with any appropriate subsystem.

More in detail, the ADS7846 probe function takes the following actions:

  1. Allocate memory for spi_transfer and spi_message data structure.
  2. Load the device settings.
  3. Configure the device hardware.
  4. Create the per-device sysfs nodes.
  5. If the device interrupt feature is enabled, request the interrupt and register the IRQ.
  6. If the device polling feature is enabled, register the device with the input subsystem.

On successful completion of all the above steps, meaning a successful probing, the device is bound to the driver.

Posted in Technical | Tagged , , , | 4 Comments

SPI Protocol

SPI_single_slaveThe Serial Peripheral Interface or SPI Bus is a four wire master/slave full duplex synchronous bus named by Motorola. Multiple slave devices can be hooked by utilizing chip select lines. It is used for short distance, single master communication, for example in embedded systems, sensors, and SD cards.

The bus is composed of two data pins, one clock pin, and one chip select pin:

  • SCLK – Serial Peripheral Interface Clock Signal (generated by the master) (also referred to as SCK)
  • MOSI – Master Out Slave In data (output from the master)
  • MISO – Master In Slave Out (output from the slave)
  • CS – Chip Select (also referred to as Slave Select (SS))

The SPI bus can operate with a single master device and with one or more slave devices. If a single slave device is used, the SS pin may be fixed to logic low if the slave permits it. Some slaves require a falling edge of the chip select signal to initiate an action, an example is the Maxim MAX1242 ADC, which starts conversion on a high→low transition.

SPI_three_slavesWith multiple slave devices, an independent SS signal is required from the master for each slave device. Most slave devices have tri-state outputs so their MISO signal becomes high impedance (logically disconnected) when the device is not selected. Devices without tri-state outputs cannot share SPI bus segments with other devices; only one such slave could talk to the master, and only its chip select could be activated.

Each slave may operate at different clock frequencies as well as different clock polarities and clock phases with respect to the data. The permutations of polarities and phases are referred to as SPI modes. Before beginning the communication, the bus master first configures the clock and the modes. The master then transmits the logic 0 for the desired chip over the chip select line. If a waiting period is required (such as for analog-to-digital conversion), then the master must wait for at least that period of time before starting to issue clock cycles.

During each SPI clock cycle, a full duplex data transmission occurs:

  • the master sends a bit on the MOSI line;the slave reads it from that same line
  • the slave sends a bit on the MISO line; the master reads it from that same line

SPI_8-bit_circular_transferTransmissions normally involve two shift registers of some given word size, such as eight bits, one in the master and one in the slave; they are connected in a ring. Data is usually shifted out with the most significant bit first, while shifting a new least significant bit into the same register. After that register has been shifted out, the master and slave have exchanged register values. Then each device takes that value and does something with it, such as writing it to memory. If there is more data to exchange, the shift registers are loaded with new data and the process repeats.

Transmissions may involve any number of clock cycles. When there is no more data to be transmitted, the master stops toggling its clock. Normally, it then deselects the slave. Transmissions often consist of 8-bit words. A master can initiate multiple such transmissions if it wishes/needs. However, other word sizes are also common, such as 16-bit words for touchscreen controllers or audio codecs or 12-bit words for many digital-to-analog or analog-to-digital converters. Every slave on the bus that has not been activated using its chip select line must disregard the input clock and MOSI signals, and must not drive MISO. The master must select only one slave at a time.

The timing diagram is shown below. The timing is further described below and applies to both the master and the slave device.
At CPOL=0 the base value of the clock is zero

  • For CPHA=0, data are captured on clock’s rising edge and data is propagated on a falling edge.
  • For CPHA=1, data are captured on clock’s falling edge and data is propagated on a rising edge.

At CPOL=1 the base value of the clock is one (inversion of CPOL=0)

  • For CPHA=0, data are captured on clock’s falling edge and data is propagated on a rising edge.
  • For CPHA=1, data are captured on clock’s rising edge and data is propagated on a falling edge.

SPI_timing_diagramThe data must be stable for a half cycle before the first clock cycle. The MOSI and MISO signals are usually stable (at their reception points) for the half cycle until the next clock transition. SPI master and slave devices may well sample data at different points in that half cycle.

The full-duplex capability makes SPI very simple and efficient for single master/single slave applications. Some devices use the full-duplex mode to implement an efficient, swift data stream for applications such as digital audio, digital signal processing, or telecommunications channels, but most off-the-shelf chips stick to half-duplex request/response protocols.

SPI is used to talk to a variety of peripherals, such as

  • Sensors: temperature, pressure, ADC, touchscreens, video game controllers
  • Control devices: audio codecs, digital potentiometers, DAC
  • Camera lenses: Canon EF lens mount
  • Communications: Ethernet, USB, USART, CAN, IEEE 802.15.4, IEEE 802.11, handheld video games
  • Memory: flash and EEPROM
  • Real-time clocks
  • LCD, sometimes even for managing image data
  • Any MMC or SD card (including SDIO variant)
Posted in Technical | Tagged , , | Leave a comment

I2C Protocol

I²C (Inter-Integrated Circuit) is a master slave, single-ended, serial bus used for attaching low-speed peripherals to computer motherboards and embedded systems. I²C uses only two bidirectional open-drain lines, Serial Data Line (SDA) and Serial Clock Line (SCL), pulled up with resistors. Typical voltages used are +5 V or +3.3 V. The I²C reference design has a 7-bit or a 10-bit address space. Common I²C bus speeds are the 100 kbit/s standard mode, 10 kbit/s low-speed mode, 400 kbit/s Fast mode, 1 Mbit/s Fast mode and 3.4 Mbit/s High Speed mode. The maximum number of nodes is limited by the address space, and also by the total bus capacitance of 400 pF, which restricts practical communication distances.

i2cA sample schematic with one master (a microcontroller), three slave nodes (an ADC, a DAC, and a microcontroller), and pull-up resistors Rp.

The I2C bus has two roles for nodes:

Master and Slave:

  • Master node — node that generates the clock and initiates communication with slaves
  • Slave node — node that receives the clock and responds when addressed by the master

There may be four potential modes of operation for a given bus device, although most devices only use a single role and its two modes:

  • master transmit — master node is sending data to a slave
  • master receive — master node is receiving data from a slave
  • slave transmit — slave node is sending data to the master
  • slave receive — slave node is receiving data from the master

The master is initially in master transmit mode by sending a start bit followed by the 7-bit address of the slave it wishes to communicate with, which is finally followed by a single bit representing whether it wishes to write(0) to or read(1) from the slave.

If the slave exists on the bus then it will respond with an ACK bit (active low for acknowledged) for that address. The master then continues in either transmit or receive mode (according to the read/write bit it sent), and the slave continues in its complementary mode (receive or transmit, respectively).

The address and the data bytes are sent most significant bit first. The start bit is indicated by a high-to-low transition of SDA with SCL high; the stop bit is indicated by a low-to-high transition of SDA with SCL high. All other transitions of SDA take place with SCL low.

If the master wishes to write to the slave then it repeatedly sends a byte with the slave sending an ACK bit. (In this situation, the master is in master transmit mode and the slave is in slave receive mode.)

If the master wishes to read from the slave then it repeatedly receives a byte from the slave, the master sending an ACK bit after every byte but the last one. (In this situation, the master is in master receive mode and the slave is in slave transmit mode.)
The master then either ends transmission with a stop bit, or it may send another START bit if it wishes to retain control of the bus for another transfer (a “combined message”).

Key symbols
S (1 bit) : Start bit
P (1 bit) : Stop bit
R/W (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0.
A, NA (1 bit) : Accept and reverse accept bit.
Addr (7 bits): I2C 7 bit address. Can be expanded as usual to get a 10 bit I2C address.
Comm (8 bits): Command byte, a data byte which often selects a register on the device.
Data (8 bits): A plain data byte.
Count (8 bits): A data byte containing the length of a block operation.
[..]: Data sent by I2C device, as opposed to data sent by the host adapter.

Simple send transaction
This corresponds to i2c_master_send.
S Addr W [A] Data [A] Data [A] … [A] Data [A] P

Simple receive transaction
This corresponds to i2c_master_recv.
S Addr R [A] [Data] A [Data] A … A [Data] NA P

i2c data transfer

  1. Data Transfer is initiated with a START bit (S) signaled by SDA being pulled low while SCL stays high.
  2. SDA sets the 1st data bit level while keeping SCL low (during blue bar time.)
  3. The data is sampled (received) when SCL rises (green) for the first bit (B1).
  4. This process repeats, SDA transitioning while SCL is low, and the data being read while SCL is high (B2, Bn).
  5. A STOP bit (P) is signaled when SDA is pulled high while SCL is high.

In order to avoid false marker detection, SDA is changed on the SCL falling edge and is sampled and captured on the rising edge of SCL.

At the physical layer, both SCL and SDA lines are of open-drain design, thus, pull-up resistors are needed. Pulling the line to ground is considered a logical zero while letting the line float is a logical one. This is used as a channel access method. High speed systems (and some others) also add a current source pull up, at least on SCL; this accommodates higher bus capacitance and enables faster rise times. An important consequence of this is that multiple nodes may be driving the lines simultaneously. If any node is driving the line low, it will be low. Nodes that are trying to transmit a logical one (i.e. letting the line float high) can see this, and thereby know that another node is active at the same time.

When used on SCL, this is called clock stretching and gives slaves a flow control mechanism. When used on SDA, this is called arbitration and ensures there is only one transmitter at a time.

When idle, both lines are high. To start a transaction, SDA is pulled low while SCL remains high. Releasing SDA to float high again would be a stop marker, signaling the end of a bus transaction. Although legal, this is typically pointless immediately after a start, so the next step is to pull SCL low.

Except for the start and stop signals, the SDA line only changes while the clock is low; transmitting a data bit consists of pulsing the clock line high while holding the data line steady at the desired level.

While SCL is low, the transmitter (initially the master) sets SDA to the desired value and (after a small delay to let the value propagate) lets SCL float high. The master then waits for SCL to actually go high; this will be delayed by the finite rise-time of the SCL signal (the RC time constant of the pull-up resistor and the parasitic capacitance of the bus), and may be additionally delayed by a slave’s clock stretching.

Once SCL is high, the master waits a minimum time (4 μs for standard speed I²C) to ensure the receiver has seen the bit, then pulls it low again. This completes transmission of one bit.

After every 8 data bits in one direction, an “acknowledge” bit is transmitted in the other direction. The transmitter and receiver switch roles for one bit and the erstwhile receiver transmits a single 0 bit (ACK) back. If the transmitter sees a 1 bit (NACK) instead, it learns that:

  • (If master transmitting to slave) The slave is unable to accept the data. No such slave, command not understood, or unable to accept any more data.
  • (If slave transmitting to master) The master wishes the transfer to stop after this data byte.

During the acknowledgment, SCL is always controlled by the master.

After the acknowledge bit, the master may do one of three things:

  • Prepare to transfer another byte of data: the transmitter set SDA, and the master pulses SCL high.
  • Send a “Stop”: Set SDA low, let SCL go high, then let SDA go high. This releases the I²C bus.
  • Send a “Repeated start”: Set SDA high, let SCL go high, and pull SDA low again. This starts a new I²C bus transaction without releasing the bus.

One of the more significant features of the I²C protocol is clock stretching. An addressed slave device may hold the clock line (SCL) low after receiving (or sending) a byte, indicating that it is not yet ready to process more data. The master that is communicating with the slave may not finish the transmission of the current bit, but must wait until the clock line actually goes high. If the slave is clock stretching, the clock line will still be low (because the connections are open-drain). The same is true if a second, slower, master tries to drive the clock at the same time. (If there is more than one master, all but one of them will normally lose arbitration.)

The master must wait until it observes the clock line going high, and an additional minimum time (4 μs for standard 100 kbit/s I²C) before pulling the clock low again.
Although the master may also hold the SCL line low for as long as it desires, the term “clock stretching” is normally used only when slaves do it. Although in theory any clock pulse may be stretched, generally it is the intervals before or after the acknowledgment bit which are used. For example, if the slave is a microcontroller, its I²C interface could stretch the clock after each byte, until the software decides whether to send a positive acknowledgment or a NACK.

Clock stretching is the only time in I²C where the slave drives SCL. Many slaves do not need to clock stretch and thus treat SCL as strictly an input with no circuitry to drive it.
I²C is appropriate for peripherals where simplicity and low manufacturing cost are more important than speed. Common applications of the I²C bus are:

  • Reading configuration data from EEPROMs on SDRAM, DDR SDRAM, DDR2 SDRAM memory sticks (DIMM) and other stacked PC boards
  • Accessing low speed DACs and ADCs.
  • Changing contrast, hue, and color balance settings in monitors (Display Data Channel).
  • Changing sound volume in intelligent speakers.
  • Controlling OLED/LCD displays, like in a cellphone.
  • Reading real-time clocks.
  • Turning on and turning off the power supply of system components.
Posted in Technical | Tagged , , | Leave a comment