26.6.2.4 I2C Host Operation

The I2C Host is byte-oriented and interrupt based. The number of interrupts generated is kept at a minimum by automatic handling of most incidents. The software driver complexity and code size are reduced by auto-triggering of operations, and a Special Smart mode, which can be enabled by the Smart Mode Enable bit in the Control B register (CTRLB.SMEN).

Host Clock Generation

The SERCOM peripheral supports several I2C bidirectional modes:
  • Standard mode (Sm) up to 100 kHz
  • Fast mode (Fm) up to 400 kHz
The Host clock configuration for Sm and Fm are described as follows:

Clock Generation (Standard-Mode, Fast-Mode, and Fast-Mode Plus)

In I2C Sm and Fm mode, the Host clock (SCL) frequency is determined as described in this section:

The low (TLOW) and high (THIGH) times are determined by the Baud Rate register (BAUD), while the rise (TRISE) and fall (TFALL) times are determined by the bus topology. Because of the wired-AND logic of the bus, TFALL will be considered as part of TLOW. Similarly, TRISE will be in a state between TLOW and THIGH until a high state has been detected.

Figure 26-5. SCL Timing
The following parameters are timed using the SCL low time period TLOW. This comes from the Host Baud Rate Low bit group in the Baud Rate register (BAUD.BAUDLOW). When BAUD.BAUDLOW=0, or the Host Baud Rate bit group in the Baud Rate register (BAUD.BAUD) determines it.
  • TLOW – Low period of SCL clock
  • TSU;STO – Set-up time for stop condition
  • TBUF – Bus free time between stop and start conditions
  • THD;STA – Hold time (repeated) start condition
  • TSU;STA – Set-up time for repeated start condition
  • THIGH is timed using the SCL high time count from BAUD.BAUD
  • TRISE is determined by the bus impedance; for internal pull-ups. Refer to Electrical Characteristics.
  • TFALL is determined by the open-drain current limit and bus impedance; can typically be regarded as zero. Refer to Electrical Characteristics for details.

The SCL frequency is given by:

f SCL = 1 T LOW + T HIGH + T RISE

When BAUD.BAUDLOW is zero, the BAUD.BAUD value is used to time both SCL high and SCL low. In this case the following formula will give the SCL frequency:

f SCL = f GCLK 10 + 2 B A U D + f GCLK T RISE

When BAUD.BAUDLOW is non-zero, the following formula determines the SCL frequency:

f SCL = f GCLK 10 + B A U D + B A U D L O W + f GCLK T RISE

The following formulas can determine the SCL TLOW and THIGH times:

T LOW = B A U D L O W + 5 f GCLK

T HIGH = B A U D + 5 f GCLK

Startup Timing The minimum time between SDA transition and SCL rising edge is 6 APB cycles when the DATA register is written in smart mode. If a greater startup time is required due to long rise times, the time between DATA write and IF clear must be controlled by software.
Note: When timing is controlled by user, the Smart Mode cannot be enabled.

Transmitting Address Packets

The I2C Host starts a bus transaction by writing the I2C Client address to ADDR.ADDR and the direction bit, as described in Principle of Operation. If the bus is busy, the I2C Host will wait until the bus becomes idle before continuing the operation. When the bus is idle, the I2C Host will issue a start condition on the bus. The I2C Host will then transmit an address packet using the address written to ADDR.ADDR. After the address packet has been transmitted by the I2C Host, one of four cases will arise according to arbitration and transfer direction.

Case 1: Arbitration lost or bus error during address packet transmission

If arbitration was lost during transmission of the address packet, the Host on Bus bit in the Interrupt Flag Status and Clear register (INTFLAG.MB) and the Arbitration Lost bit in the Status register (STATUS.ARBLOST) are both set. Serial data output to SDA is disabled, and the SCL is released, which disables clock stretching. In effect the I2C Host is no longer allowed to execute any operation on the bus until the bus is idle again. A bus error will behave similarly to the arbitration lost condition. In this case, the MB interrupt flag and Host Bus Error bit in the Status register (STATUS.BUSERR) are both set in addition to STATUS.ARBLOST.

The Host Received Not Acknowledge bit in the Status register (STATUS.RXNACK) will always contain the last successfully received acknowledge or not acknowledge indication.

In this case, software will typically inform the application code of the condition and then clear the interrupt flag before exiting the interrupt routine. No other flags have to be cleared at this moment, because all flags will be cleared automatically the next time the ADDR.ADDR register is written.

Case 2: Address packet transmit complete – No ACK received

If there is no I2C Client device responding to the address packet, then the INTFLAG.MB interrupt flag and STATUS.RXNACK will be set. The clock hold is active at this point, preventing further activity on the bus.

The missing ACK response can indicate that the I2C Client is busy with other tasks or sleeping. Therefore, it is not able to respond. In this event, the next step can be either issuing a stop condition (recommended) or resending the address packet by a repeated start condition. When using SMBus logic, the Client must ACK the address. If there is no response, it means that the Client is not available on the bus.

Case 3: Address packet transmit complete – Write packet, Host on Bus set

If the I2C Host receives an acknowledge response from the I2C Client, INTFLAG.MB will be set and STATUS.RXNACK will be cleared. The clock hold is active at this point, preventing further activity on the bus.

In this case, the software implementation becomes highly protocol dependent. Three possible actions can enable the I2C operation to continue:
  • Initiate a data transmit operation by writing the data byte to be transmitted into DATA.DATA.
  • Transmit a new address packet by writing ADDR.ADDR. A repeated start condition will automatically be inserted before the address packet.
  • Issue a stop condition, consequently terminating the transaction.

Case 4: Address packet transmit complete – Read packet, Client on Bus set

If the I2C Host receives an ACK from the I2C Client, the I2C Host proceeds to receive the next byte of data from the I2C Client. When the first data byte is received, the Client on Bus bit in the Interrupt Flag register (INTFLAG.SB) will be set and STATUS.RXNACK will be cleared. The clock hold is active at this point, preventing further activity on the bus.

In this case, the software implementation becomes highly protocol dependent. Three possible actions can enable the I2C operation to continue:
  • Let the I2C Host continue to read data by acknowledging the data received. ACK can be sent by software, or automatically in smart mode.
  • Transmit a new address packet.
  • Terminate the transaction by issuing a stop condition.
Note: An ACK or NACK will be automatically transmitted if smart mode is enabled. The Acknowledge Action bit in the Control B register (CTRLB.ACKACT) determines whether ACK or NACK should be sent.

Transmitting Data Packets

When an address packet with direction Host Write (see Figure 26-3) was transmitted successfully , INTFLAG.MB will be set. The I2C Host will start transmitting data via the I2C bus by writing to DATA.DATA, and monitor continuously for packet collisions.

If a collision is detected, the I2C Host will lose arbitration and STATUS.ARBLOST will be set. If the transmit was successful, the I2C Host will receive an ACK bit from the I2C Client, and STATUS.RXNACK will be cleared. INTFLAG.MB will be set in both cases, regardless of arbitration outcome.

It is recommended to read STATUS.ARBLOST and handle the arbitration lost condition in the beginning of the I2C Host on Bus interrupt. This can be done as there is no difference between handling address and data packet arbitration.

STATUS.RXNACK must be checked for each data packet transmitted before the next data packet transmission can commence. The I2C Host is not allowed to continue transmitting data packets if a NACK is received from the I2C Client.

Receiving Data Packets

When INTFLAG.SB is set, the I2C Host will already have received one data packet. The I2C Host must respond by sending either an ACK or NACK. Sending a NACK may be unsuccessful when arbitration is lost during the transmission. In this case, a lost arbitration will prevent setting INTFLAG.SB. Instead, INTFLAG.MB will indicate a change in arbitration. Handling of lost arbitration is the same as for data bit transmission.