SIM_INTERFACE(i2c_link) { void (*register_slave_address)(conf_object_t *i2c_link, conf_object_t *slave, uint32 address, uint32 mask); void (*unregister_slave_address)(conf_object_t *i2c_link, conf_object_t *slave, uint32 address, uint32 mask); void (*register_bridge)(conf_object_t *i2c_link, conf_object_t *bridge); void (*disconnect_device)(conf_object_t *i2c_link, conf_object_t *device); void (*start_request)(conf_object_t *i2c_link, conf_object_t *master, uint32 address); void (*read_request)(conf_object_t *i2c_link, conf_object_t *master); void (*ack_read_request)(conf_object_t *i2c_link, conf_object_t *master, i2c_status_t ack); void (*write_request)(conf_object_t *i2c_link, conf_object_t *master, uint8 value); void (*read_response)(conf_object_t *i2c_link, conf_object_t *slave, uint8 value); void (*ack_read_response)(conf_object_t *i2c_link, conf_object_t *slave); void (*write_response)(conf_object_t *i2c_link, conf_object_t *slave, i2c_status_t status); void (*start_response)(conf_object_t *i2c_link, conf_object_t *slave, i2c_status_t status); void (*stop)(conf_object_t *i2c_link, conf_object_t *master); }; #define I2C_LINK_INTERFACE "i2c_link"
The i2c_link
interface is implemented by the I2C
link. The interface is used by I2C devices to communicate with the
I2C link.
An I2C device implements either the i2c_slave
or the
i2c_master
interface, or both. You don't need to do
anything to connect an I2C master device to a link.
To connect an I2C slave device to an I2C link, call
register_slave_address with an address pattern
consisting of the address and mask
parameters. When there is traffic on the I2C link (as initiated by a
call to the link interface start_request function), the
target address is matched against each registered device by
checking if (target_address ^ device_address) & device_mask
== 0
; i.e., the bits that are set to 1 in the mask indicates
which bits in the address that must match.
There are three different addressing modes defined by this
protocol: 7-bit addressing, General call, and
10-bit addressing. 7-bit addressing is by far the most
common addressing mode, and at the moment the only one supported by
the official i2c_link
device. When 7-bit addressing is
used, the address fits into the lower 8 bits of the
address parameter; in other addressing modes more
than 8 bits can be used, but the addressing mode can always be
deduced from the lower 8 address bits.
In 7-bit addressing mode, the address of an I2C device is encoded
as an even 8-bit number, in the range 0x10
-
0xef
. In other words, address ranges 0x00
-
0x0f
and 0xf0
- 0xff
are reserved for
other addressing modes, and the 7-bit address is defined by bits 7
to 1 (little-endian) of the 8-bit encoded address. Bit 0 is reserved as a
read/write bit for the start_request function, and
should be 0 in both address and 0 in
mask, while bits 8 to 31 should be 0 in
address and 1 in mask.
It is an error to register two I2C slave devices to the same 7-bit address.
Use disconnect_device to completely disconnect an I2C slave device from the I2C link. If you just intend to disable the I2C functionality of the device (without disconnecting the wire), use unregister_slave_address, and use the same address and mask attributes as when the device was registered. An I2C slave device can also remove some part of the address match by unregistering itself with a different mask.
An I2C transfer is initiated by a master I2C device. The I2C device responding to the transfer is called slave. The master starts a transfer by calling the start_request function with address as argument. In 7-bit addressing mode, the address is the 7-bit address plus a read-write bit (read-write = 0 → slave-receive, read-write = 1 → slave-transmit). The read-write bit is the least significant bit. This means that all odd values sent to start function initiates a transfer where the master is requesting data from the slave.
I2C slave devices implement the i2c_slave
interface. The i2c_slave
interface and the
i2c_link
interface have identical
start_request, read_request,
ack_read_request and write_request functions
to transfer data over the link. See the i2c_slave
interface for the definitions of these functions.
I2C master devices implement the i2c_master
interface, which has the functions start_response,
read_response, ack_read_response and
write_response in common with the
i2c_link
interface. The only difference in
definition is that the I2C_status_bus_busy value is not
allowed for the status parameter of
start_response
in the i2c_link
interface, while it is allowed in the i2c_master
interface. The definitions of these functions can be found in the
documentation of the i2c_master
interface.
Here are the steps for a transfer:
In total, an I2C link can be in nine different states:
During a transfer, the actual data is delivered by the write_request and read_response function calls. The data is always delivered one byte at a time.
There are two addressing modes apart from the 7-bit addressing mode described above:
0
and mask =
0xffffffff
. Multiple slave devices can register to the
General call address; calls to start_request and
write_request will be relayed to each registered slave
device. The start_response and
write_response functions in the calling master's
i2c_master
interface will be called when
all slave devices have called the corresponding function
in the i2c_link
interface.
Similarly, the mask parameter should have bit 0 set to 0 and bits 3-7 and 16-31 set to 1.
A transmission from a master to a 10-bit addressed slave must start with a write transaction, which optionally is followed by a read transaction from the same slave. The write transaction is started by a start_request call, whose address parameter is a 16-bit number, composed in the same way as the address parameter of register_slave_address described above, with bit 0 set to 0. After writing the desired number of bytes, a repeated start command can be issued to start the read transaction to the same slave device. The repeated start command is issued by calling start_request, now with an 8-bit address parameter, which consists of the lower 8 bits from the address parameter of the previous start_request call, with bit 0 flipped to 1.
Note that a single call to register_slave_address may only register addresses from one addressing mode; it is an error to supply an address pattern that matches addresses from different addressing modes.
During write operations, ACK bits are sent in the
status parameter of the write_response
functions. During read operations, the master device sends the ACK
bit with the ack_read_request function after the
read_response function has been called by the slave. The
slave should respond with a call to the
ack_read_response function, which is relayed to the
master. The value of the ACK bit controls which functions that are
allowed as the next operation by the master device: If the ACK bit
is 0
(i.e., I2C_status_success
), the next
operation must be a read_request, while ACK = 1
(I2C_status_noack
) means that the next operation
must be stop or a repeated start_request. It
is an error to violate this rule: If the master device's software
attempts to issue a STOP or START condition after a read with
ACK=0, the master device should catch the error and log a
spec_violation
message.
The register_bridge function is used to register a
device that implements the i2c_bridge
interface. The
I2C link device will use the i2c_bridge
interface to
keep the I2C bridge device updated with which slave addresses on
the link that have something registered on them; this is mainly
useful when implementing a bridge between i2c links. For more
information, see the documentation on the i2c_bridge interface.
The disconnect_device function completely disconnects a device (slave, master, bridge or any combination thereof) from the link. The link checks which i2c interfaces the device implements, and cleanly removes all its references to the device. This mainly has following effects:
Hence, disconnect_device an I2C device which has had any kind of interaction with an I2C link, must always use disconnect_device when disconnecting.