how to not initialize variables

I will try but I doubt that this is the case. Notice that the code works if I compile it from the commandline.

Same thing here. Compilation with the hacked text editor returns “1” all the time. Using the other method works.

I used code::blocks with the following settings:

a) for building the core.a file:

		<Compiler>
			<Add option="-Os" />
			<Add option="-Wmain" />
			<Add option="-Wall" />
			<Add option="-g" />
			<Add option="-mmcu=atmega168p" />
			<Add option="-fno-exceptions -ffunction-sections -fdata-sections" />
			<Add option="-DF_CPU=16000000UL" />
		</Compiler>
		<Linker>
			<Add option="-Os" />
			<Add option="-mmcu=atmega168p" />
			<Add option="-Wl,-Map=$(TARGET_OUTPUT_FILE).map,--cref" />
		</Linker>
		<ExtraCommands>
			<Add after="$(build_dir)/make_core.sh $(obj_dir)" />
			<Mode after="always" />
		</ExtraCommands>

b) for building the hex-file of main.cpp:

		<Compiler>
			<Add option="-Os" />
			<Add option="-Wmain" />
			<Add option="-Wall" />
			<Add option="-g" />
			<Add option="-mmcu=atmega168p" />
			<Add option="-fno-exceptions -ffunction-sections -fdata-sections" />
			<Add option="-DF_CPU=16000000UL" />
			<Add directory="../arduino_core_libs" />
			<Add directory="../arduino_core_libs/Wire" />
		</Compiler>
		<Linker>
			<Add option="-Os" />
			<Add option="-mmcu=atmega168p" />
			<Add option="-Wl,-Map=$(TARGET_OUTPUT_FILE).map,--cref" />
			<Add option="-Wl,--gc-sections" />
			<Add library="../arduino_core_libs/core.a" />
			<Add library="/usr/local/avr/avr/lib/libm.a" />
			<Add directory="../arduino_core_libs" />
			<Add directory="../arduino_core_libs/Wire" />
		</Linker>

I have put the compiler options to verbose

avr-gcc -c -g -Os -w -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=21 -I/home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino /home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino/WInterrupts.c -o/tmp/build2560460169561155056.tmp/WInterrupts.c.o 
avr-gcc -c -g -Os -w -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=21 -I/home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino /home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino/pins_arduino.c -o/tmp/build2560460169561155056.tmp/pins_arduino.c.o 
avr-gcc -c -g -Os -w -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=21 -I/home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino /home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino/wiring_pulse.c -o/tmp/build2560460169561155056.tmp/wiring_pulse.c.o 
avr-gcc -c -g -Os -w -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=21 -I/home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino /home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino/wiring_shift.c -o/tmp/build2560460169561155056.tmp/wiring_shift.c.o 
avr-gcc -c -g -Os -w -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=21 -I/home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino /home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino/wiring_digital.c -o/tmp/build2560460169561155056.tmp/wiring_digital.c.o 
avr-gcc -c -g -Os -w -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=21 -I/home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino /home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino/wiring_analog.c -o/tmp/build2560460169561155056.tmp/wiring_analog.c.o 
avr-gcc -c -g -Os -w -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=21 -I/home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino /home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino/wiring.c -o/tmp/build2560460169561155056.tmp/wiring.c.o 
avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=21 -I/home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino /home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino/Print.cpp -o/tmp/build2560460169561155056.tmp/Print.cpp.o 
avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=21 -I/home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino /home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino/main.cpp -o/tmp/build2560460169561155056.tmp/main.cpp.o 
avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=21 -I/home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino /home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino/Tone.cpp -o/tmp/build2560460169561155056.tmp/Tone.cpp.o 
avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=21 -I/home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino /home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino/WMath.cpp -o/tmp/build2560460169561155056.tmp/WMath.cpp.o 
avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=21 -I/home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino /home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino/HardwareSerial.cpp -o/tmp/build2560460169561155056.tmp/HardwareSerial.cpp.o 
avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=21 -I/home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino /home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino/WString.cpp -o/tmp/build2560460169561155056.tmp/WString.cpp.o 
avr-ar rcs /tmp/build2560460169561155056.tmp/core.a /tmp/build2560460169561155056.tmp/WInterrupts.c.o 
avr-ar rcs /tmp/build2560460169561155056.tmp/core.a /tmp/build2560460169561155056.tmp/pins_arduino.c.o 
avr-ar rcs /tmp/build2560460169561155056.tmp/core.a /tmp/build2560460169561155056.tmp/wiring_pulse.c.o 
avr-ar rcs /tmp/build2560460169561155056.tmp/core.a /tmp/build2560460169561155056.tmp/wiring_shift.c.o 
avr-ar rcs /tmp/build2560460169561155056.tmp/core.a /tmp/build2560460169561155056.tmp/wiring_digital.c.o 
avr-ar rcs /tmp/build2560460169561155056.tmp/core.a /tmp/build2560460169561155056.tmp/wiring_analog.c.o 
avr-ar rcs /tmp/build2560460169561155056.tmp/core.a /tmp/build2560460169561155056.tmp/wiring.c.o 
avr-ar rcs /tmp/build2560460169561155056.tmp/core.a /tmp/build2560460169561155056.tmp/Print.cpp.o 
avr-ar rcs /tmp/build2560460169561155056.tmp/core.a /tmp/build2560460169561155056.tmp/main.cpp.o 
avr-ar rcs /tmp/build2560460169561155056.tmp/core.a /tmp/build2560460169561155056.tmp/Tone.cpp.o 
avr-ar rcs /tmp/build2560460169561155056.tmp/core.a /tmp/build2560460169561155056.tmp/WMath.cpp.o 
avr-ar rcs /tmp/build2560460169561155056.tmp/core.a /tmp/build2560460169561155056.tmp/HardwareSerial.cpp.o 
avr-ar rcs /tmp/build2560460169561155056.tmp/core.a /tmp/build2560460169561155056.tmp/WString.cpp.o 
avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=21 -I/home/udo/Desktop/electronics/arduino-0021/hardware/arduino/cores/arduino /tmp/build2560460169561155056.tmp/sketch_mar31a.cpp -o/tmp/build2560460169561155056.tmp/sketch_mar31a.cpp.o 
avr-gcc -Os -Wl,--gc-sections -mmcu=atmega328p -o /tmp/build2560460169561155056.tmp/sketch_mar31a.cpp.elf /tmp/build2560460169561155056.tmp/sketch_mar31a.cpp.o /tmp/build2560460169561155056.tmp/core.a -L/tmp/build2560460169561155056.tmp -lm 
avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 /tmp/build2560460169561155056.tmp/sketch_mar31a.cpp.elf /tmp/build2560460169561155056.tmp/sketch_mar31a.cpp.eep 
avr-objcopy -O ihex -R .eeprom /tmp/build2560460169561155056.tmp/sketch_mar31a.cpp.elf /tmp/build2560460169561155056.tmp/sketch_mar31a.cpp.hex 
Binary sketch size: 2436 bytes (of a 30720 byte maximum)

I still do not get it though. Any hints for me?

Is it possible you have more than one "avr-gcc" on the computer? Is the Arduino IDE using one compiler version and the makefile using a different compiler version?

Ah, good question. Never thought of that.
Double checked:
find, locate, whereis all agree that I have only one version.
→ this is not the reason for the strange behaviour.

[quote author=Udo Klein link=topic=56809.msg410946#msg410946 date=1301602257] Any hints for me? [/quote]

Have you built the project both ways and dumped the final elf with avr-objdump to get a feel for what the substance of the difference is? There might be a clue there.

Have you in fact brought your avr-gcc installation up to date?

[quote author=Udo Klein link=topic=56809.msg410946#msg410946 date=1301602257] I still do not get it though. Any hints for me? [/quote]

What is your ultimate goal here? To resolve this issue with the compiler? Or to count resets? Personally I had never heard of :

uint8_t reset_counter __attribute__ ((section (".noinit")));

... until I saw this thread.

You are basically wanting to take some RAM with undefined data in it, and add 1 to it on reset, yes? And if there is a way of detecting a power-on reset, as opposed to a "reset button" reset, you might conceivably initialize it on power-on.

Well, here is how to get unitialized RAM:

int * counter;

void setup() { 

  Serial.begin (115200);
  
  // get some uninitialized RAM  
  counter = (int *) malloc (sizeof (int));  
  
  // add 1 to it
  *counter++;
  
  Serial.println (*counter);
  
}

void loop() { }

Now I'm assuming here that identical code running after a reset will allocate the same memory address each time (why would it not?). And since malloc doesn't clear memory to zero it won't be initialized. So far so good. But these are my results (hitting reset):

14649
14649
14649
14649
14649
14649

It's not zero, but it's not incrementing either. Why? My guess is that the part of the heap that is allocated in this case happens to have been used previously (as part of reset processing) and happens to have 14648 left over in it (hex 0x3938).

But if this doesn't work, how can you really say that using section (".noinit") will work any better? An uninitialized variable has undefined data in it, right? This isn't guaranteed to persist over resets.

Let me put it like this, as I read the docs on .noinit, they specify the the variable is not initialized to zero. But they don't specify that the variable is untouched (eg. during initializing of other things).

The very fact that the .noinit works for some people and not others would seem to give pause to any idea of using it seriously in any sort of production environment.

Oops, I fell for the old operator-precedence trap. I can in fact get it to work:

int * counter;
void setup() { 
  Serial.begin (115200);
  
  // get some uninitialized RAM  
  counter = (int *) malloc (sizeof (int));  
  
  // add 1 to it
  (*counter)++;
  
  Serial.println (*counter);
}

void loop() { }

Output:

14651
14652
14653
14654
14655
14656

So that looks OK - you can add 1 after a reset. Still a bit dodgy, but it seems to work.

This thread is basically about satisfying my curiosity. As I already mentioned this is not for "production use". I am aware of EEProm and how to access it. I just wanted to understand what is going on. This was just an example for fooling around with the init section.

Your code will always return "1" on my Arduino. So obviously there is something that will initialize my memory. By now I suspect the bootloader to be part of the issue. However the compiler and/or linker play some role as well because I found code that will compile in the IDE but not from the commandline.

What I figure is that different Arduinos behave differently upon reset depending on unknown parameters like compiler, linker, bootloader and/or possibly other stuff.

It follows that for production use of "reset counters" eeprom or flash or external storage is the way to go. However it still leaves the question open where this different behaviour originates.

@Udo Klein:
Thank you! This technique has turned out to be rather handy for troubleshooting a reset-bug.

Yeah, fooling around leads sometimes to deeper insights. Playing with this I figured out that there are much more resets then I would have expected ;)

Which technique did you use? Memory based or EEProm based?

Playing with this I figured out that there are much more resets then I would have expected

That's not good!

Which technique did you use? Memory based or EEProm based?

The one from your original post (memory based; noinit section).

Seems to work for everyone but me :( So I stick to EEProm.

I cannot find any significant differences between your build and mine (Arduino 0022). If you post a sample Sketch and an ELF file I'm willing to compare.

Well, I am using Arduino 21. But my impression is that the cause is the bootloader. If I use an ISP and get rid of the bootloader it works as it should. If I can spend some time I will disassemble and analyze where exactly it wipes the memory.

my impression is that the cause is the bootloader.

Which version of which bootloader?

Were you equating "building from the command line" with "not using the bootloader" ?

If I build from the commandline I usually use an ISP and overwrite the bootloader. Of course I might get different compiler settings as well. If I build from the IDE I usually do not use an ISP (although I could).

So if I use the IDE then the bootloader is in place otherwise not. If I use the command line the compiler might produce different code or maybe not. However since this stuff goes so early in the init section I think I have good reason to suspect the bootloader. Especially since I did not see any code for wiping the memory in the disassembled code. With regard to the bootloader: I used the default supplied with my version of Arduino 0021.

Anyway it does not really matter: I want to have repeatable results thus EEProm seems the only way to go.

The reason why the .noinit section sometime seems to be working and sometimes not depends on the bootloader.

If for instance the Arduino 2009 is used throught the IDE, it is normally programmed by means of the bootloader that is itself a C program whose startup code clears the .bss section of the bootloader.

If the board is programmed directly (MKII ISP programmer for instance), at reset only your code is run, thus the bss and the noinit code is correctly set up (bss zeroed, noinit untouched).

If the board is programmed through the bootloader, at reset the bootloader is always launched which zeroes its bss then, if no IDE is answering and no new program is to be downloaded, the main code is launched so chances are that the bss code cleared by the bootloader clears the noinit section of the following code and the variable seems to be initialized.

In a nutshell, if the noinit section is to be used, use only direct programming.

If for instance the Arduino 2009 is used throught the IDE, it is normally programmed by means of the bootloader that is itself a C program whose startup code clears the .bss section of the bootloader.

Since this thread seems to have been re-activated, I'll point out that this is NOT true of the optiboot bootloader used on the Arduino Uno and many other recent boards. Optiboot doesn't have a .bss section, and pretty much won't touch the RAM memory at all unless you actually send bootloader commands to it. (it might trash a word or two at the top of the stack...)