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/TMS320F28020: I2C Slave transmitter - No AAS Interrupt

Part Number: TMS320F28020

Tool/software: Code Composer Studio

I am using the TMS320F28020 as a slave transmitter with slave address 0x24.  The above waveform shows the device addressed correctly, and address data =0x0000 sent, then repeated start and addressed as slave with R/W=1, then the SCL line appears to be in contention.  I do not get a AAS interrupt, not sure why.   below is the init and interrupt code.

Initialization code:

void I2Cinit(void)
{
EALLOW;
SysCtrlRegs.PCLKCR0.bit.I2CAENCLK = 1; // Start the I2C clock
EDIS;

I2caRegs.I2CMDR.bit.IRS = CLR; // held in reset state to allow changes to registers

// 7bit address master/slave, single master, master mode, I2C mode, asynchronous mode
I2caRegs.I2CMDR.bit.MST = CLR; // Set slave mode
I2caRegs.I2CMDR.bit.TRX = CLR; // Clear TX mode, set RX mode

// SMCLK, ack normally
I2caRegs.I2CPSC.bit.IPSC = 0x3; // divide I2C clock to generate frequency = 40MHz/(1+3) = 10MHz
I2caRegs.I2CCLKL = 100;
I2caRegs.I2CCLKH = 100; // Master clock = 10MHz/[(100+5)+(100+5)] = 47619Hz

// prescaler high byte, prescaler = (UC0BR0 + UC0BR1 x 256)
// Serial I2C ADDRESS
I2caRegs.I2COAR = I2C_SERIAL_DSP_ADDR; // Load the DSP address
I2caRegs.I2CMDR.bit.IRS = SET; // release form reset

iicRxpacketptr = iicRxDat; // set pointer to the start of the array.
iicTxpacketptr = iicTxDat; // set pointer to the start of the array.
I2caRegs.I2CSTR.bit.RRDY = 1; // Clear rx rdy interrupt flag by writing 1 to it
I2caRegs.I2CSTR.bit.XRDY = 1; // Clear tx empty interrupt flag by writing 1 to it
I2caRegs.I2CSTR.bit.AAS = 1; // Clear addr as slave interrupt flag by writing 1 to it
I2caRegs.I2CIER.bit.RRDY = SET; // Set receiver data ready interrupt enable
I2caRegs.I2CIER.bit.SCD = SET; // Set STOP received interrupt enable
I2caRegs.I2CIER.bit.AAS = SET; // Set Addressed as slave interrupt enable
}

Interrupt code:

#pragma CODE_SECTION(_IICIsr, "ramfuncs");

#define NOINT 0x00 // None
#define ALINT 0x01 // Arbitration lost
#define NACKINT 0x02 // NACK detected
#define ARDYINT 0x03 // Registers ready to be accessed
#define RRDYINT 0x04 // Receiver data ready
#define XRDYINT 0x05 // Transmit data ready
#define SCDINT 0x06 // Stop condition detected
#define AASINT 0x07 // Addressed as slave

__interrupt void _IICIsr(void)
{
uint16_t intsrc;

intsrc = I2caRegs.I2CISRC.all & 0x0007; // read interrupt source

switch(intsrc)
{
case RRDYINT: // RRDYINT Receive Data Ready Interrupt
   I2caRegs.I2CSTR.bit.RRDY = 1; // Clear rx rdy interrupt flag by writing 1 to it
   if(iicRxpacketptr-iicRxDat < MAX_IIC_DATA_BUFF) // dont overflow buffer
       *iicRxpacketptr++ = (uint8_t) I2caRegs.I2CDRR; // read D0...Dn-1
  else
      iicRxpacketptr = iicRxDat; // set pointer to the start of the array.
 break;
case SCDINT: // SCDINT Stop condition detected
  I2caRegs.I2CSTR.bit.SCD = 1; // Clear stop condition interrupt flag by writing 1 to it
  iicRxpacketptr = iicRxDat; // set pointer to the start of the array.

break;
case XRDYINT: // XRDYINT Transmit Data Ready Interrupt
  I2caRegs.I2CSTR.bit.XRDY = 1; // Clear tx rdy interrupt flag by writing 1 to it
  if(iicTxpacketptr-iicTxDat < MAX_IIC_DATA_BUFF) // dont overflow buffer
     I2caRegs.I2CDXR = *iicTxpacketptr++; //
  else
   iicTxpacketptr = iicTxDat; // set pointer to the start of the array.
break;
case AASINT:
   I2caRegs.I2CSTR.bit.AAS = 1; // Clear addr as slave interrupt flag by writing 1 to it
   I2caRegs.I2CSTR.bit.RRDY = 1; // Clear rx rdy interrupt flag by writing 1 to it
   I2caRegs.I2CSTR.bit.XRDY = 1; // Clear tx rdy interrupt flag by writing 1 to it
   if(I2caRegs.I2CDRR & 1) // READ cmd from main
  {
     I2caRegs.I2CMDR.bit.TRX = SET; // SET TX mode, clr RX mode
     I2caRegs.I2CIER.bit.RRDY = CLR; // CLR receiver data ready interrupt enable
     I2caRegs.I2CIER.bit.XRDY = SET; // SET TX data ready interrupt enable
     I2caRegs.I2CDXR = *iicTxpacketptr++; // send out first byte
  }
  else
  {
    I2caRegs.I2CSTR.bit.SDIR = 1; // slave direction, clear bit to indicate slave receiver

    I2caRegs.I2CMDR.bit.TRX = CLR; // CLR TX mode, set RX mode
    I2caRegs.I2CIER.bit.RRDY = SET; // Set receiver data ready interrupt enable
    I2caRegs.I2CIER.bit.XRDY = CLR; // CLR TX data ready interrupt enable
  }
break;
default:
break;
}
I2caRegs.I2CSTR.bit.RRDY = 1; // Clear rx rdy interrupt flag by writing 1 to it
I2caRegs.I2CSTR.bit.XRDY = 1; // Clear tx empty interrupt flag by writing 1 to it
I2caRegs.I2CSTR.bit.AAS = 1; // Clear addr as slave interrupt flag by writing 1 to it

PieCtrlRegs.PIEACK.all |= PIEACK_GROUP8;
// PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;
}

  • Hi,

    I am writing to let you know that a C2000 team member has been assigned to answer to this post.

    Thanks
    Vasudha
  • Steven,

    I am not sure why you would see contention unless your master I2C device is not following the Open drain bus configuration. It appears that someone is trying to hold the clock line low and control the bus, but the master that is driving this clock is not releasing the bus.

    Do you see this contention only during this procedure?
    What other devices are on the I2C bus? is it possible to remove them one-by one until the contention goes away?
    Does the F28020 ever enter the I2C interrupt and respond properly?

    Thanks,
    Mark
  • The master on the bus is an MSP430F66xx. There are no other devices on the bus.

    When I make the system just a MSP430 master transmitter that writes 8 data bytes to the TMS320 slave receiver, all is fine. See scope plot below.

    Only when I make the MSP430 a master receiver and the TMS320 the slave transmitter, do I find the contention on SCL. 

    Questions:

    1. What is the best way to switch the slave from receiver to transmitter when the master sends the slave address/data address/with R/WB=1?

  • Hi Steve,

    Steven Leone said:
    1. What is the best way to switch the slave from receiver to transmitter when the master sends the slave address/data address/with R/WB=1?

    While the device is in slave mode and not free data format mode the TRX is don't care and the peripheral will switch between receiver and transmitter based upon the R/W bit from the master. This is outlined in Table 7 from the I2C Module Reference Guide:

    Questions

    1. Can you confirm you are entering the 'case RRDYINT: // RRDYINT Receive Data Ready Interrupt' portion of the ISR when receiving data from the transmitter ("Addr 0x00" in your first post's image)?

    2. My understanding, and Mark may come in later to clarify/correct, is that the slave will respond to a Master read request with the data placed in I2CDXR register without any further configuration. In the code provided, the only time I2CDXR gets written is within the 'case XRDYINT: // XRDYINT Transmit Data Ready Interrupt' which is not enabled within the initialization code. There is a chance the contention comes from waiting for I2CDXR to be written with valid data to be ready to respond to the Master read request. Can you try adding the following to the initialization code and make sure I2CDXR gets loaded with data?

    I2caRegs.I2CIER.bit.XRDY = SET; // Set transmitter data ready interrupt enable

    Comment

    It is not clear to me either why a AASINT is not being triggered, but one thing to note is the AAS bit in the I2CSTR register is cleared by a repeated START condition or STOP condition so there is the possibility the repeated START is clearing this bit before being caught by the ISR.

    Best Regards,

    Mark-

  • That works!

    Thanks for support.  As you outlined, a slave will automatically go to TX mode on R/WB=1.  Then if the TX RDY interrupts are enabled, it will trigger.

    I really dont need the AAS interrupt, I thought I needed it to switch to TX mode.