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.

TM4C1294NCPDT: IRQ on only one pin input on a Tiva CPU running TI-RTOS

Part Number: TM4C1294NCPDT
Other Parts Discussed in Thread: SYSBIOS, EK-TM4C1294XL

I don’t have a good way to test a IRQ at the moment so I want to ask a question about if this is the best way tor at least a good o go about programming a IRQ only pin D6 .  On Port D, I have 2 input pins (D4 and D6)and I only want to interrupt on pin D6 and not D4.  This questions is more of a code review question in nature.

I will be using a TM4C1294NCPDT with CCS ccs 6.1.2 and TIRTOS 2.16.0.08.

Below is the code I have so far:

#define PORT_D_IN_PINS              (GPIO_PIN_4 + GPIO_PIN_6)

void initPort_D(void)

{

                        unsigned long port = GPIO_PORTD_BASE;

                        Hwi_Handle myHwi;

                        Hwi_Params  hwiParams;

                        Error_Block eb;

 

 

                        SysCtlPeripheralEnable(port); // enable the port

                       

                        SMALL_DELAY; // when SysCtlPeripheralEnable() is called, a small delay is needed before the device can be used.

 

                        // configure the inputs

                        ROM_GPIODirModeSet(port, PORT_D_IN_PINS, GPIO_DIR_MODE_IN);

                        MAP_GPIOPadConfigSet(port, PORT_D_IN_PINS, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

 

                        // define input IRQ on Pin D6

                        GPIOIntEnable(port, GPIO_INT_PIN_6); // from TivawareDoc enable the interrupt on pin 6

                        GPIOIntTypeSet(port, GPIO_INT_PIN_6, GPIO_FALLING_EDGE); //  from TivawareDoc  define the IRQ as falling edge

 

 

                        Error_init(&eb);

                       Hwi_Params_init(&hwiParams);

                       hwiParams.arg = 10; // pass function a argument of 10 just because….

                       hwiParams.enableInt = TRUE;    // have the IRQ enabled by default.

                       myHwi = Hwi_create(INT_GPIOD_TM4C129, portD_IntHandler, &hwiParams, &eb); // associate the IRQ  INT_GPIOD_TM4C129  (19) with the callback function portD_IntHandler() from the TI_RTOC 2.0 Doc

                       if(NULL == myHwi)

                       {

                                               printf ("Error installing IRQ %d for port D\n", INT_GPIOD_TM4C129);

                       }

                       else

                       {

                                               printf ("OK installing IRQ  %d for port D\n", INT_GPIOD_TM4C129);

                       }

                       GPIO_enableInt(GPIO_INT_PIN_6);     ); // shouldn’t be needed since the IRQ is enabled by hwiParams.enableInt = TRUE;

                       Hwi_enableInterrupt(INT_GPIOD_TM4C129);  // shouldn’t be needed since the IRQ is enabled by hwiParams.enableInt = TRUE;

}

 

void portD_IntHandler(UArg arg)

{

        static int intCounter=0;

 

        System_printf("portD_IntHandler fied %d times\n", intCounter++);

 

}

It seems I’m mixing a bunch of high level calls like Hwi_create() from the BIOS User Guide and lower level calls GPIOIntEnable() and GPIOIntTypeSet () from TivaWare.  Does this look like it will do what I want with having D4 being just a standard input pin I just read and pin D6 would be a input pin that generates a IRQ when it goes low?  I don’t think I can get the  fine control to configure only pin D6  to be a IRQ and D4 be just a input pin using the TI-RTOS API.

Thanks for any advice,

Doug

  • Hi Doug,

      I don't really spot a problem. You should be able to combine the below two lines

                            ROM_GPIODirModeSet(port, PORT_D_IN_PINS, GPIO_DIR_MODE_IN);

                            MAP_GPIOPadConfigSet(port, PORT_D_IN_PINS, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

    With:

                            MAP_GPIOPinTypeGPIOInput(port, PORT_D_IN_PINS);

    But even if don't change your code, it should work just fine as long as you let the Hwi manage your interrupt. Do not do something like below that registers the ISR outside the kernel's knowledge. It can mess up the interrupt vector that is managed by SYSBIOS. 

       GPIOIntRegister(port, portD_IntHandler);

  • Thanks for the reply. 

    My original code I posted yesterday using port D is still there in my project and it is installs the INT_GPIOD_TM4C129 correctly.   I haven't tested it yet but the IRQ installs.

    I found a EK-TM4C1294XL launchpad so I could try the same/similar code on the same processor but use the user buttons on the launchpad t o fire the interrupt.    The user buttons are connected to PJ0 and PJ1 on the launchpad.  I made a copy of the code and changes for using the port J pins 0 and 1 that are hooked to the user switches on the launchpad.  The new code below fails on Hwi_create() function since the call to Hwi_create() returns NULL.  When I replace the IRQ I install  below I find that it does not work for the IRQ's below either.

    #define INT_GPIOJ_TM4C129 67 // GPIO Port J
    #define INT_GPIOK_TM4C129 68 // GPIO Port K
    #define INT_GPIOL_TM4C129 69 // GPIO Port L


    In my new code I'm posting below using port J  I can install  INT_GPIOE_TM4C129       20    but it can't install INT_GPIOD_TM4C129 because I assume it's already installed 

    I know one reason the INT_GPIOJ_TM4C129 might not install is if it is installed some place else because I tried to reinstall INT_GPIOD_TM4C129 in my new code also and that also fails. 

    What other reasons other reasons would cause Hwi_create(INT_GPIOJ_TM4C129, portJ_IntHandler, &hwiParams, &eb); to fail other than the IRQ was previously installed?

    Doug

    #define PORT_J_IN_PINS (GPIO_PIN_0 + GPIO_PIN_1)

    void initPort_J_evalBoard(void)
    {
    unsigned long port = GPIO_PORTJ_BASE;
    Hwi_Handle myHwi;
    Hwi_Params hwiParams;
    Error_Block eb;

    SysCtlPeripheralEnable(port);
    SMALL_DELAY; // when SysCtlPeripheralEnable() is called, a small delay is needed before the device can be used.
    // do the inputs
    ROM_GPIODirModeSet(port, PORT_J_IN_PINS, GPIO_DIR_MODE_IN);
    MAP_GPIOPadConfigSet(port, PORT_J_IN_PINS, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

    // input IRQ on Pin d6
    GPIOIntEnable(port, GPIO_INT_PIN_0);
    GPIOIntTypeSet(port, GPIO_INT_PIN_0, GPIO_FALLING_EDGE);

    Error_init(&eb);
    Hwi_Params_init(&hwiParams);
    hwiParams.arg = 12; // pass function a argument of 12.
    hwiParams.enableInt = TRUE; // have the IRQ enabled
    myHwi = Hwi_create(INT_GPIOJ_TM4C129, portJ_IntHandler, &hwiParams, &eb);
    if(NULL == myHwi)
    {
    printf ("Error installing IRQ %d for port J\n", INT_GPIOJ_TM4C129);
    }
    else
    {
    printf ("OK installing IRQ %d for port J\n", INT_GPIOJ_TM4C129);
    }
    //IntEnable(INT_GPIOD_TM4C129);
    //GPIO_enableInt(GPIO_INT_PIN_0);
    //Hwi_enableInterrupt(INT_GPIOD_TM4C129);

    } // end void initPort_J(void)

    void portJ_IntHandler(UArg arg)
    {
    static int intCounter=0;

    System_printf("portJ_IntHandler fired %d times, arg = %d\n", intCounter++, arg);
    }

  • Hi Doug,

      In your main(), did you call Board_initGPIO? If you called Board_initGPIO() then it will automatically setup the interrupt vectors for GPIO including PJ and PD and many others. I think your code will interfere the settings that was done by Board_initGPIO(). 

      Please refer to TI-RTOS GPIO Interrupt example. You can import this project into your workspace. This example actually uses PJ0 as a switch to generate interrupt. 

    I'm not very knowledgeable on TI-RTOS but this is what I found after tracing the code. 

    If you open the gpiointerrupt.c of the project you will see the below snippet of code in the beginning of main(). 

    int main(void)
    {
    /* Call board init functions */
    Board_initGeneral();
    Board_initGPIO();
    Board_initUART();

    If you trace Board_initGPIO() it will call GPIO_init() as in:

    void EK_TM4C1294XL_initGPIO(void)
    {
    /* Initialize peripheral and pins */
    GPIO_init();
    }

    Look at GPIO_init below:

    /*
    * ======== GPIO_init ========
    */
    void GPIO_init()
    {
    unsigned int i, j;

    initCalled = true;

    #if defined(TIVAWARE)
    if ((HWREG(SYSCTL_DID0) & SYSCTL_DID0_CLASS_M) ==
    SYSCTL_DID0_CLASS_TM4C129) {
    gpioInterruptVectors = gpioTM4C129InterruptVectors;
    }
    else {
    gpioInterruptVectors = gpioTM4C123InterruptVectors;
    }
    #endif

    /* Initialize all entries with 'not configured' key */
    for (i = 0; i < NUM_PORTS; i++) {
    for (j = 0; j < NUM_PINS_PER_PORT; j++) {
    gpioCallbackInfo[i].pinIndex[j] = CALLBACK_INDEX_NOT_CONFIGURED;
    }
    }

    /* Configure pins and create Hwis per static array content */
    for (i = 0; i < GPIOTiva_config.numberOfPinConfigs; i++) {
    if (!(GPIOTiva_config.pinConfigs[i] & GPIO_DO_NOT_CONFIG)) {
    GPIO_setConfig(i, GPIOTiva_config.pinConfigs[i]);
    }
    if (i < GPIOTiva_config.numberOfCallbacks) {
    if (GPIOTiva_config.callbacks[i] != NULL) {
    GPIO_setCallback(i, GPIOTiva_config.callbacks[i]);
    }
    }
    }
    }

    The gpioTM4C129InterruptVectors is defined as:

    static const uint8_t gpioTM4C129InterruptVectors[] = {
    INT_GPIOA_TM4C129, INT_GPIOB_TM4C129, INT_GPIOC_TM4C129,
    INT_GPIOD_TM4C129, INT_GPIOE_TM4C129, INT_GPIOF_TM4C129,
    INT_GPIOG_TM4C129, INT_GPIOH_TM4C129, INT_GPIOJ_TM4C129,
    INT_GPIOK_TM4C129, INT_GPIOL_TM4C129, INT_GPIOM_TM4C129,
    INT_GPION_TM4C129, INT_GPIOR_TM4C129, INT_GPIOS_TM4C129,
    INT_GPIOT_TM4C129, INT_GPIOP0_TM4C129, INT_GPIOP1_TM4C129,
    INT_GPIOP2_TM4C129, INT_GPIOP3_TM4C129, INT_GPIOP4_TM4C129,
    INT_GPIOP5_TM4C129, INT_GPIOP6_TM4C129, INT_GPIOP7_TM4C129,
    INT_GPIOQ0_TM4C129, INT_GPIOQ1_TM4C129, INT_GPIOQ2_TM4C129,
    INT_GPIOQ3_TM4C129, INT_GPIOQ4_TM4C129, INT_GPIOQ5_TM4C129,
    INT_GPIOQ6_TM4C129, INT_GPIOQ7_TM4C129
    };

    GPIO_init() will later call GPIO_setConfig to configure the pins and also the Hwi for them. 

    In this example project there is also the EK_TM4C1294XL.c file that defines array of pin configurations for this example. See below snippet. You can see that PortJ and PortD are already plugged for SW1 and SW2. Maybe this is why you are getting a NULL when calling Hwi_create() to install PortJ and PortD. 

    /*
     * Array of Pin configurations
     * NOTE: The order of the pin configurations must coincide with what was
     *       defined in EK_TM4C1294XL.h
     * NOTE: Pins not used for interrupts should be placed at the end of the
     *       array.  Callback entries can be omitted from callbacks array to
     *       reduce memory usage.
     */
    GPIO_PinConfig gpioPinConfigs[] = {
        /* Input pins */
        /* EK_TM4C1294XL_USR_SW1 */
        GPIOTiva_PJ_0 | GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_RISING,
        /* EK_TM4C1294XL_USR_SW2 */
        GPIOTiva_PD_0 | GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_RISING,
    
        /* Output pins */
        /* EK_TM4C1294XL_USR_D1 */
        GPIOTiva_PN_1 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        /* EK_TM4C1294XL_USR_D2 */
        GPIOTiva_PN_0 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
    };
    
    /*
     * Array of callback function pointers
     * NOTE: The order of the pin configurations must coincide with what was
     *       defined in EK_TM4C1294XL.h
     * NOTE: Pins not used for interrupts can be omitted from callbacks array to
     *       reduce memory usage (if placed at end of gpioPinConfigs array).
     */
    GPIO_CallbackFxn gpioCallbackFunctions[] = {
        NULL,  /* EK_TM4C1294XL_USR_SW1 */
        NULL   /* EK_TM4C1294XL_USR_SW2 */
    };
    
    /* The device-specific GPIO_config structure */
    const GPIOTiva_Config GPIOTiva_config = {
        .pinConfigs = (GPIO_PinConfig *)gpioPinConfigs,
        .callbacks = (GPIO_CallbackFxn *)gpioCallbackFunctions,
        .numberOfPinConfigs = sizeof(gpioPinConfigs)/sizeof(GPIO_PinConfig),
        .numberOfCallbacks = sizeof(gpioCallbackFunctions)/sizeof(GPIO_CallbackFxn),
        .intPriority = (~0)
    };
    

  • You are correct.  My main has a call Board_initGPIO(); and that calls:

    void EK_TM4C1294XL_initGPIO(void)
    {
          /* Initialize peripheral and pins */
          GPIO_init();
    }

    I can't trace GPIO_init(); back any further that a header in GPIO.h even with the debugger.

    If I comment out the call Board_initGPIO() in main, I can install the IRQ INT_GPIOJ_TM4C129 now.   

    Do you know where the source is for the function GPIO_init();?  If I comment Board_initGPIO() out in main, I may be loosing something I need.

    Thanks,

    Doug

  • Hi Doug,

      Glad that you are making progress. If you are going to configure the GPIO pins manually using TivaWare (you still need to use Hwi to manage the interrupts ) then I don't think you will lose something by commenting out Board_initGPIO().

      I was able to trace GPIO_init() in the debugger. I just single step and it will take me to GPIO_init(). GPIO_init() is in GPIOTiva.c file which can be found in C:\ti\tirtos_tivac_2_16_00_08\products\tidrivers_tivac_2_16_00_08\packages\ti\drivers\gpio directory. 

  • OK, I have the source now.  I had to "brows to the source" but now I can see it in the debugger.  I have one or two more questions.  I now have the IRQ firing using the user buttons on the eval board but I want to be sure I am clearing the IRQ OK so it doesn't keep firing.  I first tried the commented out line "GPIO_clearInt(INT_GPIOJ_TM4C129);"and it crashes when it executed that line of code.  Am I using that function GPIO_clearIn()wrong?   I then found the GPIOIntClear() and the documentation says the second argument in the function is the flags so the flags I used the IRQ number "INT_GPIOJ_TM4C129     =  67 ".  Is that correct the correct arguments for the function GPIO_clearIn()?

    void portJ_IntHandler(UArg arg)
    {
        static int intCounter=0;

        //GPIO_clearInt(INT_GPIOJ_TM4C129);
        GPIOIntClear(GPIO_PORTJ_BASE, INT_GPIOJ_TM4C129);
        System_printf("portJ_IntHandler fired %d times, arg = %d\n", intCounter++, arg);
    }

    Thanks for all the help!

    Doug

  • Hi Doug,

      I think the reason is that you have bypassed GPIO_init() which is called by Board_initGPIO().  Since the GPIO driver has not initialized, you cannot use any GPIO APIs. Refer to section 5.5 for GPIO driver. 

  • Thank you for all the help.