You are here

I2C master read issue | Cypress Semiconductor

I2C master read issue

Summary: 11 Replies, Latest post by gmolnar_1700281 on 08 Sep 2016 03:50 AM PDT
Verified Answers: 0
Last post
Log in to post new comments.
gmolnar_1700281's picture
User
7 posts

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!

user_1377889's picture
User
10103 posts

Welcome in the forum.

When you would have used the #defined  ´values I2CM_I2C_WRITE_XFER_MODE and the corresponding value for reading all would have been correct. Same for the required ACK and NAK: there are constants to use for that. Makes reading easier than just a 0x01 and does not hide any errors.

Building your own peripherals? There is the "Component Author Guide" for general outlines on how2 build components.

Nonetheless you can build your own APIs and use them instead of the (working) provided ones.

 

Bob

gmolnar_1700281's picture
User
7 posts

Thanks for the quick answer, Bob! I've tried to use the predefined constant values, but as I excepted, no change on the bus: the I2CM_I2CMasterSendRestart function still generates the extra clock pulses as before.

user_1377889's picture
User
10103 posts

Can you please post your complete project (or at least a reduced one that shows the error), so that we all can have a look at all of your settings. To do so, use
Creator->File->Create Workspace Bundle (minimal)
and attach the resulting file.

 

Bob

 

gmolnar_1700281's picture
User
7 posts

Here you are.

user_1377889's picture
User
10103 posts

You do not terminate the transfer of the last byte red with a NAK which is usually accepted by the slave indicating that the read is finished.

The result of the reads may have set the MSB to indicate an error. SendStart(), WritByte() and SendStop()  return a state to indicate error conditions. At least during testing I would suggest you to inspect the returned values.

 

Bob

gmolnar_1700281's picture
User
7 posts

Yes, that's usual to close the transfer with NACK after the last byte, when you are reading from I2C memories, but this Vishay VEML6040 sensor device always excepts two byte long read sequences with ACK by the master at the end. I've attached the datasheet, see page 5, fig. 4.

And all in all, it doesn't resolve the strange behavior at calling the restart function, which clocks out 9 extra pulses, after sending the command byte to the slave...

I'll check the return values of the I2C functions in the following days, and'll come back with results.

 

Thanks,

Gabor

gmolnar_1700281's picture
User
7 posts

Hi,

Checked the return values, the SendStop returns 0x100, that means I2C_MSTR_ERR_BUS_ERR, the return value of the other functions is 0x00.

user_1377889's picture
User
10103 posts

In this case the I2C has been reset by software. Do you get the same result when NAKing the second byte?

 

Bob

gmolnar_1700281's picture
User
7 posts

Yes, the same.

user_1377889's picture
User
10103 posts

Out of my wits. I would suggest you to get in contact with Cypress directly: At top of this page select "Design support -> Create a Support Case" and ask your question. You will be helped by a Cypress engineer. Leave a link to this thread, so Cypress will know what you've tried already.

Bob

 

Log in to post new comments.