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.

MSP430FR50431: What does the timeout parameter mean in the I2C functions?

Part Number: MSP430FR50431

Hello TI experts,

I have a question about the driverlib in eusci_b_i2c.h. There are certain methods that come with a parameter for a timeout. For example, EUSCI_B_I2C_masterSendMultiByteFinishWithTimeout takes in an baseAddress, txData and a timeout. However, the documentation doesn't indicate what that final parameter of timeout means.

What does the timeout parameter mean in functions such as EUSCI_B_I2C_masterSendSingleByteWithTimeout, EUSCI_B_I2C_masterSendMultiByteFinishWithTimeout, EUSCI_B_I2C_masterSendMultiByteStopWithTimeout, EUSCI_B_I2C_masterReceiveMultiByteFinishWithTimeout, and so on. 

Here's the documentation for one of these methods: 

//*****************************************************************************
//
//! \brief Continues multi-byte transmission from Master to Slave with timeout
//!
//! This function is used by the Master module continue each byte of a multi-
//! byte transmission. This function transmits each data byte of a multi-byte
//! transmission to the slave.
//!
//! \param baseAddress is the base address of the I2C Master module.
//! \param txData is the next data byte to be transmitted
//! \param timeout is the amount of time to wait until giving up
//!
//! Modified bits of \b UCBxTXBUF register.
//!
//! \return STATUS_SUCCESS or STATUS_FAILURE of the transmission process.
//
//*****************************************************************************
extern bool EUSCI_B_I2C_masterSendMultiByteNextWithTimeout(uint16_t baseAddress,
uint8_t txData,
uint32_t timeout);

//*****************************************************************************
//
//! \brief Continues multi-byte transmission from Master to Slave with timeout
//!
//! This function is used by the Master module continue each byte of a multi-
//! byte transmission. This function transmits each data byte of a multi-byte
//! transmission to the slave.
//!
//! \param baseAddress is the base address of the I2C Master module.
//! \param txData is the next data byte to be transmitted
//! \param timeout is the amount of time to wait until giving up
//!
//! Modified bits of \b UCBxTXBUF register.
//!
//! \return STATUS_SUCCESS or STATUS_FAILURE of the transmission process.
//
//*****************************************************************************
extern bool EUSCI_B_I2C_masterSendMultiByteNextWithTimeout(uint16_t baseAddress,
                                                           uint8_t txData,
                                                           uint32_t timeout);

In addition, I found a function EUSCI_B_I2C_setTimeout, but that function seems to be related to something else.

  • 1) The timeout value is just a loop count while polling for something. It's denominated in "loops" not time, i.e. not calibrated. One thing this is useful for is detecting an I2C NACK, which driverlib generally doesn't check for.

    2) I2C_setTimeout is an I2C bus timeout, which triggers an interrupt (UCCLTOIFG) if SCL is held low ("stretched") for a "long time" -- there's a choice of 3 timeout values in the range 28-34 ms [Ref User Guide (SLAU367P) Sec 32.3.7.3]. It's handy for detecting if your slave is hung up.

  • Hi Bruce, thanks for your response. It's definitely helpful and makes sense when looking at the source code.

    With that in mind, would these timeout functions be useful for developing non-interrupt driven multi-byte I2C communication? The idea I had in mind is to "optimistically" send I2C messages, and if the slave doesn't respond with a NACK within the timeout period, assume that the slave received the message and continue on with the transaction. In the meantime, I could have the NACK interrupt enabled, and use it to reset the I2C bus if the slave ever does NACK a message.

    With regards to the SCL being held low, I think that might have just cracked another one of my problems with resetting the slave between debug sessions. I'll have to try using that.

    Thanks again!

  • I'm not sure I understand how your "optimistic" transactions will work, but I won't say it can't.

    Things to watch out for: (1) A NACK is one possible cause of a timeout, but not the only one. (2) Generally, the master has to take an active role in the transaction, or the flow control will freeze everything. (3) Eventually the master needs to send a Stop.

  • Here's some pseudocode for how I imagine this would work.

    int main(void) {
    
    	configure_i2c_module();
    	int timeout = 5;
    
    	// Make some transactions, and assume they go through (unless a nack occurs)
    	EUSCI_B_I2C_masterSendMultiByteStartWithTimeout(EUSCI_B1_I2C, some_data, timeout);
    		
    	EUSCI_B_I2C_masterSendMultiByteNextWithTimeout(EUSCI_B1_I2C, some_other_data, timeout);
    	
    	EUSCI_B_I2C_masterSendMultiByteFinishWithTimeout(EUSCI_B1_I2C, final_data, timeout);
    
    }
    
    __interrupt void USCIB1_ISR(void)
    {
        switch(__even_in_range(UCB1IV, USCI_I2C_UCBIT9IFG))
        {
            case USCI_I2C_UCNACKIFG:    // NAK received (master only)         
                handle_nack();
                break;
            default:
                break;
        }
    }

    The idea is that it would send the message, and if the slave doesn't explicitly respond with a NACK, just keep going. In order to make this more robust, I think the code would have to take into account other sources of interrupt as you mentioned.

    I will keep in mind that the Stop condition must be sent, and that the master must be active.

    Thank you very much again.

  • I have some concerns that this sequence wouldn't detect the bus hang condition you were describing over in the other thread -- since you're not checking for a timeout, it would fail and you wouldn't know it.

    Also, a timeout of 5 (loops) is pretty short for the second and third calls, which are expected to take at least one byte time (9 bits * BRW); it might be OK for the first call.