10 Replies Latest reply on Sep 8, 2016 3:50 AM by gmolnar_1700281

    I2C master read issue

    gmolnar_1700281

      We are working on a project, where we want to manage a Vishay VEML6040 I2C color sensor with a Cypress PSOC4 MCU. We had difficulties to process the results, what we got from the sensor, so I started to debug the issue. At first I tried to communicate the sensor with another master, using a logic pattern generator in bit-banging mode, and the sensor works perfectly.

         

      Then I started to analyze the I2C transfers from Cypress side, and noticed some strange behavior of the MCU. It seem's the bytes from the sensor aren't in the correct order, and sometimes are corrupted, compared to my logic analyzator results.

         

      I try to manage the sensor with the following C function (Data rate: 100kbps FIFO byte mode: 8bit, SW: PSOC Creator 3.3 + SP2, HW: CY8C4248LQI-BL583 on CY8CKIT-042-BLE-A)

         
      uint32 ReadColorSensor (uint32 command) {     uint32 result = 0;  //data from color sensor     uint32 resh = 0;    //data high byte     uint32 resl = 0;    //data low byte             uint32 slaveadd = 0x10; //address of RGB color sensor              I2CM_I2CMasterSendStart(slaveadd , 1);    //start transfer to address = 0x10 + WR         I2CM_I2CMasterWriteByte(command);               //send command byte (sensor internal address)         I2CM_I2CMasterSendRestart(slaveadd, 0);   //send restart to address = 0x10 + RD         resl = I2CM_I2CMasterReadByte (1u);             //read low byte         resh = I2CM_I2CMasterReadByte (1u);             //read low byte         I2CM_I2CMasterSendStop();                       //stop transfer              result = (resh << 8) + resl;              return result; }
         

      At first we send the start bit, and the slave address, then set up the slave command register (this is the internal address, to select what color level read from the sensor), then send a repeated start with the address, and at last read the two bytes from the slave, then finish the transfer with the stop bit.

         

      After deeper analysis of the I2C API, I've discovered, that the I2CM_I2CMasterSendRestart API function causes 8 extra clocks after sending the start bit, and the address byte, as you can see on the attached picture (the software is stopped after calling I2CM_I2CMasterSendRestart function). I suppose this extra clocks causes the confusion in the data bytes. I spent many hours with reading Cypress docs and debugging the API to unterstand better the working theory of the Serial Communication Block, but i wasn't able to discover how are the bus transfer triggered. I marked the attached logic analyzator pattern (i2c_transfer_logic_analysis.png), how are the byte transfer triggered by API instructions, and doesn't seems to me very consequent.

         

      1. I2CM_I2CMasterSendStart(slaveadd , 1);

         

      In this API function slave address is written into TX buffer (I2CM_TX_FIFO_WR_REG = slaveAddress;) then set the M_START_ON_IDLE bit in the I2C_M_CMD register (I2CM_I2C_MASTER_GENERATE_START;), which causes to generate the START bit, and writes the address data to the bus.

         

      2. I2CM_I2CMasterWriteByte(command);

         

      In this funtcion the writing of the TX buffer (I2CM_TX_FIFO_WR_REG = theByte;) starts the transfer, and causes to clock out the 9 SCL pulses.

         

      3. I2CM_I2CMasterSendRestart(slaveadd, 0);

         

      First set M_START bit in the I2C_M_CMD register (I2CM_I2C_MASTER_GENERATE_RESTART;) - nothing happens on the bus, then writes the address to the TX buffer (I2CM_TX_FIFO_WR_REG = slaveAddress;), this sends out the repeated start bit, writes the address byte, and after that clocks 9 extra pulses to the bus...

         

      All in all, i have two questions.

         

      1. I'd like to know, how to implement this two byte read with repeated start condition.

         

      2. Are there any other documention, than PSoC 4 BLE Registers Technical Reference Manual and PSoC 4 BLE Architecture Technical Reference Manual, where i'm able to find more information to make our own API managing the SCB peripharial?

         

      Thanks for your answer!