AT32 UC3C, proper Timer interrupt setup

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Alright,

so I work on a project, that needs to call a function on a regular 1ms basis. The simplest solution that I came up with is implement this via timer interrupt.

As you may guess, I failed.

 

The timer is running but the ISR is not fired. I'm checking this via breakpoints. (one in the main-while-loop, the other in the interrupt)

I had a look at the disassembly, there I saw, that enable global interrupts has been optimized away.

 

But thats not all. If I remove "Disable_global_interrupt();" then the Interrupt is instantly fired after the interrupt was set up and after the ISR was completed the MCU is going into an "Bus Error Instruction Fetch" - Exception.

 

I've searched the Internet and the Datasheet for two days now, without finding any clues.

 

Does someone have any ideas how this can happen? Or how I should proceed?

 

 

here is all of my code:

#include <avr32/io.h>
#include <asf.h>

volatile uint32_t counterVar = 0;
volatile uint32_t maincounter = 0;

__attribute__((_interrupt_))
void timerISR_forABCC()
{
    counterVar++;
    tc_read_sr(&AVR32_TC0,0);
    
}

void ini_timer_kopiert()
{
    INTC_register_interrupt(&timerISR_forABCC, AVR32_TC0_IRQ0, AVR32_INTC_INT0);
    
    AVR32_TC0.channel[0].IER.cpcs = 1;
    AVR32_TC0.channel[0].CMR.waveform.wave = 1;
    AVR32_TC0.channel[0].CMR.waveform.wavsel = 2;
    AVR32_TC0.channel[0].CMR.waveform.tcclks = 2;
    AVR32_TC0.channel[0].RC.rc = 32000;
    AVR32_TC0.channel[0].CCR.clken = 1;
    AVR32_TC0.channel[0].CCR.swtrg = 1;
    
}

int main(void)
{
    Disable_global_interrupt();
    
    INTC_init_interrupts();
    
    ini_timer_kopiert();
    
    Enable_global_interrupt();
    
    /* Replace with your application code */
    while (1)
    {
        maincounter = AVR32_TC0.channel->CV.cv;
        
    }
}

 

 

This topic has a solution.

[insert smart signature here]

Last Edited: Mon. Oct 10, 2016 - 01:10 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I tried with maximum optimisation and the Enable_global_interrupt() is not optimised away.
Look for a csrf 0x10 instruction which clears the Global Interrupt Mask (GM) (bit-16) in the Status Register.
The assembly code that you see in the .lss output is not always aligned perfectly with your C statements.


When I compile your code, I get a '_interrupt_' attribute directive ignored warning which produces incorrect entry/exit code for the ISR.
The correct format for the interrupt attribute is __interrupt__ (2 underscores)


The following should work. (The static removes a no previous prototype for ... warning.)


__attribute__((__interrupt__))
static void timerISR_forABCC( void )

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for your effords!

I found the Enable_global_interrupt() again after an clean solution.

 

I somehow overlooked the warning, it's working now! :)

(After adding the second underscores)

[insert smart signature here]

Last Edited: Mon. Oct 10, 2016 - 01:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sometimes Atmel Studio 7 seems to hide some warnings unless you do a clean solution or a rebuild solution.

That's probably why I didn't notice it in the first place.

 

I couldn't reproduce this behaviour, but I've checked it on another project where I forgot the double underscore, too. I could start the build as often as I wanted, but the warning would not show up. Then I did a rebuild and the warning appeared. After this, the warning stayed as long as the underscores were missing.

[insert smart signature here]

Last Edited: Mon. Oct 10, 2016 - 01:25 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

a_random_Martin wrote:
Sometimes Atmel Studio 7 seems to hide some warnings unless you do a clean solution or a rebuild solution. That's probably why I didn't notice it in the first place.

A warning (until you use -Werror) is not fatal. So if you have:

 

foo.c (with something that creates a warning)

bar.c (the main file you work on).

 

Then the first time you build the GNU make system will spot that there is not a foo.o or bar.o that is the same age as foo.c or bar. so it will issue the commands:

 

avr32-gcc -c foo.c - o foo.o

<warning for that file output now>

avr32-gcc -c bar.c -o bar.o

avr-32-gcc foo.o bar.o -o proj.elf

 

But if you now just work on bar.c and rebuild the make system will "see" that foo.o is younger than foo.c so it won't build that one. So now you see:

 

avr32-gcc -c bar.c -o bar.o

avr-32-gcc foo.o bar.o -o proj.elf

 

with no warning. Each time you change bar.c and build then you just see the above - there's no reason for foo.o to be built again as it is up to date. If you now edit foo.c then it will be younger than foo.o so if you build you will see:

 

avr32-gcc -c foo.c - o foo.o

<warning for that file output now>

avr-32-gcc foo.o bar.o -o proj.elf

 

This time bar.o was not built because bar.c had not changed. Now maybe you switch back to working on bar.c. As foo.c is not being changed it will not be built. No warning will be seen.

 

If you now use "Clean" or "Build all" (which really just means "Clean" then Build) then that will erase foo.o and bar.o. So the next time you build it's just like when you started:

 

avr32-gcc -c foo.c - o foo.o

<warning for that file output now>

avr32-gcc -c bar.c -o bar.o

avr-32-gcc foo.o bar.o -o proj.elf

 

but from now on, unless you change foo.c it will not be built so you won't see the warning. This is different to an error. An error would prevent foo.o being created so, as far as make is concerned, foo.c should be attempted to build every time until foo.o exists.

 

You may want to explore -Werror or just "Build all" every time - AVR builds are generally so small it doesn't really matter if you build everything everytime.