Volatile not working as anticipated

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

Hi,

Let me first say that I am not well versed in C or in the compiler, but I thought I was making good progress until I hit this problem today. I was trying to use a timer0 overflow with a global count variable. Seemed pretty straight forward, but the volatile command just didn't work. Everytime the ISR was entered, the variable was reset to 0. I ended up piecing it together with two register variables, but I really want to know what I was doing wrong. It is run on a ATMega324A

//Counter variable
register unsigned char pwm_countlo asm("r9"); 
register unsigned char pwm_counthi asm("r10"); 
//volatile uint16_t pwm_count=0; <- this is what I was trying to use



main(){
while loop}


ISR(TIMER0_OVF_vect)
{
   
   //This will be used to turn the valve on and off
   //Increment our variable
   uint16_t temp_pwm;
   
   temp_pwm = pwm_counthi;
   temp_pwm = temp_pwm<<8;
   temp_pwm += pwm_countlo;
   
   temp_pwm = temp_pwm + 1;
   
   //PORTD = 0x0;
   
   if((temp_pwm <= Valve_on_time))//&&(pwm_count > 0))
   {
		PORTD |= 0b00000100; //Turn on Valve. 
   }
   
   if(temp_pwm > Valve_on_time)
   {
	  PORTD &= 0b11111011;
   }
   
   if (temp_pwm == Period){	       
	  temp_pwm=0;
   }
   pwm_counthi = (unsigned char)(temp_pwm>>8);
   pwm_countlo = (unsigned char)(temp_pwm);
		
   
}

There has go tot be a better way! Thanks

tim

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

If the variable is only used in the ISR, then there is no need for it to be volatile. Please show us the code that didn't work, showing us the code that does work gets us nowhere.

And if this is just straight PWM, why aren't you using the timer in PWM mode?

Regards,
Steve A.

The Board helps those that help themselves.

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

Thanks for the reply Steve. I was initially zeroing the variable in the main() but later changed it to the declaration. Also, the period of this PWM is ~1second, which I thought was way too slow for the built in PWM. I will go back and check that. Is it a problem if I declare the variable volatile and don't use it as such? Also, if it is not volatile will it maintain its value upon each call to the ISR? The code that did not work was:

#define Valve_on_time	200				/* the number of timer0 cycles the valve is on for
										   This is based on the XTAL frequency and the timer 
										   prescaler.  In this case 200/1221 = .1638 Seconds */
#define Period			1046			/* 1046/1221 = .857 Seconds */


//Counter variable
volatile uint16_t pwm_count;

ISR(TIMER0_OVF_vect)
{
   //Increment our variable
   pwm_count++
   
   if((pwm_count <= Valve_on_time))
   {
		PORTD |= 0b00000100; //Turn on Valve. Reverse polarity because of transistor driver
   }
   
   if(pwm_count > Valve_on_time)
   {
	  PORTD &= 0b11111011;
   }
   
   if (pwm_count == Period){	       
	  pwm_count=0;
   }	
   
}


int main(void)
{
	
	// Prescaler = FCPU/64
   TCCR0B|=(1<<CS01)|(1<<CS00);

   //Enable Overflow Interrupt Enable
   TIMSK0 |=(1<<TOIE0);

   //Initialize Counter
   TCNT0=0;

   //Initialize our varriable
   pwm_count=0;
    
	
		//hard coded to Wiring of Sherpa 2 Board
	//Set directions
	DDRC = 0xFF; // All of port C out
	DDRD = 0b00001110; // TX and Valve line outputs
	PORTC = 0;
	PORTD = 0b00000000;

	sei();
	
    for (;;) {
		...loop stuff...
    }
	}
	

Your help is greatly appreciated.

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

Quote:

//Initialize our varriable
pwm_count=0;

This code is superfluous anyway - it's a global so it's guaranteed to hold 0 at the start anyway.

If it really is only used in the ISR() you might want to consider making it a static within that function to limit it's scope. Like other .bss variables it will also be guaranteed to initialise to 0 if "static" is used.

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

The above code seems like it should work- apart from the fact that pwm_count++ has no ; at the end of the line.
Rather than use overflow, you can use the ctc mode and choose a more useful time period, say, 10ms.

And rather than test for <= then test for >, you would do the first test then use 'else' rather than test for >.
eg:

If (pwm_count <= VALVE_ON_TIME)
{
.....}
else
{
.....}

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

Thanks. I had an else statement, but was pulling my hair out when this wasn't working and tried changing everything. Also, the lack of the ";" was fixed at compile time. The timeframe is based on a mathematical model, so I don't really care if it is nice round seconds.

So, would a static variable hold its value between calls to the ISR? Is there anything wrong with the way I ended up solving the problem?

Thanks again.

tim

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

Quote:
Is it a problem if I declare the variable volatile and don't use it as such?

Apart from incapacitating the optimizer for this specific variable, no problem.
Quote:
Also, if it is not volatile will it maintain its value upon each call to the ISR?

Yes. The volatile keyword is there for telling the compiler that "another independent path of execution" might touch the variable. If you use the variable only in the ISR there is no "other independent path of execution" that is touching it.

But then, as Cliff said, it might as well be a static variable inside the ISR.

Here's my take on function-static variables:

We need to deine two terms:

Scope - which is the range of code where a variable is visible.
Extent - which is the span of execution time during which the variable exists.

A "file-global" variable has "file-global" scope (as long as no local variable with the same name hides it) and an extent of the duration of the execution of the program.

A local variable declared static within a function has function-wide scope, and extent of the duration of the execution of the program. I.e. there exists one such variable throughout the duration of the complete program execution, regardless of how many calls are made to the unction. All invocations of the function sees the same variable.

A local variable not declared static has function-wide scope and an extent that is the duration of the invocation of the function. Every invocation of the function sees its own variable.

Since you want a variable that should retain it's value between calls to the ISR, and it need only be visible inside the ISR you might as well opt for a local static variable.

Semi-OT: Since this atually combines data and behaviour into one construct, you're actually well on the way into object-oriented programming. When you ned several object instances, or inheritance you will need to switch to another programming language.. :wink:

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Fantastic information. I am just re-cutting my teeth with C, and I greatly appreciate all of the feedback.

tim

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

Just to demonstrate static:

int use_static(void) {
 static int n = 5;
 return n++;
}

int not_static(void) {
  int n = 5;
  return n++;
}

int main(void) {
  int i;
  for (i=0; i<10; i++) {
    printf("%2d %2d\n", use_static(), not_static());
  }
}

This produces:

 5  5
 6  5
 7  5
 8  5
 9  5
10  5
11  5
12  5
13  5
14  5

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

Quote:
int use_static(void) {
static int n = 5;
return n++;
}
...so "return" has higher precedence than "++"? I never knew that. So much to learn...

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

Quote:
...so "return" has higher precedence than "++"?
I don't understand what you mean. 'return' has no precedence in evaluation order.
The '++' is a post increment (in this instance), so the statement takes the value of 'n' then increments it.

--greg
Still learning, don't shout at me, educate me.
Starting the fire is easy; the hardest part is learning how to keep the flame!

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

Quote:
...so "return" has higher precedence than "++"?
Post-increment (or decrement) always happens after the statement is evaluated (or at least after the variable being incremented is used in the statement), so this has nothing to do with precedence. Conversely, pre-increment/decrement happens before evaluation.

Regards,
Steve A.

The Board helps those that help themselves.

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

so return n++ means

return n
n = n + 1

..subject to the mental mindjump of the increment happening after the function has returned?

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

Think of it as a temporary variable existing for the return value...

retVal = n;
n = n + 1;
return retVal;

While there exists no such named variable, a storage location for the return value exists.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

OK, now this is driving me nuts. If I use the code below, the PORTD.2 goes high and never goes low again. I can't see how this is any different than your example, but the exact same code works with a reserved register. Am I being totally obtuse about something? Thanks again.

tim

ISR(TIMER0_OVF_vect)
{
   //This will be used to turn the valve on and off
   //Increment our variable
   static uint16_t temp_pwm = 0;
   
   temp_pwm++;
   if((temp_pwm <= Valve_on_time))//&&(pwm_count > 0))
   {
		PORTD |= 0b00000100; //Turn on Valve. Reverse polarity because of transistor driver
   }
   
   if(temp_pwm > Valve_on_time)
   {
	  PORTD &= 0b11111011;
   }
   
   if (temp_pwm == Period){	       
	  temp_pwm=0;
   }
   
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Signed/unsigned problem?

Your code is not showing the definition and assignment of Valve_on_time, and I'm too lazy to scroll up to see if it's there. Same for pwm_count. Post mimimal but complete, buildable code examples.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Quote:

assignment of Valve_on_time

It's a macro - I know you didn't realise this because for some reason he didn't capitalise the name but it is a macro fixed at 200.

Oh and Period is 1046. Again a strangely named macro pretending to be a variable.

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

MartinM57 wrote:
so return n++ means

return n
n = n + 1

..subject to the mental mindjump of the increment happening after the function has returned?


I sort of see how you were thinking about it. This is what actually occurs.

1. The value of n is loaded into a register pair.

2. n is incremented.

3. the function returns. Unless of course optimization inlines this, then there is no return.

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

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

Quote:

This is what actually occurs.

Show that - I simply don't believe it. I get:

int not_static(void) {
  int n = 5;
  return n++;
}
  c2:	85 e0       	ldi	r24, 0x05	; 5
  c4:	90 e0       	ldi	r25, 0x00	; 0
  c6:	08 95       	ret

(or were you talking about the static variant?)

EDIT2: actually the static case is really mad!

int use_static(void) {
 static int n = 5;
 return n++;
  a6:	20 91 09 01 	lds	r18, 0x0109
  aa:	30 91 0a 01 	lds	r19, 0x010A
  ae:	2f 5f       	subi	r18, 0xFF	; 255
  b0:	3f 4f       	sbci	r19, 0xFF	; 255
  b2:	30 93 0a 01 	sts	0x010A, r19
  b6:	20 93 09 01 	sts	0x0109, r18
  ba:	21 50       	subi	r18, 0x01	; 1
  bc:	30 40       	sbci	r19, 0x00	; 0
}
  be:	c9 01       	movw	r24, r18
  c0:	08 95       	ret

Last Edited: Thu. Jun 30, 2011 - 07:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, for 16-bit ints the signed/unsigned problems should be occurring for values greater than 32K-1, and those triggers and limits are well below that so it's something else. I can't spot it - so it's either intricate or too bloody obvious..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

OK, so I have simplified it as much as I think I can (and corrected some lowercase). It builds and programs and the same thing is happening. While my immediate program is working using the register solution above, I am going to have to pass some variables between main and ISR soon. Other than this, I am liking my first AVR experience very much. This is maddening PORTD.2 still never goes low.

#include 
#include 
#include 

#define F_CPU 20000000              /**< clock frequency in Hz, used to calculate delay timer */
#define VALVE_ON_TIME	200				/* the number of timer0 cycles the valve is on for
										   This is based on the XTAL frequency and the timer 
										   prescaler.  In this case 200/1221 = .1638 Seconds */
#define PERIOD			1046			/* 1046/1221 = .857 Seconds */


int main(void)
{
	// Prescaler = FCPU/64
   TCCR0B|=(1<<CS01)|(1<<CS00);
   //Enable Overflow Interrupt Enable
   TIMSK0 |=(1<<TOIE0);
   //Initialize Counter
   TCNT0=0;
   
	sei();

    while(1)
    {
        //TODO:: Please write your application code 
		
    }
}

ISR(TIMER0_OVF_vect)
{
   static int temp_pwm = 0;
   
   temp_pwm++;
   
   if((temp_pwm <= VALVE_ON_TIME))
   {
		PORTD |= 0b00000100;
   }
   
   if(temp_pwm > VALVE_ON_TIME)
   {
	  PORTD &= 0b11111011;
   }
   
   if (temp_pwm == PERIOD){	       
	  temp_pwm=0;
   }
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ahem... I fail to spot you setting DDRD in that code.. :wink:

EDIT: If you take the code in the body of the ISR, make a new project, pland the ISR code into an ordinary function and write a main acts as a test harness that calls the function repeatedly you can confirm that it works correctly in the AVR Simulator in AVR Studio. Should be a five-minute manouvre..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Thu. Jun 30, 2011 - 08:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Of course not.
1 and 0 is 1
or is it? I'm tired :(
No, it's 0.
Johans right.

--greg
Still learning, don't shout at me, educate me.
Starting the fire is easy; the hardest part is learning how to keep the flame!

Last Edited: Thu. Jun 30, 2011 - 08:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

gregsmithcts wrote:
Of course not.
1 and 0 is 1
or is it? I'm tired :(

You need sleep.. Or coffee..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Which version of Studio are you using?

When I'm tired, reading other peoples code is often confusing (perhaps I shouldn't do it) unless it's written in a style I'm accustomed to.
As you are only flipping a bit up and down, why not represent it like...

PORTD |= (1<<2); // on

and

PORTD &= ~(1<<2); //off

That's what I'm used to seeing ;) There is no need to decode a bit mask in your head, and little chance that it can be interpreted any other way than what it say's.

--greg
Still learning, don't shout at me, educate me.
Starting the fire is easy; the hardest part is learning how to keep the flame!

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

clawson wrote:
Quote:

This is what actually occurs.

Show that - I simply don't believe it.

This is the code:

int use_static(void) { 
 static int n = 5; 
 return n++; 
} 

int not_static(void) { 
  int n = 5; 
  return n++; 
} 

int main(void) {

	volatile int return_val; 
 
	return_val = use_static();

	return_val = not_static();

	while(1);

	return 1;

} 

Relavent .lss output. Optimization -O0:

000000da :

int use_static(void) { 
  da:	df 93       	push	r29
  dc:	cf 93       	push	r28
  de:	cd b7       	in	r28, 0x3d	; 61
  e0:	de b7       	in	r29, 0x3e	; 62
 static int n = 5; 
 return n++; 
  e2:	80 91 00 01 	lds	r24, 0x0100
  e6:	90 91 01 01 	lds	r25, 0x0101
  ea:	9c 01       	movw	r18, r24
  ec:	01 96       	adiw	r24, 0x01	; 1
  ee:	90 93 01 01 	sts	0x0101, r25
  f2:	80 93 00 01 	sts	0x0100, r24
  f6:	c9 01       	movw	r24, r18
} 
  f8:	cf 91       	pop	r28
  fa:	df 91       	pop	r29
  fc:	08 95       	ret

000000fe :

int not_static(void) { 
  fe:	df 93       	push	r29
 100:	cf 93       	push	r28
 102:	00 d0       	rcall	.+0      	; 0x104 
 104:	cd b7       	in	r28, 0x3d	; 61
 106:	de b7       	in	r29, 0x3e	; 62
  int n = 5; 
 108:	85 e0       	ldi	r24, 0x05	; 5
 10a:	90 e0       	ldi	r25, 0x00	; 0
 10c:	9a 83       	std	Y+2, r25	; 0x02
 10e:	89 83       	std	Y+1, r24	; 0x01
  return n++; 
 110:	29 81       	ldd	r18, Y+1	; 0x01
 112:	3a 81       	ldd	r19, Y+2	; 0x02
 114:	89 81       	ldd	r24, Y+1	; 0x01
 116:	9a 81       	ldd	r25, Y+2	; 0x02
 118:	01 96       	adiw	r24, 0x01	; 1
 11a:	9a 83       	std	Y+2, r25	; 0x02
 11c:	89 83       	std	Y+1, r24	; 0x01
 11e:	c9 01       	movw	r24, r18
} 
 120:	0f 90       	pop	r0
 122:	0f 90       	pop	r0
 124:	cf 91       	pop	r28
 126:	df 91       	pop	r29
 128:	08 95       	ret

0000012a 
: int main(void) { 12a: df 93 push r29 12c: cf 93 push r28 12e: 00 d0 rcall .+0 ; 0x130 130: cd b7 in r28, 0x3d ; 61 132: de b7 in r29, 0x3e ; 62 volatile int return_val; return_val = use_static(); 134: 0e 94 6d 00 call 0xda ; 0xda 138: 9a 83 std Y+2, r25 ; 0x02 13a: 89 83 std Y+1, r24 ; 0x01 return_val = not_static(); 13c: 0e 94 7f 00 call 0xfe ; 0xfe 140: 9a 83 std Y+2, r25 ; 0x02 142: 89 83 std Y+1, r24 ; 0x01 144: ff cf rjmp .-2 ; 0x144 00000146 <_exit>: 146: f8 94 cli 00000148 <__stop_program>: 148: ff cf rjmp .-2 ; 0x148 <__stop_program>

Relavent .lss output. Optimization -Os:

000000da :

int use_static(void) { 
 static int n = 5; 
 return n++; 
  da:	20 91 00 01 	lds	r18, 0x0100
  de:	30 91 01 01 	lds	r19, 0x0101
  e2:	2f 5f       	subi	r18, 0xFF	; 255
  e4:	3f 4f       	sbci	r19, 0xFF	; 255
  e6:	30 93 01 01 	sts	0x0101, r19
  ea:	20 93 00 01 	sts	0x0100, r18
  ee:	21 50       	subi	r18, 0x01	; 1
  f0:	30 40       	sbci	r19, 0x00	; 0
} 
  f2:	c9 01       	movw	r24, r18
  f4:	08 95       	ret

000000f6 :

int not_static(void) { 
  int n = 5; 
  return n++; 
} 
  f6:	85 e0       	ldi	r24, 0x05	; 5
  f8:	90 e0       	ldi	r25, 0x00	; 0
  fa:	08 95       	ret

000000fc 
: int main(void) { fc: df 93 push r29 fe: cf 93 push r28 100: 00 d0 rcall .+0 ; 0x102 102: cd b7 in r28, 0x3d ; 61 104: de b7 in r29, 0x3e ; 62 int use_static(void) { static int n = 5; return n++; 106: 80 91 00 01 lds r24, 0x0100 10a: 90 91 01 01 lds r25, 0x0101 10e: 01 96 adiw r24, 0x01 ; 1 110: 90 93 01 01 sts 0x0101, r25 114: 80 93 00 01 sts 0x0100, r24 118: 01 97 sbiw r24, 0x01 ; 1 int main(void) { volatile int return_val; return_val = use_static(); 11a: 9a 83 std Y+2, r25 ; 0x02 11c: 89 83 std Y+1, r24 ; 0x01 return_val = not_static(); 11e: 85 e0 ldi r24, 0x05 ; 5 120: 90 e0 ldi r25, 0x00 ; 0 122: 9a 83 std Y+2, r25 ; 0x02 124: 89 83 std Y+1, r24 ; 0x01 126: ff cf rjmp .-2 ; 0x126 00000128 <_exit>: 128: f8 94 cli 0000012a <__stop_program>: 12a: ff cf rjmp .-2 ; 0x12a <__stop_program>

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

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

Larry which version of GCC are you using.

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

gcc version 4.3.3 (WinAVR 20100110)

Which incidentally isn't in my path. Had to go to the directory it is in. I haven't had a need to use command line tools yet. I would like to though. Any ideas on a tutorial for installing a toolchain or is just setting the path to WinAVR good enough?

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

Last Edited: Fri. Jul 1, 2011 - 08:06 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But that's what I used and it generated different code?!? OK, which model of AVR were you building for? I used 168.

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

Cliff, originally a 324a. I just tried 168, 324a, 32u4, and 328p. I get the same code results.

Are you sure you don't have another version of gcc in your path?

Also I was editing my post above when you replied.

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
E:\avr>make

-------- begin --------
avr-gcc (WinAVR 20100110) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Compiling C: test.c
avr-gcc -c -mmcu=atmega168 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshor
t-enums -Wall -Wstrict-prototypes --save-temps -fverbose-asm -Wa,-adhlns=./test.lst  -std=gnu99 -MMD -MP -MF .dep/test.o
.d test.c -o test.o

then:

E:\avr>type test.lss



00000094 <.do_clear_bss_start>:
  94:   a2 31           cpi     r26, 0x12       ; 18
  96:   b1 07           cpc     r27, r17
  98:   e1 f7           brne    .-8             ; 0x92 <.do_clear_bss_loop>
  9a:   0e 94 64 00     call    0xc8    ; 0xc8 
9e: 0c 94 6c 03 jmp 0x6d8 ; 0x6d8 <_exit> 000000a2 <__bad_interrupt>: a2: 0c 94 00 00 jmp 0 ; 0x0 <__vectors> 000000a6 : #include int use_static(void) { static int n = 5; return n++; a6: 20 91 09 01 lds r18, 0x0109 aa: 30 91 0a 01 lds r19, 0x010A ae: 2f 5f subi r18, 0xFF ; 255 b0: 3f 4f sbci r19, 0xFF ; 255 b2: 30 93 0a 01 sts 0x010A, r19 b6: 20 93 09 01 sts 0x0109, r18 ba: 21 50 subi r18, 0x01 ; 1 bc: 30 40 sbci r19, 0x00 ; 0 } be: c9 01 movw r24, r18 c0: 08 95 ret

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

Look at what it inlined in main. Try it with -O0 too.

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

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

Greg,

I am using Studio 5. Is this a mistake? I saw some posts that seemed to say that 4 was still the best, but they were of mixed ages.

Thanks for the idea of putting it as a normal function and testing it that way. When I do that, the static implementation works, but I still can not get a volatile solution to work. This is really making me feel like a fool.

I have winAVR installed as well and it seems like it has a different avr-gcc version. Should I link to that instead? Thank you for your tireless attention!

tim

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

moultim, personally I don't think AS5 is ready for prime time yet. I am going to wait until it gets better reviews and acceptance before using it.

Cliff, did you figure out why you have different code than I do?

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

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

Quote:

Cliff, did you figure out why you have different code than I do?

No. This is the exact source code I used:

#include 

int use_static(void) {
 static int n = 5;
 return n++;
}

int not_static(void) {
  int n = 5;
  return n++;
}

int main(void) {
  int i;
  for (i=0; i<10; i++) {
    printf("%2d %2d\n", use_static(), not_static());
  }
}

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

Quote:
I am using Studio 5. Is this a mistake?
IMO yes.
Try installing Studio4 and build with that (and the appropriate toolchain) and see if there is any (significant) difference.
Better still, dump that M$ rubbish completely and join the *ix revolution ;)

--greg
Still learning, don't shout at me, educate me.
Starting the fire is easy; the hardest part is learning how to keep the flame!

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

Using your code, mega168, and -Os gives:

Relavent .lss output.

000000a6 :
#include  

int use_static(void) { 
 static int n = 5; 
 return n++; 
  a6:	20 91 09 01 	lds	r18, 0x0109
  aa:	30 91 0a 01 	lds	r19, 0x010A
  ae:	2f 5f       	subi	r18, 0xFF	; 255
  b0:	3f 4f       	sbci	r19, 0xFF	; 255
  b2:	30 93 0a 01 	sts	0x010A, r19
  b6:	20 93 09 01 	sts	0x0109, r18
  ba:	21 50       	subi	r18, 0x01	; 1
  bc:	30 40       	sbci	r19, 0x00	; 0
} 
  be:	c9 01       	movw	r24, r18
  c0:	08 95       	ret

000000c2 :

int not_static(void) { 
  int n = 5; 
  return n++; 
} 
  c2:	85 e0       	ldi	r24, 0x05	; 5
  c4:	90 e0       	ldi	r25, 0x00	; 0
  c6:	08 95       	ret

000000c8 
: int main(void) { c8: ef 92 push r14 ca: ff 92 push r15 cc: 0f 93 push r16 ce: 1f 93 push r17 d0: cf 93 push r28 d2: df 93 push r29 d4: c0 e0 ldi r28, 0x00 ; 0 d6: d0 e0 ldi r29, 0x00 ; 0 int i; for (i=0; i<10; i++) { printf("%2d %2d\n", use_static(), not_static()); d8: 80 e0 ldi r24, 0x00 ; 0 da: e8 2e mov r14, r24 dc: 81 e0 ldi r24, 0x01 ; 1 de: f8 2e mov r15, r24 e0: 05 e0 ldi r16, 0x05 ; 5 e2: 10 e0 ldi r17, 0x00 ; 0 #include int use_static(void) { static int n = 5; return n++; e4: 80 91 09 01 lds r24, 0x0109 e8: 90 91 0a 01 lds r25, 0x010A ec: 01 96 adiw r24, 0x01 ; 1 ee: 90 93 0a 01 sts 0x010A, r25 f2: 80 93 09 01 sts 0x0109, r24 f6: 01 97 sbiw r24, 0x01 ; 1 } int main(void) { int i; for (i=0; i<10; i++) { printf("%2d %2d\n", use_static(), not_static()); f8: 00 d0 rcall .+0 ; 0xfa fa: 00 d0 rcall .+0 ; 0xfc fc: 00 d0 rcall .+0 ; 0xfe fe: ed b7 in r30, 0x3d ; 61 100: fe b7 in r31, 0x3e ; 62 102: 31 96 adiw r30, 0x01 ; 1 104: ad b7 in r26, 0x3d ; 61 106: be b7 in r27, 0x3e ; 62 108: 12 96 adiw r26, 0x02 ; 2 10a: fc 92 st X, r15 10c: ee 92 st -X, r14 10e: 11 97 sbiw r26, 0x01 ; 1 110: 93 83 std Z+3, r25 ; 0x03 112: 82 83 std Z+2, r24 ; 0x02 114: 15 83 std Z+5, r17 ; 0x05 116: 04 83 std Z+4, r16 ; 0x04 118: 0e 94 a3 00 call 0x146 ; 0x146 return n++; } int main(void) { int i; for (i=0; i<10; i++) { 11c: 21 96 adiw r28, 0x01 ; 1 11e: 8d b7 in r24, 0x3d ; 61 120: 9e b7 in r25, 0x3e ; 62 122: 06 96 adiw r24, 0x06 ; 6 124: 0f b6 in r0, 0x3f ; 63 126: f8 94 cli 128: 9e bf out 0x3e, r25 ; 62 12a: 0f be out 0x3f, r0 ; 63 12c: 8d bf out 0x3d, r24 ; 61 12e: ca 30 cpi r28, 0x0A ; 10 130: d1 05 cpc r29, r1 132: c1 f6 brne .-80 ; 0xe4 printf("%2d %2d\n", use_static(), not_static()); } } 134: 80 e0 ldi r24, 0x00 ; 0 136: 90 e0 ldi r25, 0x00 ; 0 138: df 91 pop r29 13a: cf 91 pop r28 13c: 1f 91 pop r17 13e: 0f 91 pop r16 140: ff 90 pop r15 142: ef 90 pop r14 144: 08 95 ret 00000146 : printf and other crud here 000006d8 <_exit>: 6d8: f8 94 cli 000006da <__stop_program>: 6da: ff cf rjmp .-2 ; 0x6da <__stop_program>

Both functions are inlined in main. The registers are set up for the printf.

The portion of code before "#include " is function not_static().

The portion of code following "#include " is function use_static().

Note the increment of n in the inlined function use_static. Then notice the subtract to use the correct number of n for the printf.

  e0:	05 e0       	ldi	r16, 0x05	; 5
  e2:	10 e0       	ldi	r17, 0x00	; 0
#include  

int use_static(void) { 
 static int n = 5; 
 return n++; 
  e4:   80 91 09 01    lds   r24, 0x0109 
  e8:   90 91 0a 01    lds   r25, 0x010A 
  ec:   01 96          adiw   r24, 0x01   ; 1 
  ee:   90 93 0a 01    sts   0x010A, r25 
  f2:   80 93 09 01    sts   0x0109, r24 
  f6:   01 97          sbiw   r24, 0x01   ; 1 
} 

It is strange that the actual function use_static() code does not contain the "adiw r24, 0x01 ; 1" in it.

Try using the code I posted, it gets rid of the printf crud.

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

Last Edited: Fri. Jul 1, 2011 - 08:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

gregsmithcts wrote:
Better still, dump that M$ rubbish completely and join the *ix revolution ;)

Hey, watch it buster! :lol:

I use both OS environments. :)

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

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

I think I got it, but I don't understand it. I installed AVRStudio 4 (on another computer, this one is 64 bit and I was having problems with it). I wrote some sample code and compiled it using all of the variants we have discussed (static, volatile and register). I can now use the volatile variable, but any time I use the line:

temp_pwm++;

It does not work. All solutions work now by replacing that line with:

temp_pwm = temp_pwm + 1;

This experience has jaded me enough to abandon ++ forever!

Greg,

I hear you. I used to exclusively run Linux in college and after until I had to buy CAD software (Solidworks and ProEngineer -- I am primarily a mechanical engineer). However, windows7 is a pretty superior product.

Thanks

tim

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

Quote:

It does not work. All solutions work now by replacing that line with:


Then you are doing something wrong or probably interpreting the result incorrectly.

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

Quote:
Then you are doing something wrong
I must agree with Cliff. Pre and Post increment and decrement are a mainstay of efficient 'C' coding. I've never once had cause to question it's outcome or reliability. There is something else going on that you/we have yet to uncover.

--greg
Still learning, don't shout at me, educate me.
Starting the fire is easy; the hardest part is learning how to keep the flame!

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

Agreed, but I am not sure it is me. Studio4 did not have the option for a 324a device, just a 324p so I went with that. Silly me changed two things at once. Now, I recompiled with the 324p option in studio5 and I am getting the same happy results. So, as best I can tell, it has something to do with the 324a definition file. Any idea where that is so I can diff it with the 324p?

Ps. If I would have seen your signature earlier, it would have saved me about 2 hours with the Jtag fuse setting!

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

Time (again) for you to post a complete (minimal) example of your failing code. Which, one would hope, now contains all the hints, tips, and tricks (best practice), that you've picked up on your journey to this point ;)

--greg
Still learning, don't shout at me, educate me.
Starting the fire is easy; the hardest part is learning how to keep the flame!

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

On my Win7 machine the files for AS5 are at the directory shown. they are .xml files.

C:\Program Files (x86)\Atmel\AVR Tools\Partdescriptionfiles>diff atmega324a.xml atmega324p.xml

For AS4 using WinAVR they use the same file as indicated in io.h. Found in the C:\WinAVR-20100110\avr\include\avr directory.

#elif defined (__AVR_ATmega324P__) || defined (__AVR_ATmega324A__)
#  include 

Use AVR Studio 4. AS5 has "issues".

Post your latest code as Greg has suggested.

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

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

larryvc wrote:
Use AVR Studio 4. AS5 has "issues".

Definitely. The Toolchain in AS5 has a known Bug when compiling for ATmega324a. See:
https://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=107811
especially this post
https://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=837468#837468

Programmers never die
they just GOSUB without RETURN

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

I will post a cleaned up example later tonight after I grab a few beers and reset my brain a bit. I would like to use studio4, but I can't get it running on my main w7(64) computer (which has my logic analyzer, Programmer, etc). Thanks again for all of your help.

tim

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

moultim wrote:
I would like to use studio4, but I can't get it running on my main w7(64) computer

Why can't you get it running?

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

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

Quote:
Why can't you get it running?

Quote:
w7(64)
:)
You are not alone.
M$ users have been having all sorts of issues. A few weeks googling should turn up various solutions that sometimes work ;)

--greg
Still learning, don't shout at me, educate me.
Starting the fire is easy; the hardest part is learning how to keep the flame!

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

Be nice Greg. :) AVR Studio 4 installs without any problems on 99.99% of the Win7 machines out there. The other .01% are trying to install it in Parallels on a Mac. :wink:

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

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

:)

--greg
Still learning, don't shout at me, educate me.
Starting the fire is easy; the hardest part is learning how to keep the flame!