We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
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
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.
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
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
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?
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 }
Lot of thanks for your example code.
I have checked the code in the blinky project,the timer interrupt is working.
I have one doubt,
In your code you did't enable the Peripheral Clock for PIOA, But you are using the PIOA for LED.
Q1.Without Enable the Peripheral Clock for PIOA how it is working?
With regards&Thanks Murthy.R