Когда я собираю этот эскиз для Юн:
int led = 7;
void setup() {
pinMode(led, OUTPUT);
}
void loop() {
digitalWrite(led, HIGH);
}
Я получил:
Sketch использует 5,098 байт (17%) памяти для хранения программ.
Максимум составляет 28 672 байта. Глобальные переменные используют 153 байта (5%) динамической памяти, оставляя 2,407 байтов для локальных переменных. Максимум - 2560 байт.
Даже когда я компилирую эскиз BareMinimum:
void setup() {
// setup
}
void loop() {
// loop
}
Я получил:
Sketch использует 4548 байт (15%) памяти для хранения программ.
Максимум составляет 28 672 байта. Глобальные переменные используют 151 байт (5%) динамической памяти, оставляя 2,409 байт для локальных переменных. Максимум - 2560 байт.
Почему простой минимальный эскиз занимает 15% выделенного пространства для хранения программы? И почему очень простой эскиз занимает 17% памяти программы? По данным сайта Arduino :
Это легко использовать, имея в своей программе множество строк. Например, объявление типа:
char message[] = "I support the Cape Wind project.";
помещает 33 байта в SRAM (каждый символ занимает байт плюс терминатор '\ 0').
Тем не менее, ни в одном из этих эскизов не объявлено ни одной строки.
Кажется, что они могут импортировать или использовать другие библиотеки / классы, которые я не определяю. Может быть, он импортирует системную библиотеку по умолчанию? Или что-то еще?
источник
У вас уже есть несколько очень хороших ответов. Я публикую это только для того, чтобы поделиться статистикой, которую я однажды сделал, и я задал себе те же вопросы: что занимает так много места на минимальном наброске? Какой минимум необходим для достижения той же функциональности?
Ниже приведены три версии минимальной мигающей программы, которая переключает светодиод на контакт 13 каждую секунду. Все три версии были скомпилированы для Uno (без USB), используя avr-gcc 4.8.2, avr-libc 1.8.0 и arduino-core 1.0.5 (я не использую Arduino IDE).
Во-первых, стандартным способом Arduino:
Это составляет 1018 байт. Используя
avr-nm
и разборку , я разбил этот размер на отдельные функции. От самого большого до самого маленького:В приведенном выше списке первый столбец представляет собой размер в байтах, а второй столбец указывает, поступает ли код из базовой библиотеки Arduino (A, всего 822 байта), среды выполнения C (C, 148 байтов) или пользователя (U 48 байт).
Как видно из этого списка, самой большой функцией является подпрограмма, обслуживающая прерывание переполнения таймера 0. Эта процедура отвечает за отслеживание времени и необходима
millis()
,micros()
иdelay()
. Вторая по величине функцияinit()
, которая устанавливает аппаратные таймеры для ШИМ, включает прерывание TIMER0_OVF и отключает USART (который использовался загрузчиком). И эта, и предыдущая функция определены в<Arduino directory>/hardware/arduino/cores/arduino/wiring.c
.Следующая версия C + avr-libc:
Разбивка отдельных размеров:
Это 132 байта для среды выполнения C и 26 байтов пользовательского кода, включая встроенную функцию
_delay_ms()
.Следует отметить, что, поскольку эта программа не использует прерывания, таблица векторов прерываний не нужна, и на ее место может быть помещен обычный пользовательский код. Следующая версия сборки делает именно это:
Он собран (с
avr-gcc -nostdlib
) только в 14 байтов, большинство из которых используются для задержки переключения так, чтобы мигание было видимым. Если вы удалите этот цикл задержки, вы получите 6-байтовую программу, которая мигает слишком быстро, чтобы ее можно было увидеть (с частотой 2 МГц):источник
Я написал пост о том, почему для мигания одного светодиода требуется 1000 байт? ,
Краткий ответ: «Не нужно 2000 байтов, чтобы мигать два светодиода!»
Более длинный ответ заключается в том, что стандартные библиотеки Arduino (которые вам не нужны, если вы не хотите их использовать) имеют некоторые приятные функциональные возможности, упрощающие вашу жизнь. Например, вы можете адресовать контакты по номеру во время выполнения, где библиотека преобразует (скажем) контакт 8 в правильный порт и правильный битовый номер. Если вы жестко запрограммировали доступ к порту, вы можете сохранить эти издержки.
Даже если вы их не используете, стандартные библиотеки включают в себя код для подсчета «тиков», чтобы вы могли узнать текущее «время» (вызывая
millis()
). Для этого он должен добавить издержки некоторых подпрограмм обработки прерываний.Если вы упростите (на Arduino Uno) этот эскиз, вы уменьшите использование памяти программы до 178 байт (в IDE 1.0.6):
Хорошо, 178 байтов не так много, и из этого первые 104 байта являются векторами аппаратного прерывания (4 байта каждый, для 26 векторов).
Возможно, для мигания светодиода требуется всего 74 байта. И из этих 74 байтов большинство - это код, сгенерированный компилятором для инициализации глобальной памяти. Если вы добавите достаточно кода, чтобы мигать два светодиода:
Затем размер кода увеличивается до 186 байт. Поэтому вы можете утверждать, что
186 - 178 = 8
для мигания светодиода нужны только байты.Итак, 8 байт для мигания светодиода. Звучит довольно эффективно для меня.
Если вы испытываете желание попробовать это дома, я должен отметить, что хотя приведенный выше код мигает двумя светодиодами, он действительно работает очень быстро. На самом деле они мигают с частотой 2 МГц - см. Скриншот. Канал 1 (желтый) - это контакт 12, канал 2 (голубой) - это контакт 13.
Как видите, выходные выводы имеют прямоугольную форму с частотой 2 МГц. Вывод 13 изменяет состояние 62,5 нс (один такт) перед выводом 12 из-за порядка переключения выводов в коде.
Поэтому, если у вас нет намного лучших глаз, чем у меня, вы на самом деле не увидите никакого эффекта моргания.
В качестве забавного дополнения вы можете на самом деле переключать два контакта в том же объеме программного пространства, что и переключение одного контакта.
Это составляет 178 байтов.
Это дает вам более высокую частоту:
Теперь мы до 2,66 МГц.
источник
init()
(как этоmain()
делает нормальный ), файл wiring.c (которыйinit
в нем есть) не был связан. В результате обработка для обработчиков прерываний (formillis()
иmicros()
т. Д.) Была исключена. Вероятно, не особенно практично пропускать это, если вам никогда не нужно рассчитывать время, но факт в том, что эскиз увеличивается в размере в зависимости от того, что вы в него положили. Например, если вы используете Serial, то и программная память, и оперативная память получают удар.