I2C

Macros

I2C_OFFSET_0
0x205000
I2C_OFFSET_1
0x804000

The BCM2835/6/7 has three BSC (I2C) controllers, from which only one is connected to the I2C pins. The older Pis (where the last four digits of the revision number are less than 0004) have BSC0 connected to the pins, all the other BSC1. The configure script tries to read the /proc/cpuinfo file, which includes the revision number, and than defines USE_I2C_BUS_0 accordingly. See Installation

I2C_SIZE

This macro holds the size of the I2C registers which needs to be mapped. It has the value 0x18

I2C_FIFO_SIZE I2C_C_I2CEN I2C_C_ST I2C_C_CLEAR I2C_C_READ I2C_S_RXS I2C_S_TXD I2C_S_DONE

Registers

volatile uint32_t *i2c_base_ptr

This pointer points, when mapped, to the base of the I2C registers.

struct i2c_register_map

This struct maps the registers of the BSC controller. The names of the struct members correspond to the registers from the Datasheet:

struct i2c_register_map {
    uint32_t C;
    uint32_t S;
    uint32_t DLEN;
    uint32_t A;
    uint32_t FIFO;
    uint32_t DIV;
    uint32_t DEL;
    uint32_t CLKT;
};
I2C
#define I2C ((volatile struct i2c_register_map *)i2c_base_ptr)

By using this macro, the registers of the I2C can be accessed like this I2C->FIFO.

Structs

i2c_config_t

This struct is used to configure the I2C controller:

typedef struct {
    uint8_t addr: 7;
    uint16_t div;
    uint16_t clkstr;
} i2c_config_t;
uint8_t addr: 7

This member holds the address of the I2C device that should be contacted. I2C addresses have a length of seven bits.

uint16_t div

This member sets the clock divider for the BSC controller.

Note

The clock source is the core clock with a frequency, according to the Datasheet, of 150 MHz and according to this file and other sources of 250 MHz. When I tested the clock speed of I2C and SPI with a logic analyzer, it seems that 250 MHz is correct (at least for the Raspberry Pi Zero I use).

uint16_t clkstr

This member sets the clock stretch timeout (or delay). This means that the master will wait clkstr cycles after the rising clock edge for the slave to respond. After this the timeout flag is set.

Functions

uint32_t * i2c_map(void)

This function maps the I2C registers. It calls peripheral_map() with the values I2C_OFFSET and I2C_SIZE. I2C_OFFSET is defined in i2c.c.

void i2c_unmap(void)

This function unmaps the I2C registers.

void i2c_configure(i2c_config_t *config)

This function configures the BSC controller with the i2c_config_t pointed to by config.

void i2c_start(void)

Starts the BSC controller and clears the flag register.

void i2c_stop(void)

Disables the BSC controller.

void i2c_write_byte(uint8_t byte)

Write a byte of data.

uint8_t i2c_read_byte(void)

This function receives a byte of data and returns it.

void i2c_write_data(const uint8_t *data, uint16_t length)

This function writes length bytes of data pointed to by data.

void i2c_read_data(uint8_t *data, uint16_t length)

This function receives length bytes of data and writes them to the array data.

void i2c_write_register(uint8_t reg, uint8_t data)

This function writes to bytes of data. First reg and then data.

Note

You cannot use two calls to i2c_write_byte() instead of this function because this is only one transmission, while two times i2c_write_byte() would be two different transmissons.

uint8_t i2c_read_register(uint8_t reg)

In contrast to i2c_write_register() you can use a call to i2c_write_byte() and to i2c_read_byte(). This is because I2C needs to make two transmissions anyway to change the read / write bit.