1 Reply Latest reply on Mar 8, 2018 3:56 AM by user_24585443

    PSoC4 vs PSoC5 I2C/SMBus question

    user_24585443

      Hello,

       

      I am trying to get an SMBus communication working, but having a strange issue. (I am aware of i2C vs SMBus differences and I use a safe speed of 50 kbps). I am trying to implement a Read Word command (here is a nice application note describing all the details: https://www.nxp.com/docs/en/application-note/AN4471.pdf ), meaning in I2C language: Send START for the device address and WRITE. Send the command (register address). Send REPEATED START and read 3 bytes (word has two bytes and this is followed by a Packet Error Check, PEC).

       

      1) I connected an MLX90614 sensor to an I2C Master (fixed function) component of a PSoC 5LP, CY8C5868AXI-LP035.

      The following code does exactly as described above, works good. (I stripped all the code comments and variables declarations to get to the core of the process I am using. All variables are correctly defined uint8_t variables and for the record, read_bytes_count = 3)

       

          I2C_MasterClearReadBuf();
          
          I2C_MasterSendStart(i2c_device_address, I2C_WRITE);
          I2C_MasterWriteByte(i2c_register_address);
        
          I2C_MasterReadBuf(i2c_device_address, read_buffer, read_bytes_count, (I2C_MODE_REPEAT_START | I2C_MODE_COMPLETE_XFER));   
        
          while (0u == (I2C_MasterStatus() & I2C_MSTAT_RD_CMPLT));
      

       

      2) I tried to port this code to a PSoC 4 device, specifically CY8C4245AXI-483 . A different component is available here, I2C (SCB mode), set as I2C Master (again, 50 kbps).

      The only difference is, that this API introduces timeout for all I2C commands, which I tried to set to 5 ms / 10 ms / 35 ms, without any luck.

      (My component name is I2C, so the API is named I2C_I2C.... , sorry for the confusion.)

       

          I2C_I2CMasterClearReadBuf();
          
          I2C_I2CMasterSendStart(i2c_device_address, I2C_WRITE, I2C_COMMAND_TIMEOUT_MS);
          I2C_I2CMasterWriteByte(i2c_register_address, I2C_COMMAND_TIMEOUT_MS);
      
          I2C_I2CMasterReadBuf(i2c_device_address, read_buffer, read_bytes_count, (I2C_I2C_MODE_REPEAT_START | I2C_I2C_MODE_COMPLETE_XFER));   
        
          while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_RD_CMPLT));
      

       

       

      The same code gets stuck at

      while (0u == (I2C_MasterStatus() & I2C_MSTAT_RD_CMPLT));
      

       

      which leads me to an I2C_MASTER.c generated file:

      uint32 I2C_I2CMasterStatus(void)
      {
          uint32 status;
      
      
          I2C_DisableInt();  /* Lock from interruption */
      
      
          status = (uint32) I2C_mstrStatus;
      
      
          if (I2C_CHECK_I2C_MASTER_ACTIVE)
          {
              /* Add status of master pending transaction: MSTAT_XFER_INP */
              status |= (uint32) I2C_I2C_MSTAT_XFER_INP;
          }
      
      
          I2C_EnableInt();   /* Release lock */
      
      
          return(status);
      }
      

       

      The code infinitely goes into this branch:

              status |= (uint32) I2C_I2C_MSTAT_XFER_INP;
      

       

      Which is very strange, as there is a timeout set both when calling the I2C functions, plus there is a SMBus timeout embedded in the connected sensor.

       

      I connected the bus to a logic analyzer and I got the following: Send START for the device address and WRITE. (ACK) Send the command (register address). (ACK).

      That's it, no buffer read function happens, not even repeated start.

       

      Any idea what to do next?

       

      Thank you for any advice.

      David

        • 1. Re: PSoC4 vs PSoC5 I2C/SMBus question
          user_24585443

          I have just figured out the problem: PSoC4 locks the SCL line in case the mentioned above:

           

              I2C_MasterSendStart(i2c_device_address, I2C_WRITE);
              I2C_MasterWriteByte(i2c_register_address);
          
              I2C_MasterReadBuf(i2c_device_address, read_buffer, read_bytes_count, (I2C_MODE_REPEAT_START | I2C_MODE_COMPLETE_XFER));
          

           

          Which leads to an infinite loop of the I2C state, I2C_MSTAT_XFER_INP - Transfer in progress

           

          I had to change the code to also send the first byte using a buffer technique (and the I2C_MODE_NO_STOP is necessary).

           

              uint8_t *write_buffer;
              write_buffer = &i2c_register_address;
              
              I2C_I2CMasterWriteBuf(i2c_device_address, write_buffer, ONE_BYTE_LENGTH, I2C_I2C_MODE_NO_STOP);
              
              // blocking - waits until master completes a write transfer
              while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT));
               
              I2C_I2CMasterReadBuf(i2c_device_address, read_buffer, read_bytes_count, I2C_I2C_MODE_REPEAT_START);   
            
              // blocking - waits until master completes a read transfer
              while (0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_RD_CMPLT));
          

           

          I also had to remove I2C_MODE_COMPLETE_XFER from the MasterReadBuf parameters.

           

          PSoC4 and PSoC5 use different components and there is a slight difference in the datasheet.

           

          SCB 4.0 on PSoC 4:

           

          I2C Master (fixed function) 3.5 on PSoC 5:

           

          Maybe it is just a wording, but maybe there is a difference in the HW.

           

          #define I2C_I2C_MODE_COMPLETE_XFER     (0x00u)    /* Full transfer with Start and Stop       */
          #define I2C_I2C_MODE_REPEAT_START      (0x01u)    /* Begin with a ReStart instead of a Start */
          #define I2C_I2C_MODE_NO_STOP           (0x02u)    /* Complete the transfer without a Stop    */
          

           

          I would expect it to be 2 bits meaning:

          [bits7:2] not important

          [bit1]: 0 = START, 1 = REPEAT START

          [bit0]: 0 = STOP, 1 = NO STOP

           

          David