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.

RTOS/MSP430F5529: I2C driver block

Part Number: MSP430F5529
Other Parts Discussed in Thread: TMP006, MSP-EXP430F5529LP,

Tool/software: TI-RTOS

Hi,

when I use the RTOS I2C driver, the program will block if the I2C device not connect. If my machine's i2c device bad, the machine will hang because i2c driver block. It can't be accepted.

Is there any RTOS I2C driver with timeout examples?

tirtos_msp43x_2_20_00_06 and bios_6_46_00_23

  • Hi,

    You can use the I2C driver in either blocking mode or callback mode. You can find a full description of the I2C driver and how to use it here. Additionally, you can find information on all the TI RTOS Drivers by following the link below:

    Best regards, 

    Caleb Overbay

  • Hi, Caleb

     I use example I2C_TMP006, use MSP-EXP430F5529LP.

     The program will block if I don't connect I2C device.

     The program is blocked on I2CUSCIB_transfer() function,  Semaphore_pend(Semaphore_handle(&(object->transferComplete)), BIOS_WAIT_FOREVER) as below show:

        /*
         * I2CUSCIB_primeTransfer is a longer process and
         * protection is needed from the I2C interrupt
         */
        USCI_B_I2C_disableInterrupt(hwAttrs->baseAddr, ALL_INTERRUPTS);
        I2CUSCIB_primeTransfer(object, hwAttrs, transaction);
        USCI_B_I2C_enableInterrupt(hwAttrs->baseAddr, ALL_INTERRUPTS);
    
        if (object->transferMode == I2C_MODE_BLOCKING) {
            Log_print1(Diags_USER1,"I2C:(%p) Pending on transferComplete semaphore",
                                    hwAttrs->baseAddr);
            /*
             * Wait for the transfer to complete here.
             * It's OK to block from here because the I2C's Hwi will unblock
             * upon errors
             */
            Semaphore_pend(Semaphore_handle(&(object->transferComplete)),
                    BIOS_WAIT_FOREVER);
    
            Log_print1(Diags_USER1, "I2C:(%p) Transaction completed",
                                     hwAttrs->baseAddr);
    
            /* Hwi handle has posted a 'transferComplete' check for Errors */
            if (object->mode == I2CUSCIB_IDLE_MODE) {
                Log_print1(Diags_USER1, "I2C:(%p) Transfer OK", hwAttrs->baseAddr);
                ret = true;
            }
        }
        else {
            /* Always return true if in Asynchronous mode */
            ret = true;
        }
    
    

  • Hi,

    As I described before you can use the I2C driver in either blocking or callback mode. You can see the check for this in the code you've posted:

    if (object->transferMode == I2C_MODE_BLOCKING) {

    The example you've mentioned is using the driver in blocking mode. So you'll need to reconfigure the I2C params before opening the I2C driver as specified in the links I previously provided. Here is an example provided in the links of setting up the driver in callback mode:

    I2C_Handle      handle;
    I2C_Params      params;
    I2C_Transaction i2cTransaction;
    I2C_Params_init(&params);
    params.transferMode  = I2C_MODE_CALLBACK;
    params.transferCallbackFxn = someI2CCallbackFunction;
    handle = I2C_open(someI2C_configIndexValue, &params);
    if (!handle) {
        System_printf("I2C did not open");
    }

    Best regards, 
    Caleb Overbay

  • Hi,

    I following the program and find the blocking place as below red line while(!(HWREG8(baseAddress + OFS_UCBxIFG) & UCTXIFG)):

    void USCI_B_I2C_masterSendMultiByteFinish(uint16_t baseAddress,
                                              uint8_t txData)
    {
        //If interrupts are not used, poll for flags
        if(!(HWREG8(baseAddress + OFS_UCBxIE) & UCTXIE))
        {
            //Poll for transmit interrupt flag.
            while(!(HWREG8(baseAddress + OFS_UCBxIFG) & UCTXIFG))
            {
                ;
            }
        }
    
        //Send single byte data.
        HWREG8(baseAddress + OFS_UCBxTXBUF) = txData;
    
        //Poll for transmit interrupt flag.
        while(!(HWREG8(baseAddress + OFS_UCBxIFG) & UCTXIFG))
        {
            ;
        }
    
        //Send stop condition.
        HWREG8(baseAddress + OFS_UCBxCTL1) |= UCTXSTP;
    }
    

    In I2CUSCIB_transfer(...) function, after call 

        USCI_B_I2C_disableInterrupt(hwAttrs->baseAddr, ALL_INTERRUPTS);
        I2CUSCIB_primeTransfer(object, hwAttrs, transaction);
        USCI_B_I2C_enableInterrupt(hwAttrs->baseAddr, ALL_INTERRUPTS);
    

    will goto interrupt process

    void I2CUSCIB_hwiIntFxn(UArg index)
    {
        unsigned int            key;
        uint8_t                 intStatus;
        I2CUSCIB_Object        *object = (&I2C_config[index])->object;
        I2CUSCIB_HWAttrs const *hwAttrs = (&I2C_config[index])->hwAttrs;
    
        /* Get the interrupt status of the I2C controller */
        intStatus = USCI_B_I2C_getInterruptStatus(hwAttrs->baseAddr,ALL_INTERRUPTS);
    
        Log_print1(Diags_USER2, "Status Reg: 0x%x", intStatus);
    
        /* Clear interrupt source */
        USCI_B_I2C_clearInterrupt(hwAttrs->baseAddr, ALL_INTERRUPTS);
    
        .........
    .......... return; }

    intStatus just get the UCTXIFG, and UCNACKIFG will be ignore, so the program will bolck on USCI_B_I2C_masterSendMultiByteFinish() function. 

    if I use break point on the line intStatus = USCI_B_I2C_getInterruptStatus(hwAttrs->baseAddr,ALL_INTERRUPTS) then step to next sentence, the intStatus will get UCTXIFG and UCNACKIFG. It seams that the time from set I2C start to interrupt process get intStatus, is not enough to get UCNACKIFG.

  • Hi,

    Just to confirm, you are using the driver in callback mode and it is still blocking on the portions of code you've specified above?

    Best regards,
    Caleb Overbay
  • Hi,

    Both callback and block mode  will blocking on the the portions if no device connect to I2C Bus.

  • Hi, 

    If the driver is still blocking when using callback mode you'll need to create a timeout for the portions of code that it's blocking on. This can be done using one of the MSP430F5529 timers to count for a designated period of time then break from the loop after it times out. If you need more help implementing something like this let me know where you need assistance and we can work from there. 

    Best regards, 
    Caleb Overbay

**Attention** This is a public forum