0
\$\begingroup\$

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.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

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.

\$\endgroup\$
5
  • \$\begingroup\$ I'm giving it a try right now. It looks like there is a MasterSendRestart that I'll use \$\endgroup\$ Oct 23, 2015 at 22:08
  • \$\begingroup\$ @LegenDiary: Now that you're using restarts, are you getting acknowledge (the status variable in your new code)? The datasheet says "The acknowledge during the command phase indicates whether or not the MTP memory will be able to service the read request." \$\endgroup\$
    – Ben Voigt
    Oct 23, 2015 at 22:46
  • \$\begingroup\$ I am using the internal debugger to step through each command. Each status returns 0. I've even written to a register then tried to read it back, but it doesn't work. Looking at the register mapping I assumed it was 2 bytes. I tried it both ways, but neither worked \$\endgroup\$ Oct 23, 2015 at 23:17
  • \$\begingroup\$ Some ICs require restart, others are fine with stop starts. \$\endgroup\$
    – Passerby
    Oct 24, 2015 at 5:33
  • \$\begingroup\$ @Passerby: This datasheet uses different notation for (stop/start or restart) from (only works with restart). \$\endgroup\$
    – Ben Voigt
    Oct 24, 2015 at 15:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.