Оптимизация размера программы

Я пытаюсь сэкономить несколько байт размера программы. Я столкнулся с проблемой, которую не могу понять, и надеюсь, что кто-нибудь мне поможет.

Взгляните на этот пустой скетч. Это занимает всего 444 байта:

void setup()
{
}

void loop()
{
}

Однако этот – уже 1332 байта!

void f() {
    Serial.println(1);
}


void setup()
{
}

void loop()
{
}

- Почему? Предполагается, что функция f() будет отключена на этапе связывания. Но это не так. И что я могу сделать, чтобы отрезать такие вещи, поскольку они не используются в коде?

, 👍1

Обсуждение

Проблема не в f(), а в том, что вы теперь используете объект Serial, который является массивным., @Majenko

@Majenko Можно ли как-то его оптимизировать?, @zhekaus

Не вставляйте код, который вам не нужен? Если вы хотите, чтобы необязательный код использовал #ifdef и т. Д., чтобы включить/исключить его, чтобы компилятор никогда его не видел., @Majenko

@Majenko, Как я знаю, неиспользуемый код должен быть оптимизирован во время связывания или около того., @zhekaus

Вы *можете* обнаружить, что создание f() static, как в static void f () { , даст компилятору достаточно информации, чтобы на ранней стадии распознать, что f не используется, и не позволит ему создавать зависимости для println, которые он позже должен будет работать, чтобы выяснить, может ли он устранить; это не особенно связано с Arduino., @timemage

Если вам не нравится большая "Последовательная" реализация, вы можете реализовать какой-нибудь голый металлический драйвер UART, например https://exploreembedded.com/wiki/Serial_UART_Interface_with_AVR..., @Maximilian Gerhardt


1 ответ


7

Использование последовательного объекта вытягивает HardwareSerial0.o в вашу программную компоновку. Этот файл определяет, среди прочего, ISR ( процедуры прерывания службы), связанные с последовательным портом. ISR определяются с помощью макроса ISR() из acr-libc. Этот макрос создает прототип функции и присваивает ей некоторые атрибуты, включая атрибут used, который говорит компоновщику, что он должен считать функцию используемой, даже если он не может обнаружить ни одного вызова этой функции в скомпилированной программе. ISR не может быть удален, и он, в свою очередь, сохраняет много кода из последовательной реализации.

Edit: Как указал busybee в комментарии, хотя f() не может быть удален во время ссылки, он может быть удален во время компиляции, если вы даете ему статический квалификатор. Это имеет дополнительное преимущество, вызывая предупреждение компилятора:

предупреждение: 'void f()' определен, но не используется [-Wunused-function]

,

Вы могли бы добавить, что отсутствующий static заставляет компилятор включать f() в первую очередь. Все остальное потом втягивается этим., @the busybee

@thebusybee: Верно, я отредактировал свой ответ., @Edgar Bonet