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.

Timer0 oneshot interrupt

Other Parts Discussed in Thread: TM4C123GH6PM

I Need the your help, been racking my brains out for a bit, and I need your help.

This is a test program o figure out how to use the timer0 in a one shot mode repeatedly as required. the larger part is I'm using the the Comparator function and interrupt, when the COMP is triggered I need a 200ms-300ms delay to trigger another function.

I just can't get the timer to trigger the interrupt and generate a delay.

Regards

Roman

// ***************************************************************************
//  PF1 = RED led
//  PF2 = BLUE led
//  PF3 = GREEN led
//  PF0 = SW2
//  PF4 = SW1
// ****************************************************************************
#include <stdint.h>
#include "tm4c123gh6pm.h"

extern void Timer0IntHandler(void);
void delay_sec(uint32_t);

#define SYSDIV 2
#define LSB 0
#define timer_int 0x00080000
#define timer0_cnt_dwn 0x000F000 // TIMER COUNT VALUE <<<<<<<<<<<<<<<<<<<<<<<<<
#define red 0x0002
#define blue 0x0004
#define green 0x0008
#define sw2 0x0001

volatile uint32_t ui32Loop;
volatile uint32_t ui32Loop2;
volatile uint32_t nope;
volatile uint32_t temp = 0;

//*****************************************************************************
//
//*****************************************************************************
int
main(void)
{
    SYSCTL_RCC2_R |= SYSCTL_RCC2_USERCC2;
    SYSCTL_RCC2_R |= SYSCTL_RCC2_BYPASS2;
    SYSCTL_RCC_R &= ~SYSCTL_RCC_XTAL_M;        // clear XTAL field
    SYSCTL_RCC_R += SYSCTL_RCC_XTAL_16MHZ;     // configure for 16 MHz crystal
    SYSCTL_RCC2_R &= ~SYSCTL_RCC2_OSCSRC2_M;   // clear oscillator source field
    SYSCTL_RCC2_R += SYSCTL_RCC2_OSCSRC2_MO;   // configure for main oscillator source
    SYSCTL_RCC2_R &= ~SYSCTL_RCC2_PWRDN2;
    SYSCTL_RCC2_R |= SYSCTL_RCC2_DIV400;
    SYSCTL_RCC2_R &= ~SYSCTL_RCC2_SYSDIV2_M;   // clear system clock divider field
    SYSCTL_RCC2_R &= ~SYSCTL_RCC2_SYSDIV2LSB;  // clear bit SYSDIV2LSB
    SYSCTL_RCC2_R += (SYSDIV<<23)|(LSB<<22);   // divide by (2*SYSDIV+1+LSB)

    while((SYSCTL_RIS_R&SYSCTL_RIS_PLLLRIS)==0){};

    SYSCTL_RCC2_R &= ~SYSCTL_RCC2_BYPASS2;
    SYSCTL_RCGCGPIO_R = SYSCTL_RCGCGPIO_R4 + SYSCTL_RCGCGPIO_R5; // * enable GPIO E & F
    SYSCTL_RCGCTIMER_R = SYSCTL_RCGCTIMER_R0 + SYSCTL_RCGCTIMER_R1; //enable clk timer0

    // Do a dummy read to insert a few cycles after enabling the peripheral.
    ui32Loop = SYSCTL_RCGC2_R;

       GPIO_PORTF_LOCK_R = GPIO_LOCK_KEY;
    GPIO_PORTF_CR_R = GPIO_LOCK_LOCKED;

    GPIO_PORTF_DIR_R = 0x0E;
    GPIO_PORTF_DR2R_R &= ~GPIO_0;
    GPIO_PORTF_DEN_R = 0x0F;
    GPIO_PORTF_PUR_R |= GPIO_0;
    GPIO_PORTF_AMSEL_R = 0;
    ui32Loop = SYSCTL_RCGC2_R;
    GPIO_PORTF_DATA_R &= ~(0x0E);

// *************************************************************************
//  timer   698
// *************************************************************************
    TIMER0_CTL_R &= ~(TIMER_CTL_TAEN + TIMER_CTL_TBEN); // disable timers
    TIMER0_CFG_R = TIMER_CFG_32_BIT_TIMER;  // 32-bit timer configuration
    TIMER0_TAMR_R |= TIMER_TAMR_TAMR_1_SHOT | TIMER_TAMR_TAMIE + TIMER_TAMR_TAWOT;
    TIMER0_TAILR_R = 0xFFFFFFFF;  //    load timer value  750
    TIMER0_IMR_R = 0x1F;  //TIMER_IMR_CAMIM; // Capture Mode Match Interrupt Mask
    TIMER0_ICR_R = 0x1F; //TIMER_ICR_CAECINT;// clear timer0A capture match flag

// *************************************************************************
//  interrupt
// *************************************************************************
    NVIC_EN0_R = timer_int;
    NVIC_ST_CTRL_R |= NVIC_ST_CTRL_INTEN;
    NVIC_UNPEND0_R |= timer_int;  // clear interrupt

    GPIO_PORTF_DATA_R &= ~(green); // Turn Off LED
    while(1)  // loop forever
        {
            if ((GPIO_PORTF_DATA_R & GPIO_0)== 0)
            {
                TIMER0_CTL_R |= TIMER_CTL_TAEN;
                   GPIO_PORTF_DATA_R |= green;
            }
            GPIO_PORTF_DATA_R &= ~(red);  //  reset off LEDS
            GPIO_PORTF_DATA_R &= ~(green);
            GPIO_PORTF_DATA_R &= ~(blue);
//               delay_sec(1000);
          }
}
// *****************************************************************
//                          end of Main
// *****************************************************************
void delay_sec(uint32_t waste_time) //  used to see the LEDs flash for testing
{

    for(ui32Loop = 0; ui32Loop < waste_time; ui32Loop++)
        {
        }
}
void Timer0IntHandler(void)
{
    GPIO_PORTF_DATA_R &= ~(green);
//    TIMER0_CTL_R &= ~TIMER_CTL_TAEN; // disable timers
    TIMER0_ICR_R = 0x1F; //TIMER_ICR_CAMCINT;// GPTM TimerA Capture Mode Match INT Clear

       GPIO_PORTF_DATA_R |= red; // never comes on WHY ?????
     delay_sec(1000);
}

  • Hi Roman,

    Most forum members here are not used to programming using direct register read/write. Any reply could take some time.

    I suggest you review the timer example program. See, how Timer Interrupt Handlers are set to trigger.

    -kel

  • Hi Roman,

    Couple of clarification sought

    1. After the code if you put a breakpoint on the Interrupt Handler, does the Breakpoint get reached

    2. Does the GPIO if after all the configuration turn the LED's as expected.

    One thing here is that while the Interrupt has been enabled and NVIC configured, you have to map the interrupt handler in the Interrupt Vector table as well.

    As Kel mentioned it would be simpler doing it by using the examples and TIVAWare API's.

    Regards

    Amit

  • Thanks for the quick response, I appreciate any help I can get.

    question is, am I performing the right method to initiate the one shot timer.

     TIMER0_CTL_R |= TIMER_CTL_TAEN;

    I have single stepped through the app it runs but not sure if the timer is actually counting.

    1. After the code if you put a breakpoint on the Interrupt Handler, does the Breakpoint get reached

      I put a RED LED to turn on, if the interrupt is serviced, never does

    2. Does the GPIO if after all the configuration turn the LED's as expected.

      if ((GPIO_PORTF_DATA_R & GPIO_0)== 0)
                {
                    TIMER0_CTL_R |= TIMER_CTL_TAEN;
                       GPIO_PORTF_DATA_R |= green;
                }
                GPIO_PORTF_DATA_R &= ~(red);  //  reset off LEDS
                GPIO_PORTF_DATA_R &= ~(green);
                GPIO_PORTF_DATA_R &= ~(blue);
    //               delay_sec(1000);
              }

     

    the Green LED comes on when the SW0 is pressed so I know it gets there

     

    One thing here is that while the Interrupt has been enabled and NVIC configured, you have to map the interrupt handler in the Interrupt Vector table as well.

          IntDefaultHandler,                      // ADC Sequence 2 16
        IntDefaultHandler,                      // ADC Sequence 3 17
        IntDefaultHandler,                      // Watchdog timer 18
        Timer0IntHandler,                     // Timer 0 subtimer A 19
        IntDefaultHandler,                      // Timer 0 subtimer B 20
        IntDefaultHandler,                      // Timer 1 subtimer A 21
        IntDefaultHandler,                      // Timer 1 subtimer B 22
        IntDefaultHandler,                      // Timer 2 subtimer A 23

    As Kel mentioned it would be simpler doing it by using the examples and TIVAWare API's.

    I prefer to do this method as I have more control over the processor, in addition it's more direct as opposed to being a bit cryptic when using API's. Also it reduces memory used, when the final version is compiled I can remove many of the header files and unnecessary " #define" files to reduce memory usage .

    Regards

    Roman

  • Hi Roman,

    I went through the code again and while it looks to be OK, the CM4 Processor Interrupt Enable is not called. The function to do so is IntMasterEnable()

    To make sure that this is the issue, what you would need to do is let the code run and after the expected time you should check the GPT RIS register. If that is set then it is the IntMasterEnable not being used as the issue.

    Regards

    Amit Ashara

  • Roman bere said:

    1. After the code if you put a breakpoint on the Interrupt Handler, does the Breakpoint get reached

      I put a RED LED to turn on, if the interrupt is serviced, never does

     HI, an LED just lit if software is OK, this is never sure. Everything can go wrong and code behave badly misprogramming a port, a programming port can exist or a defect can be in place.

     A break point when reached assure code is here or there and also show you stack and other information too.

  • Hi,

    @Roman, not using driverlib - you have been bitten by some unexplained/undocumented behavior of timers - namely in TimerConfig function, TI uses to set the TIMER_TAMR_TAPWMIE and TIMER_TBMR_TBPWMIE flags for any timer configuration…. see the TimerConfig function code in driverlib (which you do not do…).

    Also, you should configure your timer for one-shot behavior, not match since it is not right, much simpler (or configure for match interrupt if counting up) and enable for timer overflow interrupt. To work in one-shot, just TimerLoad Set() with a value and then enable the timer. Inside interrupt do not disable the timer since after the timing expiration it is not restarted.

    Petrei

  • Thanks for the help regarding IntMasterEnable

    I found this in     "interrupt.c"

    //*****************************************************************************
    //
    //! Enables the processor interrupt.
    //!
    //! This function allows the processor to respond to interrupts.  This function
    //! does not affect the set of interrupts enabled in the interrupt controller;
    //! it just gates the single interrupt from the controller to the processor.
    //!
    //! \note Previously, this function had no return value.  As such, it was
    //! possible to include <tt>interrupt.h</tt> and call this function without
    //! having included <tt>hw_types.h</tt>.  Now that the return is a
    //! <tt>bool</tt>, a compiler error occurs in this case.  The solution
    //! is to include <tt>hw_types.h</tt> before including <tt>interrupt.h</tt>.
    //!
    //! \return Returns \b true if interrupts were disabled when the function was
    //! called or \b false if they were initially enabled.
    //
    //*****************************************************************************
    bool
    IntMasterEnable(void)
    {
        //
        // Enable processor interrupts.
        //
        return(CPUcpsie());
    }

     

    But it all so calls    "CPUcpsie()"

    found this is "cpu.c"

    //***************************************************************************

    CPUcpsie(void)
    {
        uint32_t ui32Ret;

        //
        // Read PRIMASK and enable interrupts.
        //
        __asm("    mrs     r0, PRIMASK\n"
              "    cpsie   i\n"
              "    bx      lr\n"
              : "=r" (ui32Ret));

        //
        // The return is handled in the inline assembly, but the compiler will
        // still complain if there is not an explicit return here (despite the fact
        // that this does not result in any code being produced because of the
        // naked attribute).
        //
        return(ui32Ret);
    }

    Back to my original statement, the API's are a bit convoluted

    you require "interrupt.c" which in turn requires "cpu.c".


    Instead of adding the header files, I'll just add the Assembler snip-it.

    I'll add this to the app and see what happens.

     

    Regards

    Roman

     

     

     

     

     

  • Hi Roman,

    Found the issue in the code itself. In the code you are enabling Wait on Trigger. (TIMER_TAMR_TAWOT). Thw Wait on trigger is a feature where you can daisy chain timers. For the first timer this bit has to be kept clear. Since you were setting it, the timer was waiting for trigger from the timer before it (which does not exist) and hence the configuration was not working

    TIMER0_TAMR_R |= TIMER_TAMR_TAMR_1_SHOT | TIMER_TAMR_TAMIE + TIMER_TAMR_TAWOT;

    After removing the same, the Interrupt is firing.

    TIMER0_TAMR_R |= TIMER_TAMR_TAMR_1_SHOT | TIMER_TAMR_TAMIE;

    Regards

    Amit

  • Thanks for your help, that did the trick, I was so focused on the Timer_A0 interrupt and the  NVIC registrars, did not realize it was right under my nose.

    this is the results of your help (see photo)

    I used the timer to create a delay of about 150 to 200ms delay to trigger a flash.

    This is the results a few millisec after the water drop hits the water,  this is the splash it causes.

    Regards

    Roman