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.

Conflict in interrupt handling in TM4C123

Other Parts Discussed in Thread: TM4C123GH6PZ

Hi,

I am using Port k as output and Ports F and A as inputs for  scanned matrix keyboard. Ports F and A are programmed to interrupt on both falling edges.Port K always outputs zero on all pins. Any key press triggers an Interrupt Handler in which the keys are scanned to detect a single key press. The same Interrupt handler is registered to handle Ports F and A. Also UART0 is used for communication with another controller. The Interrupt Handler for UART0 is also registered.

With no keypad activity, the communication between the two controllers happens flawless. When communication is disabled and keypad is used, the system works flawless. But under normal scenario, if both Port F, A and UART0 interrupt handlers are enabled, the system hangs intermittent and the only way to recover is through reset.

Any suggestions on understanding the issue and a solution is appreciated.

Regards,

Hemant

  • Hi Hemant,

    Which part are you exactly using? Which one from TM4C123.

    Without providing the code we can only guess the problem, could you provide it?
  • Hi Luis,

    Thanks for the response.
    I am using TM4C123GH6PZ. It may be difficult to upload the code fully. If you can give pointers I can supply the snippets as appropriate.

    Regards,

    Hemant
  • It is possible to upload zip files for the project if you click on "Use rich formatting", there it will show various editor options including the option to upload files.

    Could you also show how the GPIO A and F are connected to the keypad? Is F being used for columns and A for lines? This will make 2 interrupts being called, even if they are the same handler (which I have never seen before that being used) and that would also not be needed. So with the UART0 interrupts enabled you most likely have 3 interrupts being called at the same time.

    Edit:
    Also do you have debouncing on the keypad? The bouncing effect could cause the GPIO interrupts being called multiple times with a press, and if you have the F in columns and A on lines (or vice-versa) this will cause a lot of problems like the F calling the handler and A calling right away the same handler depending on their priority order

  • Hello Hemant,

    When a system hangs, the approach should be to be connected via the debugger to see where it hangs before the reset is done. Did you check where the code hangs?

    Regards
    Amit
  • Hi Luis,

    The keypad is connected as:
    Port K (0 to 4): Output rows
    Port F (0 to 6): Input columns
    Port A (0): Input column

    function KeyboardInit:
    {
    // PortK Keyboard ROW
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
    GPIOPinTypeGPIOOutput(GPIO_PORTK_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);

    // Output default Keyboard Row mask (0x00) to PortK
    GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0);

    // PortF.D6 to .D0 and PortA.D7 Keyboard COL
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    // Unlock PF0
    HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= 0x01;
    HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = 0;

    GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_6|GPIO_PIN_5|GPIO_PIN_4|GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_1|GPIO_PIN_0);
    GPIOPadConfigSet(GPIO_PORTF_BASE, 0x0000007F,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
    // Configure PortF and PortA for falling edge interrupt
    GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_6|GPIO_PIN_5|GPIO_PIN_4|GPIO_PIN_3
    |GPIO_PIN_2|GPIO_PIN_1|GPIO_PIN_0,GPIO_BOTH_EDGES);
    // GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_6,GPIO_BOTH_EDGES);
    GPIOIntEnable(GPIO_PORTF_BASE,GPIO_INT_PIN_6|GPIO_INT_PIN_5|GPIO_INT_PIN_4
    |GPIO_INT_PIN_3|GPIO_INT_PIN_2|GPIO_INT_PIN_1|GPIO_INT_PIN_0);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, GPIO_PIN_7);
    GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
    GPIOIntTypeSet(GPIO_PORTA_BASE, GPIO_PIN_7,GPIO_BOTH_EDGES);
    GPIOIntEnable(GPIO_PORTA_BASE, GPIO_INT_PIN_7);
    }
    function CommunicationInit:
    {
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    // Set GPIO A0 and A1 as UART pins.
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    // Configure the UART for 115,200, 8-N-1 operation.
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 9600,(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |UART_CONFIG_PAR_NONE));
    UARTEnable(UART0_BASE);
    UARTFIFODisable(UART0_BASE);

    UARTIntEnable(UART0_BASE, UART_INT_RX);
    }

    in main()
    {
    // initialisation
    // Initialise keyboard interface
    KeyboardInit();
    ui32GPIO_PORTAStatus = GPIOIntStatus(GPIO_PORTA_BASE, 1);
    ui32GPIO_PORTFStatus = GPIOIntStatus(GPIO_PORTF_BASE, 1);
    GPIOIntClear(GPIO_PORTF_BASE, ui32GPIO_PORTFStatus);
    GPIOIntClear(GPIO_PORTA_BASE, ui32GPIO_PORTAStatus);
    IntEnable(INT_GPIOF);
    IntEnable(INT_GPIOA);

    // Initialise UART0 for communication with EDM Controller
    CommunicationInit();
    IntEnable(INT_UART0);
    IntMasterEnable();
    // Rest of the code in main()
  • Sorry Port K 0 to 3 pins are used
  • Hi Amit,

    Yes we had the debugger on and it went to FaultISR. We then checked the NVIC_FAULT_STAT and NVIC_FAULT_ADDR but we have no clue how to proceed beyond this.

    Regards,

    Hemant
  • Hi Hemant,

    After you enable the clocks for the peripherals you need at least 3 clock cycles before you access their registers.
    Try adding SysCtlDelay(3) after all clocks enabled.
  • Hi Luis,

    Sorry for the lapse.

    My colleague in the team has done that in the latest code. What I sent you is a wee bit old.

    Regards,

    Hemant
  • Hello Hemant,

    What is the value of the two registers? Did you look it up the Data sheet?

    Regards
    Amit
  • Hi Amar,

    The registers under various conditions show different faults. The register we checked is NVIC_DBG_DATA.

    Latest exercise in debugging indicates that a Time used in the application to refresh the HMI periodicallt may be causing the hanging.

    We have used Time1 Sub timer A as a periodic Timer with a period of 50msec (tried different values too). The code is shown below.
    ********************************************************************************************************/
    void HMIRefreshInit(void)
    {

    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
    SysCtlDelay(3);

    TimerConfigure(TIMER1_BASE, TIMER_CFG_A_PERIODIC);
    TimerLoadSet(TIMER1_BASE, TIMER_A, SysCtlClockGet()/20);

    TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
    IntEnable(INT_TIMER1A);
    }

    In the interrupt handler for this timer, we have a switch case block that sends query to the other system over UART. This is shown below.

    ********************************************************************************************************/
    void HMIRefreshIntHandler(void) // Uses Timer1A
    {
    static uint8_t ui8ParameterRequest=0;
    switch (ui8ParameterRequest)
    {
    case 0:
    //Query GapV
    UARTSend("g");
    ui8ParameterRequest++;
    break;
    case 1:
    //Query DROZ
    UARTSend("z");
    ui8ParameterRequest++;
    break;
    case 2:
    //Query DROX
    UARTSend("x");
    ui8ParameterRequest++;
    break;
    case 3:
    //Query DROY
    UARTSend("y");
    ui8ParameterRequest++;
    break;
    case 4:
    //Query Alarms
    UARTSend("f");
    ui8ParameterRequest=0;
    break;
    }
    TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
    }
    /********************************************************************************************************

    We start and stop the timer as required in varous places in the code. We use the HMIRefreshStart() and HMIRefreshPause() functions to enable and disable the timer. This is shown below.

    ********************************************************************************************************/
    void HMIRefreshStart(void)
    {
    // Enable HourCountTimerInt
    TimerEnable(TIMER1_BASE, TIMER_A);
    // SysTickEnable();
    }
    ********************************************************************************************************/
    void HMIRefreshPause(void)
    {
    // Disable HourCountTimerInt
    TimerDisable(TIMER1_BASE, TIMER_A);
    // SysTickDisable();
    SysCtlDelay(80000);
    }
    /**************************************************************************************************

    The HMIRefreshStart() is called for the first time after HMIRefreshInit in the main(). later we toggle the timer as required. For debugging, we have kept HMIRefreshpause() and HMIRefreshStart() in only one place for simplicty.

    I noticed that if I disable HMIRefreshStart() and HMIRefreshPause() in ALL places, the application does not hang up. (Though HMIRefreshInit() still is executed in main().

    Amar, if you are in India time zone, can we talk over telephone/skype as the resolution of this issue is SUPER URGENT :(

    Thanks for your time.

    Regards.

    Hemant
  • Hi,

    The app note AN01286–May 2012 Section 3.3 Bus Fault Scenario 2 suggests debugging price and imprecise bus faults with an example on TimeLoadSet() function. However, no solution is suggested in the Summary of the section. Could this be an issue?

    Regards,

    Hemant
  • Hello Hemant,

    Precise faults are easy. Imprecise faults are the tricky one and hence the App Note mentions the procedure to do so with an example. I think the problem is arising from the manner in which the Timer is being enabled and being disabled.. If for example you do not disable the timer ever (comment out HMIRefreshPause) then does the application still hang.

    Also you are using it in Periodic Mode, while the software operation is being done as a One Shot. Is this an optimal solution?

    Regards
    Amit
  • Hi Amit,

    Yes, the applications hangs if the HMIRefreshPause is commented out.

    On debugging further per the document mentioned above we reached a point where we believe the application enters FaultISR during execution of usprintf(). This function is called inside the UART0 Interrupt handler. the TI wiki for C I/O says C I/O functions should not be called inside Interrupt handlers as they are not re-entrant. Does this apply to usprintf() also. Will taking that part of the code out of the interrupt handler help?

    Regards,

    Hemant
  • Hello Hemant

    That may be the issue. From the same wiki

    Here are some examples of functions which access the C I/O buffer, or access other global state in the C I/O subsystem:

    the entire printf family except sprintf

    Regards
    Amit
  • I am curious,

    The functions being non re-entrant does it really make them not possible to call inside the interrupt?
    Are you using in your main code any of those printf functions? Only then that would be a problem. I know it's non-optimal at all to use them inside the interrupt even if not used anywhere else but still, it's relevant to the problem.