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.

Compiler/EK-TM4C123GXL: Timer gets stops automatically while RPM measurement then Program is hanging. Here i am using GPIO interrupt too.

Part Number: EK-TM4C123GXL

Tool/software: TI C/C++ Compiler

HI, I am working with TM4C123GXl Launch pad for calculating Motor speed (RPM). Using Timer0 for calculating milliseconds ,  i am reset the millis count(variable)  every 60000 counts once. After some time program gets hanging. I would like to calculate RPM  can any one guide the by the proper steps. I have include my code below.

//*****************************************************************************
//
// timers.c - Timers example.
//
// Copyright (c) 2012-2017 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 2.1.4.178 of the EK-TM4C123GXL Firmware Package.
//
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"

//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>Timer (timers)</h1>
//!
//! This example application demonstrates the use of the timers to generate
//! periodic interrupts.  One timer is set up to interrupt once per second and
//! the other to interrupt twice per second; each interrupt handler will toggle
//! its own indicator on the display.
//!
//! UART0, connected to the Virtual Serial Port and running at 115,200, 8-N-1,
//! is used to display messages from this application.
//
//*****************************************************************************

//*****************************************************************************
//
// Flags that contain the current value of the interrupt indicator as displayed
// on the UART.
//
//*****************************************************************************
uint32_t g_ui32Flags;
volatile uint32_t millis,lastmillis=0,ms_millis=0;
int32_t Time_set;
//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************

  #define Sensor_PERIPA SYSCTL_PERIPH_GPIOA
  #define SensorBase GPIO_PORTA_BASE
  #define Sensor GPIO_PIN_5
  #define SensorInt GPIO_INT_PIN_5
  #define Sensor_PERIPA1 SYSCTL_PERIPH_GPIOA
  #define SensorBase1 GPIO_PORTA_BASE
  #define Sensor1 GPIO_PIN_6
  #define SensorInt1 GPIO_INT_PIN_6



  #ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

//*****************************************************************************
//
// The interrupt handler for the first timer interrupt.
//
//*****************************************************************************
int32_t count = 0,t_millis=0;
int32_t rpm = 0,x,;
uint32_t count1=0;
int32_t  Drum_dia=90;
void delay (unsigned int x) {
    while(x--);
}
void PortAIntHandler() {
     GPIOIntStatus(SensorBase,true);
     GPIOIntClear(GPIO_PORTA_BASE,GPIO_PIN_5);

     if( GPIOPinRead(GPIO_PORTA_BASE,GPIO_PIN_5)==32) {


         count1+=1;

     }
     GPIOIntEnable(GPIO_PORTA_BASE,GPIO_PIN_5);
}


void RPM_Cal( ) {
        x=ms_millis - lastmillis;

        if(count1>4)
        if(x==30)
        {
        count1=(count1/3);
        rpm = (int32_t) (count1/2) * 60; //  calculating RPM ... Per rotation sensor counts 2 pulse.
       // UARTprintf("\nrpm: %d ",rpm);
       // UARTprintf("\n millis: %d \t lasmillis=%d ",millis,lastmillis);
   
      //  UARTprintf("\t mpm: %d ",mpm);
        lastmillis = ms_millis;
        count1 = 0;x=0;
}
}


void Timer0IntHandler(void)
{
    char cOne;

    //
    // Clear the timer interrupt.
    //
    ROM_TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

    //
    // Toggle the flag for the first timer.
    //
    HWREGBITW(&g_ui32Flags, 0) ^= 1;

    //
    // Use the flags to Toggle the LED for this timer
    //
  //  GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, g_ui32Flags << 1);


    ROM_IntMasterDisable();
    cOne = HWREGBITW(&g_ui32Flags, 0) ? '1' : '0';

    millis += 1;                                          // converting 1ms into 100 ms
    if(millis == 100 || millis ==  t_millis) {
        t_millis=millis+100;
        ms_millis += 1;         // Every 100ms once i will get this value ms_mills =1;
         UARTprintf("\n millis:%d ",millis);
        if(millis>60000)     //setting for overflow by assumption keeping 5000000
        {
            ms_millis=0;
            lastmillis=0;
            millis=0;
            t_millis=0;

        }

    }

    ROM_IntMasterEnable();
}

//*****************************************************************************
//
// The interrupt handler for the second timer interrupt.
//
//*****************************************************************************

void
ConfigureUART(void)
{
    //
    // Enable the GPIO Peripheral used by the UART.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Enable UART0
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    //
    // Configure GPIO Pins for UART mode.
    //
    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Use the internal 16MHz oscillator as the UART clock source.
    //
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);

    //
    // Initialize the UART for console I/O.
    //
    UARTStdioConfig(0, 115200, 16000000);
}

//*****************************************************************************
//
// This example application demonstrates the use of the timers to generate
// periodic interrupts.
//
//*****************************************************************************
void sensor_config(void)
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
      //
      // Wait for the GPIOA module to be ready.
      //
          while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA))
          {
          }

      GPIOPinTypeGPIOInput(SensorBase, Sensor);
      GPIOPadConfigSet(SensorBase ,Sensor,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
      GPIOIntTypeSet(GPIO_PORTA_BASE,GPIO_PIN_5,GPIO_RISING_EDGE);
      GPIOIntRegister(GPIO_PORTA_BASE,PortAIntHandler);
      GPIOIntEnable(GPIO_PORTA_BASE, GPIO_INT_PIN_5);
}

 int main(void)
{
    Time_set=(16000000/1000);   //set the value 1ms (1s=16000000, 1ms=16000000/1000) setting timer for 1ms delay


    // Enable lazy stacking for interrupt handlers.  This allows floating-point
    // instructions to be used within interrupt handlers, but at the expense of
    // extra stack usage.
    //
    ROM_FPULazyStackingEnable();

    //akkaaa na call pannava?ok
    // Set the clocking to run directly from the crystal.
    //
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);

    //
    // Initialize the UART and write status.
    //
    ConfigureUART();


   // UARTprintf("\033[2JTimers example\n");
    //UARTprintf("T1: 0  T2: 0");

    //
    // Enable the GPIO port that is used for the on-board LED.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    //
    // Enable the GPIO pins for the LED (PF1 & PF2).
    //
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_1);


    //
    // Enable the peripherals used by this example.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);

    //
    // Enable processor interrupts.
    //
    ROM_IntMasterEnable();

    //
    // Configure the two 32-bit periodic timers.
    //
    ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
    ROM_TimerConfigure(TIMER1_BASE, TIMER_CFG_PERIODIC);
    ROM_TimerLoadSet(TIMER0_BASE, TIMER_A, Time_set);
    //ROM_TimerLoadSet(TIMER1_BASE, TIMER_A, ROM_SysCtlClockGet() / 2);

    //
    // Setup the interrupts for the timer timeouts.
    //
    ROM_IntEnable(INT_TIMER0A);
    ROM_IntEnable(INT_TIMER1A);
    ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    ROM_TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);

    //
    // Enable the timers.
    //
    ROM_TimerEnable(TIMER0_BASE, TIMER_A);
    ROM_TimerEnable(TIMER1_BASE, TIMER_A);

    sensor_config();
    while(1) {
        RPM_Cal();
       SysCtlDelay(50000);
    }
    return 0;
}

  • shriram jayabalan said:
    After some time program gets hanging.

    Can you be more specific? Is the CPU stuck in an abort routine?

    I suggest you not use a UARTPrintf() in your 1mS timer 0 interrupt routine. Printing that simple string will take over 80% of the 1mS time and may cause you to miss GPIOA interrupts.

    This seems to me an awkward way to calculate RPM. Typically you just capture the time difference between successive interrupts from your index which represents the rotational period and invert that for the RPM calculation. You can do this with a GPIO interrupt like you have configured, or use the timer directly in "Input Edge-Time Mode".

  • 'Fifteen Hours to 'CST' Countdown' Greetings,

    Bob Crosby said:
    This seems to me an awkward way to calculate RPM

    So well said!     Posters would be so (well advised) to 'properly describe their method' - rather than (apparently) having their 'thought process scrambled' - via the demands of code...

    Yet - if my group may:

    Bob Crosby said:
    just capture the time difference between successive interrupts from your index

    While this (may) work - it is less accurate than accumulating 8 or 16 such interrupt periods (then averaging) - which 'escapes' a 'flawed single measure.'    Such added period calculations appear best for 'reasonable and/or higher speeds' - as the added time-periods are unlikely (then) to negatively impact the, 'Speed Calculation's Update Rate.'

  • i couldnt understand what you are saying about time difference between interrupts and all . I am new to this can you correct my RPM calculation function .....

  • I am not sure whether  CPU gets struck  or not . To Find that i run an code for LED blink in main loop , when my code get struck my LED  gets struck in current state(ON/OFF) itself, terminal get blanked .

    This is my update code. Please check and update me any fault is there . Thanks in advance .

    //*****************************************************************************
    //
    // timers.c - Timers example.
    //
    // Copyright (c) 2012-2017 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    //
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    //
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    //
    // This is part of revision 2.1.4.178 of the EK-TM4C123GXL Firmware Package.
    //
    //*****************************************************************************
    #include "Uart1.h"

    //*****************************************************************************
    //
    //! \addtogroup example_list
    //! <h1>Timer (timers)</h1>
    //!
    //! This example application demonstrates the use of the timers to generate
    //! periodic interrupts.  One timer is set up to interrupt once per second and
    //! the other to interrupt twice per second; each interrupt handler will toggle
    //! its own indicator on the display.
    //!
    //! UART0, connected to the Virtual Serial Port and running at 115,200, 8-N-1,
    //! is used to display messages from this application.
    //
    //*****************************************************************************

    //*****************************************************************************
    //
    // Flags that contain the current value of the interrupt indicator as displayed
    // on the UART.
    //
    //*****************************************************************************
    uint32_t g_ui32Flags;
      uint32_t millis,lastmillis=0;  int32_t Time_set; //int32_t count=0;
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************

      #define Button_PERIPA SYSCTL_PERIPH_GPIOA
      #define ButtonBase GPIO_PORTA_BASE
      #define Button GPIO_PIN_5
      #define ButtonInt GPIO_INT_PIN_5


      #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif

    //*****************************************************************************
    //
    // The interrupt handler for the first timer interrupt.
    //
    //*****************************************************************************


    int32_t count = 0,t_millis=0;

    int32_t rpm = 0,ms_millis=0,x,mpm=0;
    uint32_t count1=0;

    int32_t  Drum_dia=90;
    void delay (unsigned int x) {
        while(x--);
    }
    void PortAIntHandler() {
         GPIOIntStatus(ButtonBase,true);
         GPIOIntClear(GPIO_PORTA_BASE,GPIO_PIN_5);

         if( GPIOPinRead(GPIO_PORTA_BASE,GPIO_PIN_5)==32) {

             count1+=1;

         }
         GPIOIntEnable(GPIO_PORTA_BASE,GPIO_PIN_5);
    }


    void RPM_Cal( ) {

            if(ms_millis - lastmillis==1)
            {

            UARTprintf("\n ms_millis: %d ",ms_millis);
          // UARTprintf("\ncount: %d ",count1/2);
            rpm = (int32_t) (count1/2) * 60; // calculating RPM
           UARTprintf("\nrpm: %d ",rpm)
            lastmillis = ms_millis;
            count1 = 0;x=0;


            }
    }


    void Timer0IntHandler(void)
    {
        char cOne, cTwo;

        //
        // Clear the timer interrupt.
        //
        ROM_TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

        //
        // Toggle the flag for the first timer.
        //
        HWREGBITW(&g_ui32Flags, 0) ^= 1;

        //
        // Use the flags to Toggle the LED for this timer
        //
      //  GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, g_ui32Flags << 1);


        ROM_IntMasterDisable();
        cOne = HWREGBITW(&g_ui32Flags, 0) ? '1' : '0';
        ms_millis += 1;
            if(ms_millis>100000)     //setting for overflow by assumption keeping 5000000
            {
                ms_millis=0;lastmillis=0;


            }

        ROM_IntMasterEnable();
    }

    //*****************************************************************************
    //
    // The interrupt handler for the second timer interrupt.
    //
    //*****************************************************************************

    void
    ConfigureUART(void)
    {
        //
        // Enable the GPIO Peripheral used by the UART.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

        //
        // Enable UART0
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

        //
        // Configure GPIO Pins for UART mode.
        //
        ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
        ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
        ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

        //
        // Use the internal 16MHz oscillator as the UART clock source.
        //
        UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);

        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(0, 115200, 16000000);
    }

    //*****************************************************************************
    //
    // This example application demonstrates the use of the timers to generate
    // periodic interrupts.
    //
    //*****************************************************************************


     int main(void)
    {
        Time_set=(16000000000/1000);   //set the value 1ms (1s=16000000, 1ms=16000000/1000) setting timer for 1ms delay


        // Enable lazy stacking for interrupt handlers.  This allows floating-point
        // instructions to be used within interrupt handlers, but at the expense of
        // extra stack usage.
        //
        ROM_FPULazyStackingEnable();


        //
        ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                           SYSCTL_XTAL_16MHZ);

        //
        // Initialize the UART and write status.
        //
        ConfigureUART();
        uart1_config();

       // UARTprintf("\033[2JTimers example\n");
        //UARTprintf("T1: 0  T2: 0");

        //
        // Enable the GPIO port that is used for the on-board LED.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

        //
        // Enable the GPIO pins for the LED (PF1 & PF2).
        //
        ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_1);


        //
        // Enable the peripherals used by this example.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);

        //
        // Enable processor interrupts.
        //
        ROM_IntMasterEnable();

        //
        // Configure the two 32-bit periodic timers.
        //
        ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
        ROM_TimerConfigure(TIMER1_BASE, TIMER_CFG_PERIODIC);
        ROM_TimerLoadSet(TIMER0_BASE, TIMER_A, Time_set);
        //ROM_TimerLoadSet(TIMER1_BASE, TIMER_A, ROM_SysCtlClockGet() / 2);

        //
        // Setup the interrupts for the timer timeouts.
        //
        ROM_IntEnable(INT_TIMER0A);
        ROM_IntEnable(INT_TIMER1A);
        ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
        ROM_TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);

        //
        // Enable the timers.
        //
        ROM_TimerEnable(TIMER0_BASE, TIMER_A);
        ROM_TimerEnable(TIMER1_BASE, TIMER_A);

         SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        //
        // Wait for the GPIOA module to be ready.
        //
            while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA))
            {
            }

        GPIOPinTypeGPIOInput(ButtonBase, Button);
        GPIOPadConfigSet(ButtonBase ,Button,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
        GPIOIntTypeSet(GPIO_PORTA_BASE,GPIO_PIN_5,GPIO_RISING_EDGE);
        GPIOIntRegister(GPIO_PORTA_BASE,PortAIntHandler);
        GPIOIntEnable(GPIO_PORTA_BASE, GPIO_INT_PIN_5);



        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

            //
            // Enable the GPIO pins for the LED (PF2 & PF3).
            //
            ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
        while(1) {

            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);

                   //
                   // Delay for a bit.
                   //
                   SysCtlDelay(SysCtlClockGet() / 10 / 3);

                   //
                   // Turn off the BLUE LED.
                   //
                   GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);

                   //
                   // Delay for a bit.
                   //
                   SysCtlDelay(SysCtlClockGet() / 10 / 3);
            RPM_Cal();
           
        }
        return 0;
    }

  • You may be confused about the services we offer on the forum. I am here to help you answer technical questions about the TI parts. It is not to review over 300 lines of C code for some possible error. I do want to help guide you in debugging your own code. Are you using an integrated development environment (IDE) like TI's Code Composer Studio? If so, you can stop the CPU and examine were in the code the CPU has stopped. You can also single step C lines and assembly lines. You can set breakpoints that stop the CPU when it gets to a certain point in your code. 

    Since you know your code starts running by seeing the LEDs blink. I suggest you just halt the debugger after the LEDs blink to see where it stopped. Is it in the "FaultISR()" function? Is it stuck in one of the interrupt functions? I noticed that you did not use dynamic interrupt function registration (calls to TimerIntRegister function), did you edit the startup_ccs.c file to point the interrupts to your interrupt service routines? 

  • Thanks for help me to short out the problem .My Interrupt routine was cause the problem when i have added  the TimerIntregister function ,problem was short outed .