This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Urgent: Problem in Timer interrupt program using AT91SAM7SE512-EK]

Dear Friends,
I am using the Keil uvision3 ARM version,I have developed a new project Timer interrupt program.(downloaded from Atmel website).
In compilation of the code has no problem,after i downloaded into the Flash using ULink2 ARM debugger.

When i RUN the code,there is no output,means getting hang(only once go inside the interrupt loop,not return back ).

Hereby i have attached the source code for your reference.

Could you please advice on this problem.

The source code is
// ----------------------------------------------------------------------------
// File Name : interrupt_timer.c
// Object : Timer interrupt management
// : Use AT91B_LED1 & AT91B_LED2 for status interrupt
// Creation : JPP 11-May-2006
// ----------------------------------------------------------------------------

// Include Standard LIB files
#include "include_files.h"

//* Global variable int count_timer0_interrupt; int count_timer1_interrupt;

#define TIMER0_INTERRUPT_LEVEL 1
#define TIMER1_INTERRUPT_LEVEL 7

/*-----------------*/
/* Clock Selection */
/*-----------------*/
#define TC_CLKS 0x7
#define TC_CLKS_MCK2 0x0
#define TC_CLKS_MCK8 0x1
#define TC_CLKS_MCK32 0x2
#define TC_CLKS_MCK128 0x3
#define TC_CLKS_MCK1024 0x4

//*------------------------- Internal Function --------------------------------
//*----------------------------------------------------------------------------
//* Function Name : AT91F_TC_Open
//* Object : Initialize Timer Counter Channel and enable is clock
//* Input Parameters : <tc_pt> = TC Channel Descriptor Pointer
//* <mode> = Timer Counter Mode
//* : <TimerId> = Timer peripheral ID definitions
//* Output Parameters : None
//*----------------------------------------------------------------------------
void AT91F_TC_Open ( AT91PS_TC TC_pt, unsigned int Mode, unsigned int TimerId)
//* Begin
{ unsigned int dummy;

//* First, enable the clock of the TIMER AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1<< TimerId ) ;

//* Disable the clock and the interrupts TC_pt->TC_CCR = AT91C_TC_CLKDIS ; TC_pt->TC_IDR = 0xFFFFFFFF ;

//* Clear status bit dummy = TC_pt->TC_SR; //* Suppress warning variable "dummy" was set but never used dummy = dummy; //* Set the Mode of the Timer Counter TC_pt->TC_CMR = Mode| AT91C_TC_CPCTRG ;

TC_pt->TC_RC= 0xB71B;//0x12F4; =(Time * MCK)/1024 //0x5B8D;//500Ms //* Enable the clock TC_pt->TC_CCR = (AT91C_TC_CLKEN | AT91C_TC_SWTRG ) ;
//* End
} //*------------------------- Interrupt Function -------------------------------

//*----------------------------------------------------------------------------
//* Function Name : timer0_c_irq_handler
//* Object : C handler interrupt function call by the interrupts
//* assembling routine
//* Output Parameters : increment count_timer0_interrupt
//*---------------------------------------------------------------------------- void timer0_c_irq_handler(void)
{ AT91PS_TC TC_pt = AT91C_BASE_TC0; unsigned int dummy; //* AcknowAT91B_LEDge interrupt status dummy = TC_pt->TC_SR; //* Suppress warning variable "dummy" was set but never used dummy = dummy; //count_timer0_interrupt++; //* Read the output state if ( (AT91F_PIO_GetInput(AT91C_BASE_PIOA) & LED1 ) == LED1 ) { AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, LED1); } else { AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED1); } /*if ( (AT91F_PIO_GetInput(AT91C_BASE_PIOC) & HEARTBT_OUTPUT ) == HEARTBT_OUTPUT ) { AT91F_PIO_ClearOutput(AT91C_BASE_PIOC, HEARTBT_OUTPUT); } else { AT91F_PIO_SetOutput( AT91C_BASE_PIOC, HEARTBT_OUTPUT); } */
} //*----------------------------------------------------------------------------
//* Function Name : timer1_c_irq_handler
//* Object : C handler interrupt function call by the interrupts
//* assembling routine
//* Output Parameters : increment count_timer1_interrupt
//*----------------------------------------------------------------------------
// void timer1_c_irq_handler(void)
//{
// AT91PS_TC TC_pt = AT91C_BASE_TC1;
// unsigned int dummy; //* AcknowAT91B_LEDge interrupt status
// dummy = TC_pt->TC_SR; //* Suppress warning variable "dummy" was set but never used
// dummy = dummy;
// count_timer1_interrupt++;

//* Read the output state // if ( (AT91F_PIO_GetInput(AT91D_BASE_PIO_LED) & AT91B_LED2 ) == AT91B_LED2 ) // { // AT91F_PIO_ClearOutput( AT91D_BASE_PIO_LED, AT91B_LED2 ); // } else { // AT91F_PIO_SetOutput( AT91D_BASE_PIO_LED, AT91B_LED2 ); // }
//}
//*-------------------------- External Function -------------------------------

//*----------------------------------------------------------------------------
//* Function Name : timer_init
//* Object : Init timer counter
//* Input Parameters : none
//* Output Parameters : TRUE
//*----------------------------------------------------------------------------
void timer_init ( void )
//* Begin
{ //init the timer interrupt counter count_timer0_interrupt=0; count_timer1_interrupt=0;

//* Open timer0 AT91F_TC_Open(AT91C_BASE_TC0,TC_CLKS_MCK1024,AT91C_ID_TC0);

//* Open Timer 0 interrupt AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_TC0, TIMER0_INTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, timer0_c_irq_handler); AT91C_BASE_TC0->TC_IER = AT91C_TC_CPCS; // IRQ enable CPC AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_TC0);

//* Open timer1 //AT91F_TC_Open(AT91C_BASE_TC1,TC_CLKS_MCK128,AT91C_ID_TC1);

//* Open Timer 1 interrupt /*AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_TC1, TIMER1_INTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, timer1_c_irq_handler); AT91C_BASE_TC1->TC_IER = AT91C_TC_CPCS; // IRQ enable CPC AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_TC1);*/

//* Start timer0 AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG ;

//* Start timer1 // AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG ;

//* End
}

With Regards & Thanks, Murthy.R

  • Repost your code, but this time please read the posting instructions for code - just about the textbox where you paste your code.

  • My code

    //----------------------------------------------------------------------------
    // File Name : interrupt_timer.c
    // Object : Timer interrupt management
    // : Use AT91B_LED1 & AT91B_LED2 for status interrupt
    // Creation : JPP 11-May-2006
    // ----------------------------------------------------------------------------
    
    // Include Standard LIB files
    #include "include_files.h"
    
    //* Global variable int count_timer0_interrupt; int count_timer1_interrupt;
    
    #define TIMER0_INTERRUPT_LEVEL 1
    #define TIMER1_INTERRUPT_LEVEL 7
    
    /*-----------------*/
    /* Clock Selection */
    /*-----------------*/
    #define TC_CLKS 0x7
    #define TC_CLKS_MCK2 0x0
    #define TC_CLKS_MCK8 0x1
    #define TC_CLKS_MCK32 0x2
    #define TC_CLKS_MCK128 0x3
    #define TC_CLKS_MCK1024 0x4
    
    //*------------------------- Internal Function --------------------------------
    //*----------------------------------------------------------------------------
    //* Function Name : AT91F_TC_Open
    //* Object : Initialize Timer Counter Channel and enable is clock
    //* Input Parameters : <tc_pt> = TC Channel Descriptor Pointer
    //* <mode> = Timer Counter Mode
    //* : <TimerId> = Timer peripheral ID definitions
    //* Output Parameters : None
    //*----------------------------------------------------------------------------
    void AT91F_TC_Open ( AT91PS_TC TC_pt, unsigned int Mode, unsigned int TimerId)
    //* Begin
    { unsigned int dummy;
    
    //* First, enable the clock of the TIMER AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1<< TimerId ) ;
    
    //* Disable the clock and the interrupts TC_pt->TC_CCR = AT91C_TC_CLKDIS ; TC_pt->TC_IDR = 0xFFFFFFFF ;
    
    //* Clear status bit dummy = TC_pt->TC_SR; //* Suppress warning variable "dummy" was set but never used dummy = dummy; //* Set the Mode of the Timer Counter TC_pt->TC_CMR = Mode| AT91C_TC_CPCTRG ;
    
    TC_pt->TC_RC= 0xB71B;
    //* Enable the clock
    TC_pt->TC_CCR = (AT91C_TC_CLKEN | AT91C_TC_SWTRG ) ;
    //* End
    } //*------------------------- Interrupt Function -------------------------------
    
    //*----------------------------------------------------------------------------
    //* Function Name : timer0_c_irq_handler
    //* Object : C handler interrupt function call by the interrupts
    //* assembling routine
    //* Output Parameters : increment count_timer0_interrupt
    //*---------------------------------------------------------------------------- void timer0_c_irq_handler(void)
    { AT91PS_TC TC_pt = AT91C_BASE_TC0; unsigned int dummy; //* AcknowAT91B_LEDge interrupt status dummy = TC_pt->TC_SR; //* Suppress warning variable "dummy" was set but never used dummy = dummy; //count_timer0_interrupt++; //* Read the output state if ( (AT91F_PIO_GetInput(AT91C_BASE_PIOA) & LED1 ) == LED1 )
    { AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, LED1);
    } else {
    AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED1); }
    
    
    //*-------------------------- External Function
    //*----------------------------------------------------------------------------
    //* Function Name : timer_init
    //* Object : Init timer counter
    //* Input Parameters : none
    //* Output Parameters : TRUE
    //*----------------------------------------------------------------------------
    void timer_init ( void )
    //* Begin
    { //init the timer interrupt counter count_timer0_interrupt=0; count_timer1_interrupt=0;
    
    //* Open timer0 AT91F_TC_Open(AT91C_BASE_TC0,TC_CLKS_MCK1024,AT91C_ID_TC0);
    
    //* Open Timer 0 interrupt AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_TC0, TIMER0_INTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, timer0_c_irq_handler); AT91C_BASE_TC0->TC_IER = AT91C_TC_CPCS; // IRQ enable CPC AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_TC0);
    
    
    //* Start timer0
    AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG ;
    
    
    //* End
    }
    

  • Hello Nanju Murthy,

    be sure that you acknowledge every interrupt at the end of your ISR by writing to register AIC_EOICR (AIC->AIC_EOICR = 0;).

    See also user manual for this chip. Chapter "Advanced Interrupt Controller", "AIC End of Interrupt Command Register"

    Best Regards,
    Martin

  • Hi Martin,

    Thanks for your suggestion.

    I have given this line
    "AT91F_AIC_AcknowledgeIt (AT91C_BASE_AIC);"
    at the end of the timer0_irq_handler function.
    But the result is same means the control is never return.

    With regards,
    Murthy.R

  • Hello Nanju Murthy,

    It is also necessary to clear the interrupt reason (source).
    For a timer interrupt this is done by reading the status register. I think you have commented out this line in your ISR.
    --> //* AcknowAT91B_LEDge interrupt status dummy = TC_pt->TC_SR;

    Best Regards,
    Martin

  • "I think you have commented out this line in your ISR.
    --> //* AcknowAT91B_LEDge interrupt status dummy = TC_pt->TC_SR;"

    I think that's just a result of his failure to read the instructions on posting source code...

    www.danlhenry.com/.../keil_code.png

    See: http://www.keil.com/forum/docs/thread10699.asp

  • Hi Martin,

    This is what i did in the code

    void timer0_c_irq_handler(void)
    {
    AT91PS_TC TC_pt = AT91C_BASE_TC0;
     unsigned int dummy;
     dummy = TC_pt->TC_SR;
     dummy = dummy;
    if ( (AT91F_PIO_GetInput(AT91D_BASE_PIO_LED) & AT91B_LED1 ) == AT91B_LED1 )
    {
     AT91F_PIO_ClearOutput( AT91D_BASE_PIO_LED, AT91B_LED1|AT91B_LED2 );
    }
    else
    {
    AT91F_PIO_SetOutput( AT91D_BASE_PIO_LED, AT91B_LED1|AT91B_LED2 );
    }
    
    AT91F_AIC_AcknowledgeIt (AT91C_BASE_AIC);
    }
    
    

    With regards,
    Murthy.R

  • Is that how you actually write your code?

    Do you find it clear and easy to read?

    Most people find it helps to use indentation and whitespace to lay-out their code for easier reading; eg,

    void timer0_c_irq_handler(void)
    {
       AT91PS_TC    TC_pt = AT91C_BASE_TC0;
       unsigned int dummy;
    
       dummy = TC_pt->TC_SR;
       dummy = dummy;
    
       if( ( AT91F_PIO_GetInput(AT91D_BASE_PIO_LED) & AT91B_LED1 )
           == AT91B_LED1 )
       {
          AT91F_PIO_ClearOutput( AT91D_BASE_PIO_LED, AT91B_LED1|AT91B_LED2 );
       }
       else
       {
          AT91F_PIO_SetOutput( AT91D_BASE_PIO_LED, AT91B_LED1|AT91B_LED2 );
       }
    
       AT91F_AIC_AcknowledgeIt( AT91C_BASE_AIC );
    }
    


    Doing complex operations inside the 'if' like that doesn't help readability, and making a separate assignment is unlikely to affect performance...

  • Hello Nanju Murthy,

    Please use the keyword volatile for the definition of your dummy variable.

     volatile unsigned int dummy;
     dummy = TC_pt->TC_SR;
     dummy = dummy;
    

    volatile tells the compiler that the varible can be modified externally to the implementation.

    Best Regards,
    Martin

  • HI Martin,
    I have tried this volatile also the result is same.
    here by i have enclosed the initialization code.
    Is there any wrong please check and advise me.

    void timer_init ( void )
    {
    AT91F_TC_Open(AT91C_BASE_TC0,TC_CLKS_MCK1024,AT91C_ID_TC0);
    
    AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC,
                                    AT91C_ID_TC0,
                                    TIMER0_INTERRUPT_LEVEL,
                                    AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
                                    timer0_c_irq_handler);
    
         AT91C_BASE_TC0->TC_IER = AT91C_TC_CPCS;
         AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_TC0);
    
    
         AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG ;
    
    
    }
    

    With regards,
    Murthy.

  • Hello Murthy,

    I have no idea what is going wrong.

    Did you test the timer in polling mode?
    Do not enable the interrupt and check the TC Status register in a loop to see whether the compare flag is set.
    Is the clock for the Timer enabled and working?
    Check the CLKSTA bit in the TC Status register.
    Maybe it is a good idea to check the ATMEL website to see if there is an example for a timer using interrupts.

    Best Regards,
    Martin

  • Hi Martin,

    Thanks for your suggestion.

    I have tested the timer in polling mode.
    without enable the interrupt and checked.
    The TC Status register the compare flag is set.
    The clock for the Timer enabled and working.

    I have one doubt
    "should i include any IRQ0.s files in my project?"

    If necessary means please give me the downloaded links.

    Please advise me on this.

    with regards,
    Murthy.R

  • Hello Murthy,

    I think you do not need the IRQ0.s file for you Timer Interrupt.
    Is the peripheral clock for the timer enabled?
    Check PMC_PCER register (see AT91SAM7SE512 user manuel chapter "Power Management Controller (PMC) User Interface").

    You wrote that the timer interrupt occurs only once. That means, that the interrupt is not acknowledged anyhow.

    Please check your interrupt service routine that the following things are done:
    - clear interrupt in AIC Interrupt Clear command register
    - read Timer Status register (clearing interrupt reason)
    - acknowledge interrupt by writing to AIC End of Interrupt Command Register

    Best Regards,
    Martin

  • Hi Martin,
    i have checked the PMC for timer,that is enabled.

    I have a startup code "SAM7.s"
    In this file some configuration settings are there.

    Q1.Do i have to make any changes on this STACK settings?

    I have installed the KEIL in "C:/KEIL"folder.
    and also installed the patch file in the same folder.

    Q2.Is this installation procedure correct?

    Please advise me on this.

    with regards,
    Murthy.R

  • Hello Murthy,

    I do not know which patch file you mean.

    Take the example C:\Keil\ARM\Boards\Atmel\AT91SAM7SE-EK\Blinky and replace Blinky.c
    with the following code and you have a Timer0 interrupt which ticks every 10ms.

    #include <AT91SAM7SE512.H>              // AT91SAM7SE512 definitions
    #include <lib_AT91SAM7SE512.h>          // AT91SAM7SE512 library functions
    #include "../AT91SAM7SE-EK.h"           // AT91SAM7SE-EK board definitions
    
    unsigned int led = 0;
    
    // Timer0 ISR
    void tim0_isr (void) __irq {
    static int msCnt = 0;
    
      if (msCnt++ > 10) {                                     // switch LED every 100ms
        msCnt = 0;
        if ((led ^=1) == 0)
          AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, AT91B_LED1); // LED on
        else
          AT91F_PIO_SetOutput  (AT91C_BASE_PIOA, AT91B_LED1); // LED off
        }
    
      AT91C_BASE_AIC->AIC_EOICR = AT91C_BASE_TC0->TC_SR;      //  Interrupt Ack
      AT91C_BASE_AIC->AIC_ICCR  = (1 << AT91C_ID_TC0);        //  Interrupt Ack
    
      *AT91C_AIC_EOICR = 0;                                   // End of Interrupt
    }
    
    // Main Program
    int main (void) {
    
      AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, 1 << AT91C_ID_PIOB); // Enable Clock for PIO
      AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, AT91B_LED_MASK);            // PIO for LEDs as Output
      AT91F_PIO_SetOutput(AT91C_BASE_PIOA, AT91B_LED_MASK);            // turn off LEDs
    
      AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, 1 << AT91C_ID_TC0);  // Enable Clock for TIM0
      AT91C_BASE_TC0->TC_CCR    = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
      AT91C_BASE_TC0->TC_CMR    = 2 | AT91C_TC_CPCTRG;
      AT91C_BASE_TC0->TC_RC     = 14975;                                        // period is 10ms
      AT91C_BASE_TC0->TC_IER    = AT91C_TC_CPCS;
    
      // TIM0 Interrupt: Mode and Vector with Lowest Priority and Enable */
      AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC0] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | AT91C_AIC_PRIOR_HIGHEST;
      AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC0] = (unsigned long) tim0_isr;
      AT91C_BASE_AIC->AIC_IECR = (1 << AT91C_ID_TC0);
    
      while (1);                                                       // Loop forever
    }
    

    Best Regards,
    Martin