Saturday, August 20, 2011

Source code optimization tips for Atmel AVR programmers also Arduino and clones

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(;;) { } 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). If possible, avoid calling functions from inside the interrupt routine.
  17. Use the smallest possible memory model.

Five Hints to Reduce RAM Requirements
  1. All constants and literals should be placed in Flash by using the Flash keyword.
  2. Avoid using global variables if the variables are local in nature. This also saves code space. Local variables are allocated from the stack dynamically and are removed when the function goes out of scope.
  3. If using large functions with variables with a limited lifetime within the function, the use of subscopes can be beneficial.
  4. Get good estimates of the sizes of the software Stack and return Stack (Linker File).
  5. Do not waste space for the IDATA0 and UDATA0 segments unless you are using tiny variables (Linker File).

Checklist for Debugging Programs
  1. Ensure that the CSTACK segment is sufficiently large.
  2. Ensure that the RSTACK segment is sufficiently large.
  3. Ensure that the external memory interface is enabled if it should be enabled and disabled if it should be disabled.
  4. If a regular function and an interrupt routine are communicating through a global variable, make sure this variable is declared volatile to ensure that it is reread from RAM each time it is checked.

No comments: