I2C can’t read from FT201XS

ci2c

I'm using a cypress microcontroller to read some values from the FT201XS-R chip. I can get acknowledgment, but I can't seem to read. Here's the datasheet.
I'm attempting to do a read of register 4 of the MTP memory as outlined on page 39 of the datasheet.

Here's my code

int main{

    uint8 addr = 0x22;
    uint8 WriteBuffer[16];



    UART_1_Start();

// I added this because the I2C will be pulled low by a slave when addressing goes wrong. This helps to make it still work
    while(I2C_1_sda_Read() == 0) // SDA hang low
    {
        I2C_1_SET_I2C_SCL_HSIOM_SEL(I2C_1_HSIOM_GPIO_SEL); //Switch to GPIO    
        I2C_1_scl_Write(0);
        CyDelay(1);
        I2C_1_scl_Write(1);
        CyDelay(1);
        I2C_1_SET_I2C_SCL_HSIOM_SEL(I2C_1_HSIOM_I2C_SEL); //Switch to Component
    }


    WriteBuffer[0] = 0x10; // this is the address mtp signal
    status = i2c_send(0x00,WriteBuffer,1u);

    WriteBuffer[0] = 0x00;
    WriteBuffer[1] = 0x04; // this is register 4
    status = i2c_send(addr,WriteBuffer,2);

    WriteBuffer[0] = 0x14; // this is the mtp register read value
    status = i2c_send(0x00,WriteBuffer,1u);
    readData = i2c_recieve(addr);

}

uint32 i2c_send(uint8 addr, uint8 * data, uint8 count){
    uint32 status=1;
    uint8 i =0;
    uint8 check;
    I2C_1_I2CMasterClearStatus();
    status = I2C_1_I2CMasterSendStart(addr, 0u);
    while(status){
        I2C_1_I2CMasterClearStatus();
        I2C_1_I2CMasterSendStop();
        CyDelay(10);
        status = I2C_1_I2CMasterSendStart(addr, 0u);
    }

    for (;i<count;i++){
        check = *(data+i);
       status = I2C_1_I2CMasterWriteByte(*(data+i)); 
    }

    I2C_1_I2CMasterSendStop();
    CyDelay(10);
    return status;


}

uint8 i2c_recieve(uint8 addr){
    uint32 status;
    uint32 readData;
    CyDelay(10);
    status = I2C_1_I2CMasterSendStart(addr, I2C_1_I2C_READ_XFER_MODE);
    while(status){
        I2C_1_I2CMasterClearStatus();
        I2C_1_I2CMasterSendStop();
        CyDelay(10);
        status = I2C_1_I2CMasterSendStart(addr, I2C_1_I2C_READ_XFER_MODE);
    }
    readData= I2C_1_I2CMasterReadByte(I2C_1_I2C_NAK_DATA);
    I2C_1_I2CMasterSendStop();
    return readData;


}

I am able to do all of the I2C send commands, but when I try to do an I2C recieve, the status hangs on 2, which is the SCB_I2C_MSTR_NOT_READY error. This corresponds to this description:

Master is not ready for to start transfer. A master still has not
completed previous transaction or a slave operation is in progress (in
multi-master-slave configuration). Nothing was sent on the bus. The
attempt has to be retried.

What do I need to change to get the register read to work?

EDIT ***************

I created a new function to perform the read

uint32 i2c_read_mem(uint8 addr, uint8 reg){
    uint32 status=1;
    uint32 readData;
    uint8 i =0;
    uint8 check;



    status = I2C_1_I2CMasterSendStart(0x00, 0);
    status = I2C_1_I2CMasterWriteByte(0x10);
    status = I2C_1_I2CMasterSendRestart(addr,0);
    status = I2C_1_I2CMasterWriteByte(0x00);
    status = I2C_1_I2CMasterWriteByte(reg);
    status = I2C_1_I2CMasterSendRestart(0x00,0);
    status = I2C_1_I2CMasterWriteByte(0x14);
    status = I2C_1_I2CMasterSendRestart(addr,1);
    readData= I2C_1_I2CMasterReadByte(I2C_1_I2C_ACK_DATA);
    I2C_1_I2CMasterSendStop();
    return readData;


}

With this function, I2C no longer hangs, but it always returns 0. According to this document, I should see the usb vid at byte 2 and 3. yet when I run

for (i=0; i<20; i++){
        readData = i2c_read_mem(addr, i);
        CyDelay(1);
}

all values returned are 0.

Best Answer

The datasheet shows an I2C restart between the (general call + MTP address command) phase and the (slave + MTP address bytes) phase, and again between the (general call + MTP transfer command) and the (slave + data bytes), but your code performs a stop and then a start in each of these cases.

Your abstraction layer is too high, you need to either use the low-level I2C actions for this, or else add a parameter to i2c_send to inhibit the STOP action at the end.