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.

CCS/MSP432P401R: I2C communication gets stuck at Poll for transmit interrupt flag

Part Number: MSP432P401R

Tool/software: Code Composer Studio

Hello,

i want to read and write to registers on a VL53L0X and i have already gotten help here (

CCS/MSP432P401R: problems connecting sensor VL53L0X via I2C - MSP low-power microcontroller forum - MSP...

e2e.ti.com
Part Number: MSP432P401R Tool/software: Code Composer Studio Hello, i try to connect the Tof Sensor VL53L0X with MSP432 Launchpad via I2C. The sensor is connected
).

I try to implement a Arduino library from github to my msp432, so i can use the tof-sensor.

My Code looks like this:

#include "driverlib.h"
#include "TofSensor.h"


#define SLAVE_ADDRESS_1 0x29


// Decode VCSEL (vertical cavity surface emitting laser) pulse period in PCLKs
// from register value
// based on VL53L0X_decode_vcsel_period()
#define decodeVcselPeriod(reg_val)      (((reg_val) + 1) << 1)

// Encode VCSEL pulse period register value from period in PCLKs
// based on VL53L0X_encode_vcsel_period()
#define encodeVcselPeriod(period_pclks) (((period_pclks) >> 1) - 1)

// Calculate macro period in *nanoseconds* from VCSEL period in PCLKs
// based on VL53L0X_calc_macro_period_ps()
// PLL_period_ps = 1655; macro_period_vclks = 2304
#define calcMacroPeriod(vcsel_period_pclks) ((((uint32_t)2304 * (vcsel_period_pclks) * 1655) + 500) / 1000)


eUSCI_I2C_MasterConfig i2cConfig =
{
        EUSCI_B_I2C_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
        3000000,                               // 3Mhz
        EUSCI_B_I2C_SET_DATA_RATE_400KBPS,      // Desired I2C Clock of 400khz
        0,                                      // No byte counter threshold
        EUSCI_B_I2C_NO_AUTO_STOP
};


bool TofSensor_Init(bool io_2v8)
{

    // Configure P6.4 for EUSCI_B1_SPI_I2C EUSCI_B1_SPI_I2C.SCL P6.5 for EUSCI_B1_SPI_I2C EUSCI_B1_SPI_I2C.SDA
         MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6, GPIO_PIN4 + GPIO_PIN5, GPIO_PRIMARY_MODULE_FUNCTION);

        MAP_GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN0);

        /* Initializing I2C Master to SMCLK at 400khz with no autostop */
        MAP_I2C_initMaster(EUSCI_B1_BASE, &i2cConfig);

        /* Specify slave address */
        MAP_I2C_setSlaveAddress(EUSCI_B1_BASE, SLAVE_ADDRESS_1);

        MAP_I2C_setMode(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_MODE);

        /* Enable I2C Module to start operations */
        MAP_I2C_enableModule(EUSCI_B1_BASE);

        //Boot sensor
        MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P6,GPIO_PIN0);
        __delay_cycles(1000);// Delay for sensor to be ready
        uint8_t address=0xC0;
        uint8_t regC0;
        MAP_I2C_masterSendSingleByte(EUSCI_B1_BASE,address);
        regC0 = MAP_I2C_masterReceiveSingleByte(EUSCI_B1_BASE);

Sometime it stucks in the masterSendSingleByte function at:
//Poll for transmit interrupt flag.
    while (!(EUSCI_B_CMSIS(moduleInstance)->rIFG.r & UCTXIFG))
        ;

I can't figure out why. For your information, I wanted to use VL53L0X without interrupts and therefore GPIO1 is not connected.
Maybe someone can explain why it stucks it the function?

Thanks in advance.

  • >        __delay_cycles(1000);// Delay for sensor to be ready

    Supposing that your CPU is running at 3MHz, this is about 300 usec. VL53L0x data sheet (DocID029104 Rev 2) Fig 9 says that startup can take (40+1) msec. My guess is that you're getting a NACK since the device hasn't completed startup.

    SendSingleByte doesn't check for NACK. One option is to use I2C_masterSendSingleByteWithTimeout. If that function times out, it does not send a Stop, so if you see a failure (returns false) you need to call something like I2C_masterReceiveMultiByteStop (don't dwell on the function's name). I'm guessing that the units for the "timeout" parameter are about 1 usec (at 3MHz).

    And bump your startup delay to something like 45 msec.

  • thanks for you answer.

    i tried it with setting a higher delay and the MAP_I2C_masterSendSingleByteWithTimeout function, with no success. It is always false.

    __delay_cycles(135000);// 45ms at 3Mhz Delay for sensor to be ready
    //__delay_cycles(2160000);// 45ms at 48 Mhz
    bool test = MAP_I2C_masterSendSingleByteWithTimeout(EUSCI_B1_BASE,address,1000);
            if(test)
            {
                regC0 = MAP_I2C_masterReceiveSingleByte(EUSCI_B1_BASE);
            }
            else
            {
                printf("False");
            }

    Maybe you have another idea?

  • Are you seeing a NACK? Pause in the debugger, and check Registers->EUSCI_B1->IFG for UCNACKIFG.

    [Edit: Also, as a matter of completeness, add a:

    > MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P6,GPIO_PIN0);

    to make sure the device really resets (XSHUT low then high).]

  • thanks again for you answer.

    i put MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P6,GPIO_PIN0); at the beginning so that the Port is low, but it didnt change anything.

    I dont get a NACK.

    That is a picture of my EUSCI_B1.

    I find out that it is only workin with the MAP_I2C_masterSendSingleByteWithTimeout function, MAP_I2C_masterSendSingleByte does not work.

    But now i stuck at writing into a register:

    void writeReg (uint8_t reg, uint8_t value)
    {
        bool reg_bool = MAP_I2C_masterSendSingleByteWithTimeout(EUSCI_B1_BASE,reg,1000);
        bool value_bool = MAP_I2C_masterSendSingleByteWithTimeout(EUSCI_B1_BASE,value,1000);
        if (reg_bool && value_bool)
        {
            printf("test");
        }
    }

    the bool values are just for testing. Do i need to use MAP_I2C_masterSendMultiByteStart for writing into a register?

    Can you tell me which unit the timout is, is it seconds or ms or cpu-cycles? The documentation doesnt declare a unit: timeout is the amount of time to wait until giving up

  • The write sequence is a multi-byte sequence, as seen in the VL53L0x data sheet (Fig 15). You'll need the MultiByte functions in the Driverlib UG (no doc#?) Sec 12.2.

    It's curious that the Timeout version works and the non-Timeout doesn't. It sounds vaguely like Erratum USCI43, but that mentions only RXIFG, not TXIFG.

    As I mentioned, my estimate for the timeout unit is about 1 usec at 3MHz (decrement+branch). It's probably affected by optimization.

  • Sorry for my late response!

    I got it working to write to the register even to a 16bit register.

    But now i have a new problem... When i debug the code everything is working as expected, but if I run the code without debugging it cannot write to the registers. I think it's to fast.

    I read in the vl53l0x doc about the "Bus free time between transmissions" so i added delays but i didnt work.

    Here is an example:

    void writeReg (uint8_t reg, uint8_t value)
    {
        __delay_cycles(96000); //2 ms  48Mhz
        bool reg_bool = MAP_I2C_masterSendMultiByteStartWithTimeout(EUSCI_B1_BASE,reg,1000);
        bool value_bool = MAP_I2C_masterSendMultiByteFinishWithTimeout(EUSCI_B1_BASE,value,1000);
        MAP_I2C_masterSendMultiByteStopWithTimeout(EUSCI_B1_BASE,1000);
        __delay_cycles(96000); //2 ms  48Mhz
        if (reg_bool && value_bool)
        {
            printf("writeReg success \n");
        }
        else
        {
            printf("writeReg failed \n");
        }
        //__delay_cycles(6000); //2 ms 3Mhz
        //__delay_cycles(96000); //2 ms 48Mhz
    }

    Does anyone have any ideas?

    thanks in advance!

  • It already fails when I try to read from i2c for the second time.

    uint8_t readReg (uint8_t address)
    {
        uint8_t value=0x00;
        /* Wait until ready */
            while (MAP_I2C_isBusBusy(EUSCI_B1_BASE)){
                ;
            }
        bool reag_reg = MAP_I2C_masterSendSingleByteWithTimeout(EUSCI_B1_BASE,address,100000);
        if(reag_reg)
        {
            value = MAP_I2C_masterReceiveSingleByte(EUSCI_B1_BASE);
            printf("read success \n");
        }
        else{
            printf("read failed \n");
        }
        //__delay_cycles(6000); //2 ms bei 3Mhz
            __delay_cycles(96000); //2 ms bei 48Mhz
        return value;
    }

    The bus stays busy. register view:

    UCBSTATW 0x0350eUSCI_Bx Status Register [Memory Mapped]

    UCBCNT 00000011 Hardware byte counter value

    UCSCLLOW 1 - UCSCLLOW_1 SCL low

    UCGC 0 - UCGC_0 General call address received

    UCBBUSY 1 - BUSY Bus busy

  • I did it, I had to add a delay in some places.

**Attention** This is a public forum