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 Busy- and Error Flags on TM4C1292

Other Parts Discussed in Thread: TM4C1292NCPDT, TM4C129DNCZAD

Hello out there,


I'm using a TM4C1292NCPDT and I've got several problems with I2C.

First of all I realized the Busy-Flag in I2CMCS doesn't seem to be stable right after executing I2CMasterControl() function. I solved this problem by waiting a few clock cycles before waiting on the busy flag with I2CMasterBusy(). But maybe there is an other possibility. Has anyone had similar problems? How did you solve it?

The other issue I have is related to the error flags by reading the I2CMCS with I2CMasterErr(). The function always returns 0, although there was no address acknoledge. Am I doing something wrong?


The function I use for transmitting via I2C looks like this:

/**
****************************************************************************
*           
\b Name:    Bi_I2CTransmit
*           
* \brief    transmits a defined number of bytes via I2C instance and don't check for errors
*           
* \param   	I2CName			=> typedef enum ::i2cID (see 'Bi_I2C.h')
* \param	SlaveAddr		=> I2C address of desired slave device
* \param	DataPtr			=> pointer to data to transmit
* \param	NumBytes		=> number of bytes to transmit
*           
* \return   returns the number of transmitted bytes
*           
* \remark
*			- function used waits until data is transmitted
*			- I2C errors are ignored
*           
****************************************************************************/
U32 Bi_I2CTransmit(const i2cID I2CName, const U8 SlaveAddr, const U8 *DataPtr, const U32 NumBytes)
{
	U32 I2CBase     = I2CGetBase(I2CName);
    U32 ErrState    = 0;
	U32 Bytes       = 0;
	
	if (I2CBase != 0)
	{
		// Wait for I2C controller to be idle
		while ( I2CMasterBusy(I2CBase) );
		
		// Prepare write to slave address
		I2CMasterSlaveAddrSet(I2CBase, SlaveAddr, false);
		
		// Whait until I2C bus is not busy	
		while ( I2CMasterBusBusy(I2CBase) );
		
		while ( (Bytes < NumBytes)&&(ErrState==0) )
		{
            // Tranfer nex byte to I2C hardware and wait for idle state
  			I2CMasterDataPut(I2CBase, DataPtr[Bytes]);
            while ( I2CMasterBusy(I2CBase) );
			
			// Single byte send requested
			if (NumBytes == 1)
			{
				// Initiate single send
				I2CMasterControl(I2CBase, I2C_MASTER_CMD_SINGLE_SEND);
			}
			// First byte to transmit
			else if ( Bytes == 0 )
			{
				// Initiate start
				I2CMasterControl(I2CBase, I2C_MASTER_CMD_BURST_SEND_START);
			}
			// Last byte to transmit
			else if ( Bytes == NumBytes-1 )
			{
				// Initiate stop
				I2CMasterControl(I2CBase, I2C_MASTER_CMD_BURST_SEND_FINISH);
			}
			// All other bytes
			else
			{
				I2CMasterControl(I2CBase, I2C_MASTER_CMD_BURST_SEND_CONT);
			}
            
            // Wait a few cycles then wait for I2C controller to be idle
            for (U32 Wait=15; Wait>0; Wait--);
            
            while ( I2CMasterBusy(I2CBase) );
            
            // Check for I2C Errors
            ErrState = I2CMasterErr(I2CBase);
            
            if (ErrState == 0)
			{
                Bytes++;
            }
		}
	}
	
	return Bytes;
}

  • Hello Daniel,

    You are correct on the both the points you made

    1. After setting the I2CMCS there is some time for which the I2C Master is not busy. So a delay or complemented while statement may be used. A delay is also equally helpful

    while (!( I2CMasterBusBusy(I2CBase) ));
    while ( I2CMasterBusBusy(I2CBase) );

    2. When polling the I2CMasterBusy, the final read which causes the Master to become IDLE, causes the ADDR or DATA not acknowledged status bit to be cleared as well. You can alternatively use the I2CMRIS register as well to check for ADDR or DATA NACK and clear the sticky status bit in the I2CMRIS using I2CMICR before any new transaction.

    Hope this information helps

    Regards

    Amit

  • Hello Amit,

    thanks a lot for your quick answer! This information will help me a lot!

    Sry for my late reply! I thought I will get an email, when my post is replied but obviously there was none. Never mind...

    Best regards
    Daniel

  • I'm afraid, but I still have problems with the I2C. I try to poll the Addess ACK after writing to a I2C EEPROM but the processor leaves the loop, waiting for the Adress ACK, although there was none.

  • Hello Daniel,

    Are you polling the I2CMRIS or I2CMCS register? As I mentioned earlier, reading the I2CMCS for Busy Status will cause the ACK bit status to be lost since the register is a Read Clear.

    A code post of the section which would detail this would be useful for a code review

    Regards

    Amit

  • I'm polling the raw interrupt status for the NACK bit, as you suggested. But I still use the I2CMasterBusy() function because the datasheet says the I2C error status is valid when I2C is not busy, only.
    I did't get how am I supposed to check for the I2C busy status, then?


    The code is shown below. The Bi_I2CTransmit() function is polled for it's return. In this way, the Bi_EEPROMWrite() function keeps on transmitting I2C data untill the correct number of bytes was sent and thus the I2C EEPROM is no longer busy.

    /**
    ****************************************************************************
    *
    \b Name:    Bi_I2CTransmit
    *
    * \brief    Transmit data via I2C interface.
    *
    * This is a blocking function witch waits after each byte until the I2C master
    * hardware is no longer busy. After each byte I2C errors will be checked. In
    * case of an error transmission will be stopped. Check the return parameter
    * to see if transmission was successful.
    *
    * \param   	I2CName     determines the I2C module to use. Possible values
    *                       are defined in enumerated type ::i2cID.
    * \param	SlaveAddr   is the I2C address of desired slave device.
    * \param	DataPtr	    points to the data witch will be transmitted via I2C.
    * \param	NumBytes	is the number of bytes to transmit.
    *
    * \return   Returns the number of transmitted bytes.
    *
    * \note     Do not place breakpoints between I2CMasterControl() call and 
    *           "not-busy, busy, not-busy" waiting! Otherwise processor will
    *           loop forever.
    *
    * \warning  In some cases this functions causes problems because reading
    *           I2C status does not work correctly. Usually it takes some time
    *           after using the I2CMasterControl() api until the busy flag is
    *           stable. If this makes problems use a for() loop instead of
    *           waiting for "not-busy, busy, not-busy".
    *           This problem is NOT documented in the processor's errata sheet!
    *
    ****************************************************************************/
    U32 Bi_I2CTransmit(const i2cID I2CName, const U8 SlaveAddr, const U8 *DataPtr, const U32 NumBytes)
    {
    	U32 I2CBase     = I2CGetBase(I2CName);
        U32 NAckState   = 0;
    	U32 Bytes       = 0;
    	
    	if (I2CBase != 0)
    	{
    		// Wait for I2C controller to be idle
    		while ( I2CMasterBusy(I2CBase) );
    		
    		// Prepare write to slave address
    		I2CMasterSlaveAddrSet(I2CBase, SlaveAddr, false);
    		
    		// Wait until I2C bus is not busy	
    		while ( I2CMasterBusBusy(I2CBase) );
    		
    		while ( (Bytes < NumBytes)&&(NAckState==0) )
    		{
                // Tranfer nex byte to I2C hardware and wait for idle state
      			I2CMasterDataPut(I2CBase, DataPtr[Bytes]);
                while ( I2CMasterBusy(I2CBase) );
    			
    			// Single byte send requested
    			if (NumBytes == 1)
    			{
    				// Initiate single send
    				I2CMasterControl(I2CBase, I2C_MASTER_CMD_SINGLE_SEND);
    			}
    			// First byte to transmit
    			else if ( Bytes == 0 )
    			{
    				// Initiate start
    				I2CMasterControl(I2CBase, I2C_MASTER_CMD_BURST_SEND_START);
    			}
    			// Last byte to transmit
    			else if ( Bytes == NumBytes-1 )
    			{
    				// Initiate stop
    				I2CMasterControl(I2CBase, I2C_MASTER_CMD_BURST_SEND_FINISH);
    			}
    			// All other bytes
    			else
    			{
    				I2CMasterControl(I2CBase, I2C_MASTER_CMD_BURST_SEND_CONT);
    			}
                
                // Wait a few cycles then wait for I2C controller to be idle
                //for (U32 Wait=20; Wait>0; Wait--);
                while ( !(I2CMasterBusy(I2CBase)) );
                while (   I2CMasterBusy(I2CBase)  );
                
                // Check for I2C Errors by reading raw interrupt status
                NAckState = (I2CMasterIntStatusEx(I2CBase, false) & I2C_MASTER_INT_NACK);
                I2CMasterIntClearEx(I2CBase, I2C_MASTER_INT_NACK);
                
                if ( NAckState == 0)
    			{
                    Bytes++;
                }
                else if ( NumBytes != 1)
                {
                    I2CMasterControl(I2CBase, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP);
                    // note: this cmd is only required if this was no single byte transfer
                }
    		}//while ( (Bytes < NumBytes)&&(ErrState==0) )
    	}//if (I2CBase != 0)
    	
    	return Bytes;
    }

  • Hello Daniel,

    Thanks for the code. Based on the code, it would mean that if a Address ACK is recieved, the next byte would be sent. If the Slave device is ACKing the address then all is good.

    Now the million $ question: Is the Slave device sending NACK and the loop is incrementing?

    Regards

    Amit

  • Hello Amit.


    When there was no acknowledge (NAckState != 0), Bytes won't be incremented. The while-loop stops, because NAckState is != 0 and the number of transmitted bytes is returned. In case of a adress NACK that would be 0. Before returning, the STOP command is executed by calling I2CMasterControl(I2CBase, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP).


    The Bi_I2CTransmit() function is called like this by Bi_EEPROMWrite():

    // Wirte data to EEPROM...
            do
            {
                CurrBytesSent = Bi_I2CTransmit(I2C_0, EEPROM_ADDR, DataToSend, CurrBytes+2);
            } while ( (CurrBytesSent-2) != CurrBytes );

    Don't mind about the (CurrBytesSent-2) thing, That's because Bi_EEPROMWirte() adds the 2 byte command code for the EEPROM to the number of bytes, desired to write to the EEPROM. For the paging the Bi_EEPROMWrite() function needs to know how many bytes were already wirtten to the EEPROM and how many bytes there are left to write...never mind.
    The point is that the Bi_I2CTransmit() function sometimes returns a non 0 value although there was no ACK.

    Regards

    Daniel

  • Hello Daniel,

    So when the EEPROM Slave returns a No ACK then the transaction "must" get stopped and the number of pending bytes returned. As I read your message, that is what is happening.

    But if you are saying that you get a No ACK but still the transfer continue till 0 bytes then it would require a scope plot to correspond the code and the actual HW behavior.

    Regards

    Amit

  • Hi Amit,


    I'm sorry, I think I found the problem: In case I stopped the I2C communication due to an NACK the "busy, not-busy, busy" waiting does not work. So I made a for (U32 Wait=20; Wait>0; Wait--); loop. This loop seems to be too short, in some cases. Therefore the Bi_I2CTransmit() function read the wrong NAckStatus and returned a non-zero value though there was no ACK.
    But the problem is still that the I2C's busy flag is not stable after calling I2CMasterControl(). How can I solve this? There is no busy flag in the raw interrupt status...

    Regards

    Daniel

  • Hello Daniel,

    Due to delay in processing after writing a control word in MCS, this may happen. To avoid this you can use so that it first waits for I2C Master to get busy and then waits for the command

    while(!I2CMasterBusy(I2C0_BASE));

    while(I2CMasterBusy(I2C0_BASE));

    Alternatively, the following (100 is just a arbitrary number)

    SysCtlDelay(100);

    while(I2CMasterBusy(I2C0_BASE));

    Regards

    Amit

  • Hi Amit,

    as I said, I tried this already. But it doesn't work allways:

    while(!I2CMasterBusy(I2C0_BASE));
    while(I2CMasterBusy(I2C0_BASE));

    Is ther no other possibility to check for I2C busy status? Is looping with for() or SysCtlDelay() the only one to solve this issue?

    I just tried this, but it doesn't work, too:

    while ( !(I2CMasterIntStatusEx(I2CBase, false)& I2C_MASTER_INT_DATA ) );

    Regards

    Daniel

  • Hello Daniel,

    The use of while or delay loop has worked reliably so far. Is there a possibility that there is some other interrupt source which is causing it to miss the timing.

    The Interrupt bits may be used, to signal end of the data byte transfer, but before the while loop do make sure that the I2CMRIS bits are cleared by writing 1 to I2CMICR bits. Or alternatively use the Interrupt Handler to send data and wait till Stop Interrupt is asserted

    Regards

    Amit

  • I got the solution!!!! :)

    // Wait for the current byte to be transmitted. Then whait for the
    // I2C master to be idle.
    while ( !(I2CMasterIntStatusEx(I2CBase, false) & I2C_MASTER_INT_DATA) );
    while (   I2CMasterBusy(I2CBase)  );
    
    // Check for I2C Errors by reading raw interrupt status
    NAckState = (I2CMasterIntStatusEx(I2CBase, false) & I2C_MASTER_INT_NACK);
    I2CMasterIntClearEx(I2CBase, I2C_MASTER_INT_NACK|I2C_MASTER_INT_DATA);
    // I2C status can not be used, because the NACK status will be overwritten
    // by the I2CMasterBusy() function.
    

  • Hello TI World:

    I too am having serious issues with the I2C in the TM4C129x microcontroller and with the documentation: DS-TM4C129DNCZAD-15863.2743, SPMS440B.

    The comment by TI employee and Guru Amit (on July 8, 2014) to supposedly solve the issue(s) follows:

    Due to delay in processing after writing a control word in MCS, this may happen. To avoid this you can use so that it first waits for I2C Master to get busy and then waits for the command  

    while(!I2CMasterBusy(I2C0_BASE));  

    while(I2CMasterBusy(I2C0_BASE));

    However, if the TM4C129x I2C ‘happens’ to not have that ‘this may happen’ occurrence described when writing a control word (i.e. writing to I2C Master Control Status (MCS) register, offset 4), the device will simply get stuck for eternity at: while(!I2CMasterBusy(I2C0_BASE));

    Thank you,

    Tim Ball TDB Consulting

  • Hello Tim,

    TM4C129 was meant to have a better Interrupt based solution when compared to TM4C123 so that polling mode could be removed. However since a lot of customer code still used polling we ran into this issue. After considering all the requirements and possible issue with the method that I have mentioned, the suggestion had been modified to put a dummy delay instead of the ! condition. A delay of 100 has been found to be sufficient even for 120MHz operation.

    Regards
    Amit
  • Hello TI:

    For the "I got the solution!!!! :)" solution to work, is it true that it is absolutely positively necessary to first enable interrupts using I2CMasterIntEnableEx() with an associated handler function etcetera, etcetera, etcetera?
    If so, does this mean that it is absolutely positively impossible to reliably use the polling mode of the Tiva TM4C129X I2C (and 123?)?
    If so, please indicate so in ALL TM4C129X (and 123?) Data Sheets, Technical Reference Manuals, and other documentation as well as the TivaWare Peripheral Library documentation.

    Thank you,
    Tim
  • Hello Tim,

    No. It is possible to use the polling method provided the delay mechanism is used. The interrupt mechanism is better on 129 when compared to 123 besides the changes made for FIFO, Burst Mode.

    Regards
    Amit
  • Hello Amit:

    Thank you for your quick responses.

    After executing and closely examining many I2C transfers on the TM4C129X while utilizing the TivaWare I2C functions, it has been discovered that you are absolutely correct that it is absolutely positively necessary to include a delay (e.g. SysCtlDelay(100);) after writing to the Master Control/Status (MCS) register. If that delay is not performed, and the busy bit happens to get “stuck”, the command is likely to be ignored and the NEXT command written will be implemented instead, completely skipping the previous command and causing all sorts of havoc in the I2C transfers with slave devices.

    Note too that the defined constant names in the TivaWare Peripheral Driver Library for the MCS register values are not quite intuitive and are indeed misleading (e.g. I2C_MASTER_CMD_SINGLE_RECEIVE).

    Also, values specified in the Tiva TM4C129DNCZAD Microcontroller DATA SHEET (DS-TM4C129DNCZAD-15863.2743, SPMS440B), section ‘21.3.1.5 Repeated Start’ and in figures referred to are erroneous in that a 0X07 (Stop, Start, Run) (i.e. I2C_MASTER_CMD_SINGLE_RECEIVE) must be written to the MCS register for a “Master RECEIVE with Repeated START after Master TRANSMIT”.

    Appreciatively,

    Tim

  • Hello Tim

    Which version of the data sheet are you referring to. I checked the June 18, 2014 version of the data sheet and the command being written to MCS in the figure is 1011 which is ACK, START and RUN

    Regards
    Amit
  • Hello Amit:

    In regard to the SysCtlDelay(100); required after writing to the MCS register for I2C polling with the TM4C129X, it has been discovered that 100 cycles is too much of a delay for some devices (e.g. Compass device).

    So far, 50 cycles has proven to be acceptable with a Compass device and a Gyroscope device. I will be communicating with other I2C devices as well and will report my findings.

    In regard to the Repeated Start, the only MCS value that has successfully accessed I2C devices (e.g. Compass and Gyroscope) is 07H (STOP, START, RUN and not 03H (START, RUN) nor 0BH (ACK, START, RUN) as shown in the Data Sheet pages in question that follow, which are in the June 18, 2014 version that you referred to:

    Thank you,

    Tim Ball

    TDB Consulting

  • Hello Tim,

    That would be the cause because the flowchart only mentions a Repeated Start as after that the user may have multiple data to read or write. if the intent is however to just read one byte then indeed it has to be terminated with 0x7.

    Regards
    Amit
  • CAUTION! It appears that such issues may be due to calling the I2CMasterBusBusy(ui32Base) function instead of the I2CMasterBusy(ui32Base) function.

  • NOTE: Each I2CMasterControl() call must be followed by SysCtlDelay(100) call followed by I2CMasterBusy() call (NOT I2CMasterBusBusy()).

    Have demonstrated that when less than SysCtlDelay(20) is used, the data read can be incorrect (e.g. data read is that of the previous read and not the most recent read).

    Have also demonstrated that up to SysCtlDelay(100000) (one-hundred thousand) reads data properly on Gyroscope and Compass.

    Have a nice evening,

    Tim

  • Hello TI (e.g. Amit):

    The Data Sheet of June 18, 2014 indicates that the I2C Master Control/Status (offset 4) Register BUSBSY bit indicates if the I2C bus is currently idle or busy and the BUSY bit indicates if the I2C controller is currently idle or busy.

    I have noticed that others have also, apparently, erroneously used the TivaWare function I2CMasterBusBusy() instead of I2CMasterBusy(). As demonstrated and resolved in previous comments about those functions, there is indeed a difference between those two bits. I would like to know what the effective difference is between those two bits (i.e. BUSBSY (bus busy) and BUSY (controller busy)) as far as signaling, timing, and which interrupt each of those bits is associated with and how much of a delay can be expected after the associated interrupt till the bit is set or cleared.

    Thank you,

    Tim

  • Hello Tim,

    The BUSBUSY is a passive monitoring of the I2C Line. When any master (including the TM4C master on a multimaster bus) places a START condition the I2C controller declares a BUSBUSY till a STOP condition is not placed.

    The BUSY condition is when the I2C Master Controller starts a transaction on the bus.

    From an interrupt perspective, none of them are represented in the Interrupt Status. However BUSY condition can be interpreted from the the interrupt status register bits like START, STOP.

    Regards
    Amit
  • Hi Amit,

    I used HT 7Segment kit connected with tiva TI123 , and the protocol is I2C.
    I Used it to display values every ~100ms 

    I made a WriteBytes Function and Consider what all you said ,  But after Some Second the code Stuck, So I make Special Timer for it not to stuck.
    timer worked correctly and Packet was sent after stuck , but the kit don't response after Stuck.
    and After Stuck my System Timer is Broken !!!

    BOOLEAN EF_BOOLEAN_I2C_Write(U8_t DeviceAddress, U8_t Address, U8_t* DataPtr, U8_t NoOfBytes )
    {
        volatile U8_t ReturnedValue = TRUE;
        volatile U8_t NoAckStatus = TRUE;
    
        U8_t DataCnt = 0;
    //todo add new
        EF_void_TimerStart (I2C_TIMER_ID);
    
        while( ( I2CMasterBusy(I2C_MASTER_BASE) &&  (!EF_BOOLEAN_Timer_IsTimedOut (I2C_TIMER_ID))  ) );
    
        if (EF_BOOLEAN_Timer_IsTimedOut (I2C_TIMER_ID) == TRUE)
        {
            EF_void_TimerStop (I2C_TIMER_ID);
            EF_void_TimerReset(I2C_TIMER_ID);
            ReturnedValue = FALSE;
        }
        EF_void_TimerStop (I2C_TIMER_ID);
        EF_void_TimerReset(I2C_TIMER_ID);
    
        /* define the Device address with read flag =false */
        I2CMasterSlaveAddrSet(I2C_MASTER_BASE, DeviceAddress, false);
        SysCtlDelay(100);
    
        /* Define the wanted Address in the Device to write in */
        I2CMasterDataPut(I2C_MASTER_BASE, Address);
    
        /* start sending */
        I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);
        /* waiting for Sending */
    //    while(!I2CMasterBusy(I2C_MASTER_BASE));
        SysCtlDelay(100);
    
        EF_void_TimerStart (I2C_TIMER_ID);
    
        while( ( I2CMasterBusy(I2C_MASTER_BASE) &&  (!EF_BOOLEAN_Timer_IsTimedOut (I2C_TIMER_ID))  ) );
    
        if (EF_BOOLEAN_Timer_IsTimedOut (I2C_TIMER_ID) == TRUE)
        {
            EF_void_TimerStop (I2C_TIMER_ID);
            EF_void_TimerReset(I2C_TIMER_ID);
            ReturnedValue = FALSE;
    
        }
        EF_void_TimerStop (I2C_TIMER_ID);
        EF_void_TimerReset(I2C_TIMER_ID);
    
    //    if(I2CMasterErr(I2C_MASTER_BASE) != I2C_MASTER_ERR_NONE)
    //    {
    //        return 0;
    //    }
    
        /* send data */
        for(DataCnt = NoOfBytes; DataCnt > 1; DataCnt--) // data
        {
            I2CMasterDataPut(I2C_MASTER_BASE, *DataPtr++);
    
            /* define it is sending continuously */
            I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    
            /* waiting for Sending */
    //        while(!I2CMasterBusy(I2C_MASTER_BASE));
            SysCtlDelay(100);
            EF_void_TimerStart (I2C_TIMER_ID);
    
            while( ( I2CMasterBusy(I2C_MASTER_BASE) &&  (!EF_BOOLEAN_Timer_IsTimedOut (I2C_TIMER_ID))  ) );
    
            if (EF_BOOLEAN_Timer_IsTimedOut (I2C_TIMER_ID) == TRUE)
            {
                EF_void_TimerStop (I2C_TIMER_ID);
                EF_void_TimerReset(I2C_TIMER_ID);
                ReturnedValue = FALSE;
    
            }
            EF_void_TimerStop (I2C_TIMER_ID);
            EF_void_TimerReset(I2C_TIMER_ID);
    //        _delay_ms(10);
    
    //        if(I2CMasterErr(I2C_MASTER_BASE) != I2C_MASTER_ERR_NONE)
    //        {
    //            return 0;
    //        }
        }
    
        /* send the last byte and definig it was the last one */
        I2CMasterDataPut(I2C_MASTER_BASE, *DataPtr);
        I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
        /* waiting for Sending */
        //Returns true if the I2C Master is busy;
    //    while(!I2CMasterBusy(I2C_MASTER_BASE));
        SysCtlDelay(100);
        EF_void_TimerStart (I2C_TIMER_ID);
    
        while ( !(I2CMasterIntStatusEx(I2C_MASTER_BASE, false) & I2C_MASTER_INT_DATA) );
    
        while( ( I2CMasterBusy(I2C_MASTER_BASE) &&  (!EF_BOOLEAN_Timer_IsTimedOut (I2C_TIMER_ID))  ) );
    
        if (EF_BOOLEAN_Timer_IsTimedOut (I2C_TIMER_ID) == TRUE)
        {
            EF_void_TimerStop (I2C_TIMER_ID);
            EF_void_TimerReset(I2C_TIMER_ID);
            ReturnedValue = FALSE;
            I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP);
        }
        EF_void_TimerStop (I2C_TIMER_ID);
        EF_void_TimerReset(I2C_TIMER_ID);
    
        // Check for I2C Errors by reading raw interrupt status
        NoAckStatus = (I2CMasterIntStatusEx(I2C_MASTER_BASE, false) & I2C_MASTER_INT_NACK);
        I2CMasterIntClearEx(I2C_MASTER_BASE, I2C_MASTER_INT_NACK|I2C_MASTER_INT_DATA);
        if ( NoAckStatus == 0)
        {
    //        Bytes++;
        }
        else if ( NoOfBytes > 1)
        {
            I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP);
            // note: this cmd is only required if this was no single byte transfer
        }
        HWREG(I2C_MASTER_BASE + I2C_O_MICR) |= NoAckStatus;
    
    //    if(I2CMasterErr(I2C_MASTER_BASE) != I2C_MASTER_ERR_NONE)
    //    {
    //        return 0;
    //    }
    
        _delay_ms(50);
    
        return ReturnedValue;
    
    }

    Thank you,

  • Hello Ibrahim,

    Where does the code get stuck?

    Regards
    Amit
  • always stuck after some seconds at the Last Byte (I always sent 10 bytes in this application)

        I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
    
        /* waiting for Sending */
    
        //Returns true if the I2C Master is busy;
    
    //    while(!I2CMasterBusy(I2C_MASTER_BASE));
    
        SysCtlDelay(100);
    
        EF_void_TimerStart (I2C_TIMER_ID);
    
    
        while ( !(I2CMasterIntStatusEx(I2C_MASTER_BASE, false) & I2C_MASTER_INT_DATA) );
    
    /***** Stuck here and don't need to work correctly with any new Bytes (But it will receive again without stuck but 7Seg was still displaying the stuck value)*****/
        while( ( I2CMasterBusy(I2C_MASTER_BASE) &&  (!EF_BOOLEAN_Timer_IsTimedOut (I2C_TIMER_ID))

  • Hello Ibrahem,

    So is the BUSY flag still set and the timer has not timed out?

    Regards
    Amit
  • time is out and I think busy flag is low as Many Bytes will be sent correctly (but with the stuck displayed value) after this Stuck was happended
  • Hello Ibrahem

    If bytes are being sent, then you would need to wait for the Busy flag before proceeding.

    Regards
    Amit
  • I made this but still displaying the stuck value on 7 seg kit
    To work correctly, I should disconnected the power and then connect it >>>> and so on ...
    and there is a strange effect , I made a timer interrupt every 1ms (as if my System tick) , when stuck happened , the timeout check for this timer is broken !!!
  • Hello Ibrahem,

    First of all the code should not stay in the Busy Loop unless there is a glitch on the board which causes a misalignment. Can you check the same after enabling the glitch filter?

    Regards
    Amit
  • I put it in the init code , but the same Result .

    I2CMasterGlitchFilterConfigSet(I2C_MASTER_BASE, I2C_MASTER_GLITCH_FILTER_8);
  • Hello Ibrahem,

    I would ask you to check the failing transaction on a scope. Start from the point where the transaction starts till it gets stuck and capture the waveform for both SCL and SDA. Then check if the transactions sees any issue like clock or data glitch and when it gets stuck in the BUSY state, is the SCL being driven low by the Slave!!!

    Regards
    Amit
  • Unfortunately I don't have a scope.
    but I measured the Volt on SCL by Avometer and found that the SCL pin was high.

  • Hello Ibrahem,

    I would try to get hold of a Scope or a Logic Analyzer to understand the failing transaction.

    Regards
    Amit
  • Unfortunately I can't get any one of them.
    Is there Anther Solution except this ? Is there a software Solution ?

    Thank you in advance,
  • Hello Ibrahem,

    Unfortunately not. Did you check LogicPort. It is a low cost 34 channel logic analyzer. It should be easy to procure one.

    Regards
    Amit