Other Parts Discussed in Thread: TMP101, C2000WARE
Tool/software:
I am accessing an I2C temperature device (TMP101) from CM. The CM is setup as I2C Master on the bus. It just configures the I2C slave device and then reads out temperature data every second.
When looking at the traffic on a logic analyzer, it looks exactly as expected and the device is returning the correct data. This tells me that the bus transactions are correct (the device ACKs correctly). But in the CM firmware, I often get duplicate values when reading the 2 bytes of data from the I2CMDR register. I am not using the interrupt or FIFO mechanisms and just doing a background polling loop. I noticed that the last valid value is kept in the MDR register, so reading the register at the wrong time (or if it isn't being updated as expected) would result in duplicate values.
I was following the documented flow charts from the TRM. Is there an example of how these APIs are to be used? When is the data in the MDR valid and ready, and how can the firmware tell? The only one in the C2000Ware example area is not applicable.
void i2cTemperaturePoll(uint32_t i2cInstance) { if(I2C_isMasterBusy(TEMPERATURE_I2C_BASE)) { return; }; // Set I2C target address // FC: write slave address to I2CMSA I2C_setSlaveAddress(TEMPERATURE_I2C_BASE, i2cAddresses[i2cInstance], I2C_MASTER_READ); // FC: Check busy (may be omitted in single master system) while(I2C_isBusBusy(TEMPERATURE_I2C_BASE)); // Start transaction // FC: write xxx0_1011 to I2CMCS I2C_setMasterConfig(TEMPERATURE_I2C_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START); for (int i = 0; i < TEMPERATURE_I2C_DATA_BYTES; i++) { // FC: read I2CMCS while(I2C_isMasterBusy(TEMPERATURE_I2C_BASE)); // FC: ERROR bit == 0? i2cBusStatus[i2cInstance] |= I2C_getMasterErr(TEMPERATURE_I2C_BASE); // Grab read first data byte // FC: Read data from I2CMDR rawData[i] = I2C_getMasterData(TEMPERATURE_I2C_BASE); if (i < TEMPERATURE_I2C_DATA_BYTES - 1) { // Continue transaction and STOP // FC: write xxx0_1001 to I2CMCS I2C_setMasterConfig(TEMPERATURE_I2C_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT); } else { // FC: last byte // FC: write xxx0_1101 to I2CMCS I2C_setMasterConfig(TEMPERATURE_I2C_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH_ACK); } } // FC: Check busy while(I2C_isMasterBusy(TEMPERATURE_I2C_BASE)); // FC: ERROR bit == 0? i2cBusStatus[i2cInstance] |= I2C_getMasterErr(TEMPERATURE_I2C_BASE); }
I did edit the CM I2C API to define the config type I2C_MASTER_CMD_BURST_RECEIVE_FINISH_ACK. This type is defined as:
//! BURST RECEIVE FINISH I2C_MASTER_CMD_BURST_RECEIVE_FINISH = 0x00000005U, //! BURST RECEIVE FINISH WITH ACK I2C_MASTER_CMD_BURST_RECEIVE_FINISH_ACK = 0x0000000dU,
This config ACKs the data from the device. Its not 100% necessary, but matches the expected bus transactions.
Thanks!