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/MSP430FR5969: TI-RTOS 2.20 - I2Ctmp006 example does not works - I2C_transfer() stucks

Part Number: MSP430FR5969

Tool/software: TI-RTOS

Hi,

We are using Texas Instruments' CCS6.2.0 program,

the MCU MSP430FR5969, and also a Bosh BME280 sensor,

which is connected by I2C to MCU under TI-RTOS 2.20 communcations system and XDCtools 3.32.0.6.

At CC6.2.0 program we have downloaded "i2ctmp006_MSP_EXP430FR5969" example. Registers have been changed to BME280.

At "MSP_EXP430FR5969.c" file, pins through which we connect the sensor to MCU have been configured by the following function:

void MSP_EXP430FR5969_initI2C(void){

/*

* NOTE: TI-RTOS examples configure EUSCIB0 as either SPI or I2C. Thus,

* a conflict occurs when the I2C & SPI drivers are used simultaneously in

* an application. Modify the pin mux settings in this file and resolve the

* conflict before running your the application.

*/

GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3,

GPIO_PIN6 | GPIO_PIN5, GPIO_SECONDARY_MODULE_FUNCTION);

I2C_init();

}

At file "i2ctmp006.cfg", at the end of the script it has been added the following:

var hwiParams = new halHwi.Params();

/* I2C Hwi for the EUSCI driver */

hwiParams.arg = 1;

halHwi.create(47, "&I2CEUSCIB_hwiIntFxn", hwiParams);

At file "i2ctmp006.c" the task that is responsible for reading/writing on sensor has been programmed

Void taskFxn(UArg arg0, UArg arg1)

{

unsigned int i;

uint8_t txBuffer[2];

uint8_t rxBuffer[2];

I2C_Handle i2c;

I2C_Params i2cParams;

I2C_Transaction i2cTransaction;

/* Create I2C for usage */

I2C_Params_init(&i2cParams);

i2cParams.transferMode = I2C_MODE_CALLBACK;

i2cParams.bitRate = I2C_400kHz;

// i2cParams.custom =

i2c = I2C_open(Board_I2C_TMP, &i2cParams);

if (i2c == NULL) {

System_abort("Error Initializing I2C\n");System_flush();

}

else {

System_printf("I2C Initialized!\n");System_flush();

}

/* Point to the T ambient register and read its 2 bytes */

txBuffer[0] = 0xE0;

txBuffer[1] = 0xB6;

i2cTransaction.slaveAddress = 0x76; //Board_TMP006_ADDR;

i2cTransaction.writeBuf = txBuffer;

i2cTransaction.writeCount = 2;

i2cTransaction.readBuf = NULL;

i2cTransaction.readCount = 0;

// RESET

I2C_transfer(i2c, &i2cTransaction);

Task_sleep(3000);

txBuffer[0] = 0xD0;

i2cTransaction.slaveAddress = 0x76; //Board_TMP006_ADDR;

i2cTransaction.writeBuf = txBuffer;

i2cTransaction.writeCount = 1;

i2cTransaction.readBuf = rxBuffer;

i2cTransaction.readCount = 1;

/* Take 20 samples and print them out onto the console */

for (i = 0; i < 20; i++) {

if (I2C_transfer(i2c, &i2cTransaction)) {

System_printf("Sample %u: %d - %x (C) -- ", i, rxBuffer[0], rxBuffer[0]);System_flush();

System_printf("2: - %x (C)\n", rxBuffer[1]);System_flush();

}

else {

System_printf("I2C Bus fault\n");System_flush();

}

System_flush();

Task_sleep(1000);

}

/* Deinitialized I2C */

I2C_close(i2c);

System_printf("I2C closed!\n");

System_flush();

}

If the following sentence 
i2cParams.transferMode = I2C_MODE_BLOCKING;

is changed for

i2cParams.transferMode = I2C_MODE_CALLBACK;

it does not blocked but it does not work.

We think something is missing on proyect configuration, buy we are not sure if it is due to hardware interruption or I2C configuration.

Thanks

  • Hi AArmandoGG,

    P3.5/P3.6 do not connect to the eUSCI_B0 module, the only pins available for I2C communication on this device are P1.6/P1.7.  Beyond that you should provide more debug details and logic analyzer or oscilloscope screenshots of the communication bus.

    Regards,
    Ryan

  • Hi

    Thanks a lot. You were right about pins. But unfortunately, problem remains ☹. Would you mind lending us a helping hand please?I2CEUSCIB.h

    /*
     * Copyright (c) 2015-2016, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    #include <stdint.h>
    #include <stdbool.h>
    #include <xdc/runtime/Error.h>
    #include <xdc/runtime/Assert.h>
    #include <xdc/runtime/Diags.h>
    #include <xdc/runtime/Log.h>
    
    #include <ti/drivers/i2c/I2CEUSCIB.h>
    
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/family/msp430/ClockFreqs.h>
    #include <ti/sysbios/hal/Hwi.h>
    #include <ti/sysbios/knl/Semaphore.h>
    
    /* driverlib header files */
    #include <eusci_b_i2c.h>
    
    /*
     *  Pull in the generic MSP430 header file, which will bring in the device
     *  specific header file.  The device specific msp430 header file will
     *  have __MSP430_HAS_EUSCI_B0__ defined if the device supports EUSCI B0.
     */
    #include <msp430.h>
    
    #ifdef __MSP430_HAS_EUSCI_B0__
    
    #define ERROR_INTERRUPTS (EUSCI_B_I2C_NAK_INTERRUPT | \
                              EUSCI_B_I2C_ARBITRATIONLOST_INTERRUPT)
    
    #define ALL_INTERRUPTS (EUSCI_B_I2C_RECEIVE_INTERRUPT0  | \
                            EUSCI_B_I2C_TRANSMIT_INTERRUPT0 | \
                            ERROR_INTERRUPTS)
    
    extern const I2C_Config I2C_config[];
    
    /* Prototypes */
    void         I2CEUSCIB_cancel(I2C_Handle handle);
    void         I2CEUSCIB_close(I2C_Handle handle);
    int          I2CEUSCIB_control(I2C_Handle handle, unsigned int cmd, void *arg);
    void         I2CEUSCIB_init(I2C_Handle handle);
    I2C_Handle   I2CEUSCIB_open(I2C_Handle handle, I2C_Params *params);
    static void  I2CEUSCIB_primeTransfer(I2CEUSCIB_Object        *object,
                                        I2CEUSCIB_HWAttrs const *hwAttrs,
                                        I2C_Transaction *transferMessage);
    bool         I2CEUSCIB_transfer(I2C_Handle handle,
                                         I2C_Transaction *transaction);
    static void  I2CEUSCIB_blockingCallback(I2C_Handle handle,
                                           I2C_Transaction *msg,
                                           bool transferStatus);
    static void  I2CEUSCIB_completeTransfer(I2C_Handle handle);
    
    /* I2C function table for I2CI2CEUSCIB implementation */
    const I2C_FxnTable I2CEUSCIB_fxnTable = {
        I2CEUSCIB_cancel,
        I2CEUSCIB_close,
        I2CEUSCIB_control,
        I2CEUSCIB_init,
        I2CEUSCIB_open,
        I2CEUSCIB_transfer
    };
    
    static const uint32_t bitRate[] = {
        EUSCI_B_I2C_SET_DATA_RATE_100KBPS,  /*  I2C_100kHz = 0 */
        EUSCI_B_I2C_SET_DATA_RATE_400KBPS   /*  I2C_400kHz = 1 */
    };
    
    /*
     *  ======== I2CEUSCIB_cancel ========
     */
    void I2CEUSCIB_cancel(I2C_Handle handle)
    {
        I2CEUSCIB_HWAttrs const *hwAttrs = handle->hwAttrs;
        I2CEUSCIB_Object *object = handle->object;
        EUSCI_B_I2C_initMasterParam eusciI2cParams;
        uint32_t clockFreq;
        uint16_t key;
    
        /* just return if no transfer is in progress */
        if (!object->headPtr) {
            return;
        }
    
        /* disable interrupts, send STOP to complete any transfer */
        key = Hwi_disable();
        EUSCI_B_I2C_disableInterrupt(hwAttrs->baseAddr, ALL_INTERRUPTS);
        EUSCI_B_I2C_masterReceiveMultiByteStop(hwAttrs->baseAddr);
    
        /* call the transfer callback for the current transfer, indicate failure */
        object->transferCallbackFxn(handle, object->currentTransaction, false);
    
        /* also dequeue and call the transfer callbacks for any queued transfers */
        while (object->headPtr != object->tailPtr) {
            object->headPtr = object->headPtr->nextPtr;
            object->transferCallbackFxn(handle, object->headPtr, false);
        }
    
        /* clean up object */
        object->currentTransaction = NULL;
        object->headPtr = NULL;
        object->tailPtr = NULL;
        object->mode = I2CEUSCIB_IDLE_MODE;
    
        /* re-initialize the I2C peripheral */
        switch (hwAttrs->clockSource) {
            case EUSCI_B_I2C_CLOCKSOURCE_ACLK:
                clockFreq = ClockFreqs_getFrequency(ClockFreqs_Clock_ACLK);
                break;
    
            case EUSCI_B_I2C_CLOCKSOURCE_SMCLK:
                clockFreq = ClockFreqs_getFrequency(ClockFreqs_Clock_SMCLK);
                break;
        }
    
        /* disable and the re-initialize master mode */
        EUSCI_B_I2C_disable(hwAttrs->baseAddr);
        eusciI2cParams.selectClockSource = hwAttrs->clockSource;
        eusciI2cParams.i2cClk = clockFreq;
        eusciI2cParams.dataRate = object->bitRate;
        eusciI2cParams.byteCounterThreshold = 0;
        eusciI2cParams.autoSTOPGeneration= EUSCI_B_I2C_NO_AUTO_STOP;
        EUSCI_B_I2C_initMaster(hwAttrs->baseAddr, &eusciI2cParams);
    
        /* clear any pending interrupts */
        EUSCI_B_I2C_clearInterrupt(hwAttrs->baseAddr, ALL_INTERRUPTS);
    
        /* enable I2CEUSCIB Module to start operations */
        EUSCI_B_I2C_enable(hwAttrs->baseAddr);
    
        /* unmask I2CEUSCIB interrupts */
        EUSCI_B_I2C_enableInterrupt(hwAttrs->baseAddr, ALL_INTERRUPTS);
    
        Hwi_restore(key);
    }
    
    /*
     *  ======== I2CEUSCIB_close ========
     */
    void I2CEUSCIB_close(I2C_Handle handle)
    {
        I2CEUSCIB_Object        *object = handle->object;
        I2CEUSCIB_HWAttrs const *hwAttrs = handle->hwAttrs;
    
        /* Check to see if a I2C transaction is in progress */
        Assert_isTrue(object->headPtr == NULL, NULL);
    
        /* Mask I2C interrupts */
        EUSCI_B_I2C_disableInterrupt(hwAttrs->baseAddr, ALL_INTERRUPTS);
    
        /* Disable the I2C Master */
        EUSCI_B_I2C_disable(hwAttrs->baseAddr);
    
        Semaphore_destruct(&(object->mutex));
        if (object->transferMode == I2C_MODE_BLOCKING) {
            Semaphore_destruct(&(object->transferComplete));
        }
    
        object->isOpen = false;
    
        Log_print1(Diags_USER1, "I2C: Object closed 0x%x", hwAttrs->baseAddr);
    
        return;
    }
    
    /*
     *  ======== I2CEUSCIB_control ========
     *  @pre    Function assumes that the handle is not NULL
     */
    int I2CEUSCIB_control(I2C_Handle handle, unsigned int cmd, void *arg)
    {
        /* No implementation yet */
        return (I2C_STATUS_UNDEFINEDCMD);
    }
    
    /*
     *  ======== I2CEUSCIB_hwiIntFxn ========
     *  Hwi interrupt handler to service the I2C peripheral
     *
     *  The handler is a generic handler for an I2C object.
     */
    void I2CEUSCIB_hwiIntFxn(UArg index)
    {
        uint8_t                  intStatus;
        unsigned int             key;
        I2CEUSCIB_Object        *object = (&I2C_config[index])->object;
        I2CEUSCIB_HWAttrs const *hwAttrs = (&I2C_config[index])->hwAttrs;
    
        /* Get the interrupt status of the I2C controller */
        intStatus = EUSCI_B_I2C_getInterruptStatus(hwAttrs->baseAddr,ALL_INTERRUPTS);
    
        Log_print1(Diags_USER2, "Status Reg: 0x%x", intStatus);
    
        /* Clear interrupt source */
        EUSCI_B_I2C_clearInterrupt(hwAttrs->baseAddr, ALL_INTERRUPTS);
    
        /* Check for I2C Errors */
        if ((intStatus & ERROR_INTERRUPTS) || (object->mode == I2CEUSCIB_ERROR)) {
            /* Some sort of error happened! */
            object->mode = I2CEUSCIB_ERROR;
    
            /* Try to send a STOP bit to end all I2C communications immediately
             *
             * EUSCI_B_I2C_masterReceiveMultiByteStop only sends a STOP condition
             * which is needed here
             */
            EUSCI_B_I2C_masterReceiveMultiByteStop(hwAttrs->baseAddr);
    
            Log_print2(Diags_USER1, "I2C:(%p) ISR I2C Bus fault (Status Reg: 0x%x)",
                                     hwAttrs->baseAddr,
                                     intStatus);
        }
    
        /* No errors, now check what we need to do next */
        switch (object->mode) {
    
            /*
             * ERROR case is OK because if an Error is detected, a STOP bit is
             * sent; which in turn will call another interrupt. This interrupt
             * call will then post the transferComplete semaphore to unblock the
             * I2C_transfer function
             */
            case I2CEUSCIB_ERROR:
            case I2CEUSCIB_IDLE_MODE:
                I2CEUSCIB_completeTransfer((I2C_Handle)&I2C_config[index]);
                break;
    
            case I2CEUSCIB_WRITE_MODE:
                if (object->writeCountIdx) {
    
                    /* If we're on last byte to write and have NO data to read */
                    if ((object->writeCountIdx == 1) && (!object->readCountIdx)) {
                        /* Next state: Idle mode */
                        object->mode = I2CEUSCIB_IDLE_MODE;
    
                        /* Send last byte with STOP bit */
                        EUSCI_B_I2C_masterSendMultiByteFinish(hwAttrs->baseAddr,
                                                              *(object->writeBufIdx));
    
                        EUSCI_B_I2C_clearInterrupt(hwAttrs->baseAddr,
                                                   EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
                        Log_print2(Diags_USER2, "I2C:(%p) ISR I2CEUSCIB_WRITE_MODE:"
                                                "Data to write: 0x%x;"
                                                "Writing w/ STOP bit",
                                                 hwAttrs->baseAddr,
                                                *(object->writeBufIdx));
    
                        I2CEUSCIB_completeTransfer((I2C_Handle)&I2C_config[index]);
                    }
                    else {
                        /* Write data contents into data register */
                        EUSCI_B_I2C_masterSendMultiByteNext(hwAttrs->baseAddr,
                                                        *(object->writeBufIdx));
    
                        Log_print3(Diags_USER2,
                                "I2C:(%p) ISR I2CEUSCIB_WRITE_MODE: "
                                "Data to write: 0x%x; "
                                "To slave: 0x%x",
                                hwAttrs->baseAddr,
                                *(object->writeBufIdx),
                                object->currentTransaction->slaveAddress);
    
                        object->writeBufIdx++;
                        object->writeCountIdx--;
                    }
                }
                /*
                 * Done writing data to the I2C slave. If no data needed to be read,
                 * the ISR would not get here as it would have finished the I2C
                 * transfer in the logical check above.
                 */
                else {
                    /* Next state: Receive mode */
                    object->mode = I2CEUSCIB_READ_MODE;
    
                    if (object->readCountIdx > 1) {
                        /* Start the I2C transfer in master receive mode */
                        EUSCI_B_I2C_masterReceiveStart(hwAttrs->baseAddr);
                        Log_print1(Diags_USER2, "I2C:(%p) I2CEUSCIB_WRITE_MODE: -> I2CEUSCIB_READ_MODE; "
                                        "Reading w/ RESTART",
                                         hwAttrs->baseAddr);
                    }
                    else {
                    /*
                     * Start the I2C transfer in master receive mode by sending a
                     * START and STOP bit since it's the last byte
                     */
                        EUSCI_B_I2C_masterReceiveStart(hwAttrs->baseAddr);
                        while ( EUSCI_B_I2C_masterIsStartSent(hwAttrs->baseAddr) ) ;
                        EUSCI_B_I2C_masterReceiveMultiByteStop(hwAttrs->baseAddr);
    
                        Log_print1(Diags_USER2, "I2C:(%p) I2CEUSCIB_WRITE_MODE: -> I2CEUSCIB_READ_MODE; "
                                        "Reading w/ RESTART and STOP",
                                         hwAttrs->baseAddr);
                    }
                }
                break; /* I2CEUSCIB_WRITE_MODE */
    
            case I2CEUSCIB_READ_MODE:
                /* Data read from RXBUF and next byte has already been shifted */
                object->readCountIdx--;
    
                if (object->readCountIdx == 1) {
                    /* Timing critical block which mustn't be simplified - START */
                    key = Hwi_disable();
    
                    EUSCI_B_I2C_masterReceiveMultiByteStop(hwAttrs->baseAddr);
                    *(object->readBufIdx) =
                        EUSCI_B_I2C_masterReceiveMultiByteNext(hwAttrs->baseAddr);
    
                    Hwi_restore(key);
                    /* Timing critical block which mustn't be simplified - END */
    
                    Log_print2(Diags_USER2, "I2C:(%p) ISR I2CEUSCIB_READ_MODE: "
                        "Read data byte: 0x%x ", hwAttrs->baseAddr,
                        *(object->readBufIdx));
    
                    object->readBufIdx++;
                }
                else {
                    *(object->readBufIdx) =
                        EUSCI_B_I2C_masterReceiveMultiByteNext(hwAttrs->baseAddr);
    
                    Log_print2(Diags_USER2, "I2C:(%p) ISR I2CEUSCIB_READ_MODE: "
                        "Read data byte: 0x%x ", hwAttrs->baseAddr,
                        *(object->readBufIdx));
    
                    if (object->readCountIdx) {
                        /* Increment buffer pointer */
                        object->readBufIdx++;
                    }
                    else {
                        /* Next state: Idle mode */
                        object->mode = I2CEUSCIB_IDLE_MODE;
                        I2CEUSCIB_completeTransfer((I2C_Handle)&I2C_config[index]);
                    }
                }
                break; /* I2CEUSCIB_READ_MODE */
    
            default:
                object->mode = I2CEUSCIB_ERROR;
                break;
        }
    
        return;
    }
    
    /*
     *  ======== I2CEUSCIB_completeTransfer =======
     */
    static void I2CEUSCIB_completeTransfer(I2C_Handle handle)
    {
        I2CEUSCIB_Object    *object = handle->object;
    
        Log_print1(Diags_USER2, "I2C:(%p) ISR Transfer Complete",
                   ((I2CEUSCIB_HWAttrs const  *)(handle->hwAttrs))->baseAddr);
    
        /*
         * Perform callback in a HWI context, thus any tasks or SWIs
         * made ready to run won't start until the interrupt has
         * finished
         */
        object->transferCallbackFxn(handle,
                                    object->currentTransaction,
                                    !((bool)object->mode));
    
        /* See if we need to process any other transactions */
        if (object->headPtr == object->tailPtr) {
            /* No other transactions need to occur */
            object->currentTransaction = NULL;
            object->headPtr = NULL;
    
            Log_print1(Diags_USER2,"I2C:(%p) ISR No other I2C transaction in queue",
                       ((I2CEUSCIB_HWAttrs const  *)(handle->hwAttrs))->baseAddr);
        }
        else {
            /* Another transfer needs to take place */
            object->headPtr = object->headPtr->nextPtr;
    
            Log_print2(Diags_USER2, "I2C:(%p) ISR Priming next I2C transaction "
                                    "(%p) from queue",
                       ((I2CEUSCIB_HWAttrs const *)(handle->hwAttrs))->baseAddr,
                       (UArg)object->headPtr);
    
            I2CEUSCIB_primeTransfer(object,
                                   (I2CEUSCIB_HWAttrs const *)(handle->hwAttrs),
                                   object->headPtr);
        }
    
        return;
    }
    
    /*
     *  ======== I2CEUSCIB_init ========
     */
    void I2CEUSCIB_init(I2C_Handle handle)
    {
        /* Mark the object as available */
        ((I2CEUSCIB_Object *)(handle->object))->isOpen = false;
    }
    
    /*
     *  ======== I2CEUSCIB_open ========
     */
    I2C_Handle I2CEUSCIB_open(I2C_Handle handle, I2C_Params *params)
    {
        unsigned int                key;
        uint32_t                    clockFreq;
        EUSCI_B_I2C_initMasterParam eusciI2cParams;
        Semaphore_Params            semParams;
        I2CEUSCIB_Object           *object = handle->object;
        I2CEUSCIB_HWAttrs const    *hwAttrs = handle->hwAttrs;
    
        /* Determine if the device index was already opened */
        key = Hwi_disable();
        if (object->isOpen == true) {
            Hwi_restore(key);
            return (NULL);
        }
        /* Mark the handle as being used */
        object->isOpen = true;
        Hwi_restore(key);
    
        /* Save parameters */
        object->transferMode = params->transferMode;
        object->transferCallbackFxn = params->transferCallbackFxn;
    
        /*
         * Create threadsafe handles for this I2C peripheral
         * Semaphore to provide exclusive access to the I2C peripheral
         */
        Semaphore_Params_init(&semParams);
        semParams.mode = Semaphore_Mode_BINARY;
        Semaphore_construct(&(object->mutex), 1, &semParams);
    
        /*
         * Store a callback function that posts the transfer complete
         * semaphore for synchronous mode
         */
        if (object->transferMode == I2C_MODE_BLOCKING) {
            /*
             * Semaphore to cause the waiting task to block for the I2C
             * to finish
             */
            Semaphore_construct(&(object->transferComplete), 0, &semParams);
    
            /* Store internal callback function */
            object->transferCallbackFxn = I2CEUSCIB_blockingCallback;
        }
        else {
            /* Check to see if a callback function was defined for async mode */
            Assert_isTrue(object->transferCallbackFxn != NULL, NULL);
        }
    
        /* Get the I2C clock input frequency */
        switch (hwAttrs->clockSource) {
            case EUSCI_B_I2C_CLOCKSOURCE_ACLK:
                clockFreq = ClockFreqs_getFrequency(ClockFreqs_Clock_ACLK);
                Log_print1(Diags_USER1, "ClockFreqs_getFrequency ACLK: %d", clockFreq);
                break;
    
            case EUSCI_B_I2C_CLOCKSOURCE_SMCLK:
                clockFreq = ClockFreqs_getFrequency(ClockFreqs_Clock_SMCLK);
                Log_print1(Diags_USER1, "ClockFreqs_getFrequency SMCLK: %d", clockFreq);
                break;
    
            default:
                Log_error0("I2C: Error determining clock source");
                I2CEUSCIB_close(handle);
                return (NULL);
        }
    
        /* Specify the idle state for this I2C peripheral */
        object->mode = I2CEUSCIB_IDLE_MODE;
    
        /* Clear the head pointer */
        object->headPtr = NULL;
        object->tailPtr = NULL;
    
        Log_print1(Diags_USER1, "I2C: Object created 0x%x", hwAttrs->baseAddr);
    
        eusciI2cParams.selectClockSource = hwAttrs->clockSource;
        eusciI2cParams.i2cClk = clockFreq;
        eusciI2cParams.dataRate = bitRate[params->bitRate];
        object->bitRate = bitRate[params->bitRate];
        eusciI2cParams.byteCounterThreshold = 0;
        eusciI2cParams.autoSTOPGeneration= EUSCI_B_I2C_NO_AUTO_STOP;
        EUSCI_B_I2C_initMaster(hwAttrs->baseAddr, &eusciI2cParams);
    
        /* Clear any pending interrupts */
        EUSCI_B_I2C_clearInterrupt(hwAttrs->baseAddr, ALL_INTERRUPTS);
    
        /* Enable I2CEUSCIB Module to start operations */
        EUSCI_B_I2C_enable(hwAttrs->baseAddr);
    
        /* Unmask I2CEUSCIB interrupts */
        EUSCI_B_I2C_enableInterrupt(hwAttrs->baseAddr, ALL_INTERRUPTS);
    
        /* Return the handle */
        return (handle);
    }
    
    /*
     *  ======== I2CEUSCIB_primeTransfer =======
     */
    static void I2CEUSCIB_primeTransfer(I2CEUSCIB_Object        *object,
                                        I2CEUSCIB_HWAttrs const *hwAttrs,
                                        I2C_Transaction         *transaction)
    {
        /* Store the new internal counters and pointers */
        object->currentTransaction = transaction;
    
        object->writeBufIdx = transaction->writeBuf;
        object->writeCountIdx = transaction->writeCount;
    
        object->readBufIdx = transaction->readBuf;
        object->readCountIdx = transaction->readCount;
    
        Log_print2(Diags_USER1, "I2C:(%p) Starting transaction to slave: 0x%x",
                                 hwAttrs->baseAddr,
                                 object->currentTransaction->slaveAddress);
    
        /* Specify the I2C slave address */
        EUSCI_B_I2C_setSlaveAddress(hwAttrs->baseAddr,
            object->currentTransaction->slaveAddress);
    
        /* Start transfer in Transmit mode */
        if (object->writeCountIdx) {
            /* Update the I2C mode */
            object->mode = I2CEUSCIB_WRITE_MODE;
    
            EUSCI_B_I2C_setMode(hwAttrs->baseAddr, EUSCI_B_I2C_TRANSMIT_MODE);
    
            /* Start the I2C transfer by sending the start bit */
            EUSCI_B_I2C_masterSendStart(hwAttrs->baseAddr);
    
            Log_print1(Diags_USER2, "I2C:(%p) I2CEUSCIB_IDLE_MODE: -> I2CEUSCIB_WRITE_MODE; "
                                    "Writing w/ START",
                                     hwAttrs->baseAddr);
        }
        /* Start transfer in Receive mode */
        else {
            /* Update the I2C mode */
            object->mode = I2CEUSCIB_READ_MODE;
            EUSCI_B_I2C_setMode(hwAttrs->baseAddr, EUSCI_B_I2C_RECEIVE_MODE);
            EUSCI_B_I2C_masterReceiveStart(hwAttrs->baseAddr);
    
            if (object->readCountIdx > 1) {
                Log_print1(Diags_USER2, "I2C:(%p) I2CEUSCIB_IDLE_MODE: -> I2CEUSCIB_READ_MODE; "
                                        "Reading w/ ACK",
                                         hwAttrs->baseAddr);
            }
            else {
                /*
                 * Need to wait for the start bit to have transmitted before we can
                 * tell it to send a stop bit.
                 */
                while (EUSCI_B_I2C_masterIsStartSent(hwAttrs->baseAddr));
    
                EUSCI_B_I2C_masterReceiveMultiByteStop(hwAttrs->baseAddr);
    
                Log_print1(Diags_USER2, "I2C:(%p) I2CEUSCIB_IDLE_MODE: -> I2CEUSCIB_READ_MODE; "
                                        "Reading w/ NACK",
                                         hwAttrs->baseAddr);
            }
        }
    }
    
    /*
     *  ======== I2CEUSCIB_transfer ========
     */
    bool I2CEUSCIB_transfer(I2C_Handle handle,
                                  I2C_Transaction *transaction)
    {
        unsigned int             key;
        bool                     ret = false;
        I2CEUSCIB_Object        *object = handle->object;
        I2CEUSCIB_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);
    
        /*
         * I2CEUSCIB_primeTransfer is a longer process and
         * protection is needed from the I2C interrupt
         */
        EUSCI_B_I2C_disableInterrupt(hwAttrs->baseAddr, ALL_INTERRUPTS);
        I2CEUSCIB_primeTransfer(object, hwAttrs, transaction);
        EUSCI_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 == I2CEUSCIB_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);
    }
    
    /*
     *  ======== I2CEUSCIB_blockingCallback ========
     */
    static void I2CEUSCIB_blockingCallback(I2C_Handle handle,
                                          I2C_Transaction *msg,
                                          bool transferStatus)
    {
        I2CEUSCIB_Object        *object = handle->object;
    
        Log_print1(Diags_USER1, "I2C:(%p) posting transferComplete semaphore",
                   ((I2CEUSCIB_HWAttrs const *)(handle->hwAttrs))->baseAddr);
    
        /* Indicate transfer complete */
        Semaphore_post(Semaphore_handle(&(object->transferComplete)));
    }
    
    #endif /*  __MSP430_HAS_EUSCI_B0__ */
    

    Pins are already connected the following way:

            BME280                 MSP430FR5969        

            VCC                  VCC  // 5V

            GND                  GND

            SCL                   P1_6 // CLK (clock)

            SDA                  P1_7 // DATA

            CSB                   -      // not neccesary

            SD0                  GND  // slaveaddress: 0x76

     

    Program has the following files: 

    i2ctmp006.c                                             // main

    Board.h

    MSP_EXP430FR5969.h

    MSP_EXP430FR5969.c

    i2ctmp006.cfg

    I2C communication is configured: 

    i2ctmp006.c

    // Task that Works for the following communication: - TI example:

    Void taskFxn(UArg arg0, UArg arg1)
    {
        uint8_t         txBuffer[2];                 // buffer de escritura a I2C
        uint8_t         rxBuffer[1];                 // buffer de lectura  de I2C
        
        I2C_Handle      i2c;
        I2C_Params      i2cParams;
        I2C_Transaction i2cTransaction;
     
        /* Creamos I2C */
        I2C_Params_init(&i2cParams);
        i2cParams.transferMode = I2C_MODE_CALLBACK;
        i2cParams.transferCallbackFxn = (I2C_CallbackFxn) espera;
        i2cParams.bitRate = I2C_400kHz;
        
        /* Abrimos I2C */
        if ((i2c = I2C_open(Board_I2C_TMP, &i2cParams)) == NULL) { System_abort("Error Initializing I2C\n"); System_flush(); }
        else { System_printf("I2C Initialized!\n"); System_flush(); }
     
        /* Lectura del ID del sensor BME280: register address 0xD0 -  register data: 0x60 (valor que se debiera obtener en la lectura)*/
        txBuffer[0] = 0xD0; // register address
        txBuffer[1] = 0x00; // reset register (protocolo I2C)
        
        i2cTransaction.slaveAddress = 0x76;          // slave address
        i2cTransaction.writeBuf = txBuffer;
        i2cTransaction.writeCount = 2;                  // bytes a escribir
        i2cTransaction.readBuf = rxBuffer;
        i2cTransaction.readCount = 1;                  // bytes a leer
        
        
        if (I2C_transfer(i2c, &i2cTransaction)) { System_printf("Register data: %d (C)\n", rxBuffer[0]); System_flush(); }
            else { System_printf("I2C Bus fault\n"); System_flush(); }
     
        /* Cerramos I2C */
        I2C_close(i2c);
        System_printf("I2C closed!\n");
     
        System_flush();
    }
     

    MSP_EXP430FR5969.h (has not been modified) – it was configured to be use for I2CB0; we mean, EUSCIB0

    /*!

     *  @def    MSP_EXP430FR5969_I2CName

     *  @brief  Enum of I2C names on the MSP_EXP430FR5969 dev board

     */

    typedef enum MSP_EXP430FR5969_I2CName {

        MSP_EXP430FR5969_I2CB0 = 0,

        MSP_EXP430FR5969_I2CCOUNT

    } MSP_EXP430FR5969_I2CName;

    MSP_EXP430FR5969.c

    /*
     *  =============================== I2C ===============================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(I2C_config, ".const:I2C_config")
    #pragma DATA_SECTION(i2cEUSCIBHWAttrs, ".const:i2cEUSCIBHWAttrs")
    #endif
     
    #include <ti/drivers/I2C.h>
    #include <ti/drivers/i2c/I2CEUSCIB.h>
     
    I2CEUSCIB_Object i2cEUSCIBObjects[MSP_EXP430FR5969_I2CCOUNT];
     
    const I2CEUSCIB_HWAttrs i2cEUSCIBHWAttrs[MSP_EXP430FR5969_I2CCOUNT] = {
        {
            .baseAddr = EUSCI_B0_BASE,
            .clockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK
        }
    };
     
    const I2C_Config I2C_config[] = {
        {
            .fxnTablePtr = &I2CEUSCIB_fxnTable,
            .object = &i2cEUSCIBObjects[0],
            .hwAttrs = &i2cEUSCIBHWAttrs[0]
        },
        {NULL, NULL, NULL}
    };
     
    /*
     *  ======== MSP_EXP430FR5969_initI2C ========
     */
    void MSP_EXP430FR5969_initI2C(void)
    {
        /*
         * NOTE: TI-RTOS examples configure EUSCIB0 as either SPI or I2C.  Thus,
         * a conflict occurs when the I2C & SPI drivers are used simultaneously in
         * an application.  Modify the pin mux settings in this file and resolve the
         * conflict before running your the application.
         */
        GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
            GPIO_PIN6 | GPIO_PIN7, GPIO_SECONDARY_MODULE_FUNCTION);
     
        I2C_init();
    }

    // here are pins through which communication is done:

    i2ctmp006.cfg

    // at the end of the script we have added the hardware interruption catch, to deal with I2C driver:

    var halHwi0Params = new halHwi.Params();
    halHwi0Params.instance.name = "halHwi0";
    Program.global.halHwi0 = halHwi.create(47, "&I2CEUSCIB_hwiIntFxn", halHwi0Params);
     

    // On header MSP430FR5969.h we find that interruption vector points to USCI_B0 with number 47

    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define USCI_B0_VECTOR          ".int47"                     /* 0xFFEE USCI B0 Receive/Transmit */
    #else
    #define USCI_B0_VECTOR          (47 * 1u)                    /* 0xFFEE USCI B0 Receive/Transmit */
    #endif

    ---

    Initially, it seems to be a bug in I2C driver for TI-RTOS of Driverlib.

    Once communication has begun, we see how data are transferred and received on analyzer.

     It seems that the problem is on function I2CEUSCIB_hwiIntFxn() of I2CEUSCIB.c module, as it does not pick hardware interruption, or as it does not clean it, and it does not dump received bytes at reader buffer.

    At all Texas’ forums, it is said that driver seems to have the semaphore that deal with mentioned interruption wrongly configured, so it keeps on an infinite loop waiting to close communication.  

    There have been proposed the following possible solutions: 

    - top u a TIMEOUT on semaphore

    - to use I2C_Cancel() function to close communication

    - to use I2C_MODE_CALLBACK module ad deal the above mentioned possible solutions in only one function, that means to manipulate the driver to access to critical sections.

    ( find attached files for I2C driver module  for EUSCIB)

     

  • What is the VCC and pull-up resistance values? If it is 5 V as indicated in the notes then it will not work properly on a MSP430 device which operates at a maximum of 3.6 V. Have you tried running the TI-RTOS examples without any modifications, or a C or DriverLib example? Views of the communication bus would be appreciated.

    Regards,
    Ryan
  • My apologizes Ryan, it was a errata: VCC=3.3V
    We have tried with driverlib I2C and it works perfectly. But in RTOS we have the problem we have explained you on above message.

    would you mind lending us a helping hand with this issue please?

    Thanks in advance,
    Angel
  • I have submitted a code bug investigation and will let you know of the outcome.

    Regards,
    Ryan

**Attention** This is a public forum