How to get a little bit more FLASH room on Teensy 3.x

Status
Not open for further replies.

xxxajk

Well-known member
Here is the compile results of the Blink example using the Arduino IDE with teensyduino installed:
Code:
   text    data     bss     dec     hex filename
  12776    1460    1992   16228    3f64 /tmp/build9046952037514765870.tmp/Blink.cpp.elf

Can we do better? Yes we can!

Code:
   text    data     bss     dec     hex filename
   5568     164    1444    7176    1c08 build/Blink.elf

How is this possible? It all has to do with updating one set of tools, and linking things properly.
Basically there are a whole bunch of variables, unused routines, and even unused code sections linked into your program, even though the linker is told to throw them out, because they were explicitly contained in the object files linked. Hopefully Paul will fix this in the future... ;)

1: You will need to recompile your tools and install them over the top of your install. You can get it here: https://github.com/xxxajk/ARM-Toolchain

2: install this where you have your sketches (see the readme) https://github.com/xxxajk/Arduino_Makefile_master

3: Use create a Makefile containing the following, and change BOARD to teensy3 if you are using that.:
Code:
BOARD = teensy31

# set your Arduino tty port here
PORT = /dev/ttyACM0

# And finally, the part that brings everything together for you.
include ../Arduino_Makefile_master/_Makefile.master

then type make and you can see the results for your self.

Note: This has been tested on Linux, will be tested on MacOS fairly soon, and should work on Windows if you got Cygwin installed.
 
Mac (10.9) has a few occurences of 'head' utility called with incompatible parameters (easily fixable) but then on my machine I get a segfault from arm-none-eabi-objdump and arm-none-eabi-c++filt (among last commands issued). Will spend some time on it.
 
A 40% reduction in code size. But the app blinky.cpp is tiny though dragging a big train of code with it. Such is modern computing.
What would the reduction be for a project with, say, 50KB of application code, rather than tiny blinky.cpp plus all the fixed overhead of the large quantity of dead and n/a code?

I guess some of this is the Arduino philosophy - no library management to help the linker omit n/a code.
 
Last edited:
Mac (10.9) has a few occurences of 'head' utility called with incompatible parameters (easily fixable) but then on my machine I get a segfault from arm-none-eabi-objdump and arm-none-eabi-c++filt (among last commands issued). Will spend some time on it.

Did you recompile your binutils?
 
Doesn't the linker automatically check to see if the .o is needed by looking at symbols/functions referenced?

Not if it is explicitly told to link in a .o file. Searches are done on AR files, which are libraries, not on .o files.

The whole reason to list a file to explicitly link, is that you want the something from that to end up in the binary, because you expect to be referencing something from it, or to it.

Example:
The .o file contains, a bitmap of a picture, and a routine that does something with that information, or has a pointer to it.
If you were to include it as a .o, and never reference it from your program, you will find that it is in your binary, because something referenced it.
It doesn't see that you don't actually USE it. This is not a bug, it is a feature. How else would start up code, or main end up in the program?

Now, if this is in an AR file...
Since it isn't asked for to begin with, the picture and code or pointer won't end up in your program code because there is no reference to begin with.
That is why we use libraries.

To recap:
Object files include code and data almost always. There are a few exceptions, but there is no need to go into those details.
Libraries only include the minimum required pieces of code and data needed for your program. If you don't ask for something, it won't appear in your program.
 
Doesn't the linker automatically check to see if the .o is needed by looking at symbols/functions referenced?
Not for .o files by default. It does do this for static archives (.a files).

Even if the linker did this, you would still get extra code if you have multiple functions in a single object file, and only a few functions are used.

If you compile code with -ffunctions-sections and -fdata-sections, and then pass --gc-sections to the linker (usually via the option -Wl,--gc-sections when using the GCC driver), then the compiler will compile each function and global data to a different ELF section, and the linker will delete sections that have no references in the final output.
 
Not for .o files by default. It does do this for static archives (.a files).

Even if the linker did this, you would still get extra code if you have multiple functions in a single object file, and only a few functions are used.

If you compile code with -ffunctions-sections and -fdata-sections, and then pass --gc-sections to the linker (usually via the option -Wl,--gc-sections when using the GCC driver), then the compiler will compile each function and global data to a different ELF section, and the linker will delete sections that have no references in the final output.

Yes, however there are a few cases within the teensy3 core code where stuff that isn't used is still actually referenced.
The idea is to just not reference them in the first place, and let ld do the right thing.

Edit:
Example, Blink does not reference Serial, but this will end up in the program if you tell the IDE you want to be a serial device.
Using an AR archive, Serial, and the buffers for it will not end up in the final output.
 
Last edited:
Did you recompile your binutils?

No actually, I just downloaded gcc-arm-embedded (to check on nanospecs and code reduction) from launchpad. I haven't spent much time on it so I can't remember if I used the toolchain from teensyduino. Will give it another go this weekend.
 
No, the problem is that Paul has all the .o files linking in explicitly, instead of ld looking for what it actually needs.
This results in alot of unused variables and code linking in.

Yeah. Early on, sometime in August 2012, I was having trouble getting the core.a stuff to work, so I just switched to linking all the .o files to "solve" the problem. It's remained that way ever since.

I really ought to update this in 1.19 or 1.20....
 
Paul: All you have to do is consider the mk20dx128.o file as a crt.o...
This is the only one to link explicitly from core, and make sure it is first in the list, and it won't matter if you redundantly include it in the AR.
Considering it can reduce flash size, and reduces RAM usage, I think this should be before anything new, besides, the fix is very simple.
 
Paul: One other note about doing things this way... It eliminates problems with overriding functions.
The usual AR linking goes like this: Functions get picked from user code, then the libraries, and finally core-- you list the ARs in that order.
This is how the normal build system works, and it makes sense... It allows user code to trump everything, and 'libraries' to trump anything in the core.
IMHO it is one of the few things the Arduino people got right.
 
No actually, I just downloaded gcc-arm-embedded (to check on nanospecs and code reduction) from launchpad. I haven't spent much time on it so I can't remember if I used the toolchain from teensyduino. Will give it another go this weekend.

Ok following up I get the segfault with the toolchain installed by Teensyduino, gcc-arm-embedded doesn't have arm_cortexM4l_math.a

Need to spend some time on it but no time until tomorrow.
 
I know java... Mind if I help?

Just grab the Arduino IDE 1.0.5 source code, and replace the .java files with the copies in the "src" folder the installer creates in your copy of Arduino. Edit the java code and rebuild the IDE. Copy PDE.JAR from the freshly compiled IDE into the copy with Teensyduino installed and restart.
 
Took a quick look at the code... and, I think I can do this using the prefrences file (boards.txt) directly. :) Details soon.
 
Okay, the IDE does a few stupid things, formatting is total hell to look at, but I got a fix. It is all of 4 lines of code, and 2 edits to boards.
Have to fetch, build IDE and it should work out just fine.
:cool:
 
First, get boards.txt from the above post, and decompress this file View attachment pde.zip

Next make a backup of pde.jar and boards.txt, just in case things don't work out for you.
Then copy the new pde.jar and boards.txt where they belong.

On my system these files are located at
/opt/Arduino/lib
and
/opt/Arduino/hardware/teensy

Not knowing where your install is, or what operating system you use, that is the best instructions I can give you,
If this is too much for you then wait for Paul to make a test installer for you.
 
Status
Not open for further replies.
Back
Top