AnsweredAssumed Answered

baremetal I2C bus lockup

Question asked by Alexander Agudelo on Dec 16, 2015
Latest reply on Jan 7, 2016 by Alexander Agudelo

Hi, I'm working on a bare metal I2C multimaster library for the MKL25Z4 and I'm having issues when trying to enumerate attached devices to the bus.


The process I follow is basically: START --> Write[address] --> STOP. By checking the ACK bit I know if there is a device listening or not.


It works from time to time but on most occasions the bus stays lock with both SDL and SCL lines low:

The picture above shows a device attached "listening" on address 0x03. See how the ACK is issued by the servant device, but the master seems unable to STOP the transmission. This doesn't seem to happen when sending actual data (START -->WRITE[address] --> BYTE[1] --> BYTE[2] --> ... --> STOP).


My Read method:


int read_byte(){
     _i2c_t.i2c->C1 &= ~I2C_C1_TX_MASK;                    // Set RX mode
     _i2c_t.i2c->C1 &= ~I2C_C1_TXAK_MASK;               // Enable ACK
     byte = (_i2c_t.i2c->D & 0xFF);                                   // Read
     wait_for_bit(I2C_S_IICIF_MASK);                              // Wait for the transfer to be over
     _i2c_t.i2c->S |= I2C_S_IICIF_MASK;                        // Clear out the interrupt flag


I'm not using interrupts so the servant device is continuously checking the status register in order to detect a transaction:

if(_i2c.i2c->S & (I2C_S_TCF_MASK | I2C_S_IAAS_MASK | I2C_S_BUSY_MASK | I2C_S_IICIF_MASK)){
// Master sending
while(_i2c_t.i2c->S & I2C_S_BUSY_MASK){  // Keep reading as long as the line is active


I have tried multiple things but the lines always end up locked (low). I even tried enabling the Glitch Filter just in case it was a noise issue, but it didn't work. Lines use 2k2 resistors to VCC.


Also, any advice on how to recover from this? I can detect it using the SMB->SHTF1 and SHTF2 registers, but so far the only way to do it is by hard resetting the chip.


Any help will be appreciated.