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.

CCS: Is it possible to control i2c ack or i2c tx latency outside of interrupt



Tool/software: Code Composer Studio

I'm using TI USB adapter interface connect to 28035 evm board.

Is it possible to control i2c ack or i2c tx latency outside of interrupt.
I'd like to collection data inside the interrupt and make some operation outside the interrupt.
So that the interrupt won't necessary being blocked while processing data.
I thought I could ignore the tx interrupt until the processing done.
With small latenty it seems work fine, but longer latency...
I wonder if I could control the ack or response time to master device, so that I can have enough time to
parse the data.

unsigned char InBuffer[BUFSIZ];
unsigned char OutBuffer[BUFSIZ];
int InBufIndex = 0;
int InBufPos = 0;
int OutBufIndex = 0;
int OutBufPos = 0;

void main(void)
{
	InitSysCtrl();
	InitGpio();
	DINT;
	InitPieCtrl();
	IER = 0x0000;
	IFR = 0x0000;
	InitPieVectTable();
	EALLOW;
	PieVectTable.TINT0 = &cpu_timer0_isr;
	PieVectTable.I2CINT1A = &I2CSlaveInt1a;
	InitI2C();
	InitCpuTimers();
	ConfigCpuTimer(&CpuTimer0, 60, 10000);
	CpuTimer0Regs.TCR.all = 0x4001;
	IER |= M_INT1;
	IER |= M_INT8;
	PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
	PieCtrlRegs.PIEIER8.bit.INTx1 = 1;
	EINT;
	ERTM;

	for (;;) {
		/* check data for every 100ms or 500ms */
		I2CDataHandler();
	}
}

void InitI2C(void)
{
    I2caRegs.I2COAR = 0x50;
    I2caRegs.I2CPSC.all = 9;
    I2caRegs.I2CCLKL = 10;
    I2caRegs.I2CCLKH = 5;
    I2caRegs.I2CIER.all = 0x7f;
    I2caRegs.I2CMDR.bit.IRS = 1;
    I2caRegs.I2CMDR.bit.RM = 0;
}

interrupt void I2CSlaveInt1a(void)
{
    Uint16 intSrc = I2caRegs.I2CISRC.bit.INTCODE;

    switch (intSrc) {
    case I2C_NO_ISRC:
        break;

    case I2C_ARB_ISRC:
        break;

    case I2C_NACK_ISRC:
        break;

    case I2C_ARDY_ISRC:
        info.ardyCount++;
        if (I2caRegs.I2CSTR.bit.NACK == 1) {
            I2caRegs.I2CMDR.bit.STP = 1;
            I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
        }
        break;

    case I2C_RX_ISRC:
		/* receive data in the interrupt */
        InBuffer[InBufPos++] = I2caRegs.I2CDRR;
        break;

    case I2C_TX_ISRC:
		/* transmit the rest of the data in the interrupt */
        if (OutBufIndex < OutBufPos) {
            I2caRegs.I2CDXR = OutBuffer[OutBufIndex++];
            OutBufIndex &= 0xff;
        }
        break;

    case I2C_SCD_ISRC:
        break;

    case I2C_AAS_ISRC:
        break;
    }

    PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;
}

void I2CDataHandler(void)
{
	OutBuffer[0] = 0x22;
	OutBuffer[1] = 0x23;
	OutBufPos = 2;
	OutBufIndex = 0;
	
	I2caRegs.I2CDXR = OutBuffer[0];
	OutBufIndex++;
}

  • Hi Archer,

    Could you explain a little more about your setup? Are you configuring your c2000 as a master-transmitter/receiver, as a slave, etc? Which format are you using (7-bit addressing, 10-bit addressing, and Free Data mode)? What exactly are you wanting the interrupt to handle and what are you wanting to be done within main?

    For all three modes an ACK is generated by the receiver after receiving a byte. Also, please look into the following user guide to see if it has the answer you are looking for.

    www.ti.com/.../sprufz9d.pdf

    Hope this helps,
    Kevin
  • Hello Kevin,

    Thanks for replying.
    My c2000(28035) is configured as a slave device using 7-bit addressing mode.
    And the master device is TI's USB-TO-GPIO (www.ti.com/.../USB-TO-GPIO).

    As mentioned in previous post, I'd like to receive all the data in the interrupt, and then handle the data in main loop.
    After the data is processed, then response to the master device (PC).
    The main purpose is not to occupy the interrupt.
    After the data is processed, then trigger transmitter interrupt or send an ack to the master device.

    I thought I could control the response time by ingoring the first tx interrupt. (not to send a byte to I2CaRegs.I2CDXR)

    As you see in the switch case I2C_TX_ISRC, this might be ignored if the data has not been handled.
    And after the data is processed in I2CDataHandler, write a byte into I2CaRegs.I2CDXR to continue the transmitter interrupt.

    www.ti.com/.../sprufz9d.pdf (page 15, slave-transmitter mode section)

    However, it seems the interrupt does not work like I expected.
    If the response time (latency) is longer, I2C might get failed.


    So I wonder if it is possible to control i2c ack or i2c tx latency outside of interrupt,
    or I have to handle the data processing in the interrupt?


    Sincerely,
    Archer
  • Hi Archer,

    Sorry it took me so long to get back to you.

    I don't believe there is a way to control ACK latency as it is sent by the receiver to the transmitter after each byte. This is in accordance with the I2C protocol specifications.

    I think you can somewhat control TX latency and design your program to save data to global variables within your interrupt and process the saved data outside of the interrupt. Your slave device can hold SCL low while it processes the data (RSFULL = 1 in I2CSTR) and then transmit it back to the master afterwards. The reference guide explains this in a little more detail.

    Hope this helps,

    Kevin
  • Hello Kevin,

    Thanks for replying.
    I think control the latency is not quite accurate, my mistake.
    I will try to set RSFULL to 1 to see if this could achieve my goal.
    Thanks so much for replaying me.


    Sincerely,
    Archer