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.

I2C F28377D interrupt Issue

Hello,

I'm working with the Delfino TMX320F28377D and I'm implementing the I2C communication
but I'm having problems when I try to read near to the maximum speed 390KHz.

void I2CA_Init(void)
{
// I2C Module Clock = SysClockOut/(I2C_IPC+1)
I2caRegs.I2CPSC.all = 18;
I2caRegs.I2CCLKL = 10; // I2C Clock Low Time
I2caRegs.I2CCLKH = 5; // I2C Clock High Time

I2caRegs.I2CIER.all = 0x00; //first, clear the Interrupt Enable Register
I2caRegs.I2CIER.bit.ARDY = 1; //Register access ready interrupt
I2caRegs.I2CIER.bit.SCD = 1; //Stop condition detection
I2caRegs.I2CIER.bit.RRDY = 1; //Receive Data Ready
//I2caRegs.I2CIER.bit.ARBL = 1;

I2caRegs.I2CMDR.all = 0x0020; // Clear the Mode Register and enable I2C Module

I2caRegs.I2CFFTX.all = 0x00; // first, clear the FIFO Rx register and then
//// set the individual bits.
I2caRegs.I2CFFTX.bit.I2CFFEN = 1; // Enable FIFO Mode
I2caRegs.I2CFFTX.bit.TXFFRST = 1; // Enable Transmit FIFO (16 byte Tx fifo)
I2caRegs.I2CFFTX.bit.TXFFIL = 0; // interrupt when Tx FIFO is empty.
I2caRegs.I2CFFTX.bit.TXFFIENA = 0; // Disable Tx FIFO interrupt until Ready to transmit.
I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1; // Clear the TXFFINT flag.


I2caRegs.I2CFFRX.all = 0x00;
I2caRegs.I2CFFRX.bit.RXFFRST = 1; // Enable Rx FIFO (16 byte Rx fifo)
I2caRegs.I2CFFRX.bit.RXFFINTCLR = 1;
// level is = I2C_RX_INTERRUPT_LEVEL.
I2caRegs.I2CFFRX.bit.RXFFIENA = 0; // Disable Rx FIFO interrupt.


For the first access to the EEPROM the settings of the I2C for address the devive and write the read address are the next:

I2caRegs.I2CCNT = 2; // Load Byte count.
I2caRegs.I2CDXR.all = ByteHigh; // high byte of the register to be read.
I2caRegs.I2CDXR.all = ByteLow; // low byte of the register to be read.

//SET --> I2CMDR_IRS | I2CMDR_STT | I2CMDR_MST | I2CMDR_TXR
// I2C Module Enabled
// Generate START condition
// MASTER mode
// TRANSMIT mode

I2caRegs.I2CMDR.all = 0x2620;


Then in the ISR when ARDY trigers I send a start condition again and I check for the SCD and RRDY interrupts.

//ISR Rutine:
interrupt void i2c_int1a_isr(void) // I2C-A
{
uint16_t IntSource;
uint8_t rxFifoCounter, idx;

// Read interrupt source
IntSource = I2caRegs.I2CISRC.all;

switch(IntSource)
{
case I2C_NO_ISRC: // =0 None
break;

case I2C_ARB_ISRC: // =1 Arbitration lost
break;

case I2C_NACK_ISRC: // =2 No-acknowledgment condition detected
break;

case I2C_ARDY_ISRC: // =3 Registers ready to be accessed
if(I2caRegs.I2CSTR.bit.NACK == 0) // Check NACK from device
{
I2caRegs.I2CCNT = ByteCount; // Set up the number of bytes to recive.
//SET --> I2CMDR_IRS | I2CMDR_STT | I2CMDR_STP| I2CMDR_MST | I2CMDR_TXR
I2caRegs.I2CMDR.all = 0x2C20; // Send "repeated" Start with Read (TRX off) and Stop.
ackNotReceived = 0; // Clear ACK Flag
}
else
{ // NACK BIT RECEIVED (I2C FAIL)
I2caRegs.I2CMDR.bit.STP = 1; // Send stop condition
I2caRegs.I2CSTR.bit.NACK = 1; // Clear NACK Flag
}
break;

case I2C_RX_ISRC: // =4 Receive data ready
rxFifoCounter = I2caRegs.I2CFFRX.bit.RXFFST;
for(idx=0;idx<rxFifoCounter;idx++)
{
ReadReg[I2cIndex++] = I2caRegs.I2CDRR.all; // Read data recived and increment index
}
break;

case I2C_TX_ISRC: // =5 Transmit data ready
transmitDataInCourse = 0;
break;

case I2C_SCD_ISRC: // =6 // When stop condition is detected clear dataNotReceived Flag
dataNotReceived = 0; // to avoid timeout timer.
if(I2caRegs.I2CSTR.bit.NACK == 0) // NACK Received
{
ackNotReceived = 0;
}
else // NACK BIT RECEIVED (I2C FAIL)
{
I2caRegs.I2CMDR.bit.STP = 1; // Send stop condition
I2caRegs.I2CSTR.bit.NACK = 1; // Clear ACK Flag
}
break;

case I2C_AAS_ISRC: // =7 Addressed as slave
break;

default:
asm(" ESTOP0"); // Halt on invalid number.
break;
}

// Enable future I2C (PIE Group 8) interrupts
PieCtrlRegs.PIEACK.all |= PIEACK_GROUP8;
}

It seems that works fine but some times when I repeat a read sequence several times, I can see in the I2C_RX_ISRC the RX FIFO have more than one byte and depends on the time I2cIndex doesn't match with the real data index. It seams like some interrupt doesn't triger.

Has somebody had a similar experience?

Thanks.

  • Hi Dani,

    Shouldn't the IPSC be 19 (SYSCLK/MODULE_CLK - 1, 200/10 - 1) for a module clock of 10MHz? You should get a bus clock of 400KHz. I cant imagine the 28377 missing interrupts as it seems like you have sufficient cycles (200*10^6/400*10^3 * 9 (Sr+ADDR+R) ~ 5000 cycles) to implement the code in the ISR for back-to-back reads.

    You can confirm that by dropping the bus speed and seeing if you get more that 1 byte in the FIFO at any given time.

  • Hi Vishal,

    First, I set IPSC to 40 getting a bus clock about 200KHz. With these conditions I repeated the test. On the test I read in a loop always the same memory block, checking the expected value.

    To know whether I get more than 1 byte in the FIFO I put this trap in the interrupt "Receive data ready".

           Case I2C_RX_ISRC:

                 rxFifoCounter = I2caRegs.I2CFFRX.bit.RXFFST;

                 if(rxFifoCounter > 1)

          // asm("   ESTOP0"); // Halt on invalid number.

                   asm("   NOP");

    With this speed it works fine.

    But when I set IPSC = 19 I get more than 1 byte on the FIFO sometimes .

    Thank you.

  • Sounds like the interrupts are coming in faster than they can be serviced. You may have to scope the time between sucessive reads, then benchmark how long the I2C interrupt service routine is to be sure that the interrupts are coming in too fast.

    I'm not sure what can be done about that other than to operate in FIFO mode