Optimizing for small Flash size

Davidelvig

Well-known member
I have a project using 58% of flash (on Teensy 3.2 architecture) and I need to get under 50% to try the easiest form of OTA updates.

Can someone point me to strategies to whack unneeded code from my project, including libraries included by libraries that I don't really need.

Here's the Dependency Graph from my project, compiled in VS Code (Teensy 3.2, VS Code, Platformio, MacOS)

Code:
Dependency Graph
|-- <RunningMedian> 0.3.4
|-- <TeensyID> 1.3.3
|-- <Madgwick> 1.2.0
|-- <SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library> 1.2.9
|   |-- <SPI> 1.0
|   |-- <Wire> 1.0
|-- <Adafruit GFX Library> 1.10.13
|   |-- <SPI> 1.0
|   |-- <Adafruit BusIO> 1.11.2
|   |   |-- <Wire> 1.0
|   |   |-- <SPI> 1.0
|   |-- <Wire> 1.0
|-- <Adafruit ST7735 and ST7789 Library> 1.9.2
|   |-- <Adafruit GFX Library> 1.10.13
|   |   |-- <SPI> 1.0
|   |   |-- <Adafruit BusIO> 1.11.2
|   |   |   |-- <Wire> 1.0
|   |   |   |-- <SPI> 1.0
|   |   |-- <Wire> 1.0
|   |-- <SPI> 1.0
|-- <Adafruit BusIO> 1.11.2
|   |-- <Wire> 1.0
|   |-- <SPI> 1.0
|-- <SD> 1.2.4
|   |-- <SPI> 1.0
|-- <LinkedList> 0.0.0-alpha+sha.dac3874d28
|-- <dbLibs>
|   |-- <dbUtility>
|   |   |-- <RunningMedian> 0.3.4
|   |-- <SPI> 1.0
|   |-- <dbMIDI>
|   |   |-- <dbUtility>
|   |   |   |-- <RunningMedian> 0.3.4
|   |-- <SD> 1.2.4
|   |   |-- <SPI> 1.0
|   |-- <dbSTEMLibs>
|   |   |-- <dbMIDI>
|   |   |   |-- <dbUtility>
|   |   |   |   |-- <RunningMedian> 0.3.4
|   |-- <RunningMedian> 0.3.4
|   |-- <EEPROM> 2.0
|   |-- <Adafruit GFX Library> 1.10.13
|   |   |-- <SPI> 1.0
|   |   |-- <Adafruit BusIO> 1.11.2
|   |   |   |-- <Wire> 1.0
|   |   |   |-- <SPI> 1.0
|   |   |-- <Wire> 1.0
|   |-- <Adafruit ST7735 and ST7789 Library> 1.9.2
|   |   |-- <Adafruit GFX Library> 1.10.13
|   |   |   |-- <SPI> 1.0
|   |   |   |-- <Adafruit BusIO> 1.11.2
|   |   |   |   |-- <Wire> 1.0
|   |   |   |   |-- <SPI> 1.0
|   |   |   |-- <Wire> 1.0
|   |   |-- <SPI> 1.0
|   |-- <SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library> 1.2.9
|   |   |-- <SPI> 1.0
|   |   |-- <Wire> 1.0
|   |-- <Madgwick> 1.2.0
|   |-- <TeensyID> 1.3.3
|   |-- <Time> 1.6.1
|   |-- <LinkedList> 0.0.0-alpha+sha.dac3874d28
|-- <dbMIDI>
|   |-- <dbUtility>
|   |   |-- <RunningMedian> 0.3.4
|-- <dbUtility>
|   |-- <RunningMedian> 0.3.4
Building in release mode
Linking .pio/build/teensy31/firmware.elf
Checking size .pio/build/teensy31/firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [====      ]  38.8% (used 25432 bytes from 65536 bytes)
Flash: [======    ]  58.2% (used 152548 bytes from 262144 bytes)
Building .pio/build/teensy31/firmware.hex

I've also included a directory listing of the build directory, which shows size of object files.
All of the files beginning with "db..." are my own - which I understand pretty well. The others are libraries.
Code:
./FrameworkArduino:
total 792
-rw-------@ 1 davidelvig   5652 Mar  9 14:38 AudioStream.cpp.o
-rw-------@ 1 davidelvig   1920 Mar  9 14:38 CrashReport.cpp.o
-rw-------@ 1 davidelvig   2988 Mar  9 14:38 DMAChannel.cpp.o
-rw-------@ 1 davidelvig   6820 Mar  9 14:38 EventResponder.cpp.o
-rw-------@ 1 davidelvig   1572 Mar  9 14:38 HardwareSerial.cpp.o
-rw-------@ 1 davidelvig   8892 Mar  9 14:38 HardwareSerial1.cpp.o
-rw-------@ 1 davidelvig   9356 Mar  9 14:38 HardwareSerial2.cpp.o
-rw-------@ 1 davidelvig   9356 Mar  9 14:38 HardwareSerial3.cpp.o
-rw-------@ 1 davidelvig    776 Mar  9 14:38 HardwareSerial4.cpp.o
-rw-------@ 1 davidelvig    776 Mar  9 14:38 HardwareSerial5.cpp.o
-rw-------@ 1 davidelvig    776 Mar  9 14:38 HardwareSerial6.cpp.o
-rw-------@ 1 davidelvig   1676 Mar  9 14:38 IPAddress.cpp.o
-rw-------@ 1 davidelvig   2608 Mar  9 14:38 IntervalTimer.cpp.o
-rw-------@ 1 davidelvig   5292 Mar  9 14:38 Print.cpp.o
-rw-------@ 1 davidelvig   5400 Mar  9 14:38 Stream.cpp.o
-rw-------@ 1 davidelvig   2016 Mar  9 14:38 Time.cpp.o
-rw-------@ 1 davidelvig   4048 Mar  9 14:38 Tone.cpp.o
-rw-------@ 1 davidelvig   2516 Mar  9 14:38 WMath.cpp.o
-rw-------@ 1 davidelvig  20164 Mar  9 14:38 WString.cpp.o
-rw-------@ 1 davidelvig   4484 Mar  9 14:38 analog.c.o
-rw-------@ 1 davidelvig   1304 Mar  9 14:38 avr_emulation.cpp.o
-rw-------@ 1 davidelvig   3948 Mar  9 14:38 eeprom.c.o
-rw-------@ 1 davidelvig    992 Mar  9 14:38 keylayouts.c.o
-rw-------@ 1 davidelvig   1028 Mar  9 14:38 main.cpp.o
-rw-------@ 1 davidelvig   4912 Mar  9 14:38 math_helper.c.o
-rw-------@ 1 davidelvig   1016 Mar  9 14:38 memcpy-armv7m.S.o
-rw-------@ 1 davidelvig    552 Mar  9 14:38 memset.S.o
-rw-------@ 1 davidelvig  10140 Mar  9 14:38 mk20dx128.c.o
-rw-------@ 1 davidelvig   1796 Mar  9 14:38 new.cpp.o
-rw-------@ 1 davidelvig   2600 Mar  9 14:38 nonstd.c.o
-rw-------@ 1 davidelvig  12472 Mar  9 14:38 pins_teensy.c.o
-rw-------@ 1 davidelvig    768 Mar  9 14:38 ser_print.c.o
-rw-------@ 1 davidelvig  11040 Mar  9 14:38 serial1.c.o
-rw-------@ 1 davidelvig   9628 Mar  9 14:38 serial2.c.o
-rw-------@ 1 davidelvig   8928 Mar  9 14:38 serial3.c.o
-rw-------@ 1 davidelvig    764 Mar  9 14:38 serial4.c.o
-rw-------@ 1 davidelvig    764 Mar  9 14:38 serial5.c.o
-rw-------@ 1 davidelvig    764 Mar  9 14:38 serial6.c.o
-rw-------@ 1 davidelvig    772 Mar  9 14:38 serial6_lpuart.c.o
-rw-------@ 1 davidelvig   1032 Mar  9 14:38 serialEvent.cpp.o
-rw-------@ 1 davidelvig   1036 Mar  9 14:38 serialEvent1.cpp.o
-rw-------@ 1 davidelvig   1036 Mar  9 14:38 serialEvent2.cpp.o
-rw-------@ 1 davidelvig   1036 Mar  9 14:38 serialEvent3.cpp.o
-rw-------@ 1 davidelvig    772 Mar  9 14:38 serialEvent4.cpp.o
-rw-------@ 1 davidelvig    772 Mar  9 14:38 serialEvent5.cpp.o
-rw-------@ 1 davidelvig    772 Mar  9 14:38 serialEvent6.cpp.o
-rw-------@ 1 davidelvig   1052 Mar  9 14:38 serialEventUSB1.cpp.o
-rw-------@ 1 davidelvig   1052 Mar  9 14:38 serialEventUSB2.cpp.o
-rw-------@ 1 davidelvig   1368 Mar  9 14:38 touch.c.o
-rw-------@ 1 davidelvig    768 Mar  9 14:38 usb_audio.cpp.o
-rw-------@ 1 davidelvig   3068 Mar  9 14:38 usb_desc.c.o
-rw-------@ 1 davidelvig   8620 Mar  9 14:38 usb_dev.c.o
-rw-------@ 1 davidelvig    772 Mar  9 14:38 usb_flightsim.cpp.o
-rw-------@ 1 davidelvig   3956 Mar  9 14:38 usb_inst.cpp.o
-rw-------@ 1 davidelvig    772 Mar  9 14:38 usb_joystick.c.o
-rw-------@ 1 davidelvig    772 Mar  9 14:38 usb_keyboard.c.o
-rw-------@ 1 davidelvig   3836 Mar  9 14:38 usb_mem.c.o
-rw-------@ 1 davidelvig   8896 Mar  9 14:38 usb_midi.c.o
-rw-------@ 1 davidelvig    768 Mar  9 14:38 usb_mouse.c.o
-rw-------@ 1 davidelvig    764 Mar  9 14:38 usb_mtp.c.o
-rw-------@ 1 davidelvig    768 Mar  9 14:38 usb_rawhid.c.o
-rw-------@ 1 davidelvig    768 Mar  9 14:38 usb_seremu.c.o
-rw-------@ 1 davidelvig   5112 Mar  9 14:38 usb_serial.c.o
-rw-------@ 1 davidelvig    768 Mar  9 14:38 usb_serial2.c.o
-rw-------@ 1 davidelvig    768 Mar  9 14:38 usb_serial3.c.o
-rw-------@ 1 davidelvig    768 Mar  9 14:38 usb_touch.c.o
-rw-------@ 1 davidelvig   1916 Mar  9 14:38 yield.cpp.o
 
./lib0b9:
total 96
drwxr-xr-x@ 5 davidelvig    160 Mar  9 14:38 SD
-rw-------@ 1 davidelvig  48006 Mar  9 14:38 libSD.a
 
./lib0b9/SD:
total 32
-rw-------@ 1 davidelvig  5212 Mar  9 14:38 File.cpp.o
-rw-------@ 1 davidelvig  7648 Mar  9 14:38 SD.cpp.o
drwxr-xr-x@ 5 davidelvig   160 Mar  9 14:38 utility
 
./lib0b9/SD/utility:
total 72
-rw-------@ 1 davidelvig  10468 Mar  9 14:38 Sd2Card.cpp.o
-rw-------@ 1 davidelvig  15228 Mar  9 14:38 SdFile.cpp.o
-rw-------@ 1 davidelvig   5476 Mar  9 14:38 SdVolume.cpp.o
 
./lib0f1:
total 72
drwxr-xr-x@ 3 davidelvig     96 Mar  9 14:38 dbMIDI
-rw-------@ 1 davidelvig  34792 Mar  9 14:38 libdbMIDI.a
 
./lib0f1/dbMIDI:
total 64
-rw-------@ 1 davidelvig  32524 Mar  9 14:38 dbMIDI.cpp.o
 
./lib14e:
total 40
drwxr-xr-x@ 5 davidelvig    160 Mar  9 14:38 Adafruit ST7735 and ST7789 Library
-rw-------@ 1 davidelvig  19592 Mar  9 14:38 libAdafruit ST7735 and ST7789 Library.a
 
./lib14e/Adafruit ST7735 and ST7789 Library:
total 48
-rw-------@ 1 davidelvig  6412 Mar  9 14:38 Adafruit_ST7735.cpp.o
-rw-------@ 1 davidelvig  4944 Mar  9 14:38 Adafruit_ST7789.cpp.o
-rw-------@ 1 davidelvig  6412 Mar  9 14:38 Adafruit_ST77xx.cpp.o
 
./lib3c1:
total 16
drwxr-xr-x@ 3 davidelvig    96 Mar  9 14:38 TeensyID
-rw-------@ 1 davidelvig  4296 Mar  9 14:38 libTeensyID.a
 
./lib3c1/TeensyID:
total 8
-rw-------@ 1 davidelvig  3988 Mar  9 14:38 TeensyID.cpp.o
 
./lib5e9:
total 56
drwxr-xr-x@ 7 davidelvig    224 Mar  9 14:38 dbSTEMLibs
-rw-------@ 1 davidelvig  27186 Mar  9 14:38 libdbSTEMLibs.a
 
./lib5e9/dbSTEMLibs:
total 64
-rw-------@ 1 davidelvig   1720 Mar  9 14:38 dbCRC.cpp.o
-rw-------@ 1 davidelvig   3012 Mar  9 14:38 dbMIDIStem.cpp.o
-rw-------@ 1 davidelvig  13744 Mar  9 14:38 dbSTEM.cpp.o
-rw-------@ 1 davidelvig   2172 Mar  9 14:38 dbSTEMDispatch.cpp.o
-rw-------@ 1 davidelvig   3668 Mar  9 14:38 dbSTEMSerial.cpp.o
 
./lib697:
total 24
drwxr-xr-x@ 3 davidelvig     96 Mar  9 14:38 SPI
-rw-------@ 1 davidelvig  10704 Mar  9 14:38 libSPI.a
 
./lib697/SPI:
total 24
-rw-------@ 1 davidelvig  9716 Mar  9 14:38 SPI.cpp.o
 
./lib7b3:
total 48
drwxr-xr-x@ 5 davidelvig    160 Mar  9 14:38 Adafruit BusIO
-rw-------@ 1 davidelvig  20576 Mar  9 14:38 libAdafruit BusIO.a
 
./lib7b3/Adafruit BusIO:
total 48
-rw-------@ 1 davidelvig  6640 Mar  9 14:38 Adafruit_BusIO_Register.cpp.o
-rw-------@ 1 davidelvig  4192 Mar  9 14:38 Adafruit_I2CDevice.cpp.o
-rw-------@ 1 davidelvig  6856 Mar  9 14:38 Adafruit_SPIDevice.cpp.o
 
./lib88d:
total 664
drwxr-xr-x@ 27 davidelvig     864 Mar 10 16:01 dbLibs
-rw-------@  1 davidelvig  336164 Mar  9 14:47 libdbLibs.a
 
./lib88d/dbLibs:
total 712
-rw-------@ 1 davidelvig  17168 Mar 10 16:01 ESP_OverStem.cpp.o
-rw-------@ 1 davidelvig   1528 Mar  9 14:38 GlobalVars.cpp.o
-rw-------@ 1 davidelvig    944 Mar  9 14:38 MIDI_Name.c.o
-rw-------@ 1 davidelvig   7728 Mar 10 16:01 dbBattery.cpp.o
-rw-------@ 1 davidelvig  29268 Mar 10 16:01 dbConfig.cpp.o
-rw-------@ 1 davidelvig  30448 Mar 10 16:01 dbDisplay.cpp.o
-rw-------@ 1 davidelvig  32180 Mar 10 16:01 dbIMU.cpp.o
-rw-------@ 1 davidelvig  12692 Mar 10 16:01 dbLog.cpp.o
-rw-------@ 1 davidelvig  18992 Mar 10 16:01 dbMIDICommands.cpp.o
-rw-------@ 1 davidelvig   3512 Mar  9 14:38 dbMIDIConsumers.cpp.o
-rw-------@ 1 davidelvig  11868 Mar  9 14:38 dbMIDIFile.cpp.o
-rw-------@ 1 davidelvig  12260 Mar  9 14:38 dbMIDIFileRunner.cpp.o
-rw-------@ 1 davidelvig   8328 Mar  9 14:38 dbMIDIFileWriter.cpp.o
-rw-------@ 1 davidelvig  19804 Mar 10 16:01 dbMIDIPlayer.cpp.o
-rw-------@ 1 davidelvig  13260 Mar  9 14:38 dbMIDISynth.cpp.o
-rw-------@ 1 davidelvig   6720 Mar 10 16:01 dbPressure.cpp.o
-rw-------@ 1 davidelvig   7964 Mar 10 16:01 dbRTC.cpp.o
-rw-------@ 1 davidelvig  20636 Mar  9 14:38 dbSD.cpp.o
-rw-------@ 1 davidelvig   5332 Mar  9 14:38 dbTouchPin.cpp.o
-rw-------@ 1 davidelvig  30076 Mar 10 16:01 dbTrumpet.cpp.o
-rw-------@ 1 davidelvig    772 Mar 10 16:01 dbUnitTests.cpp.o
-rw-------@ 1 davidelvig   7424 Mar 10 16:01 dbUserInputs.cpp.o
-rw-------@ 1 davidelvig   6616 Mar  9 14:38 dbValue.cpp.o
-rw-------@ 1 davidelvig   4472 Mar  9 14:38 dbValveSet.cpp.o
-rw-------@ 1 davidelvig   3224 Mar  9 14:47 dbVersion.cpp.o
 
./lib91d:
total 8
drwxr-xr-x@ 3 davidelvig    96 Mar  9 14:38 EEPROM
-rw-------@ 1 davidelvig  2270 Mar  9 14:38 libEEPROM.a
 
./lib91d/EEPROM:
total 8
-rw-------@ 1 davidelvig  2052 Mar  9 14:38 EEPROM.cpp.o
 
./liba68:
total 40
drwxr-xr-x@ 4 davidelvig    128 Mar  9 14:38 Time
-rw-------@ 1 davidelvig  16630 Mar  9 14:38 libTime.a
 
./liba68/Time:
total 40
-rw-------@ 1 davidelvig   5588 Mar  9 14:38 DateStrings.cpp.o
-rw-------@ 1 davidelvig  10156 Mar  9 14:38 Time.cpp.o
 
./libb1c:
total 128
drwxr-xr-x@ 4 davidelvig    128 Mar  9 14:38 SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library
-rw-------@ 1 davidelvig  65030 Mar  9 14:38 libSparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library.a
 
./libb1c/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library:
total 80
-rw-------@ 1 davidelvig  38428 Mar  9 14:38 ICM_20948.cpp.o
drwxr-xr-x@ 3 davidelvig     96 Mar  9 14:38 util
 
./libb1c/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library/util:
total 48
-rw-------@ 1 davidelvig  20980 Mar  9 14:38 ICM_20948_C.c.o
 
./libba5:
total 32
drwxr-xr-x@ 3 davidelvig     96 Mar  9 14:38 dbUtility
-rw-------@ 1 davidelvig  15994 Mar  9 14:38 libdbUtility.a
 
./libba5/dbUtility:
total 32
-rw-------@ 1 davidelvig  14792 Mar  9 14:38 dbUtility.cpp.o
 
./libbcc:
total 16
drwxr-xr-x@ 3 davidelvig    96 Mar  9 14:38 RunningMedian
-rw-------@ 1 davidelvig  5836 Mar  9 14:38 libRunningMedian.a
 
./libbcc/RunningMedian:
total 16
-rw-------@ 1 davidelvig  5164 Mar  9 14:38 RunningMedian.cpp.o
 
./libc60:
total 128
drwxr-xr-x@ 6 davidelvig    192 Mar  9 14:38 Adafruit GFX Library
-rw-------@ 1 davidelvig  65456 Mar  9 14:38 libAdafruit GFX Library.a
 
./libc60/Adafruit GFX Library:
total 128
-rw-------@ 1 davidelvig  34120 Mar  9 14:38 Adafruit_GFX.cpp.o
-rw-------@ 1 davidelvig   7704 Mar  9 14:38 Adafruit_GrayOLED.cpp.o
-rw-------@ 1 davidelvig  15932 Mar  9 14:38 Adafruit_SPITFT.cpp.o
-rw-------@ 1 davidelvig    768 Mar  9 14:38 glcdfont.c.o
 
./libc66:
total 24
drwxr-xr-x@ 3 davidelvig     96 Mar  9 14:38 Madgwick
-rw-------@ 1 davidelvig  11064 Mar  9 14:38 libMadgwick.a
 
./libc66/Madgwick:
total 24
-rw-------@ 1 davidelvig  10680 Mar  9 14:38 MadgwickAHRS.cpp.o
 
./libd56:
total 32
drwxr-xr-x@ 6 davidelvig    192 Mar  9 14:38 Wire
-rw-------@ 1 davidelvig  13350 Mar  9 14:38 libWire.a
 
./libd56/Wire:
total 40
-rw-------@ 1 davidelvig   764 Mar  9 14:38 Wire.cpp.o
-rw-------@ 1 davidelvig   768 Mar  9 14:38 WireIMXRT.cpp.o
-rw-------@ 1 davidelvig  9956 Mar  9 14:38 WireKinetis.cpp.o
drwxr-xr-x@ 3 davidelvig    96 Mar  9 14:38 utility
 
./libd56/Wire/utility:
total 8
-rw-------@ 1 davidelvig  760 Mar  9 14:38 twi.c.o
 
./src:
total 40
-rw-------@ 1 davidelvig  16624 Mar 10 16:01 main.cpp.o
 
If using Arduino, try the easiest thing first, Tools > Optimize to "Smallest Code".

On PlatformIO you'll probably need to edit some config file to set the compiler flags the same or similarly to that menu. I believe it uses -Os and --specs=nano.specs.

Using nano.specs means printf() will lose the ability to print floating point numbers, which trims about 20K from the code size. But Serial.print() can still use them.
 
Thanks, Paul. I'll have a look at the PlatformIO build flags.
I would have to wean myself from printf's with floats... but I could define them out.


I'm also wondering about two hefty libraries in particular:
- Adafruit GFX for my small color display - text and simple shapes (no images)
- Sparkfun 9DoF IMU Breakout for my IMU chip (ICM_20948).

I expect those libraries are built to do "all possible things" and I likely need only a subset.
If anyone has alternate (smaller) libraries for TFT screen driving and Invensense IMU sensing, I'd welcome a reference.
 
The self-hosted web-based PlatformIO Home interface provides some good tools for inspecting project code sizes.

Look under the Inspect section and you can browse around symbols and sections to see where the worst offenders might be.

If you don't use the IDE, you can start it from the command line with "p
 
I'm also wondering about two hefty libraries in particular:
- Adafruit GFX for my small color display - text and simple shapes (no images)
- Sparkfun 9DoF IMU Breakout for my IMU chip (ICM_20948).

I expect those libraries are built to do "all possible things" and I likely need only a subset.
If anyone has alternate (smaller) libraries for TFT screen driving and Invensense IMU sensing, I'd welcome a reference.

By definition LTO will strip out code that the linker determines is not used. Looking at https://docs.platformio.org/en/latest/platforms/teensy.html#optimization have you tried setting one of the build_flags that include _LTO
 
Oh my goodness, @thebigg !
-D TEENSY_OPT_SMALLEST_CODE - drops it to 45%
-D TEENSY_OPT_SMALLEST_CODE_LTO - drops it to 40%

I'm going to see if this runs well.

and thanks @blackketter, I'll check that as well.
 
Well, dang!

both of these:
-D TEENSY_OPT_SMALLEST_CODE
-D TEENSY_OPT_SMALLEST_CODE_LTO
cause a non-functional app.
I cannot see entrance to the setup() function
(i.e. Serial.print() does nothing after the usual Serial.begin(...);

I'll do some more digging.
 
No luck yet with optimizing parameters at compile/link time.
I know I have a chunk of code in the Adafruit libraries:
#include "Adafruit_ST7789.h"
#include "Adafruit_ST77xx.h"
These are meant to support a hoard of displays, and lots of functions.

I need plain text and simple shapes.
Small (1.4") SPI display only, no touch screen

Anyone aware of a small alternate library for this kind of display?
 
If you haven't used the 'pio home' interface, give it a look.

Thanks, I've just take another look. I did not see before how I could "Inspect" and the drill down in the explorer looking at contributions to flash.
I see it now, and will figure out where the fat is.
 
Back
Top