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.

EK-TM4C123GXL: Order of GPIO interrupt init statements.

Part Number: EK-TM4C123GXL

I think there should be a clean example showing the order of statements used to initialize GPIO interrupts. Today I learned to things.

GPIOPinTypeGPIOInput() must come before GPIOPadConfigSet() because GPIOPadConfigSet() needs to know which pins are inputs to setup the termination resistors. Swap them and it does not work.

GPIOPadConfigSet() must come before IntEnable() or it will have no effect.

I don't want to waste time if there is a good example to use but with GPIO ISR it seems half get the status and then clear and the other have issue a clear and then try to read status.

Here what is working for me at the moment:

void initGPIO(void)
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, LED_PINS);
    GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, INT_PINS);
    GPIOPadConfigSet(GPIO_PORTF_BASE, INT_PINS, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    GPIOIntEnable(GPIO_PORTF_BASE, INT_PINS);
    GPIOIntTypeSet(GPIO_PORTF_BASE, INT_PINS, GPIO_LOW_LEVEL);
    IntPrioritySet(INT_GPIOF, 0);
    IntRegister(INT_GPIOF, GPIOIntHandler);
    IntEnable(INT_GPIOF);
    IntMasterEnable();
}

But what do I know I am a TivaWare newbie and yet older than dirt too.

BTW, where does Tiva come from?

John 

  • Hello John,

    So you actually have a bit of redundancy here.

    GPIOPinTypeGPIOOutput / GPIOPinTypeGPIOInput handle all the configurations you need in most cases as they both set the direction and pad configuration:

    void
    GPIOPinTypeGPIOInput(uint32_t ui32Port, uint8_t ui8Pins)
    {
        //
        // Check the arguments.
        //
        ASSERT(_GPIOBaseValid(ui32Port));
    
        //
        // Make the pin(s) be inputs.
        //
        GPIODirModeSet(ui32Port, ui8Pins, GPIO_DIR_MODE_IN);
    
        //
        // Set the pad(s) for standard push-pull operation.
        //
        GPIOPadConfigSet(ui32Port, ui8Pins, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
    }

    If you aren't satisfied with the default settings for the Pad, then you should not use that API and instead manually called GPIODirModeSet and GPIOPadConfigSet.

    I think there should be a clean example showing the order of statements used to initialize GPIO interrupts. Today I learned to things.

    This is something we can look into improving in the future. The datasheet helps explain a bit as it discusses the direction needs to be set first but there isn't a close tie in from the datasheet description to the exact APIs used.

    GPIOPadConfigSet() must come before IntEnable() or it will have no effect.

    In general the interrupt enables are triggered after the peripheral is fully configured as you don't want to risk an interrupt firing before configuration is finished.

    BTW, where does Tiva come from?

    Branding / marketing from back in the day... I don't know the whole story on it but its not really how we present the devices. All our marketing collateral is for "TM4C microcontrollers" and not "Tiva-C". But TivaWare is very well known / established as the name of our SDK so it remains (and TM4CWare sounds very clunky in comparison I'd say Wink).

    Best Regards,

    Ralph Jacobi

  • Thanks for the clarification. The TivaWare Peripheral Driver Library says nothing about GPIOPinTypeGPIOInput()  calling GPIOPadConfigSet(). So it is easy to see how one could be confused. But now I am afraid I must dig into the source code for any function I find in the Peripheral Driver Library. 

    TM4CWare,  double clunky. Reminds me of my days on the HARM program where everyone called it the HARM MIssile.

  • Hi John,

    Yeah we can probably do a better job for commenting on that but the majority of TivaWare functions do not call a different one.

    The Getting Started Guide I linked has a section 4.1 for how to quickly debug driverlib calls. Might be helpful early on as you learn so if something isn't working how you expect, you can quickly access the source code for it. 

    Best Regards,

    Ralph Jacobi

  • Ralph,

    I don't think GPIOPinTypeGPIOInput() calls GPIOPadConfigSet() anymore. If I just use GPIOPinTypeGPIOInput() and leave an input unconnected and use a falling edge trigger the ISR get called repeatedly. If I add GPIOPadConfigSet() after GPIOPinTypeGPIOInput() it does not get called, suggesting that it is activating the weak pullup.

    Also if I set a high level interrupt trigger and ground the pin why does my ISR get called between  IntEnable(INT_GROUP) and IntMasterEnable() in my gpio setup routine? GPIOIntStatus() is returning zero.

    John

  • Hello John,

    I'll quote myself here:

    If you aren't satisfied with the default settings for the Pad, then you should not use that API and instead manually called GPIODirModeSet and GPIOPadConfigSet.

    If you need the pullup activated, then do not use GPIOPinTypeGPIOInput as that sets it for standard push-pull.

    Replace that with both of these calls:

    GPIODirModeSet(GPIO_PORTF_BASE, INT_PINS, GPIO_DIR_MODE_IN);
    
    GPIOPadConfigSet(GPIO_PORTF_BASE, INT_PINS, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

    For other peripherals the GPIO Pin Type tends to work very well as for I2C/SPI/UART/PWM etc. the type of output you want never changes. But for GPIO input / output, you have to exercise judgment about if its useful or not.

    If I were to go back in time and re-write the API from day one, I'd have allowed for the GPIO one specifically, the pad configuration like GPIO_PIN_TYPE_STD or GPIO_PIN_TYPE_STD_WPU to be passed in so you can use it and get the right setting (unless you need to change current strength), but that shipped sailed long ago and adding a new API would just add confusion. We just need to document better how to use these APIs in the manual.

    Also if I set a high level interrupt trigger and ground the pin why does my ISR get called between  IntEnable(INT_GROUP) and IntMasterEnable() in my gpio setup routine? GPIOIntStatus() is returning zero.

    Can you try using GPIOIntClear to clear any potential lingering flags and then do that sequence?

    Also we've found that IntMasterEnable(); persists after call so in theory you don't need after calling it once unless IntMasterDisable(); is used... but the 'in theory' bit is that you are using a device which called it and hasn't been reset. Which is usually only the case in development. So we recommend to always have it just for assurance it will be called. I bring all this up because due to that behavior, the interrupt would fire on IntEnable being called as the Master Enable has already been set. That explains why the interrupt is able to be received between IntEnable and IntMasterEnable.

    Best Regards,

    Ralph Jacobi