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.

TM4c123GXL interrupt only fires once

Other Parts Discussed in Thread: TM4C123GH6PM

Hello

I've been working on this project for a few weeks, mostly learning and reading the  Tiva TM4C123GH6PM Microcontroller (SPMS377) data sheet.

I run into a problem I don't know the cause what is preventing the Timer_A from continuously counting and when it matches the preset value to reset and firing another interrupt then restart the timer..

this program is simple the RED led flashes via a delay loop, then the Green led to light when an interrupt occurs, but the interrupt only occurs once, and I don't know why, that's why I'm asking for your help.

I'm using CCS 5.4.0    windows XP

TIVA  TM4C123GH6PM

Appreciate any help

Regards

Roman

====================================================================

#include <stdint.h>
#include "inc/tm4c123gh6pm.h"

extern void Timer0IntHandler(void);

void delay_sec(void);
volatile uint32_t ui32Loop;
volatile uint32_t nope;

#define SYSDIV 2
#define LSB 0
#define timer_int 0x00080000

#define red 0x0002
#define blue 0x0004
#define green 0x0008
//*****************************************************************************
//
// Blink the on-board LED.
//
//*****************************************************************************
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;


    // Enable the GPIO port that is used for the on-board LED.
    SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOF;
    SYSCTL_RCGCTIMER_R = SYSCTL_RCGCTIMER_R0 + SYSCTL_RCGCTIMER_R1;  // p334

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

    // Enable the GPIO pin for the LED (PF3).  Set the direction as output, and
    // enable the GPIO pin for digital function.
    GPIO_PORTF_DIR_R = 0x0E;
    GPIO_PORTF_DEN_R = 0x0E;
    ui32Loop = SYSCTL_RCGC2_R;
    GPIO_PORTF_DATA_R &= ~(0x0E);
    delay_sec();
// *************************************************************************
//  timer   698
// *************************************************************************


    TIMER0_CFG_R = TIMER_CFG_32_BIT_TIMER;  // 00000000   p721
    TIMER0_TAILR_R = 0x04FAF000;  // 0x000186A;    //   load timer value  750
    TIMER0_TAMR_R |= TIMER_TAMR_TAMR_PERIOD + TIMER_TAMR_TAMIE; //    0x2       723

    TIMER0_IMR_R = TIMER_IMR_TATOIM; // set interupt 739
    TIMER0_CTL_R = TIMER_CTL_TAEN; // enable the timer and start counting 731
// *************************************************************************
//  interrupt
// *************************************************************************
    NVIC_EN0_R = timer_int;
    NVIC_ST_CTRL_R |= NVIC_ST_CTRL_INTEN;

    while(1)
    {
            delay_sec();
            GPIO_PORTF_DATA_R |= red;
            delay_sec();
            GPIO_PORTF_DATA_R &= ~(red);
            GPIO_PORTF_DATA_R &= ~(green); // reset green INT may have set it
    }
}

void delay_sec(void)
{
    for(ui32Loop = 0; ui32Loop < 200000; ui32Loop++)
        {
        }
}
void Timer0IntHandler(void)
{
    GPIO_PORTF_DATA_R |= green;  
    NVIC_DIS0_R  |= timer_int;    
}

==================================================================================

  • Hi Roman,

         Does your Timer0IntHandler(), clears the Timer Interupt?

         You need to clear the Timer Interrupt. See below from the timer example program. I admire your coding with direct address read/write. However, I would recommend using the Tivaware API's. Much more readable.

    void
    Timer1IntHandler(void)
    {
    //
    // Clear the timer interrupt.
    //
    ROM_TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);

    }

  • Your main problem is likely that:

    NVIC_DIS0_R  |= timer_int;

    disables the timer interrupt rather than clearing it.

    I know some people prefer writing their code to access registers directly but you may like to take a look at our DriverLib C API which is part of the TivaWare package for our chips. This makes writing code a great deal easier and makes what you are trying to do very much more obvious to the reader. As far as customization and maintainability go, I strongly suspect that you will find that a DriverLib-based application is a far cheaper option, especially when you are building something more than a very small number of lines long.

  • Thanks  Markel

    I initially had this problem with clearing the Interrupt, I resolved this by

    void Timer0IntHandler(void)
    {
        GPIO_PORTF_DATA_R |= green;  
        NVIC_DIS0_R  |= timer_int;    //#define timer_int 0x00080000
    }


    In the main loop the red led flashes to show it's in the main body and running.

    then Timer0_A completes it's count this will cause an interrupt making the Green led flash (about 1 every second) . then upon resetting the interrupt flag causes a return to the main body and the red led will start to flash again.

    Well when I run this the red led flashes for about 1 sec then I get 1 green flash (interrupt) then return to the main body and resume flashing the red led.

    Problem is it does not cause any additional green led flashed every second. leads me to believe I did something wrong with the timer config, it's acting as a one shot not a continuous as my intentions.

    Why don't I use the API, I like to know how the internal operation works, this provides fewer clock cycles and faster run times, In addition it's closer to assembler.

     




  • Hi Dave

    I'll try a different method to clear the interrupt flag, the Data Sheet was not very descriptive.

    I like to use API's but first  I like to know how the register work and their operations, this provides a better understanding of the machine, and what happens internally, plus this gets me closer to assembler code

    Regards

    Roman

  • You need to clear the interrupt in the timer, not the NVIC. Look in the datasheet for GPTMICR.

  • Hello Dave

    That did the trick

    void Timer0IntHandler(void)
    {
        GPIO_PORTF_DATA_R |= green;  
        TIMER0_ICR_R = TIMER_ICR_TATOCINT; // clear interrupt
    }


    Thanks for your help, and quick response, it's greatly appreciated.

    I may be back for more help in the future as the next part is to add ADC


    Have a great day


    Regards

    Roman