I am working on one project that can hardly fit into 64k of microcontroller memory. And I thought it might be time to look at different compilers to choose which one can reduce the program size more aggressively.
I present to your attention a small comparison.
For the test, I made a project in Cube MX that includes USB_DEVICE and Mass Storage Class. These are pretty large libraries for testing.
The resulting main.c looks something like this:
int main()
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USB_DEVICE_Init();
}
Define USBD_DEBUG_LEVEL is set to 0 so that USB stack debug messages do not require printf
Included compilers:
- IAR EWARM 8.32.1
- arm-none-eab-gcc 7-2018-q2-update (STM32 Cube IDE 1.4.2)
- ARMCC v5.06 update 7 (Keil uVision 5.32 environment)
- ARMCC v6.14.1 (Keil uVision 5.32 environment)
IAR settings:
- Optimized for size
- Run-time library NORMAL
- No low level IO (printf disabled)
- Linker optimizations enabled: Inline small routines, merge duplicate sections
GCC settings:
- Reduced runtime library --specs = nano.specs
- Optimize for size -Os
- Place functions in their own sections --ffunction-sections
- Place data in their own sections --ffdata-sections
- Discard unused sections -Wl, --gc-sections
Armcc5 settings:
- Use micro lib
- Use cross module optimization
- Optimization -O3
- One ELF section per function --split_sections
Armcc6 settings:
- Use micro lib
- Optimization image size -Oz
- One ELF section per function --split_sections
Gcc | armcc5 | IAR | armcc6 | |
Firmware size | 14036 | 13548 | 12997 | 12984 |
UPD
IAR has a multi-file compilation option. If you turn it on, then IAR goes ahead by a significant margin. The firmware is reduced to 12,746 bytes.
As you can see, armcc6 is slightly better than IAR. It is followed by armcc5, 4% behind, and gcc is 8% behind the leader.
It should be noted that the KEIL option "Use cross module optimization" significantly increased the compilation time, but did not nearly reduce the code size.