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  [ 4 posts ] 
Author Message
 Post subject: TC0 RC Compare interrupt which doesn't work
PostPosted: Thu Feb 04, 2010 9:16 pm 
Offline

Joined: Thu Feb 04, 2010 3:44 pm
Posts: 9
Hi there,
I searched in the forum (hopefully deep enough) but I found nothing about my problem, so here I am...


My application involves a constant clock to be generated by the micro-controller (AT91SAM7S-256 @ 48Mhz), and an interrupt to occur on each falling edge of the same clock, to do some required stuff.
In first instance I've tried to build a program which blinks a led using a simple interrupt service routine (called on each falling edge of the generated clock): TC0 module is used in Waveforme 10 mode, TIOA0 (PA0) is controlled by TC0 and is the output pin on where the constant clock is being output (in this case this is useless because the led is not there, but is a useful test for my final application). A fast forced interrupt is setup to occur on each falling edge of PA0 clock, I accomplished this by requesting TC0 module to send an interrupt request to AIC every time RC comparison occurs (this also makes TC0 restart and PA0 pin to get low by the way). In this case the interrupt should occur every about 1 second or so, and it works just fine. The led blinks at the required rate and the clock signal is there on PA0. Just fine.
After that, I wanted to do the same thing, but with a quite higher clock frequency. This one should be around 1.5Mhz. So here it is what I did to modify my existing working code: change TC0 clock input to be MCLK/2 (was MCLK/1024) and change RA and RC values. And guess what: it stopped working :( In further debugging I discovered that the interrupt service routine was being called only once, and after that, not any further.
One last desperate hope drove me to place another dummy-read of the TC0 status register (which, AFAIK, clears the interrupt). This had the effect of making the interrupt to occur, but unfortunately with wrong timings! To better explain the situation I'm attacching an image which should make it clear:


Image


The first (upper) waveform is the clock output, this is controlled by TC0 module and works just fine, the clock is correct.
The second (lower) waveform is the pin that I'm manually toggling on every interrupt entry (which should occur on every falling edge of the clock), and this doesn't work as intended. As you can see, it doesn't get low where it should, and neither it does when it should get high, it looks like the toggling, then the interrupt calling, is being delayed.

These below are the "hot" parts of the code:

This is the part of code that setup TC0 and AIC:
Code:
/* Setup the Advanced Interrupt Controller */
init_aic:      ldr      R0, =AT91C_BASE_AIC
            ldr      R1, =0x00000020
            str      R1, [R0, #0x04*12]
            ldr      R0, =AT91C_BASE_AIC
            ldr      R1, =(1<<12)
            str      R1, [R0, #0x140]

/* Setting up TC_CMR0 */
init_tc0:      ldr      R0, =AT91C_BASE_TC0
            ldr      R1, =0x0009C000
            str      R1, [R0, #0x04]
/* Setting up TC_IER0, interrupting on RC compare */
            ldr      R0, =AT91C_BASE_TC0
            ldr      R1, =0x00000010
            str      R1, [R0, #0x24]
/* Loading RA and RC (compare regs) */
            ldr      R0, =AT91C_BASE_TC0
            ldr      R1, =8
            str      R1, [R0, #0x14]
            ldr      R0, =AT91C_BASE_TC0
            ldr      R1, =16
            str      R1, [R0, #0x1C]
/* Setting up TC_CCR0, TC0 starts */
            ldr      R0, =AT91C_BASE_TC0
            ldr      R1, =0x00000005
            str      R1, [R0, #0x00]

/* Clearing FIQ Interrupt Mask*/
            mrs      R1, CPSR
            bic      R1, R1, #(1<<6)
            msr      CPSR, R1

/* Enabling TC0 Interrupt */
            ldr      R0, =AT91C_BASE_AIC
            ldr      R1, =(1<<12)
            str      R1, [R0, #0x120]



This is the interrupt handling routine:
Code:
fiq_handler:
/* Read TC0_SR (Interrupt Acknowledgement) */
            ldr      R8, =AT91C_BASE_TC0
            ldr      R9, [R8, #0x20]

/* Toggling PIOA18 (blinking led) */
            ldr      R8, =AT91C_BASE_PIOA
            ldr      R9, [R8, #0x38]
            tst      R9, #(1<<18)

            ldrne   R8, =AT91C_BASE_PIOA
            ldrne   R9, =(1 << 18)
            strne   R9, [R8, #0x34]         /* Led OFF */

            ldreq   R8, =AT91C_BASE_PIOA
            ldreq   R9, =(1 << 18)
            streq   R9, [R8, #0x30]         /* Led ON */

/* Read TC0_SR (Interrupt Acknowledgement),
/* without this one (theorically useless) the
/* cpu would be interrupted only once and not any further!!!!!! */
            ldr      R8, =AT91C_BASE_TC0
            ldr      R9, [R8, #0x20]

/* Clearing TC0 Interrupt */
            ldr      R8, =AT91C_BASE_AIC
            ldr      R9, =(1<<12)
            str      R9, [R8, #0x128]

/* Returning from fast interrupt */
            subs   PC, LR, #4



By the way when I build up the program for the first time (the one that blinks a led, which works) it didn't work because I did not place any dummy-read of the TC0 status register there in the interrupt handling routine. I read the AT91SAM7-S datasheet over and over but I really found nothing about reading the status register, I had to find it somewhere on the network... now I'm wondering: is there something about this in the datasheet? If yes: where? If not: Why shouldn't atmel say anything about such an important aspect of TC0 ?

Could someone help me figuering out why the program won't work? Thanks in advantage for any further help!


Top
 Profile  
 
 Post subject: Re: TC0 RC Compare interrupt which doesn't work
PostPosted: Sat Feb 06, 2010 5:00 am 
Offline

Joined: Thu Mar 02, 2006 1:32 pm
Posts: 127
Location: Switzerland
Hi

Concerning the clearing of timer interrupt, this is a problem with the user's manual - this detail is missing: see also http://www.at91.com/forum/viewtopic.php/f,15/t,18877/

Since your are using what looks like a direct and short FIQ one would expect the interrupt routine time to be very short and so be able to keep up with the 1.5MHz interrupt rate. However I would take a step back and verify this:

1) Slow the clock down so that you can see the delay (in your scope shot it is not clear which edge the interrupt belongs to. It also doesn't seem to be a fixed delay, but this could be because it is also dependent on the point in time that the last timer interrupt is cleared and so the next made possible again. (Eg. factor 10 or 20 slower would be suitable)

2) Try also toggling the interrupt twice in the interrupt routine. This will show you then how fast a back-to back port toggle can be achieved (as reference for port peripheral delays - which can be rather longer than one expects depending on which bus the peripheral is on).

3) Are you sure that interrupts are not being blocked by other activities that are taking place on the board (other interrupts could have a dramatic effect, depending on priorities)?

4) Are you sure that the CPU is operating as fast as you expect? The PLL seems OK since the timer divides are giving the expected frequency but check that the CPU is also from the same clock and not running slowly.

Regards

Mark

www.uTasker.com


Top
 Profile  
 
 Post subject: Re: TC0 RC Compare interrupt which doesn't work
PostPosted: Sat Feb 06, 2010 9:53 pm 
Offline

Joined: Thu Feb 04, 2010 3:44 pm
Posts: 9
Quote:
Concerning the clearing of timer interrupt, this is a problem with the user's manual - this detail is missing: see also http://www.at91.com/forum/viewtopic.php/f,15/t,18877/


As a consequence I'd like to suggest Atmel to change that manual as soon as possible, this could be quite a big problem for those who are trying to build up a new project without knowing this issue!

Quote:
Since your are using what looks like a direct and short FIQ one would expect the interrupt routine time to be very short and so be able to keep up with the 1.5MHz interrupt rate. However I would take a step back and verify this:


After following your advice (thank you about those points) I figuered out that my initial project can't be done.
First of all I slowed down TC0's input CLK (from MCLK/2 to MCLK/32). Then I added some instructions to the interrupt handling code which basically bring a PIO port to HIGH level when entering fiq_handler, and bring it LOW when exiting the same routine. With this I discovered that my routine takes about 1.280 us to get done (PIO controller delays aren't taken into account but they shouldn't be that bad). At first this sounded kinda weird to me since one cycle length should be 1/48*1.1 (~23ns) and only a few instructions are listed there. Anyways, on further investigations (ARM7TDMI-S datasheet), I discovered that many ARM instructions (even if they do not branch) require some additional cycles. After this, I managed to make an approximate calculation of how many cycles the routine should require: teorically around 40 cycles. This means that, even without any delay (due to fiq triggering, PIO controller, memory controller or whatever) the machine would approximately take 1 us to get done. This means that I couldn't be able to keep the routine up with my 1.5MHz clock (which has a period of about 670 ns). And this definitely is the reason of the weird behaviour that I've previously described.


Thank you one more time Mark, you were really helpful!


Top
 Profile  
 
 Post subject: Re: TC0 RC Compare interrupt which doesn't work
PostPosted: Sat Feb 06, 2010 11:32 pm 
Offline

Joined: Thu Mar 02, 2006 1:32 pm
Posts: 127
Location: Switzerland
Hi

The Timer status register contains various flags which indicate whether an event has occurred "since the last read of the register" - this implies that the read of the register resets bits that have been set - and could be asserting interrupts.

Other peripheral descriptions explicitly note that a read of a certain register (usually its status register) is required; the timer description can thus be confusing.

I will point this fact out to my contacts so that it can be improved in the future (no guaranty though), but this forum should also help anyone searching for a method to solve such a problem.

Regards

Mark


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

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: Google [Bot] 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: