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 driver and NAK behaviour

Other Parts Discussed in Thread: TM4C1231H6PGE

I have tm4C1231h6pge, and I tried both tirtos 1.10.00.23 and 1.21.00.09 with the same behaviour.

I can communicate successfully through i2c from Tiva to an EEprom, using I2C_transfer() function.

Conversely when the slave replies a NAK the function I2C_transfer() never returns.

I tried both I2C_MODE_BLOCKING and I2C_MODE_CALLBACK

How to avoid this behaviour?

best regards

  • Mastupristi,

    That's a bug, the driver should never get stuck in a manner that it doesn't return. I filed a bug to add a timeout feature to the I2C_transfer API (SDOCM00106457).

    I'm wondering if there is something going on with the I2C bus that would prevent the I2C controller from getting interrupts. Have you attempted to analyze on happening on the I2C bus? Are the I2C pins pulled high?

    Are you doing anything else in your application, such as disabling global interrupts or something?

    What EEPROM are you using? I'd like to try to replicate this.

  • Hi Tom,

    i have developed a simple sample to replicate the behaviour (it is attached).

    is very simple: I trigger the i2c transaction from a task. A pin goes hi before call to I2C_transfer() and the goes low after:

    Void task1(UArg arg0, UArg arg1)
    {
    	// setup the pin
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);
        ROM_GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_5);
        ROM_GPIOPinWrite(GPIO_PORTJ_BASE, GPIO_PIN_5, 0);
    
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
        /* I2C0 Init */
        /* Enable the peripheral */
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
    
        /* Configure the appropriate pins to be I2C instead of GPIO. */
        ROM_GPIOPinConfigure(GPIO_PB2_I2C0SCL);
        ROM_GPIOPinConfigure(GPIO_PB3_I2C0SDA);
        ROM_GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
        ROM_GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
    //    ROM_I2CMasterInitExpClk(I2C0_BASE, 24576000UL, false);
    
        I2C_init();
    
        I2C_Params  i2cParams;
    
        /* Create I2C for usage */
        I2C_Params_init(&i2cParams); // ok defaults
        hI2c = I2C_open(I2CIDX, &i2cParams);
    
        UChar c;
        I2C_Transaction i2cTransaction;
    
        i2cTransaction.slaveAddress = 0x30; /* 7-bit slave address, not present on bus */
        i2cTransaction.writeBuf = &c; /* txBuffer to be TX'd */
        i2cTransaction.writeCount = 1;
        i2cTransaction.readBuf = NULL;           /* rxBuffer to be RX'd */
        i2cTransaction.readCount = 0;             /* Number of bytes to be RX'd */
    
        ROM_GPIOPinWrite(GPIO_PORTJ_BASE, GPIO_PIN_5, GPIO_PIN_5);
        I2C_transfer(hI2c, &i2cTransaction);
        ROM_GPIOPinWrite(GPIO_PORTJ_BASE, GPIO_PIN_5, 0);
    }
    

    note that I deliberately make a transaction with device 0x30 that is not present on the i2c bus.

    I also have the scope trace:

    the green and cyan trace are SDA and SCL signals, and the magenta is the moving pin (PJ5), ant it never get back to low.

    If I try to debug and place a breakpoint on line 39, just after I2C_transfer() call, that point is never reached.

    I have tried to debug also the source code of TI-RTOS driver, in particular I2CTiva_transfer() in file ti/tirtos_1_21_00_09/packages/ti/drivers/i2c/I2CTiva.c:

    /*
     *  ======== I2CTiva_transfer ========
     */
    Bool I2CTiva_transfer(I2C_Handle handle, I2C_Transaction *transaction)
    {
        UInt                   key;
        Bool                   ret = FALSE;
        I2CTiva_Object        *object = handle->object;
        I2CTiva_HWAttrs const *hwAttrs = handle->hwAttrs;
    
        /* Check if anything needs to be written or read */
        if ((!transaction->writeCount) && (!transaction->readCount)) {
            /* Nothing to write or read */
            return (ret);
        }
    
        if (object->transferMode == I2C_MODE_CALLBACK) {
            /* Check if a transfer is in progress */
            key = Hwi_disable();
            if (object->headPtr) {
                /* Transfer in progress */
    
                /*
                 * Update the message pointed by the tailPtr to point to the next
                 * message in the queue
                 */
                object->tailPtr->nextPtr = transaction;
    
                /* Update the tailPtr to point to the last message */
                object->tailPtr = transaction;
    
                /* I2C is still being used */
                Hwi_restore(key);
                return (TRUE);
            }
            else {
                /* Store the headPtr indicating I2C is in use */
                object->headPtr = transaction;
                object->tailPtr = transaction;
            }
            Hwi_restore(key);
        }
    
        /* Acquire the lock for this particular I2C handle */
        Semaphore_pend(Semaphore_handle(&(object->mutex)), BIOS_WAIT_FOREVER);
    
        /*
         * I2CTiva_primeTransfer is a longer process and
         * protection is needed from the I2C interrupt
         */
        Hwi_disableInterrupt(hwAttrs->intNum);
        I2CTiva_primeTransfer(object, hwAttrs, transaction);
        Hwi_enableInterrupt(hwAttrs->intNum);
    
        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 == I2C_IDLE_MODE) {
                Log_print1(Diags_USER1, "I2C:(%p) Transfer OK", hwAttrs->baseAddr);
                ret = TRUE;
            }
        }
        else {
            /* Always return true if in Asynchronous mode */
            ret = TRUE;
        }
    
        /* Release the lock for this particular I2C handle */
        Semaphore_post(Semaphore_handle(&(object->mutex)));
    
        /* Return the number of bytes transfered by the I2C */
        return (ret);
    }
    

    I f I place a break point at line 72, that point is never reached, but if I place the breakpoint at line 64 (the Semaphore_post()) I can go ahead step by step, and all goes well.

    I think that in normal conditions it will hangs on Semaphore_post(), as if the i2c interrupt trigger any more.

    Tom Kopriva said:

    What EEPROM are you using? I'd like to try to replicate this.

    I use an M24M02, but as told above you can replicate by sending a write transaction to an inexistent address.

    best regards

    max

    hello_TivaTM4C1231H6PGE.tar.gz
  • Max,

    I was able to reproduce the NACK with a bad I2C address. I've added a fix below in i2c/I2CTiva.c at L381 that worked for me. I created another bug ID to track this problem (SDOCM00106479).

    Can you try adding this fix in C:\ti\tirtos_1_21_00_09\packages\ti\drivers\i2c\I2CTiva.c and then rebuild TI-RTOS drivers?

    c:\ti\tirtos_1_21_00_09>..\xdctools_3_25_04_88\gmake.exe -f tirtos.mak drivers

            object->mode = I2C_ERROR;
    
            if (errStatus & (I2C_MASTER_ERR_ARB_LOST | I2C_MASTER_ERR_ADDR_ACK)) {
                I2CTiva_completeTransfer((I2C_Handle) arg);
            }
            else 

  • I tried:

    ubuntu@ubuntu-VirtualBox:~/ti/tirtos_1_21_00_09$ ../xdctools_3_25_04_88/gmake -f tirtos.mak drivers
    gmake: *** c:/ti/tirtos_1_21_00_09/products/MSP430Ware_1_60_02_09a: No such file or directory.  Stop.
    gmake: *** [msp430ware] Error 2
    

    I am under linux, so directory in not c:/ti/tirtos....

    I take a look at tirtos.mak, and there are so many places where c: is specified. is there another make file written for linux or I have to modify tirtos.mak by hand?

    best regards

    max

  • Max,

    You have to modify tirtos.mak. Please refer to section 8.1 ("Rebuilding TI-RTOS") in the TI-RTOS User Guide (<TI-RTOS install dir>/docs/spruhd4e.pdf) for more details.

    Todd

  • I tried to follow section 8.1.

    I modified tirtos.mak, and tried to buld... but no file is built:

    ubuntu@ubuntu-VirtualBox:~/ti/tirtos_1_21_00_09$ ../xdctools_3_25_04_88/gmake -f tirtos.mak clean-drivers
    ubuntu@ubuntu-VirtualBox:~/ti/tirtos_1_21_00_09$ ../xdctools_3_25_04_88/gmake -f tirtos.mak drivers
    

    I search for i2c_tivaware.aem4f, but I cannot find it in any directory.

    And another issue is that it try to build also dirivers for MSP430. and it search for MSP430 compiler, so I modified tirtos.mak in this way:

    ifeq ("$(CCS_BUILD)", "true")
        XDCARGS += \
    #       ti.targets.C28_float='$(ti.targets.C28_float)' \
    #       ti.targets.arm.elf.M3='$(ti.targets.arm.elf.M3)' \
           ti.targets.arm.elf.M4F='$(ti.targets.arm.elf.M4F)'
    #       ti.targets.msp430.elf.MSP430X='$(ti.targets.msp430.elf.MSP430X)' 
    #       MSP430HEADERS='$(MSP430HEADERS)'
    #       allmsp430ware += msp430ware
    endif
    

    but I don't know if it is correct. Where can I find more detailed help about tirtos recompilation?

    I attach tirtos.mak and build log.

    best regards

    max

    tirtos_build.tar.gz
  • Max,

    I haven't seen that error before. I'd undo the comments in tirtos.mak and comment out the other "ccOpts" from tirtos.bld instead.

    var ccOpts = {
    //    "ti.targets.C28_float"             : " -mo -g ",
    //    "ti.targets.arm.elf.M3"            : " -ms -g --gcc --define=ccs ",
        "ti.targets.arm.elf.M4F"           : " -ms -g --gcc --define=ccs ",
    //    "ti.targets.msp430.elf.MSP430X"    : " -g ",
    
    //    "iar.targets.msp430.MSP430X_small" : " ",
    //    "iar.targets.arm.M4F"              : " -Dewarm -DIAR",
    
    //    "gnu.targets.arm.M3"              : " -g -D gcc ",
    //    "gnu.targets.arm.M4F"             : " -g -D gcc ",
    };

  • another problem.

    ubuntu@ubuntu-VirtualBox:~/ti/tirtos_1_21_00_09$ ../xdctools_3_25_04_88/gmake -f tirtos.mak drivers
    tirtos.mak:90: *** Recursive variable `MSP430HEADERS' references itself (eventually).  Stop.
    

    it's frustrating...

    I attach tirtos.mak and tirtos.bld to be sure have modified them in the right way.

    best regards

    max

    tirtos_build_files.tar.gz
  • Max,

    I'm able to reproduce this problem and I agree with you it's frustrating for me too.

    It's definitely a bug and we'll fix it. I'll get back to you with a set of files and instructions that will for you.

  • 4382.M4Fonly.zip

    Max,

    Attached are the tirtos.mak and tirtos.bld files that build M4F only. The problem you getting here was a corner case for which we didn't test for in 1.21 makefiles. This fortunately won't be a problem for our next major release as we're overhauling the makefile system.

    I hope this will get you on your way in the I2C NAK problem that you're seeing. Let me know how it goes if this doesn't work out... Sorry about the frustrations.

  • Unfortunately still does not work.

    I attach build log. I run the following command line:

    ../xdctools_3_25_04_88/gmake -f tirtos.mak drivers

    but if you search for "drivers" word into log file you cannot find anything, as if the drivers were not to be built.

    Where am I wrong?

    best regards

    max

     

  • I tried removing the directory packages/ti/examples to speedup build.


    nothing change.
     
    I attach new log. It seems that only packages/ti/tirtos directory is considered, but no binary, library or other files are built
     
    I am getting more and more frustrated
     
    best regards
    max
  • Max,

    mastupristi said:
    I tried removing the directory packages/ti/examples to speedup build.

    What do you mean by "removing"? I can't say what will happen if directories are deleted from packages/. The tirtos.mak and tirtos.bld files worked for me on a fresh install if TI-RTOS.

    I'd suggest to start with a fresh install of TI-RTOS and copy the posted tirtos.bld and tirtos.mak. From within the TI-RTOS directory call:

    ../xdctools_3_25_04_88/gmake -f tirtos.mak clean-drivers drivers

    Check if TI-RTOS driver libraries exist at ./packages/ti/driver/lib/*.aem4f

    ls ./packages/ti/drivers/lib/*/*.aem4f

    After verifying the libraries exist, update the I2C driver with the fix and then you should just be able to call

    ../xdctools_3_25_04_88/gmake -f tirtos.mak drivers

  • Libraries have been successfully built. My first test on patched i2c driver are positive.

    Now start a more intensive test session.

     

    best regards