|
| 1 | +# Optimizations |
| 2 | + |
| 3 | +The goal is to reduce the size of the generated binaries. This is done by |
| 4 | +aiding the linker to eleminate dead code by splitting large source files and |
| 5 | +by hand-optimizing individual functions. |
| 6 | + |
| 7 | +## Results |
| 8 | + |
| 9 | +The sum of all these optimizations reduces the total size of Blink.ino by |
| 10 | +more than 30%, saving more than 800 bytes of precious flash space: |
| 11 | + |
| 12 | + code | data| RAM| flash total |split stage |
| 13 | + ---- | ----| ----| ---- |------------ |
| 14 | + 2507 | 138| 72| 2645 |before split |
| 15 | + 2450 | 138| 72| 2588 |after splitting wiring.c |
| 16 | + 2381 | 138| 72| 2519 |after splitting wiring_digital.c |
| 17 | + 1799 | 138| 72| 1937 |after splitting HardwareSerial.c |
| 18 | + 1686 | 138| 72| 1824 |after optimizing pinMode() |
| 19 | + |
| 20 | +Data is mostly the tables to map the Arduino pin numbers to the actual port |
| 21 | +registers. RAM is mostly the transmit and receive buffers for serial |
| 22 | +communication. These can't easily be optimized out. |
| 23 | + |
| 24 | + |
| 25 | +## Splitting files |
| 26 | + |
| 27 | +The SDCC linker does not detect unused functions and constants in an object |
| 28 | +file. It always links the whole file even if only a single symbol contained |
| 29 | +in the file is referenced. This results in pretty bloated binaries if the |
| 30 | +SPL is used. |
| 31 | + |
| 32 | +Splitting larger source files into smaller units and compile them |
| 33 | +individually before building the libraries helps the SDCC linker to |
| 34 | +eleminate dead code and to produce smaller binaries. |
| 35 | + |
| 36 | +Splitting files is worthwhile for all SPL files and at least some of the |
| 37 | +bigger Arduino core files. |
| 38 | + |
| 39 | + |
| 40 | +### The stategy |
| 41 | + |
| 42 | +The SPL consists of many source files with a very regular structure. This |
| 43 | +allows to automate the splitting process with very little preparation work. |
| 44 | + |
| 45 | +All SPL functions are documented with a doxygen comment block. The beginning |
| 46 | +of this comment block is a line with only "/**", that can easily be used as |
| 47 | +a marker for splitting the files. |
| 48 | + |
| 49 | +Only the very first block is special. It contains definitions and prototypes |
| 50 | +that are needed all over the module. This block is saved as a `.h` file and |
| 51 | +`#include`'d by all the following blocks. |
| 52 | + |
| 53 | +In most cases this is already sufficient. Only in very rare cases the |
| 54 | +position of a split needs the be edited. This is automatically done by the |
| 55 | +patches in the `patches/` directory. |
| 56 | + |
| 57 | +**To prevent a split**: Change the `/**` line into something different, `/***` |
| 58 | +is used in the scripts. |
| 59 | + |
| 60 | +**To force a split**: Add an empty Doxygen comment block: |
| 61 | +```c |
| 62 | +/** |
| 63 | + */ |
| 64 | +``` |
| 65 | + |
| 66 | + |
| 67 | +### Splitting the SPL files |
| 68 | + |
| 69 | +Splitting and compiling the SPL libraries is moved into the separate project |
| 70 | +[spl-splitter](https://github.com/tenbaht/spl-splitter) now. |
| 71 | + |
| 72 | + |
| 73 | + |
| 74 | +### Split Arduino core files |
| 75 | + |
| 76 | +`wiring.c`, `wiring_digital.c` and `HardwareSerial.c` all compile into quite |
| 77 | +large binaries. All of them are linked with almost |
| 78 | +every project. This is true even if no serial communication is used since |
| 79 | +main.c references `serialEvent()` and this way pulls in all of |
| 80 | +HardwareSerial. |
| 81 | + |
| 82 | +Splitting these three files reduces the size of simple sketches |
| 83 | +significantly. It does not help so much for complex sketches that use almost |
| 84 | +all functions of these modules. |
| 85 | + |
| 86 | + |
| 87 | + |
| 88 | +## Optimizing individual functions |
| 89 | + |
| 90 | +`pinMode()` sticks out when looking at the size of individual functions. 270 |
| 91 | +bytes for just setting the IO-mode of a pin. A re-write in assember reduces |
| 92 | +this to just 147 bytes. |
0 commit comments