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.
Hello there,
i configured the I2C with FiFO and it worked successfully. that is my code below, it is a simple code that writes three values at ISL29023's registers and reads it back to make sure that the communication works successfully
ISL29023 Address is 0x44
and the register address is 0x04
uint8_t ui8I2CTransmitData[4] = {0x04, 2 , 250 ,4 }; //register address + 3 values
uint8_t ui8I2CReceiveData[3] = {0x00, 0x00, 0x00};
uint32_t ui32SysClock;
uint32_t ui32Index;
ui32SysClock = SysCtlClockFreqSet(SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_25MHZ | SYSCTL_CFG_VCO_480, 120000000);
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
SysCtlDelay(10);
GPIOPinConfigure(GPIO_PB2_I2C0SCL);
GPIOPinConfigure(GPIO_PB3_I2C0SDA);
GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
//
// Configure The I2C Master
//100 kbps
I2CMasterInitExpClk(I2C0_BASE, ui32SysClock, false);
I2CTxFIFOConfigSet(I2C0_BASE,(I2C_FIFO_CFG_TX_MASTER|I2C_FIFO_CFG_TX_TRIG_1));
I2CRxFIFOConfigSet(I2C0_BASE,(I2C_FIFO_CFG_RX_MASTER|I2C_FIFO_CFG_RX_TRIG_3));
I2CTxFIFOFlush(I2C0_BASE);
I2CRxFIFOFlush(I2C0_BASE);
//writing data at the sensor register using FiFO
I2CMasterBurstLengthSet(I2C0_BASE,0x4);
I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, false);
for(ui32Index=0;ui32Index<4;ui32Index++)
{
I2CFIFODataPut(I2C0_BASE, ui8I2CTransmitData[ui32Index]);
}
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_SINGLE_RECEIVE);
while(!I2CMasterBusy(I2C0_BASE));
while(I2CMasterBusy(I2C0_BASE));
//writing the register address that i will read from it
I2CMasterBurstLengthSet(I2C0_BASE,0x1);
I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, false);
for(ui32Index=0;ui32Index<1;ui32Index++)
{
I2CFIFODataPut(I2C0_BASE, ui8I2CTransmitData[ui32Index]);
}
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_SINGLE_RECEIVE);
//check stop condition
while(!I2CMasterBusy(I2C0_BASE));
while(I2CMasterBusy(I2C0_BASE));
//reading the 3 values from the sensor
I2CMasterBurstLengthSet(I2C0_BASE,0x3);
I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, true);
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_SINGLE_RECEIVE);
for(ui32Index=0;ui32Index<3;ui32Index++)
{
ui8I2CReceiveData[ui32Index] = I2CFIFODataGet(I2C0_BASE);
}
but every time i read the three values i must wait at "I2CFIFODataGet(I2C0_BASE);" to catch every new data. so i have to wait three times(N times) to read the three values(N values).
So my simple question is :
is there any possible way to read the whole values after just one wait or one check instead of waiting at every new byte?
thanks.
Hello,
Might a "simple answer" serve your, "simple question?"
From the current "Peripheral Driver Library User's Guide:"
16.2.2.13 I2CMasterControl
Description: Function is used to control the state of the Master send & receive operations. The ui8Cmd parameter can be one of the following values:
I2C_MASTER_CMD_FIFO_SINGLE_SEND
I2C_MASTER_CMD_FIFO_SINGLE_RECEIVE
I2C_MASTER_CMD_FIFO_BURST_SEND_START
I2C_MASTER_CMD_FIFO_BURST_SEND_CONT
I2C_MASTER_CMD_FIFO_BURST_SEND_FINISH
I2C_MASTER_CMD_FIFO_BURST_SEND_ERROR_STOP
I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START
I2C_MASTER_CMD_FIFO_BURST_RECEIVE_CONT
I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH
I2C_MASTER_CMD_FIFO_BURST_RECEIVE_ERROR_STOP
Those parameters (highlighted) appear to "better match" your objectives - do they not?
Unfortunately - this (otherwise) excellent User Guide provides NO examples of this (more complex) "Burst Mode." (suspected to resolve your issue!)
Vendor staff have assured that they are "NEAR" updating of TivaWare. It is hoped that (beyond the simplest) of code examples will arrive w/that update... Perhaps evidence of that "nearness" would (nicely) satisfy your "fair/proper" request...
Hello Mohamed,
To add to cb1's advice, we do have a burst example coming with the new TivaWare but not using FIFO mode, you can see how we handle it here though:
//***************************************************************************** // // This function will read three 8-bit data from the I2C slave. The first // two 8-bit data forms the humidity data while the last 8-bit data is the // checksum. This function illustrates three different I2C burst mode // commands to read the I2C slave device. // //***************************************************************************** void I2CReadCommand(uint32_t * pui32DataRx) { // // Modify the data direction to true, so that seeing the address will // indicate that the I2C Master is initiating a read from the slave. // MAP_I2CMasterSlaveAddrSet(I2C7_BASE, SHT21_I2C_ADDRESS, true); // // Setup for first read. Use I2C_MASTER_CMD_BURST_RECEIVE_START // to start a burst mode read. The I2C master continues to own // the bus at the end of this transaction. // MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START); // // Wait until master module is done transferring. // The I2C module has a delay in setting the Busy flag in the register so // there needs to be a delay before checking the Busy bit. The below loops // wait until the Busy flag is set, and then wait until it is cleared to // indicate that the transaction is complete. This can take up to 633 CPU // cycles @ 100 kbit I2C Baud Rate and 120 MHz System Clock. Therefore, a // while loop is used instead of SysCtlDelay. // while(!MAP_I2CMasterBusy(I2C7_BASE)) { } while(MAP_I2CMasterBusy(I2C7_BASE)) { } // // Read the first byte data from the slave. // pui32DataRx[0] = MAP_I2CMasterDataGet(I2C7_BASE); // // Setup for the second read. Use I2C_MASTER_CMD_BURST_RECEIVE_CONT // to continue the burst mode read. The I2C master continues to own // the bus at the end of this transaction. // MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT); // // Wait until master module is done transferring. // while(!MAP_I2CMasterBusy(I2C7_BASE)) { } while(MAP_I2CMasterBusy(I2C7_BASE)) { } // // Read the second byte data from the slave. // pui32DataRx[1] = MAP_I2CMasterDataGet(I2C7_BASE); // // Setup for the third read. Use I2C_MASTER_CMD_BURST_RECEIVE_FINISH // to terminate the I2C transaction. At the end of this transaction, // the STOP bit will be issued and the I2C bus is returned to the // Idle state. // MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); // // Wait until master module is done transferring. // while(!MAP_I2CMasterBusy(I2C7_BASE)) { } while(MAP_I2CMasterBusy(I2C7_BASE)) { } // // Note the third 8-bit data is the checksum byte. It will be // left to the users as an exercise if they want to verify if the // checksum is correct. pui32DataRx[2] = MAP_I2CMasterDataGet(I2C7_BASE); }
Hello Ralph,
Good to see this - poster & my crüe thank you.
Do you believe that poster's desire to, "Read 3 I2C bytes" is sufficient justification to add the complexity of the "BURST_FIFO" style Commands?"
Perhaps even of greater interest/value - might you outline,
"When the transition from (the simpler) "I2C_MASTER_CMD_BURST functions TO (the more complex) I2C_MASTER_CMD_BURST_FIFO" function group appears indicated?" Also - what (measurable benefits) may result from such 'added complexity?'
Such detail likely makes this "CMD_BURST_FIFO" function far more compelling. Without this detail (nowhere explained that we can tell) more questions than answers arise... Thank you...
Hello cb1,
That is a good question to raise, especially given right now we are talking 3 bytes which appears to be a small amount.
One thing I found in a past post from Amit is a comment that "I2CFIFODataGet will get only one byte at a time. The true value of the FIFO comes when the uDMA is used."
Another consideration here is that the FIFO buffers are only 8 bytes deep.
The FIFO's can be configured with specific threshold points to trigger the FIFO service interrupt.
For how uDMA ties into this, there are the following details from the D/S for Master Module µDMA Functionality:
When the Master Control/Status (I2CMCS) register is set to enable BURST and the master I2C µDMA channel is enabled in the DMA Channel Map Select n (DMACHMAPn) registers in the µDMA, the master control module will assert either the internal single µDMA request signal (dma_sreq) or multiple µDMA request signal (dma_req) to the µDMA
A single µDMA request (dma_sreq) will be asserted by the Master module when the Rx FIFO has at least one data byte present in the FIFO and/or when the Tx FIFO has at least one space available to fill. The dma_req (or Burst) signal will be asserted when Rx FIFO fill level is higher than trigger level and/or the Tx FIFO burst length remaining is less than 4 bytes and the FIFO fill level is less than trigger level.
If a single transfer or BURST operation has completed, the µDMA sends a dma_done signal to the master module represented by the DMATX/DMARX interrupts in theI2CMIMR/I2CMRIS/I2CMMIS/I2CMICR registers.
My personal view based on the information presented above is that 3 bytes would not justify the use of FIFO w/ uDMA, and I would just use a standard three byte burst. The one case I could see otherwise is to be hands off with the RX process via uDMA and just fetch the data with an interrupt, but I feel you would have to be in some very timing critical applications to make those added hurdles worthwhile just for a few bytes.
Thank you, Ralph. That's great past detail - yet users (especially my group) remain in the dark as to:
Unless I am (especially) dense - far more detail (especially 'well commented' code examples) is required before users can benefit (at all) from these, "8 FIFO_BURST" (pardon) "mystery parameters!"
The µDMA adds to the complexity mix - yet the (almost) "TOTAL LACK of CLEAR "BURST_FIFO" USAGE EXPLANATION" is likely to produce, "An endless loop of frustrated users - yearning to effectively, "Exploit & Benefit from that Parameter SWELLING!"
Hello Ralph,
thanks for the information, "I2CFIFODataGet" is only getting the last byte that was received from the slave. this function just reads from "I2CFIFODATA" register that contains the current byte being read in the RX FIFO stack. so i have to wait at each byte until it is placed in the RX FIFO and then read it by the function that i mentioned before.
So my question is : Is there any way to just wait one time till all the bytes receive (so the program can do something else and comeback ) and after that read all bytes from RX FIFO at one time instead using µDMA or i must use µDMA to do that ?
thanks.
Hello Mohamed,
From what I've seen, you need to use the uDMA for the FIFO to be useful otherwise it's basically the same as not using the FIFO at all.
I am not seeing any indication that without uDMA you can just wait for all bytes to be received without doing anything in between. You could may be look to lessen the waiting by using interrupts to read in the bytes as they arrive and handle other tasks in between. I don't think that would save you much though. And again keep in mind the FIFO is just 8 bytes deep so you need to either receive less than 8 bytes or be ready to help clear some of it regardless of if you use the DMA or not.