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/TMS320F28377D: I2C stall at ARDY after setup MDR register

Part Number: TMS320F28377D

Tool/software: Code Composer Studio

Hi, I'm using F28377 to communicate with MSP430FR2XXX by I2C, F28377 as master.

In 28377 master Tx mode,  after Tx condition(MDR) setting, I wait ARDY to 1, and check ACK for data transmit, however, it is usually stall ARDY check. 

ARDY is always 0 no matter how long I wait, all I can do is to reset the I2C modele (IRS = 0).

here's the question:

1. If ARDY is 0 after setting Tx MDR, does it means the start bit, slave address, direction, one of them is fail during transmit?

2. While stall on ARDY( = 0), the STR.BB is 0, is that means the start bit is fail? or because ARDY == 0, all I2C register is unreachable?

3. Does MSP430 hold SDA low may make ARDY stall at 0?

  • Hi Willie,

    Is the ARDY stall happening after you set the STT bit (start condition) and the slave address is sent? Can you share your I2C init and setup code for the F2837x master device? Checking the I2C waveforms with a logic analyzer would likely help debug this further as well.

    You should be able to do something like the below for a master transmitter:

        //
        // Wait until the STP bit is cleared from any previous master communication
        // Clearing of this bit by the module is delayed until after the SCD bit is
        // set. If this bit is not checked prior to initiating a new message, the
        // I2C could get confused.
        //
        if (I2caRegs.I2CMDR.bit.STP == 1)
        {
            return I2C_STP_NOT_READY_ERROR;
        }
    
        //
        // Setup slave address
        //
        I2caRegs.I2CSAR = slave_addr;
    
        //
        // Check if bus busy
        //
        if (I2caRegs.I2CSTR.bit.BB == 1)
        {
            return I2C_BUS_BUSY_ERROR;
        }
    
        //
        // Set up as master transmitter
        // FREE + MST + TRX + IRS
        //
        I2caRegs.I2CMDR.all = 0x4620;
    
        //
        // Setup number of bytes to send
        // == (# of register bytes) + (# of data[] buffer bytes)
        //
        I2caRegs.I2CCNT = reg_size + data_size;
    
        I2caRegs.I2CMDR.bit.STT = 0x1; // Send START condition
        I2caRegs.I2CMDR.bit.STP = 0x1; // STOP condition will be
                                       // generated when I2CCNT is zero
    
        while(!I2caRegs.I2CSTR.bit.ARDY) // Wait for slave address to be sent
        {
            if(I2caRegs.I2CSTR.bit.XSMT == 0)
            {
                break; // ACK received on slave address
            }
        }
    
        #if I2C_NACK_CHECK // check if NACK was received
            if(I2caRegs.I2CSTR.bit.NACK == 1)
            {
                I2caRegs.I2CMDR.bit.STP = 1;
                I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
    
                return I2C_NACK_ERROR;
            }
        #endif

    Best,

    Kevin

  • hi, Kevin

    ARDY stall after setting MDR = 0x26A0, here's my setup code

    int I2C_MSP430_Tx(Uint16 Slave_address, Uint16 TransBuffer[], Uint16 Trans_DataBytes)
    {
    	int index_byte = 0;	// in bytes
    	Uint16 NACK_retryCnt = 0;
            Uint32 ClearSTP_retryCnt = 0;
    	I2caRegs.I2CSAR.all = Slave_address;
    
    	do {
    		NACK_retryCnt++;
    		if( NACK_retryCnt > MAXRETRY_NACK ) {
    			I2caRegs.I2CMDR.bit.STP = 1;		// Send Stop cmd
    			return TxFAIL;
    		}
    
    		I2caRegs.I2CSTR.bit.NACK = 1; // Clear NACK condition
    		DELAY_US(10);
    
    		if( ClearSTPTimeout() == TimeOut_Happen ) {
    			return TxFAIL;
    		}
    
    		// Setup I2C Tx Command Byte
    		I2caRegs.I2CMDR.all = 0x26A0;			// IRS, RM, TRX, MST, STT On
    
               while( I2caRegs.I2CSTR.bit.ARDY != 1 );         ////////////////////ARDY stalls HERE
    	} while( I2caRegs.I2CSTR.bit.NACK == 1 ); // Clear if NACK received
    
    	// Send Tx buffer
    	for( index_byte = 0; index_byte < Trans_DataBytes; index_byte++ ) {
    		while( I2caRegs.I2CSTR.bit.XRDY == 0 );
    		I2caRegs.I2CDXR.all = TransBuffer[index_byte];
    	}
    
    	// Send Stop cmd
    	I2caRegs.I2CMDR.bit.STP = 1;		
    	// Detect stop condition
    	if( ClearSTPTimeout() == TimeOut_Happen ) {
    		return TxFAIL;
    	}
    }
    
    int ClearSTPTimeout(void)
    {
    	Uint32 ClearSTP_retryCnt = 0;
    
    	// Detect a stop bit
    	while( I2caRegs.I2CMDR.bit.STP != 0 ) {
    		ClearSTP_retryCnt++;
    		I2caRegs.I2CSTR.bit.SCD = 1;
    		DELAY_US(5);
    
    		if( ClearSTP_retryCnt > TIMEOUTCNT_STP ) {
    			SendSTOP();
    			return TimeOut_Happen;
    		}
    	}
    
    	return TimeOut_Pass;
    }
    

  • Hi Willie,

    Are you able to probe the I2CI2C bus and provide screenshots of the waveforms? That would help debug if there's an issue more.

    Try replacing line 25 above with the below:

    while(!I2caRegs.I2CSTR.bit.ARDY) // Wait for slave address to be sent
    {
        if(I2caRegs.I2CSTR.bit.XSMT == 0)
        {
            break; // ACK received on slave address
        }
    }
    

    Best,

    Kevin

  • Hi Kevin, 

    Because of PCB layout, it is hard to probe I2C bus, I'll try to do it.

    However, can you explain why "XSMT == 0" means received ACK on address? why not detect NACK?

    Also, please answer the following question on my first post:

    1. If ARDY is 0 after setting Tx MDR, does it means the start bit, slave address, direction, one of them is fail during transmit?

    2. While stall on ARDY( = 0), the STR.BB is 0, is that means the start bit is fail? or because ARDY == 0, all I2C register is unreachable?

  • Hi Willie,

    OK, probing the bus will be the easiest way to understand what is going on.

    Willie LAi said:
    However, can you explain why "XSMT == 0" means received ACK on address? why not detect NACK?

    I think it should be XRDY flag, not XSMT actually. See the wiki article below. The NACK bit may be able to be used for ACK checking, but you'd need to include a delay since NACK is 0 on reset (i.e. wait some time for slave address to be sent out).

    https://processors.wiki.ti.com/index.php/I2C_Tips#Detecting_and_handling_NACK

    The NACK handling method described in the Wiki article is the following:

    while(!(I2caRegs.I2CSTR.bit.ARDY | I2caRegs.I2CSTR.bit.XRDY)); // Wait for slave address to be sent
    
    if(I2caRegs.I2CSTR.bit.NACK == 1) // Check for NACK
    {
    	I2caRegs.I2CMDR.bit.STP = 1;
    	I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
    
    
    	return I2C_NACK_ERROR;
    }

    Willie LAi said:

    1. If ARDY is 0 after setting Tx MDR, does it means the start bit, slave address, direction, one of them is fail during transmit?

    2. While stall on ARDY( = 0), the STR.BB is 0, is that means the start bit is fail? or because ARDY == 0, all I2C register is unreachable?

    I don't think so for either of these, ARDY is zero at reset which may have something to do with what you're seeing. The correct method is to check XRDY as well as ARDY as described in that wiki page I linked.

    Please try the above out and let me know how it works.

    Best,

    Kevin

  • Hi Kevin, 

    Kevin Allen18 said:

    I think it should be XRDY flag, not XSMT actually. 

    I said XMST because your reply say so on Sep.28. Which one is correct?

    From the wiki you post, it says " // Wait for "XRDY" flag to transmit data or "ARDY" if we get NACKed "

    Does it means ARDY make sense only on NACK detection? Here's the 28377 spec on page 2221

    ARDY at spec says I2C module registers, is it include any register? or just for NACK? if ARDY == 0 but XRDY == 1, can we trust XRDY?

    Should we wait for ARDY before access any I2C module registers?

  • Hi Willie,

    Willie LAi said:
    I said XMST because your reply say so on Sep.28. Which one is correct?

    XRDY is the correct one for the NACK checking scheme. XSMT was my mistake earlier.

    Willie LAi said:
    Does it means ARDY make sense only on NACK detection? Here's the 28377 spec on page 2221

    I tested your original code (below) on the F2806x device and ARDY got set to 1 for both the NACK and ACK cases of the slave address actually. Let me test the same on F2837x and get back to you soon.

    while( I2caRegs.I2CSTR.bit.ARDY != 1 );

    Best,

    Kevin

  • Hi Willie,

    I just tried the below code on a F28379D LaunchPad and ARDY got set to 1 for both the NACK and ACK cases, try with the STP and Bus busy checks I included. Something else must be wrong with your SW or HW. Please try probing the I2C lines to debug this further.

        //
        // Wait until the STP bit is cleared from any previous master communication
        // Clearing of this bit by the module is delayed until after the SCD bit is
        // set. If this bit is not checked prior to initiating a new message, the
        // I2C could get confused.
        //
        if (I2caRegs.I2CMDR.bit.STP == 1)
        {
            return I2C_STP_NOT_READY_ERROR;
        }
    
        //
        // Setup slave address
        //
        I2caRegs.I2CSAR.all = slave_addr;
    
        //
        // Check if bus busy
        //
        if (I2caRegs.I2CSTR.bit.BB == 1)
        {
            return I2C_BUS_BUSY_ERROR;
        }
    
        I2caRegs.I2CMDR.all = 0x26A0;
    
    
        while( I2caRegs.I2CSTR.bit.ARDY != 1 );
    
        #if I2C_NACK_CHECK // check if NACK was received
            if(I2caRegs.I2CSTR.bit.NACK == 1)
            {
                ESTOP0;
                I2caRegs.I2CMDR.bit.STP = 1;
                I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
    
                return I2C_NACK_ERROR;
            }
        #endif

    Best,

    Kevin