How to avoid optimization changing specific code

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

I am experienced (10 years) with AVR but with ICCAVR and not GCC.

If you create a driver there you have to insert very short delays of just a few clock cycles, the only way to do it is by using for example NOP instructions. In ICCAVR there is a possibility to turn off optimization during parts of the code to avoid the optimizer affects time critical code regardless if the optimizer is on or off in the rest of the code.

Is there some similar possibility in GCC?

My favorites:
1. My oscilloscope, Yokogawa DLM2024.
2. My soldering iron, Weller WD2M, WMRP+WMRT.
3. JTAGICE3 debugger.

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

No. You have the same optimisation level for the whole C file. You cannot turn it on and off partway through a C file.

So put your 'no optimise' functions into a separate C file. In the Makefile create a target specific rule for your special C file. (I do not think this is possible with the Studio IDE on-the-fly 'internal' makefile)

You can still use nops or the __delay_cycles() with ANY optimisation.

Ideally you want to write code that works properly with ANY optimisation.

Remember that avr-gcc is pretty clever with -Os.
avr-gcc is exceptionally stupid with -O0.

ImageCraft is just moderately clever. But bear in mind that one day it will get better. So it is worth using 'volatile' properly in ANY code, because all compilers are likely to improve over the years.

David.

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

Just as side note:

It is (or "will be" related to avr-gcc) possible with gcc 4.5.

GCC 4.5 documentation wrote:
optimize
The optimize attribute is used to specify that a function is to be compiled with diferent optimization options than specifed on the commandline. Arguments can either be numbers or strings. Numbers are assumed to be an optimization level. Strings that begin with O are assumed to be an optimization option, while other options are assumed to be used with a -f prefx. You can also use the ‘#pragma GCC optimize’ pragma to set the optimization options that afect more than one function.
...

Stefan Ernst

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

I currently use avr-gcc 4.3.3 (WinAvr-20100110)

I always let others enjoy the new features of an avr-gcc release. As far as I can see they generally break more things than they fix.

So I would prefer a solution that works with all recent releases of avr-gcc. But yes, it looks as if optimisation will be alterable within a C file as a standard pragma.

David.

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

bengtr wrote:
I am experienced (10 years) with AVR but with ICCAVR and not GCC.

If you create a driver there you have to insert very short delays of just a few clock cycles, the only way to do it is by using for example NOP instructions. In ICCAVR there is a possibility to turn off optimization during parts of the code to avoid the optimizer affects time critical code regardless if the optimizer is on or off in the rest of the code.

Is there some similar possibility in GCC?

Although GCC has permission to destroy your algorithm, in practice is does not normally do so, and a quick check of the asm listing after compilation is all that is required. For example:

if (func == DISCOVERY) {
	UCSRB &= ~((1<<TXEN) | (1 << RXEN))
	delay(BITPERIOD * 4);			
	if ((NO_ADDR == g_device_addr) && 
		!((eeprom_read_dword(EE_SERIAL) ^ *(uint32_t*)&RXBuffer[3]) 
				& asm_UTIL_htonl((0xffffffff << RXBuffer[2])))) {
		PORTD = PORTD & ~TX_DATA;
		DDRD = DDRD | TX_DATA;	
		PORTD = PORTD | TX_EN485;
		delay(BITPERIOD * 4);
		PORTD = PORTD & ~TX_EN485;
	} else {
		delay(BITPERIOD * 4);
	}

	delay(BITPERIOD*4);
	while(0==(PIND & RX_DATA)){
		delay(10);
	}	
	UCSRB |= (1<<TXEN) | (1 << RXEN);
}

In there is a sequence of volatile assignements to PORTD and DDRD. If I wanted strict conformance, I would have to put them all into one asm block, or use the comma operator. But in practice those assignment statements are executed in order, and if I wanted to put

asm volatile (" NOP"); 

in there I could do that too.
Since I want delays longer than a single NOP, I am using the AVRLIB timer macro instead.

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

melbourne wrote:
In there is a sequence of volatile assignements to PORTD and DDRD.

Sorry, that was badly written. There is a sequence of volatile assignments with a delay statement. The delay may be re-ordered or moved out of sequence by GCC, but in practice it is not.

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

Hi bengtr!
I have a question refers to ICCAVR. How to turn off optimization during parts of the code?

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

bengtr wrote:
If you create a driver there you have to insert very short delays of just a few clock cycles, the only way to do it is by using for example NOP instructions. In ICCAVR there is a possibility to turn off optimization during parts of the code to avoid the optimizer affects time critical code regardless if the optimizer is on or off in the rest of the code.
Others are commenting on optimization.
I'd look for other ways to get what you want.
Maybe something like this:
fred=greg;
asm (" NOP" : "=r"(fred) : "0"(fred));
hank=fred;

The NOP has to come after the first assignment.
Otherwise the NOP might get an early value of fred.
The NOP has to come before the second assignment.
Otherwise hank might get an early value of fred.

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles