Optimized away my counter.

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

Atmel Studio, started new C project. Target ATmega328 P Xplained Mini.  My counter "cnt" was optimized away.

Solved by making cnt a volatile. 

 

 

AS6.2 Debug with mEDBG

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

Here is the full code.

 

/*
 * timer1b.c
 *
 * Created: 9/3/2015 14:45:17
 *  Author: john
 */ 


#include <avr/io.h>


#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
volatile uint8_t state;
void prstr0(char* buf);
int main(void)
{
	state = 0;
	uint16_t cnt = 0;
	cli(); //disable interrupts
	
	//setup timer1
	TCCR1A = 0;  //see datasheet normal operation
	TCCR1C = 0;  
	TIMSK1 = 1;  //overflow interrupt enable
	DDRB = (1 << DDB5); //Configure a status LED

	sei();  //enable interrupts

	PORTB &= 0b11011111; //off LED
	state = 1;
	while(1)
	{
		if (cnt == 0)
		{
			PORTB ^= 0b00100000; //toggle LED
		}
		switch(state)
		{
			case 1:
				TCNT1 = 0X0000;    
				TCCR1B = 3;   //turn on timer with clock = F_CPU
				state = 3;
				break;
			
			case 2:
				cnt++;
				state = 1;
				break;
			case 3:

			default:
				break;
		}
			

	
	}
}


ISR (TIMER1_OVF_vect)
{
	TCCR1B = 0;  // stop the timer
    state = 2;
}

 

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

Sorry but why WOULDN'T you want the optimizing compiler to optimize away the variable?

 

BTW it's not gone completely. All the debugger means by "optimized away" is "this is being held in a couple of machine registers not a watchable SRAM location". If you study the code you will find "cnt" in something like R25:R24 and you can watch those in the "Processor" view in the debugger.

 

Except for ease of debugging (watch windows) it would be a BIG mistake to make it "volatile" because this then forces the compiler to hold it in SRAM locations and waste effort going to that RAm location and updating it every time the cariable is accessed/written. Without volatile and with optimiztion it will only be held in the two CPu registers which is exactly what you'd want.

 

The only variable in your code that MUST be volatile is "state".

Last Edited: Thu. Sep 3, 2015 - 12:09 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"Except for ease of debugging"

 

Of course I would want my variable optimized, but I would like to find it easily when debugging. 

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

Oh right then perhaps have a read of my tutorial here:

 

https://www.avrfreaks.net/forum/t...

 

"volatile" *is* the solution for short-term watching of variables in a debugger while developing optimized code but one should remember to remove all the unnecessary uses of "volatile" before you go to press. You might achieve this with:

#ifndef NDEBUG
    volatile
#endif
    uint16_t cnt;

then it wil be volatile for the "Debug" build but not volatile for the "Release" build.

 

(this works on the basis that "Release" defines the symbol NDEBUG - as it happens in recent builds of Studio6 Atmel followed my advice and now define the symbol DEBUG for the "Debug" build - but, to be sure, base this on NDEBUG not DEBUG).

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

clawson wrote:
Except for ease of debugging (watch windows) it would be a BIG mistake to make it "volatile" because this then forces the compiler to hold it in SRAM locations and waste effort going to that RAm location and updating it every time the cariable is accessed/written.
Strictly speaking, a volatile int could be held in R25:R24 .  volatile is not fussy about where a variable is held.  The point of volatile is that a variable is held in only one place.

Similarly, there is, in principle, no reason that the debugger could not find it there.

That of course requires the compiler to generate the necessary data and for the debugger to use it.

 

All that said, for most, if not all, tool sets, debuggers will not find variables in registers and volatile will cause a variable to be stored in main memory.

Iluvatar is the better part of Valar.

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

Clawson:  thanks for the pointer to your tutorial.  Very useful.

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

All that said, for most, if not all, tool sets, debuggers will not find variables in registers ...

All that said:  If the debugging involves repeated/continuous monitoring of a set of internal variables, then make the set 'volatile' until that phase has been completed.

 

But if a true debugging session, it is kind of a one-time "what is going on here".  So peek at the generated code and determine which register(s) hold the value at that particular time, and then look at that.

 

A two-edged sword.  If doing a time-critical operation, say bit-banged peripheral "as fast as possible" or repeated per-pixel or similar operations, then peppering the critical variables with 'volatile' will greatly affect the timing.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.