TM4C129DNCPDT: Does NMI Pin(PD7 - TM4C129DNCPDT) can act as normal gpio input interrupt pin with falling edge?

Part Number: TM4C129DNCPDT

Hi,

I have a question regarding the NMI pin.

Can the NMI pin be configured and used as a normal GPIO input pin? If yes, is it possible to configure it to generate a falling-edge interrupt?

Currently, I have:

  • Unlocked the NMI pin.
  • Configured it as an input.
  • Configured the interrupt for falling-edge detection.

However, when I test it, the interrupt is triggered only on the rising edge and not on the falling edge.

Is there any limitation on the NMI pin that prevents falling-edge interrupts, or is there an additional configuration step required? The pin is PD7.     

void initAcDetGPIOINTPin(void)
{
    HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    HWREG(GPIO_PORTD_BASE + GPIO_O_CR) |= AC_DET_NMI_PIN;
    HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = 0;

    // GPIO input
    MAP_GPIOPinTypeGPIOInput(AC_DET_NMI_PORT, AC_DET_NMI_PIN);
    GPIOIntTypeSet(AC_DET_NMI_PORT, AC_DET_NMI_PIN, GPIO_FALLING_EDGE);

    GPIOIntEnable(GPIO_PORTD_BASE, AC_DET_NMI_PIN);

        return;
}                     in cfg file var nmiParams = new Hwi.Params();
nmiParams.instance.name = "AC_DET_Hwi";
nmiParams.priority = 0;
Program.global.AC_DET_Hwi = Hwi.create(19, "&acPowerFailure_HWISR", nmiParams);        and I am using handler function  acPowerFailure_HWISR

  • Hello,
    Yes, PD7 can be used as a normal GPIO input after unlocking and committing the pin. Once PD7 is configured as GPIO, it can generate a falling-edge GPIO interrupt. There is no GPIO hardware limitation that prevents falling-edge detection on PD7.  Also, the interrupt should be masked while configuring the edge detection, then any pending interrupt should be cleared before enabling it. The ISR should also clear the GPIO interrupt source.


    A recommended sequence would be:
    void initAcDetGPIOINTPin(void)
    {
    /* Mask interrupt during configuration */
    GPIOIntDisable(GPIO_PORTD_BASE, GPIO_PIN_7);

    /* Unlock and commit PD7/NMI */
    HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    HWREG(GPIO_PORTD_BASE + GPIO_O_CR) |= GPIO_PIN_7;
    HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = 0;

    /* Make sure PD7 is GPIO, not NMI alternate function */
    HWREG(GPIO_PORTD_BASE + GPIO_O_AFSEL) &= ~GPIO_PIN_7;
    HWREG(GPIO_PORTD_BASE + GPIO_O_PCTL) &= ~GPIO_PCTL_PD7_M;
    HWREG(GPIO_PORTD_BASE + GPIO_O_AMSEL) &= ~GPIO_PIN_7;

    /* Configure as GPIO input */
    GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_7);

    /* Optional: enable pull-up if the external source is open-drain/active-low */
    /* GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_PIN_7,
    GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); */

    /* Configure falling-edge interrupt */
    GPIOIntTypeSet(GPIO_PORTD_BASE, GPIO_PIN_7, GPIO_FALLING_EDGE);

    /* Clear any stale pending interrupt before unmasking */
    GPIOIntClear(GPIO_PORTD_BASE, GPIO_PIN_7);

    /* Enable GPIO interrupt for PD7 */
    GPIOIntEnable(GPIO_PORTD_BASE, GPIO_PIN_7);
    }
    And in the ISR:
    void acPowerFailure_HWISR(void)
    {
    uint32_t status = GPIOIntStatus(GPIO_PORTD_BASE, true);

    GPIOIntClear(GPIO_PORTD_BASE, status);

    if (status & GPIO_PIN_7)
    {
    /* Handle PD7 falling-edge event here */
    }
    }
    The Hwi.create(19, "&acPowerFailure_HWISR", nmiParams); configuration is consistent with the GPIO Port D interrupt vector. Therefore, the issue is most likely that PD7 is still configured as the NMI alternate function, that a pending interrupt is not being cleared, or that the pin does not have a valid high-to-low transition at the pad. As a quick debug check, read back GPIOAFSEL, GPIOPCTL, GPIOIS, GPIOIBE, GPIOIEV, GPIORIS, and GPIOMIS for PD7 after initialization.

  • I have tried above codes. But the pin is triggering in both level shifting especially in rising edge.  I have tried with out this line also GPIOIntTypeSet(GPIO_PORTD_BASE, GPIO_PIN_7, GPIO_FALLING_EDGE); . In all cases the interupt is triggering in the rising edge

  • Hello Sarath, 

    Thank you for sharing this information. Since the interrupt is still firing, this means the PORT D vector is working and this is not an NMI issue since it's interrupt vector is vector 2. So now, keeping your code, I want you to first confirm that your macros, AC_DET_NMI_PIN, is defined as the bit mask GPIO_PIN_7 (which is 0x80), not the literal pin number 7. Same goes for AC_DET_NMI_PORT, confirm it equals GPIO_PORTD_BASE. 

    If this doesn't work, we need to ensure the input to the registers contain the right value. Hence, drop this right after the init...() function, and read the values in the debugger: 

    volatile uint32_t dbg_pinmask = AC_DET_NMI_PIN; // expect 0x80
    volatile uint32_t dbg_afsel = HWREG(GPIO_PORTD_BASE + GPIO_O_AFSEL); // bit7 should be 0
    volatile uint32_t dbg_pctl = HWREG(GPIO_PORTD_BASE + GPIO_O_PCTL); // [31:28] should be 0
    volatile uint32_t dbg_den = HWREG(GPIO_PORTD_BASE + GPIO_O_DEN); // bit7 = 1
    volatile uint32_t dbg_dir = HWREG(GPIO_PORTD_BASE + GPIO_O_DIR); // bit7 = 0 (input)
    volatile uint32_t dbg_is = HWREG(GPIO_PORTD_BASE + GPIO_O_IS); // bit7 = 0 (edge)
    volatile uint32_t dbg_ibe = HWREG(GPIO_PORTD_BASE + GPIO_O_IBE); // bit7 = 0 (single edge)
    volatile uint32_t dbg_iev = HWREG(GPIO_PORTD_BASE + GPIO_O_IEV); // bit7 = 0 (FALLING)
    volatile uint32_t dbg_im = HWREG(GPIO_PORTD_BASE + GPIO_O_IM); // bit7 = 1 (unmasked)

    And in the ISR, let's capture which pin was actually firing before it's cleared. Hence, add below in the ISR: 

    void acPowerFailure_HWISR(void)
    {
    uint32_t status = HWREG(GPIO_PORTD_BASE + GPIO_O_MIS); // which Port-D bit(s)?
    /* log 'status' to a circular buffer for inspection */
    GPIOIntClear(GPIO_PORTD_BASE, status);
    }

    The above helps us confirm all software configuration/firmware section is set right as expected. Also, please ensure you're not running another routine after this that might change the register values.