Atmel website | ARM Community | AVR freaks | Technical Support
Banner
 FAQ •  Search •  Register •  Login 

All times are UTC + 1 hour [ DST ]




Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: ARM Crashing - Timer Counter 0 IRQ
PostPosted: Fri Apr 22, 2011 7:26 am 
Offline

Joined: Fri Apr 22, 2011 7:13 am
Posts: 1
Hi,
All I am working on a frequency measurement project using AT91SAM7SE512. I am using timer counter in capture mode to measure the frequency from a sensor. I have configured the TC interrupt to be triggered on falling edges. I don't know why its crashing. After a while of executing the program the PMC_PCER register takes some junk value and the TC0 registers also take some junk values. The PWM and serial communication seems to work fine though. I am posting the code here pardon me of there is a way to post source code. I just signed up as I am in a tight deadline.


__irq void timer0_c_irq_handler(void)
{

int i;
status=AT91C_BASE_TC0 ->TC_SR; //Read status register
AT91C_BASE_AIC ->AIC_ICCR = 0x1000 ; //Clear the interrupt bit by writing 1 to AIC_ICCR

if ((status&0x01)==0x01)
{ overflow_counter++; //If COVFS bit is set increment the overflow counter

}else if ((status&0x20)==0x20)
{
reg_a = AT91C_BASE_TC0->TC_RA; //If register A is loaded reser overflow-counter to 0
overflow_counter=0;

}else if ((status&0x40)==0x40)
{
reg_b = AT91C_BASE_TC0->TC_RB;
if(window_counter<N_SAMPLES){
sample_values[window_counter] = (overflow_counter*65536) + reg_b-reg_a; //If register B is loaded calculate the count and add it in the array
window_counter++; //Increment the counter

}else{
window_counter =0;
for(i=0;i<N_SAMPLES;i++){
window_sum=window_sum+sample_values[i]; //add the accumulated samples
}
// window_average=window_sum>>= N_SHIFT; (Division with the number of samples)
window_average=(window_sum>>= N_SHIFT); //Divide by left shift
window_average=(window_average<<=2)+window_average; //Multiply by 5 factor acheived my shifting left by 2 and adding the same number
new_Value_Flag=1; // Flag set when a new sample is created
sample_values[window_counter] = (overflow_counter*65536) + reg_b-reg_a; //Accumulate the new sample value
}
}
AT91C_BASE_AIC->AIC_EOICR = 0 ; //Write a value to the end of interrupt register
}

void Timer0_Init(){

AT91C_BASE_PMC->PMC_PCER = (AT91C_BASE_PMC->PMC_PCER |0x1000); //Enable peripheral clock to TIOA0
AT91C_BASE_PIOB->PIO_PDR = 0x1; //Disable the Paralell IO
AT91C_BASE_PIOB->PIO_ASR = 0x1; //Select the A peripheral
AT91C_BASE_TC0-> TC_CMR = 0x000A0600; //Set the TC_CMR to detect falling edges
AT91C_BASE_TC0-> TC_IER = 0x61; //Enable interrupt to detect LDRBS, LDRAS and COVFS
AT91C_BASE_TC0->TC_CCR = 0x01 ; //Enable the clock
printf("\n\r TI");
}

void Aic_Init(){
AT91C_BASE_AIC ->AIC_SMR[12] =0x60; //Set AIC_SMR to Positive edge triggered and priority 0
AT91C_BASE_AIC ->AIC_SVR[12] = (unsigned int)timer0_c_irq_handler; //Set the AIC_SVR to interrupt service routine
AT91C_BASE_AIC ->AIC_ICCR = 0x1000 ; //Clear any interrupts
AT91C_BASE_AIC ->AIC_IECR = 0x1000; //Enable the interrupt
printf("\n\r AI");
}


Attachments:
File comment: The assembly routines in the attached file works fine and has been tested a lot so I guess the problem isn't with that.
TCO.rar [2.01 KiB]
Downloaded 20 times
Top
 Profile  
 
 Post subject: Re: ARM Crashing - Timer Counter 0 IRQ
PostPosted: Sun Jun 05, 2011 2:29 pm 
Offline

Joined: Fri Nov 19, 2010 8:46 pm
Posts: 9
[quote="arunvijaykg"]
__irq void timer0_c_irq_handler(void)
{

int i;
status=AT91C_BASE_TC0 ->TC_SR; //Read status register
[/quote]

As it is currently, I understand it that the SAM7 will allow interrupts to be executed as soon as you clear the status bit. Anyone, please correct me if I'm wrong. (This is how things work on some other microprocessors at least).
Try moving the 'status' line to the bottom of the interrupt and see if it helps.

You can make a test, to see if the interrupt is re-entered, by having a global variable initially set to 0, then increment this variable at the beginning of the interrupt, and decrementing it at the end of the interrupt.
You could then turn on a LED if the value is >= 2 right after incrementing the value.

To find the cause of the crash, try making your timer0_c_irq_handler completely empty, so that it only contains the necessary code (eg. to clear the status bit)...

__irq void timer0_c_irq_handler()
{
(void) AT91C_BASE_TC0->TC_SR; /* no need to set a variable here, as everyone usually do */
#if 0
... disabled code ...
#endif
}

You probably want to set window_sum to 0, before the for-loop.

It might be a good idea to initialize window_counter to 0 somewhere; just to make it easier to analyze the data.

In your interrupt, you have something like...

sample_values[window_counter] = ...;
window_counter++;

Below that, you have...
window_counter = 0;
sample_values[window_counter] = ...;

but you do not increment window_counter there, which means you're losing sample values.

I'd suggest doing this in both places:
sample_values[window_counter++] = ...;
and move that line outside the if-clause, as it's done in both cases...

reg_b = AT91C_BASE_TC0->TC_RB;
if(window_counter >= N_SAMPLES)
{
window_counter = 0;
...
new_Value_Flag = 1;
}
sample_values[window_counter++] = (overflow_counter * 65536) + reg_b - reg_a;

You could save some CPU-time, if you subtract sample_value[window_counter] from window_sum, before writing the new value.
-Then you'd be able to get rid of the for-loop.
You'd have to clear the array first, to get correct results, though.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: