I2C pins into GPIO on PSoC 5LP

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
JiLi_1045506
Level 1
Level 1

Hello, I am having problems with the classic stuck I2C slave problem.  The PSoC 5LP is the master, and if we get a glitch on the bus, the slave get stuck waiting for a clock pulse, and may hold the SDA line low.  The solution is to toggle extra pulses on the SCL pin until the slave I2C slave device is synced back up and releases the SDA pin.

I am am trying to implement this recovery routine, but I am having trouble taking over the SCL pin and using the I2C_SCL_Write() and I2C_SCL_Read() functions.  There must be a register that connects these pins to either the UDB I2C implementation of the FF I2C implementation.  On the PSoC 4 forum, this function is listed as:

CY_SET_REG32(CYREG_HSIOM_PORT_SEL4,  0x00000000);

But CYREG_HSIOM_PORT_SEL4 does not exist on the PSoC 5LP.  Any help with how to do this would be greatly appreciated.

Right now, in an attempt to take over the SCL and SDA IOs, I am using the following code.  The SCL wire remains a constant high, despite calling the I2C_SCL_Write() function:

    va_print("Restarting module attempt %d\r\n", i);

    MI2C_Stop();

    CyDelay(10);

 

    //set IO to GPIO from I2C

    MI2C_SDA_SetDriveMode(MI2C_SDA_DM_DIG_HIZ);

    MI2C_SCL_SetDriveMode(MI2C_SCL_DM_DIG_HIZ);

 

    sdaRead = MI2C_SDA_Read();

    sclRead = MI2C_SCL_Read();

 

    va_print("SDA pin %d, SCL pin %d\r\n", sdaRead, sclRead);

 

    va_print("Toggling SCL\r\n");

 

    MI2C_SCL_SetDriveMode(MI2C_SCL_DM_OD_LO);

    MI2C_SDA_SetDriveMode(MI2C_SCL_DM_OD_LO);

    MI2C_SCL_Write(1);

    MI2C_SDA_Write(1);

    CyDelay(1);

 

    int j;

    for(j = 0; j < 30; j++){

      va_print("Toggling loop %d\r\n", j);

      MI2C_SCL_SetDriveMode(MI2C_SCL_DM_OD_LO);

      MI2C_SDA_SetDriveMode(MI2C_SCL_DM_OD_LO);

      CyDelay(1);

      MI2C_SCL_Write(0);

      CyDelay(1);

      MI2C_SCL_Write(1);

      CyDelay(1);

      MI2C_SCL_SetDriveMode(MI2C_SCL_DM_DIG_HIZ);

      MI2C_SDA_SetDriveMode(MI2C_SCL_DM_DIG_HIZ);

      sdaRead = MI2C_SDA_Read();

      sclRead = MI2C_SCL_Read();

      va_print("SDA pin %d, SCL pin %d\r\n", sdaRead, sclRead);

      if(sdaRead != 0 && sclRead != 0){

        va_print("Toggle recovery good, exiting on toggle loop %d\r\n", j);

        break;

      }

    }

 

    va_print("SDA pin %d, SCL pin %d\r\n", sdaRead, sclRead);

    if(sdaRead != 0 && sclRead != 0){

      va_print("GPIO recovered on attempt %d\r\n", i);

      MI2C_SCL_SetDriveMode(MI2C_SCL_DM_OD_LO);

      MI2C_SDA_SetDriveMode(MI2C_SCL_DM_OD_LO);

      MI2C_SCL_Write(1);

      MI2C_SDA_Write(1);

      MI2C_Init();

      MI2C_Enable();

      CyDelay(10); 

      break;

    }

Someone here must know how to do this!  Any help would be appreciated.

0 Likes
1 Solution
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I think that I did something similar before.

Could you refer to my post below?

PSoC 5LP I2C Bus Reset Sample

Can it be a help?

moto

View solution in original post

0 Likes
1 Reply
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I think that I did something similar before.

Could you refer to my post below?

PSoC 5LP I2C Bus Reset Sample

Can it be a help?

moto

0 Likes