This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi there,
I note my same problem is reported elsewhere on the forum for another MCU, but there is no listed solution in that thread.
I am regularly Rx two bytes over I2C in the FIFO buffer on the TM4C129X. (at a 1kHz rate I get two more bytes to read). I am using burst receive so I can let the two bytes fill up the FIFO before reading them back one after the other quickly.
The No-Acknowledge (NAK) response (bit) gets delayed by two bytes, so I have to read 4 bytes from the FIFO before a NAK is automatically generated by the TM4C129X's I2C Master for the slave to interpret.
If however I set the FIFO size to 1 with I2CMasterBurstLengthSet(i2c_base, 0x01); instead of 0x02 as per the code below, the NAK is correctly sent by the master and the slave correctly stops sending data after the second byte. The problem with using a FIFO size of 1 is that it defeats the purpose of the FIFO buffer and the second read ends up taking in the order of 25-30us instead of a small fraction of that (a few us), as the I2C Tx speed is only 400kbps. This is a waste of CPU cycles for me.
I realise that the FIFO is better suited to work with interrupts, however that is not what I am using, and I would really like to get the code working with minor changes to my existing code shown below without employing interrupts. The three functions below are called one after the other, with a suitable delay of perhaps 150-200us between the initiate_Rx() and readFirstMeasByte().
My question: How can I use the FIFO buffer with *_ FIFO_BURST_RECEIVE_* while having the TMC129X Master issue a NAK after the second byte is automatically read into the Rx FIFO ?
void initiate_Rx(uint32_t i2c_base, uint8_t addr) { I2CMasterSlaveAddrSet(i2c_base, addr, true); I2CRxFIFOConfigSet(i2c_base, (I2C_FIFO_CFG_RX_MASTER|I2C_FIFO_CFG_RX_TRIG_2)); I2CRxFIFOFlush(i2c_base); I2CMasterBurstLengthSet(i2c_base, 0x02); I2CMasterControl(i2c_base, I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START); } uint8_t readFirstMeasByte(uint32_t i2c_base) { uint8_t meas_byte; while ((I2CFIFOStatus(i2c_base))&I2C_FIFO_RX_EMPTY); I2CFIFODataGetNonBlocking(i2c_base, &meas_byte); I2CMasterControl(i2c_base,I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH); meas_byte&=(uint8_t)0x3F;//mask off the top two most significant bits as these are status bits return meas_byte; } uint8_t readSecondMeasByte(uint32_t i2c_base) { uint8_t meas_byte; while ((I2CFIFOStatus(i2c_base))&I2C_FIFO_RX_EMPTY); I2CFIFODataGetNonBlocking(i2c_base, &meas_byte); return meas_byte; }
Amit Ashara said:Can you please refer to the following Technical Application Note mentioned below. The SW collateral
Hi Amit,
I've read that application note but it didn't talk about using the FIFO without interrupts.
Which part of my code needs changing to align with the app notes?
What do you mean by SW collateral?
I have only tested with FIFO sizes of 1 and 2 giving the behavior I described. I could test with higher numbers but I'm unsure how that would help you. I got the impression from the other post I referred that my problem was identical so it seems more than a coincidence I also see it. There must be something either common in our code or in the two MCU architectures.
Peter
Hi Amit,
Unfortunately your suggestion didn't work, but I found the solution thanks to your explanation ! When I tried your suggestion, NO I2C transactions took place at all.
To solve the problem all I had to do was replace I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START with I2C_MASTER_CMD_FIFO_SINGLE_RECEIVE in the first function named initiate_Rx() . I still kept the I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH in the second function. The Master now properly sends a NAK after reading the 2nd byte, using the following code:
void initiate_Rx(uint32_t i2c_base, uint8_t addr) { I2CMasterSlaveAddrSet(i2c_base, addr, true); I2CRxFIFOConfigSet(i2c_base, (I2C_FIFO_CFG_RX_MASTER|I2C_FIFO_CFG_RX_TRIG_2)); I2CRxFIFOFlush(i2c_base); I2CMasterBurstLengthSet(i2c_base, 0x02); I2CMasterControl(i2c_base,I2C_MASTER_CMD_FIFO_SINGLE_RECEIVE);//Note, using I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START here does not result in the desired NAK from Master after it reads the second byte, instead at the 4th byte (and we only want to read 2 bytes) } uint8_t readFirstMeasByte(uint32_t i2c_base) { uint8_t meas_byte; while ((I2CFIFOStatus(i2c_base))&I2C_FIFO_RX_EMPTY); I2CFIFODataGetNonBlocking(i2c_base, &meas_byte); I2CMasterControl(i2c_base,I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH); meas_byte&=(uint8_t)0x3F;//mask off the top two most significant bits as these are status bits return meas_byte; } uint8_t readSecondMeasByte(uint32_t i2c_base) { uint8_t meas_byte; while ((I2CFIFOStatus(i2c_base))&I2C_FIFO_RX_EMPTY); I2CFIFODataGetNonBlocking(i2c_base, &meas_byte); return meas_byte; }
Thanks for your very timely assistance Amit.
Peter