Timer Interrupt on XMEGA32e5

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

Back at it again.

 

Sooooo I have a simple little test program that I am trying to get running, with little success.  MAybe someone here can give me the mental goose I am in need of.

 

I have TCC4 set up in standard mode, as a simple count up timer and the overflow interrupt enabled as medium level, global interrupt enabled, as is medium level interrupt enable enabled as per START.  Clock source is system clock/64 period is set to tick every 500ms or so.

 

System clock is 2MHz from internal 8MHz RC.

 

Here is the main.c:

#include <atmel_start.h>
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>


volatile uint16_t count = 1;;


int main(void)
{
	/* Initializes MCU, drivers and middleware */
	atmel_start_init();
	 
	 
	
		
	/* Replace with your application code */
	while (1) {
		
			PORTA.OUT = ~(count);
		
		
		
	}
}

 

and the ISR that is in the driver_isr.c file:


/*
 * Code generated by START.
 *
 * This file will be overwritten when reconfiguring your START project.
 * Please copy examples or other code you want to keep to a separate file
 * to avoid losing it when reconfiguring.
 */

#include <driver_init.h>
#include <compiler.h>


ISR(TCC4_OVF_vect)
{
	/* Insert your Timer Overflow/Underflow Interrupt handling code here */
	
		count = count * 2;
		if(count > 128)	{count = 1;}
		
}

 

So, whats supposed to happen is when the timer hits the period the ISR is fired and variable COUNT is multiplied by 2.  If COUNT exceeds 128 it is reset to 1.  Then the code should jump back to MAIN and output the value of count on PORTA

 

Problem is when I hit BUILD I get an error:

Severity    Code    Description    Project    File    Line
Error        'count' undeclared (first use in this function)    PORT_COUNTER    C:\Users\jgmDESIGNS\Documents\Atmel Studio\7.0\PORT_COUNTER\PORT_COUNTER\driver_isr.c    44

 

 

I would have thought that the VOLATILE would have fixed this.  I have also tried using EXTERN with no success.

 

Where did I go wrong?

 

Jim

This topic has a solution.

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

Last Edited: Fri. Mar 22, 2019 - 05:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would have thought an

extern volatile uint16_t count;

in the file that contains the ISR should do the trick but you said you tried that.

 

Normally (in my way of thinking) I consider the "count" variable belongs to the timer and is declared in the timer file. (the 1 containing the ISR).

Then I would declare it external in main or whatever other file(s) need to access it.  It does need to be declared in both files if I'm not mistaken unless the ISR is in the  same file as main().

 

You might also try just toggling a pin/LED inside the ISR to check that it is actually firing.

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

schtevo wrote:
ou might also try just toggling a pin/LED inside the ISR to check that it is actually firing.

 

Tried that and the Led is dimly lit.  Threw the Saleae on it and the pin is a square wave at 34kh - 38khz.  WTH.

 

I have attached the project if someone wants to take a look.

 

JIm

Attachment(s): 

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

I built that - it builds without error. That is because you have commented the stuff causing the problem?!?

 

But if I uncomment all the "count" stuff and then do what schetvo suggested:

volatile uint16_t count = 1;;

int main(void)
{
	/* Initializes MCU, drivers and middleware */
	atmel_start_init();
		
	/* Replace with your application code */
	while (1) {
		PORTA.OUT = ~(count);
	}
}

and:

extern volatile uint16_t count;

ISR(TCC4_OVF_vect)
{
	/* Insert your Timer Overflow/Underflow Interrupt handling code here */
	PORTA.OUTTGL =  2;
	count = count * 2;
	if(count > 128)	{count = 1;}
		
}

Then that also builds without error. I don't have the hardware so cannot actually try it.

 

However I did change  TC_CLKSEL_DIV64_gc to  TC_CLKSEL_DIV1_gc to speed things up a bit and simulated it with a breakpoint on the count * 2 and I see it count 1,2,4,8,16,32,64,128,1,2,4... as hoped.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually I just noticed that if I break on the PORTA.OUT write in main() as well as the count*2 then it never hits the break in main(). Is this because Xmega interrupt flags have to be manually cleared in ISRs perhaps?

 

Also the code doesn't make sense anyway. In main() you have:

		PORTA.OUT = ~(count);

but in the ISR you also have:

	PORTA.OUTTGL =  2;

the write to the entire register in main() is surely going to obscure any toggling of bit 1 that the ISR might be doing?

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

clawson wrote:
Actually I just noticed that if I break on the PORTA.OUT write in main() as well as the count*2 then it never hits the break in main(). Is this because Xmega interrupt flags have to be manually cleared in ISRs perhaps?

 

OH F***!

In my haste/lazy desire to accomplish something I ignored my rule to RTFDS COMPLETELY!  I glazed over the section about the INTFLAGS register on page 181, where it clearly reads:

 

Adding this to the last line of the ISR:

TCC4_INTFLAGS = 0xff;		//clear EVERY flag in the register

Solved the problem

 

Thanks CLIFF!!

 

 

clawson wrote:
Also the code doesn't make sense anyway. In main() you have:

PORTA.OUT = ~(count);

 

but in the ISR you also have:

 

PORTA.OUTTGL = 2;

 

the write to the entire register in main() is surely going to obscure any toggling of bit 1 that the ISR might be doing?

 

That was my trying schtevo's idea of toggling a pin in the ISR to see if it fires, and for some reason I must have missed commenting out the instruction in MAIN.  OOPS!

 

 

 

Thanks to you both for stepping in on this one.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

One side note to all of this that I am curious about.....

 

I have this in main:

volatile uint16_t count = 1;

and this in the ISR:

extern volatile uint16_t count;

ad the code runs just fine.

 

If I remove either the compiler barfs, which I expect. 

 

But if I change the ISR to this:

volatile uint16_t count;

the code compiles and runs fine on the target as well. So which is the proper programming format?  Extern or no Extern?

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

You should only instantiate variables in ONE place.

 

However GCC allows for a concept called .common so that it is possible to instantiate (as long as there's no initialiser) in two or more files (then the linker matches "common" things to one location). 

 

I never really understood the point of .common - it allows for dangerous practice.

 

Just define once and declare in as many other places as you like.

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

clawson wrote:
Just define once and declare in as many other places as you like.

And using EXTERN the way I did it is correct, yes?

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

If you say
.
int n;
.
It "defines" something called 'n' I memory that is type "Int". It really creates one. To differentiate this if you use :
.
extern Int n;
.
You are only declaring a thing called 'n' of type "Int". That says "just know that if you see me mention 'n' then treat it as int but don't actually create one as I'll be defining this in another file.
.
I remember the difference between declare and defINe as there is something IN a defINe.
.
These days I actually prefer the C++ term "instantiate" to describe the place you actually create an instance of something (variable or function). That is the point you actually cause some RAM or flash to be used to actually create one.

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

clawson wrote:
. int n; . It "defines" something called 'n' I memory that is type "Int". It really creates one. To differentiate this if you use : . extern Int n; . You are only declaring a thing called 'n' of type "Int". That says "just know that if you see me mention 'n' then treat it as int but don't actually create one as I'll be defining this in another file. . I remember the difference between declare and defINe as there is something IN a defINe.

 

I'll take that as I did it right the way I did it with EXTERN then wink

 

Thanks!

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user