Я работаю над одним проектом, который с большим трудом вмещается в 64к памяти микроконтроллера. И подумалось мне, что возможно, пора взглянуть на разные компиляторы, чтобы выбрать какой более агрессивно может уменьшить размер программы.
Представляю вашему вниманию небольшое сравнение.
Для теста я сделал проект в Cube MX, который включает в себя USB_DEVICE и Mass Storage Class. Это довольно большие библиотеки для теста.
Получившийся main.c выглядит примерно так:
int main()
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USB_DEVICE_Init();
}
Дефайн USBD_DEBUG_LEVEL установлен в 0, чтобы отладочные сообщения USB стека не требовали наличия printf
Подопытные компиляторы:
- IAR EWARM 8.32.1
- arm-none-eab-gcc 7-2018-q2-update 7.3.1 (среда STM32 Cube IDE 1.4.2)
- ARMCC v5.06 update 7 (среда Keil uVision 5.32)
- ARMCC v6.14.1 (среда Keil uVision 5.32)
Настройки IAR:
- Оптимизация по размеру
- Run-time библиотека NORMAL
- Без low level IO (отключен printf)
- Включены оптимизации линкера: Inline small routines, merge duplicate sections
Настройки GCC:
- 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:
- Use micro lib
- Use cross module optimization
- Optimization -O3
- One ELF section per function --split_sections
Настройки armcc6:
- Use micro lib
- Optimization image size -Oz
- One ELF section per function --split_sections
GCC | armcc5 | IAR | armcc6 | |
Размер прошивки | 14036 | 13548 | 12997 | 12984 |
Надо отметить, что опция KEIL «Use cross module optimization» Значительно увеличила время компиляции, но ни чуть не уменьшила размер кода.
UPD1
В IAR есть опция multi-file compilation. Если ее включить, то IAR уходит вперед со значительным отрывом. Прошивка уменьшается до 12746 байт.
UPD2
Добавление опций -fsection-anchors и -fno-move-loop-invariants в gcc уменьшило прошивку еще на 12 байт.
UPD3
Спасибо Shturman-0 за подсказку как правильно использовать флаг "-flto".
Итак, -flto ставится и линкеру и компилятору.
В startup_xxx.s надо удалить все weak объявления используемых прерываний
В данном случае
// .weak USB_LP_CAN1_RX0_IRQHandler
// .thumb_set USB_LP_CAN1_RX0_IRQHandler,Default_Handler
// .weak SysTick_Handler
// .thumb_set SysTick_Handler,Default_Handler
В результате размер прошивки составил 11772 байта (для gcc 7). Gcc 9.3.1 дает 12148
GCC (-flto) | armcc5 | IAR | armcc6 | |
Размер прошивки | 11772 | 13548 | 12746 | 12984 |
И gcc обходит ближайшего соперника на 10%
gleb_l
Ух какая ностальгическая заглавная картинка у поста! Статикой пробило 8-битные воспоминания молодости. Сейчас такие конденсаторы и ПЗУ с золочеными ногами безжалостно идут под нож аффинажников.
K1804
Легендарные КМ с палладием и платиной.
sim2q
но справедливости ради — крохи остались