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.

TM4C129DNCPDT: TM4C129DNCPDT: NMI Handler with TI RTOS

Part Number: TM4C129DNCPDT

Tool/software:

Hello,

Working with TM4C129DNCPDT microcontroller with TI RTOS. Want to implement the NMI handler for my application.

Using the GPIOD - GPIO7 - NMI handler 

Following is the code,

GPIO initialization: 

_Bool initPortD(void)
{
uint8_t InitTry = 0;
do
{
MAP_SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOD);
if (InitTry++ >= PERIPHERAL_INIT_TRY_TIMES)
{
return __FAIL;
}
appSystemDelay(SYS_DELAY);
}
while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD));
MAP_GPIOPinTypeDIVSCLK(GPIO_PORTD_BASE,GPIO_PIN_7);

MAP_GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_5 | GPIO_PIN_1);
MAP_GPIOUnlockPin(GPIO_PORTD_BASE, GPIO_PIN_7);
MAP_GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_7);
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;

GPIOPinConfigure(GPIO_PD7_NMI);
IntRegister(FAULT_NMI, nmiHandler);
IntEnable(FAULT_NMI);
return __PASS;
}

// NMI handler 

void nmiHandler(void)
{

MAP_GPIOIntClear(GPIO_PORTD_BASE, GPIO_PIN_7);
nmiFlag = true;

GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_3, GPIO_PIN_3);
}

The above is the code. 

While debugging the function 

__attribute__((section(".text:abort")))
void abort(void)
{
#if defined(EMBED_CIO_BP)
__asm(" .global C$$EXITE");
#if defined(__32bis__)
__asm("C$$EXITE:.word 0xDEFED0FE");
#else
__asm(" .align 4");
#if defined(__big_endian__)
__asm("C$$EXITE:.half 0xDEFE");
#else
__asm("C$$EXITE:.half 0xD0FE");
#endif /* __big_endian__ */
#endif /* __32bis__ */

#else /* !EMBED_CIO_BP */
__asm(" .global C$$EXIT");
__asm("C$$EXIT: nop");
#endif

for (;;); /* SPINS FOREVER */
}

Kindly assist how to resolve the Issue. Is that possible to notify the NMI occurrence via UART?

Thanks in advance.

  • IntRegister(FAULT_NMI, nmiHandler);

    You cannot use IntRegister as this will destroy the vector table that has been created and managed by TI-RTOS. Refer to this post for explanation.  https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/849627/faq-can-i-update-the-vector-table-with-intregister-when-using-ti-rtos?tisearch=e2e-sitesearch&keymatch=ti-rtos%20vector%20table#

      If you look at the interrupt vector table, NMI is mapped to Vector number 2. 

    You need to use the Hwi module to let TI-RTOS manage the NMI interrupt. 

    myHwi = Hwi_create(2, (Hwi_FuncPtr)nmiHandler, &hwiParams, &eb);

  • Thanks for the communication.

    Please find the following code, modified the code as suggested but NMI interrupt is not triggered.

    volatile _Bool nmiFlag = false;

    static void NMIMonitor(void)
    {

    while (1)
    {

    if (nmiFlag)
    {
    nmiFlag = 0;
    GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_3, GPIO_PIN_3);
    }

    }

    }


    static void nmiHandler(UArg arg)
    {
    if (arg == 1)
    {
    MAP_GPIOIntClear(GPIO_PORTD_BASE, GPIO_PIN_7);
    nmiFlag = true;
    GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_3, GPIO_PIN_3);
    }
    }

    void NMIMonitorTaskInit(void)
    {
    Task_Params NMI_monitor_taskParams;
    Task_Params NMI_monitor_task;

    //error block
    Error_Block eb5;
    Error_init(&eb5);

    /* Initialize monitor task */
    Task_Params_init(&NMI_monitor_taskParams);
    NMI_monitor_taskParams.appTaskStackSize = 512; /* task size */
    NMI_monitor_taskParams.appTaskPriority =
    2; /* task priority */


    NMI_monitor_task = Task_create((taskFunctionPtr) NMIMonitor,
    &NMI_monitor_taskParams,
    &eb5); /* task create */

    // Register the NMI handler
    Hwi_Params hwiParams;
    Hwi_Params_init(&hwiParams);
    hwiParams.arg = 0;
    Hwi_create(FAULT_NMI, (Hwi_FuncPtr) nmiHandler, &hwiParams, NULL);


    // Enable the NMI interrupt
    Hwi_enableInterrupt(FAULT_NMI);

    }

    Bool initPortD(void)
    {
    uint8_t InitTry = 0;
    do
    {
    MAP_SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOD);
    if (InitTry++ >= PERIPHERAL_INIT_TRY_TIMES)
    {
    return __FAIL;
    }
    appSystemDelay(SYS_DELAY);
    }
    while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD));
    MAP_GPIOPinTypeDIVSCLK(GPIO_PORTD_BASE,GPIO_PIN_7);


    MAP_GPIOUnlockPin(GPIO_PORTD_BASE, GPIO_PIN_7);
    MAP_GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_7);
    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;
    MAP_GPIOIntTypeSet(GPIO_PORTD_BASE, GPIO_PIN_7, GPIO_FALLING_EDGE);

    GPIOPinConfigure(GPIO_PD7_NMI);
    // IntRegister(FAULT_NMI, nmiHandler);
    IntEnable(FAULT_NMI);

    return __PASS;
    }

    Please suggest anything I'm missing here. Kindly provide any sample code for the same.

  • What value is FAULT_NMI defined to?

    Can you first try the below code or even your own initPortD() on a bare-metal (No RTOS) project? I want to know if the issue on the TI-RTOS side or not.

    //
    // Unlock the Port-Pin and Set the CR bit for PD7
    //
    HWREG(GPIO_PORTD_BASE+GPIO_O_LOCK) = GPIO_LOCK_KEY;
    HWREG(GPIO_PORTD_BASE+GPIO_O_CR) |= GPIO_PIN_7;
    GPIOPinConfigure(GPIO_PD7_NMI);
    GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_PIN_7, GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD_WPD);
    GPIODirModeSet(GPIO_PORTD_BASE, GPIO_PIN_7, GPIO_DIR_MODE_HW);

  • Hi Charles, 

    Thanks for the communication.

    Regarding the NMI without RTOS code, the following is the code. But NMI is not triggered anything missing in the below code. So I checked with debugging after MAP_GPIOUnlockPin(GPIO_PORTD_BASE, GPIO_PIN_7); function going to the FAULT_ISR. Please assist to do further.

    #include <stdint.h>
    #include <stdbool.h>
    #include <inc/hw_memmap.h>
    #include <inc/hw_types.h>
    #include <inc/hw_nvic.h>
    #include <driverlib/sysctl.h>
    #include <driverlib/interrupt.h>
    #include <driverlib/pin_map.h>
    #include <driverlib/rom.h>
    #include <driverlib/rom_map.h>
    #include <driverlib/gpio.h>
    #include <driverlib/interrupt.h>
    #include <inc/hw_memmap.h>
    #include <inc/hw_ints.h>
    #include <inc/hw_gpio.h>

    #define SYSTEM_CRYSTAL SYSCTL_XTAL_16MHZ
    #define SYSTEM_MAIN_OSCILLATOR SYSCTL_OSC_MAIN
    #define SYSTEM_PLL SYSCTL_USE_PLL
    #define SYSTEM_VCO SYSCTL_CFG_VCO_240

    #define SYSTEM_MAIN_CLOCK 120000000
    // Define the register address for the System Handler Control and State Register (SHCSR)
    #define NVIC_SYS_HND_CTRL_R (*((volatile uint32_t *)0xE000ED24))

    // NMI Handler Function
    void NMI_Handler(void)
    {

    uint16_t i;
    // Handle the NMI interrupt (e.g., log the event, reset specific systems, etc.)
    while (1)
    {

    GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_1,
    GPIOPinRead(GPIO_PORTM_BASE, GPIO_PIN_1) ^ GPIO_PIN_1);

    for (i = 0; i < 60000; i++)
    ;
    // Infinite loop to indicate NMI has been triggered and handled
    }
    }

    // Function to Initialize NMI Interrupt
    void NMI_Init(void)
    {
    // Set NMI handler function pointer in the vector table (optional, if not set automatically)
    IntRegister(FAULT_NMI, NMI_Handler); // This links the NMI interrupt to your handler.

    // Enable NMI Interrupt in the System Handler Control and State Register (SHCSR)
    NVIC_SYS_HND_CTRL_R |= 0x00000002; // Set bit 1 to enable NMI interrupt
    }

    int main(void)
    {
    // Set system clock (example using 120 MHz from PLL with crystal reference)
    // SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);
    SysCtlClockFreqSet(
    (SYSTEM_CRYSTAL | SYSTEM_MAIN_OSCILLATOR | SYSTEM_PLL | SYSTEM_VCO),
    SYSTEM_MAIN_CLOCK);
    SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOM);

    while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOM))
    ;
    GPIOPinTypeGPIOOutput( GPIO_PORTM_BASE, GPIO_PIN_1); /* leds */

    MAP_GPIOUnlockPin(GPIO_PORTD_BASE, GPIO_PIN_7);
    MAP_GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_7);
    // 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;
    MAP_GPIOIntTypeSet(GPIO_PORTD_BASE, GPIO_PIN_7, GPIO_FALLING_EDGE);

    GPIOPinConfigure(GPIO_PD7_NMI);
    GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_PIN_7, GPIO_STRENGTH_8MA,
    GPIO_PIN_TYPE_STD_WPD);
    GPIODirModeSet(GPIO_PORTD_BASE, GPIO_PIN_7, GPIO_DIR_MODE_HW);

    // Initialize NMI interrupt
    NMI_Init();

    // Main loop
    while (1)
    {
    // Application code
    }
    }

  • Hi,

      Sorry the late reply as I was out of office and just got back. 

    So I checked with debugging after MAP_GPIOUnlockPin(GPIO_PORTD_BASE, GPIO_PIN_7); function going to the FAULT_ISR. Please assist to do further.

    With your newest code, I don't see MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD) getting called you configure Port D. I see you call enable Port M but not port D. 

  • Thanks for the notice. 

    Even I noticed and updated the code.

    Here my observation is going to the NMI handler. 

    With bare metal code NMI is triggering.

    What if I wanted to do with TI RTOS. Following is my code. NMI interrupt is not triggering.

    _Bool initPortD(void)
    {

    MAP_SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOD);

    while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD));
    MAP_GPIOPinTypeDIVSCLK(GPIO_PORTD_BASE,GPIO_PIN_7 );

    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;

    // Set PD7 as input
    MAP_GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_7);

    // Configure PD7 to trigger an NMI on a falling edge
    MAP_GPIOIntTypeSet(GPIO_PORTD_BASE, GPIO_PIN_7, GPIO_FALLING_EDGE);

    GPIOPinConfigure(GPIO_PD7_NMI);

    init_nmi();

    return __PASS;
    }

    void init_nmi(void)

    {

    // Register the NMI handler
     Hwi_Params hwiParams;
     Hwi_Params_init(&hwiParams);
     hwiParams.arg = 0;
     Hwi_create(FAULT_NMI, (Hwi_FuncPtr) nmiHandler, &hwiParams, NULL);


    // Enable the NMI interrupt
    Hwi_enableInterrupt(FAULT_NMI);

    }

    static void nmiHandler(UArg arg)
    {

    MAP_GPIOIntClear(GPIO_PORTD_BASE, GPIO_PIN_7);


    }

    Kindly assist to proceed further.

  • Hi,

      I have not heard back from you. I will close this thread for now. If you have any update you can write back to this post and the status will automatically change to OPEN.