Как уменьшить размер скетча

В программировании микроконтроллеров размер программы имеет значение, спору нет. Наиболее радикальный способ уменьшения размеров скетчей -- это программировать микроконтроллер без использования библиотек Arduino в принципе, программируя чип посредством интерфейса внутрисхемного программирования ICSP (In-Curciut Serial Programming) или интерфейса IEEE 1149.1 JTAG.

Но чаще всего размер скетча можно довольно сильно уменьшить в размерах и при этом значительно повысить быстродействие программы, если просто учитывать тот факт, что микроконтроллеры AVR8 имеют 8-битный размер слова и следовательно для работы с 16-разрядными переменными типа int языка программирования C им требуется две команды на каждую операцию чтения или записи данных из регистра в ОЗУ.

Иначе говоря, для начала стоит попробовать оптимизировать сам скетч на предмет размера переменных. Если переменная хранит значения от 0 до 255, то разумнее использовать для неё тип unsigned char (uint8_t), нежели int или unsigned int (uint16_t).

Второй критичный момент, на который стоит обращать внимание -- это использование классов. Программировать микроконтроллер на языке программирования C++ довольно удобно, однако размер скетча при этом получается раза в 2 больше, чем при использовании глобальных переменных и процедурного программирования на языке C.

Чтобы использовать преимущества шаблонов (template) классов С++ в случае с компилятором AVRGCC (WinAVR) приходится в основном идти на разного рода ухищрения, чтобы получаемый в результате компиляции машинный код был сравним с кодом на языке C. В качестве успешного примера использования C++ для микроконтроллеров AVR могу привести исходный код библиотеки VE_AVR (см. статью Программирование таймеров-счётчиков Arduino).

Также категорически не стоит вызывать каких-либо функций из функций-обработчиков прерываний. Связано это ограничение с тем, что соглашение о вызовах "вызывающая функция сохраняет регистры", используемая компилятором AVRGCC (WinAVR), приводит в случае обработчиков прерываний к тому, что данная функция должна при этом сохранить все 32 регистра RISC-процессора AVR8, а это в сумме 64 дополнительных команды чтения-записи регистров при каждом вызове функции-обработчика, что явно избыточно.