I'm currently trying to communicate with a slave device using I2C which expects the following protocol:
"The read data protocol is used to transmit data from IC memory locations 000h to 1FFh . Addresses 000h to 0FFh and 180h to 1FFh can be read as a block. Addresses 100h to 17Fh must be read as individual words. The memory address is sent by the bus master as a single byte value immediately after the slave address. Immediately following the memory address, the bus master issues a REPEATED START followed by the slave address. The MAX17201/MAX17205 acknowlege the address and begin transmitting data. A word of data is read as two separate bytes that the master must ACK. Because the address is automatically incremented after the least significant bit (LSb) of each word received by the IC, the MSB of the data at the next memory address can be read immediately after the acknowledgment of the LSB of data at the previous address. The master indicates the end of a read transaction by sending a NACK followed by a STOP."
Using the CSL library, I've configured the I2C as follows:
/* Setup I2C peripheral */ i2cSetup.addrMode = CSL_I2C_ADDR_7BIT; i2cSetup.bitCount = CSL_I2C_BC_8BITS; i2cSetup.loopBack = CSL_I2C_LOOPBACK_DISABLE; i2cSetup.freeMode = CSL_I2C_FREEMODE_DISABLE; i2cSetup.repeatMode = CSL_I2C_REPEATMODE_DISABLE; i2cSetup.ownAddr = (0x2F); i2cSetup.sysInputClk = CSL_I2C_SYS_CLK; // 100 Mhz i2cSetup.i2cBusFreq = CSL_I2C_BUS_FREQ; // 10 Khz
and the code I use to drive the communication is:
CSL_Status status = CSL_ESYS_FAIL; Uint16 regADDR = 0x0000; Uint16 Rx[2] = {0}; regADDR = DataBlock_regADDR & 0x00FF; // Extract LSB to send do { status = I2C_write(®ADDR, 1, DataBlock_SlaveADDR, TRUE, (CSL_I2C_START), CSL_I2C_MAX_TIMEOUT); } while( status != CSL_SOK ); status = I2C_read(Rx, 2, DataBlock_SlaveADDR, NULL, 0, TRUE, (CSL_I2C_START)|(CSL_I2C_STOP), CSL_I2C_MAX_TIMEOUT, FALSE); // if( status == CSL_I2C_BUS_BUSY_ERR){while(1){}} // if( status == CSL_I2C_NACK_ERR){while(1){}} // if( status == CSL_I2C_TIMEOUT_ERROR){while(1){}} *(Rx_data) = ( (Rx[1]<<8) | Rx[0] ); return status;
The I2C_write() is SUCCESSFUL and returns CSL_SOK. However, I2C_read returns a value of -200 ( "CSL_I2C_TIMEOUT_ERROR"). I have tried to follow the protocol as closely as possible, please notice that:
1) For I2C_write, I set the CSL_I2C_START parameter but NOT the CSL_I2C_STOP parameter because the protocol doesn't call for a stop condition after the I2C write().
2) I use I2C_write() to send the memory address ("regADDR") as the data to write, which is what the protocol seems to want.
3) For I2C_read, I set the CSL_I2C_START parameter AND the CSL_I2C_STOP parameter because the protocol calls for a repeated START and finally a STOP.
I also have tried different combinations of enabling and disabling repeat mode in i2cSetup.repeatMode, but I2C_read continues to return CSL_I2C_TIMEOUT_ERROR. Any guidance and advice would be greatly appreciated! I will continue to work out the problem and update if I find a solution.
Best,
Eddie