Go Down

Topic: How to reduce program size (Read 2441 times) previous topic - next topic

ScottG

I'm trying to understand which parts of my sketch affect program size.
Defining variable don't seem to affect it, which is surprising.  I notice that reducing the text in Serial.print() helps.  Now I mostly use Serial.print(F()) to put the strings in EEPROM, but I don't think that reduces the compile size.
Including libraries that are not actually used by the code doesn't seem to affect it.

AWOL

Quote
Now I mostly use Serial.print(F()) to put the strings in EEPROM,

PROGMEM not EEPROM.

Code size is affected by lots of things, you can write source, but if you don't call it, the compiler won't include it.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

PaulS

Quote
Now I mostly use Serial.print(F()) to put the strings in EEPROM, but I don't think that reduces the compile size.

Of course it doesn't. It actually increases it, as you've now said that constant strings should live in program (code) space, rather than SRAM.

Quote
Including libraries that are not actually used by the code doesn't seem to affect it.

Correct. AWOL alludes to why. The linker only writes to the hex file code that actually does stuff - after optimization occurs.

Code: [Select]
Defining variable don't seem to affect it, which is surprising.
Not if you understand where variables are stored. Program space is read only, unless the bootloader is uploading a new hex file. Since variables need to be written to, they are not stored in program space. So, they do not affect the amount of program space needed.

ScottG


Code: [Select]
Defining variable don't seem to affect it, which is surprising.
Not if you understand where variables are stored. Program space is read only, unless the bootloader is uploading a new hex file. Since variables need to be written to, they are not stored in program space. So, they do not affect the amount of program space needed.


I have no idea where stuff is stored, or even what the different parts are.  Any suggestions on a good source that explains this?


Nick Gammon


Of course it doesn't. It actually increases it, as you've now said that constant strings should live in program (code) space, rather than SRAM.


Huh? They were in program code space anyway.

A quick test shows that this code:

Code: [Select]
void setup ()
{
  Serial.begin (115200);
  Serial.println (F("Hello, world."));
}
void loop () {}



... takes 32 bytes more of PROGMEM (program memory) than one without the F macro. However the 32 bytes is fixed. It would be the space taken by the implementation of the routine to pull data out of Flash rather than RAM. So if you add more strings, it is still only 32 bytes larger.

So for a fixed overhead of 32 bytes of program memory, you save substantial amounts of RAM (of which you have a lot less) if you use a lot of strings.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

DuaneB

Hi,
   If you have any global variables that could be made local instead this can save a lot of memory.

   Global variables must be read from memory into registers before they can be manipulated, then written back to memory afterwards. If the same variable can be made into a local variable, the compiler has the option of storing it in registers directly. Heres an example -

Code: [Select]

// Increment a global integer

   nCounter++;
  5e:    80 91 60 00     lds    r24, 0x0060
  62:    90 91 61 00     lds    r25, 0x0061
  66:    01 96           adiw    r24, 0x01    ; 1
  68:    90 93 61 00     sts    0x0061, r25
  6c:    80 93 60 00     sts    0x0060, r24



Code: [Select]

// Increment a local integer
    nCounter++;
  6e:    2f 5f           subi    r18, 0xFF    ; 255
  70:    3f 4f           sbci    r19, 0xFF    ; 255


Duane B

rcarduino.blogspot.com
Read this
http://rcarduino.blogspot.com/2012/04/servo-problems-with-arduino-part-1.html
then watch this
http://rcarduino.blogspot.com/2012/04/servo-problems-part-2-demonstration.html

Rcarduino.blogspot.com

ScottG


   If you have any global variables that could be made local instead this can save a lot of memory.


That's good to know.

Magician

#8
Jul 05, 2012, 09:06 am Last Edit: Jul 05, 2012, 09:08 am by AWOL Reason: 1
Quote
Eighteen Hints to Reduce Code Size
1. Compile with full size optimization.
2. Use local variables whenever possible.
3. Use the smallest applicable data type. Use unsigned if applicable.
4. If a non-local variable is only referenced within one function, it should be declared static.
5. Collect non-local data in structures whenever natural. This increases the possibility of indirect addressing without pointer reload.
6. Use pointers with offset or declare structures to access memory mapped I/O.
7. Use for([font=Verdana];[/font][font=Verdana];[/font]) { } for eternal loops.
8. Use do { } while(expression) if applicable.
9. Use descending loop counters and pre-decrement if applicable.
10. Access I/O memory directly (i.e., do not use pointers).
11. Declare main as C_task if not called from anywhere in the program.
12. Use macros instead of functions for tasks that generates less than 2-3 lines assembly code.
13. Reduce the size of the Interrupt Vector segment (INTVEC) to what is actually needed by the application. Alternatively, concatenate all the CODE segments into one declaration and it will be done automatically.
14. Code reuse is intra-modular. Collect several functions in one module (i.e., in one file) to increase code reuse factor.
15. In some cases, full speed optimization results in lower code size than full size optimization. Compile on a module by module basis to investigate what gives the best result.
16. Optimize C_startup to not initialize unused segments (i.e., IDATA0 or IDATA1 if all variables are tiny or small).
17. If possible, avoid calling functions from inside the interrupt routine.
18. Use the smallest possible memory model.


AVR035.

Moderator edit: Smiley corrected.

DuaneB

Hi,

There is another AVR PDF that has previously been posted on these forums, that includes one point missing from the 18 above.

19) If functions are only used within the current file declare them as static, this gives the compiler the option to inline them eliminating all the pushing and popping code.

I tested this and was surpised to see a large function inlined inside loop, the suprising part is that the function is called within two different branches of loop, not sure how the compiler is managing it. I assume its all clever optimisation to ensure that the registers are the same whichever context it is called from (a fist level if and a deeply nested if in the else of the first level if).

Note that loop and setup have thier function prototypes defined elsewhere, but any other functions can be declared static, the compiler can then choose whether to inline them.

Duane B

rcarduino.blogspot.com
Read this
http://rcarduino.blogspot.com/2012/04/servo-problems-with-arduino-part-1.html
then watch this
http://rcarduino.blogspot.com/2012/04/servo-problems-part-2-demonstration.html

Rcarduino.blogspot.com

Go Up