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.

TMS320F28379D: GPIO pin configuration order causing strange behaviour of I2C module

Part Number: TMS320F28379D

I recently added code to configure and use the I2C module to communicate with an external temperature sensor chip. I added code to setup GPIO pins 91 and 92 for use as SDA A and SCL A along with my other GPIO initialisation. When I tested my I2C code in a standalone project, it worked correctly, but when I tried to integrate it with my existing project, the I2C module did not seem to be able to send the start and stop bits: the I2CMDR[STT] and I2CMDR[STP] bits remained high after setting them at before and after writing data on the bus.

Eventually I traced the problem to the configuration of GPIO32 for the LED on the controlCard. When I moved the GPIO91/92 configuration before this, the problem appears to be solved, but I can't think why this should be.

My I2C code is now integrated into my original project, and is working correctly, so this is more out of curiosity, and to avoid similar problems in the future by understanding it.

  • Hello Dave,

    Can you show the side-by-side code of what worked and what was failing? I can check to see if the driverlib/bitfields used are possible causing something to happen during runtime.

    Best regards,

    Omer Amir

  • Hi Omer,

    Previously the GPIO configuration was in this order:

        // Set up GPIO31 for driving LED D2 on control card
        GPIO_SetupPinOptions(31, GPIO_OUTPUT, GPIO_PUSHPULL);
        GPIO_SetupPinMux(31, GPIO_MUX_CPU1, 0);
        GPIO_WritePin(31, 1); //turn off LED
        
            // Initialize GPIOs 91 and 92 for use as SDA A and SCL A respectively
        // For unknown reasons, this must be done before GPIO31 setup
        GpioCtrlRegs.GPCCSEL4.bit.GPIO91 = 0;       // Allow manual setting of GPIO91 via CPU1 (don't think this is necessary as it only applies to GPIODAT/SET/CLEAR/TOGGLE registers)
        GpioCtrlRegs.GPCDIR.bit.GPIO91 = 0;         // Make GPIO91 an input
        GpioCtrlRegs.GPCGMUX2.bit.GPIO91 = 1;       // Select mux group for GPIO91
        GpioCtrlRegs.GPCMUX2.bit.GPIO91 = 2;        // Select mux option for GPIO91: SDAA
        GpioCtrlRegs.GPCPUD.bit.GPIO91 = 0;         // Enable pull up resistor
        GpioCtrlRegs.GPCQSEL2.bit.GPIO91 = 3;       // Asynchronous qualification
    
        GpioCtrlRegs.GPCCSEL4.bit.GPIO92 = 0;       // Allow manual setting of GPIO92 via CPU1 (don't think this is necessary as it only applies to GPIODAT/SET/CLEAR/TOGGLE registers)
        GpioCtrlRegs.GPCDIR.bit.GPIO92 = 0;         // Make GPIO92 an input
        GpioCtrlRegs.GPCGMUX2.bit.GPIO92 = 1;       // Select mux group for GPIO92
        GpioCtrlRegs.GPCMUX2.bit.GPIO92 = 2;        // Select mux option for GPIO92: SCLA
        GpioCtrlRegs.GPCPUD.bit.GPIO92 = 0;         // Enable pull up resistor
        GpioCtrlRegs.GPCQSEL2.bit.GPIO92 = 3;       // Asynchronous qualification
    

    I located the problem by commenting various each pin configuration in turn, and GPIO31 fixed the issue. When I moved GPIO31 config after 91/92, it still works correctly:

        // Initialize GPIOs 91 and 92 for use as SDA A and SCL A respectively
        // For unknown reasons, this must be done before GPIO31 setup
        GpioCtrlRegs.GPCCSEL4.bit.GPIO91 = 0;       // Allow manual setting of GPIO91 via CPU1 (don't think this is necessary as it only applies to GPIODAT/SET/CLEAR/TOGGLE registers)
        GpioCtrlRegs.GPCDIR.bit.GPIO91 = 0;         // Make GPIO91 an input
        GpioCtrlRegs.GPCGMUX2.bit.GPIO91 = 1;       // Select mux group for GPIO91
        GpioCtrlRegs.GPCMUX2.bit.GPIO91 = 2;        // Select mux option for GPIO91: SDAA
        GpioCtrlRegs.GPCPUD.bit.GPIO91 = 0;         // Enable pull up resistor
        GpioCtrlRegs.GPCQSEL2.bit.GPIO91 = 3;       // Asynchronous qualification
    
        GpioCtrlRegs.GPCCSEL4.bit.GPIO92 = 0;       // Allow manual setting of GPIO92 via CPU1 (don't think this is necessary as it only applies to GPIODAT/SET/CLEAR/TOGGLE registers)
        GpioCtrlRegs.GPCDIR.bit.GPIO92 = 0;         // Make GPIO92 an input
        GpioCtrlRegs.GPCGMUX2.bit.GPIO92 = 1;       // Select mux group for GPIO92
        GpioCtrlRegs.GPCMUX2.bit.GPIO92 = 2;        // Select mux option for GPIO92: SCLA
        GpioCtrlRegs.GPCPUD.bit.GPIO92 = 0;         // Enable pull up resistor
        GpioCtrlRegs.GPCQSEL2.bit.GPIO92 = 3;       // Asynchronous qualification
    
        // Set up GPIO31 for driving LED D2 on control card
        GPIO_SetupPinOptions(31, GPIO_OUTPUT, GPIO_PUSHPULL);
        GPIO_SetupPinMux(31, GPIO_MUX_CPU1, 0);
        GPIO_WritePin(31, 1); //turn off LED

    I appreciate the mix of bitfield and driverlib is a little unconventional (I inherited a project which partially uses driverlib, but I'm more familiar with bitfield) but shouldn't cause this issue.

    Best regards,

    Dave

  • Hello Dave,

    It looks like you're not using the traditional driverlib, as the GPIO_SetupPinOptions and GPIO_SetupPinMux are not part of the GPIO driverlib functions. I only found it as part of the device_support for F2837xD.

    When I looked at both the GPIO_SetupPinOptions and GPIO_SetupPinMux functions I found that at the end of the function they are calling EDIS, which disables a certain write protection which is needed for some of the registers. In this case, the GPIO registers you're modifying for GPIO91/92 require EALLOW (see below image from the TRM).

    When EDIS is used, you need to use EALLOW to enable the write permission for those GPIO registers. In this case, you could do the following:

        // Set up GPIO31 for driving LED D2 on control card
        GPIO_SetupPinOptions(31, GPIO_OUTPUT, GPIO_PUSHPULL);
        GPIO_SetupPinMux(31, GPIO_MUX_CPU1, 0);
        GPIO_WritePin(31, 1); //turn off LED
        
        EALLOW;
            // Initialize GPIOs 91 and 92 for use as SDA A and SCL A respectively
        // For unknown reasons, this must be done before GPIO31 setup
        GpioCtrlRegs.GPCCSEL4.bit.GPIO91 = 0;       // Allow manual setting of GPIO91 via CPU1 (don't think this is necessary as it only applies to GPIODAT/SET/CLEAR/TOGGLE registers)
        GpioCtrlRegs.GPCDIR.bit.GPIO91 = 0;         // Make GPIO91 an input
        GpioCtrlRegs.GPCGMUX2.bit.GPIO91 = 1;       // Select mux group for GPIO91
        GpioCtrlRegs.GPCMUX2.bit.GPIO91 = 2;        // Select mux option for GPIO91: SDAA
        GpioCtrlRegs.GPCPUD.bit.GPIO91 = 0;         // Enable pull up resistor
        GpioCtrlRegs.GPCQSEL2.bit.GPIO91 = 3;       // Asynchronous qualification
    
        GpioCtrlRegs.GPCCSEL4.bit.GPIO92 = 0;       // Allow manual setting of GPIO92 via CPU1 (don't think this is necessary as it only applies to GPIODAT/SET/CLEAR/TOGGLE registers)
        GpioCtrlRegs.GPCDIR.bit.GPIO92 = 0;         // Make GPIO92 an input
        GpioCtrlRegs.GPCGMUX2.bit.GPIO92 = 1;       // Select mux group for GPIO92
        GpioCtrlRegs.GPCMUX2.bit.GPIO92 = 2;        // Select mux option for GPIO92: SCLA
        GpioCtrlRegs.GPCPUD.bit.GPIO92 = 0;         // Enable pull up resistor
        GpioCtrlRegs.GPCQSEL2.bit.GPIO92 = 3;       // Asynchronous qualification
        EDIS;

    Best regards,

    Omer Amir

  • Hi Omer,

    Of course, that makes perfect sense. I have EALLOW and EDIS at the beginning and end of my GPIO initialisation, but I overlooked the fact that if I call the GPIO setup functions from device support, they are calling EDIS and so any EALLOW protected setup I do after won't take effect until I called EALLOW again.

    Thanks for finding the problem, it had me quite confused.

    Best regards,

    Dave