binary sketch sizes + Serial com..... (size tuning?)[SOLVED]

Firstly: I wanna mention, that I have tried to find some useful data myself... but I was not very much successful.

The size limitations impossed by the atmel chips on the arduino boards make me care about "binary sketch size" (btw. is there a more general term to the size of the compilation+linking output)?

The binary sketch size of the blink example for instance is "meager"(small) (1222 bytes)

ofencito@freak:~/Desktop/arduino/blink$ avr-size program.hex
text data bss dec hex filename
0 1222 0 1222 4c6 program.hex

As soon as I edit the setup() function to include a Serial.begin(9600); like this:

void setup() {                
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);    
  Serial.begin(9600);
}

the "binary sketch size" almost explodes in size and goes ab to 14'864 bytes:

ofencito@freak:~/Desktop/arduino/blink$ avr-size program.hex
text data bss dec hex filename
0 14864 0 14864 3a10 program.hex

Of course I expected that the Serial communication increases the size somewhat.
Still an about 1100% increase seems a little suprising to me.
This is mainly because I know that while the ATmega328 chip on the Arduino Uno can easily accomodate/store
this easily (it has 32'000 = almost twice the memory) I wonder how this size would have worked with most
of the other models that only came with 16k or 8k???

Since I assume there must have been a communication Serial also in the 8k version, but the 8k would of course
not be able to store the resulting about 14.8k of data I wonder if the 14.8k size is really right, or I am just
doing some wrong linking etc.

Maybe somebody can give me a glue what to use as compiler and linker flags.....

Also it would be nice if somebody would be able to test if the modified setup() function
also causes about a similar size of 14.8k "binary sketch size"??

What are you doing exactly? What Arduino is it? What version of the IDE do you have?

void setup() {                
  pinMode(13, OUTPUT);    
  Serial.begin(9600);
}

void loop () { }

That gives me, for the Uno on 1.0.3 of the IDE:

Binary sketch size: 1,968 bytes (of a 32,256 byte maximum)

So that is hardly 14K bytes.

Thank Nick for the quick reply! :slight_smile:
First of all it's been really nice of your to have tested and posted the "binary sketch size" here. thank you for that.

What are you doing exactly?(a) What Arduino is it?(b) What version of the IDE do you have?(c)

I am sorry if I have left my post without this informaiton. Thank you for asking.

(a). I have not been doing something very specific, but rather have noticed that I have this huge increase in "binary sketch size" as soon as I start using the Serial communication. So I asked this question... while indeed it was not linked to (yet) a very specific problem, but rather because of my suprise and lack of understanding. I hope this is ok!
As it seems my suspicion that this increase to a size of 14.8k is too much, was correct as your test showed me.

(b) it is an Arduino Uno that I am using. It is true that there is already quite a variaty of Arduinos and when I wrote that I have the ATmega328 microcontroller, well I might have not been specific.. ,wasn't I? (sorry!)

(c) I do actually not use the IDE provided on the side at all, but instead I have used the http://arduino.googlecode.com/files/arduino-1.0.3-linux32.tgz package (of the 1.0.3 IDE), which includes the files for development (without IDE and most importingly JAVA) inside at:

  • (general files) hardware/arduino/cores/arduino
  • (UNO pins) hardware/arduino/variants/standard/pins_arduino.h

from those I made a library which I link against. I use the avr-g++ version "avr-g++ (GCC) 4.5.3".

I dearly love not to use the IDE because in this way I am more involved in the process of creating/builing the acutal binary and uploading it to the Arduino UNO. Also I do not have, neither plan and desire to have, JAVA on my machine for various reasons. It is nice to have the IDE, but I do not require it particularily much as I use one I am quite accustomed to named (Geany).

Now I am still at a loss to figure out how my approach yields me such a much higher "binary sketch size"

Any ideas?

Simply to answer my original post and especially the part about size tuning.

First the my result (still not using the IDE) I have yielded an optimized size for the "setup()" modified blink example of 2262 bytes only:
avr-objcopy -O ihex program.elf program.hex
text data bss dec hex filename
0 2262 0 2262 8d6 program.hex
For the example as used in the post of Nick (with an empty loop) I even have smaller 1852 bytes. So the results are good now.

The (how to) size tuning information I have asked for in the post is done (as suggested already by using compiler and linker flags).
For generating the libarduino (from the source found in the 1.0.3 IDE package) I have used those compiler flags:
-Os -w -Wl,--gc-sections -ffunction-sections -fdata-sections

When compiling the final sketch I have then used those compiling flags (which incitently are the same):
-Os -w -Wl,--gc-sections -ffunction-sections -fdata-sections

The reason for the previously huge 14.8k has been that the library was not compiled with the
-Wl,--gc-sections -ffunction-sections -fdata-sections flags which did not
detach the functions within the library, meaning that Serial.begin(9600) linked in from the library
caused many other entangled functions to be linked in too, though never used. With the flags
-Wl,--gc-sections -ffunction-sections -fdata-sections added to the compilation of
the libraray this detached the functions into own objects which can be hence linked seperatly on a
"each one only when needed"-basis.
This reduced the code from 14.8k to 2262.

I hope people reading this, mostly those also shunting the IDE will benefit from this explenation given.
Since those people not using the IDE often by requirement have to know somewhat more, it might not
even be necessary for those "advanced" developers, but anyhow. There is no loss or harm caused by giving
a more fitting answer to the question or post. It might actually assist and helpe somebody.... who knows?

If you bypass the Arduino IDE and compile and link your software yourself, then you take responsibility for specifying the appropriate options. It should not come as any surprise to find that if you don't apply the appropriate optimisations then the output is not optimal.

Also note that you have been looking at the size of the image file, which is not the same as the number of bytes of program memory used by the sketch.

alexander_senseo:
...
First the my result (still not using the IDE) I have yielded an optimized size for the "setup()" modified blink example of 2262 bytes only:
avr-objcopy -O ihex program.elf program.hex
text data bss dec hex filename
0 2262 0 2262 8d6 program.hex
...
When compiling the final sketch I have then used those compiling flags (which incitently are the same):
-Os -w -Wl,--gc-sections -ffunction-sections -fdata-sections
...

Just for reference, my own results from a 1.0.3. IDE running on Mac OSX 10.6. The only difference between the two versions is a Serial.begin(9600) in setup().

   text	   data	    bss	    dec	    hex	filename
      0	   1084	      0	   1084	    43c	Blink.cpp.hex

   text	   data	    bss	    dec	    hex	filename
      0	   2362	      0	   2362	    93a	Blink.cpp.hex

The interesting thing is that your optimized code is more optimized than mine. The (default) c flags in my case (some obviously target-specific) are as follows:

-c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=103

alexander_senseo:
(c) I do actually not use the IDE provided on the side at all, but instead I have used ...

I guessed that from the command-line options you were doing, and of course if you are getting "down and dirty" then the exact thing that you are doing is relevant.

The default IDE compiler and linker options are highly aggressive, resulting in code which is very optimized and also which does not link in code which is not needed.

Even something simple like declaring a large array, and not using it at all, results in the array not appearing in the final code.

Also people may find that even after including lots of libraries their code size does not increase, but once they start calling functions in them, it does.

Thanks for your follow-up posts.

PeterH:
Also note that you have been looking at the size of the image file, which is not the same as the number of bytes of program memory used by the sketch.

That sounds interesting PeterH. Thank you for mentioning this. Can you tell some more about those different sizes. I used the avr-size tool, which I actually thought to be the way to actually see the memory of the sketch used in the flash memory afterwards. Is it not?

What is the "size of the image file"? would that be not the size of the .elf or .hex file then?

spatula:
The interesting thing is that your optimized code is more optimized than mine. [....]

I think that the reason for the difference of 100 bytes is because I do use a different main() function underlying the loop() and setup() functions in the "sketch file".

I have these modifications (the code-lines commented out) in the main():

int main(void)
{
	init();

#if defined(USBCON)
	//USBDevice.attach();
#endif
	
	setup();
    
	for (;;) {
		loop();
		//if (serialEventRun) serialEventRun(); 
	}
        
	return 0;
}

Up to now they did not seem to be that very much necessary... but there might be important reasons for them..(I would sure like to know.. thought that is another question)
I assume the skipping of those two lines of code causes the meager size difference of 100bytes (which is almost nothing anyhow)

My example above which reported:

Binary sketch size: 1,968 bytes (of a 32,256 byte maximum)

... gives this with avr-size:

$ avr-size sketch_mar09c.cpp.hex 
   text	   data	    bss	    dec	    hex	filename
      0	   1968	      0	   1968	    7b0	sketch_mar09c.cpp.hex

So, it's the same.

The file size is, of course, larger as the data is stored in hex:

-rw-r--r--  1 nick  staff  5548 10 Mar 08:42 /sketch_mar09c.cpp.hex

If I do my own main I can get the size down:

int main()
{                
  pinMode(13, OUTPUT);    
  Serial.begin(9600);
}

Gives:

Binary sketch size: 1,638 bytes (of a 32,256 byte maximum)

Of course, the "real" main does useful stuff, like calling init, which initializes the timer used for millis(), micros() etc.


Minimal sketch:

int main() 
{                
}

Size:

Binary sketch size: 176 bytes (of a 32,256 byte maximum)

alexander_senseo:
Up to now they did not seem to be that very much necessary... but there might be important reasons for them

The USB line would be for the Leonardo.

The serialEvent stuff I would happily be rid of. It's for calling your own function when serial data arrives, as if you can't work that part out for yourself.

I am much obligued for enlightening me about the purposes of the stuff left in main(). As indeed I already skipped most it anyhow I now have certainty that it was really not a big loss at all. It speaks my heart, when you say "as if you can't work that part out for yourself". Maybe it is nonetheless a necessary thing for the early beginners, which might otherwise more easily run into a discouraging "I'm stuck"-situation. The people that know about it can easily modify the main.cpp so taht it better caters their needs.

alexander_senseo:
That sounds interesting PeterH. Thank you for mentioning this. Can you tell some more about those different sizes. I used the avr-size tool, which I actually thought to be the way to actually see the memory of the sketch used in the flash memory afterwards. Is it not?

What is the "size of the image file"? would that be not the size of the .elf or .hex file then?

I'm sorry, I mis-read your post. I thought you were quoting the file size of the file containing your hex image, not the hex image size as reported by AVR.