Как действительно уменьшить эскиз

9

Я хочу сделать эскиз как можно меньшего размера для целей тестирования. Проблема в том, что когда я компилирую эскиз BareMinimum (с пустой установкой и циклом), я получаю 466 байт для Uno и колоссальные 4242 для Leonardo. Есть ли способ написать свой собственный код, который не имеет дополнительных функций (а именно, Timer0 для millis()и delay()). Я также хотел бы иметь возможность отключить функции клавиатуры / мыши для Leonardo.

Доктор
источник
4
Разве это не должно быть помечено Леонардо, а не Уно (и сосредоточиться на одной доске)? Это отдельные вопросы.
asheeshr
Я просто указываю на то, что пустой скомпилированный эскиз является большим для многих плат, особенно для плат на базе USB
TheDoctor
Я также хотел бы иметь возможность отключить функции клавиатуры / мыши для Leonardo. это второй вопрос.
asheeshr

Ответы:

3

Вы должны быть в состоянии создать свое собственное определение доски с помощью специального файлаboards.txt в соответствии с https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification . Как я вижу, в определении Леонардо есть несколько особенностей usb. Я надеюсь, что включение в компиляцию 4K основано на этих флагах, а не на типе процессора.

Где board.txt будет использовать загрузку, разделы загрузчика от Leonardo и сборки от Uno.

Все это при условии, что сборка базовой библиотеки не использует специфичные для процессора флаги для включения функций USB.

Если вы получаете такие рабочие. отпишитесь, я уверен, что другие будут заинтересованы в таком.


Я недавно столкнулся с этим 4K использованным ограничением на демонстрационной версии библиотеки, которая фактически превысила UNO и должна была вставить

#if !defined(__AVR_ATmega32U4__)
...

вокруг большого куска дополнительных функций в эскизе, чтобы поместиться на Леонардо.

Я предположил (неправильно), что этот 4K был, потому что я все еще включал Serial.print, который, когда через CDC USB на Leo. Но я вижу после сброса памяти пустого эскиза они все еще там.

C:\Users\mflaga\AppData\Local\Temp\build8958339595868119500.tmp>avr-objdump -d sketch_feb13a.cpp.elf > sketch_feb13a.cpp.elf.lst

Что имеет смысл. Поскольку Леонардо все еще требуется клиент USB-CDC (4K), чтобы обнаружить 1200 бод-соединение от AVR-DUDE, чтобы запустить удаленную перезагрузку.


Следовательно, создание собственного board.txt без USB в сборке также должно иметь

leonardo.upload.use_1200bps_touch=true

удален.

После загрузки на цель это потребует синхронизации загрузки с ручным сбросом цели. По мере возможности удаленная перезагрузка теряется.

mpflaga
источник
обновлено объяснение того, почему 4K все еще компилируется, даже если Serial.print опущен.
mpflaga
3

Я недавно хотел сделать именно это. Так как нет хорошего способа сделать это, я решил написать патч для плагина Stino Sublime -Text Arduino, чтобы сделать именно это. Впоследствии он был принят, поэтому он должен быть в любой современной установке Stino.

Это добавляет новую опцию в Stino:

введите описание изображения здесь

Использование этого режима приводит к результатам компиляции, подобным следующему:

Для Уно:

Размер двоичного эскиза: 172 байта (из 32256 байтов максимум, 0,53 процента).
Предполагаемое использование памяти: 0 байтов (максимум 1024 байта, 0,00 процента).

Для леонардо

Размер двоичного эскиза: 240 байт (из 28672 байт максимум, 0,84 процента).
Предполагаемое использование памяти: 0 байт (максимум 2560 байт, 0,00 процента).

На самом деле программирование leonardo с вышеупомянутым скомпилированным выводом, вероятно, плохая идея, так как это может нарушить функцию автоматического сброса, но вы можете , если хотите. Хет-кончик mpflaga за то, что отметил это в своем ответе.

Обратите внимание, что отчеты о памяти на самом деле неверны, но это отдельная проблема .

Код, используемый для вышеупомянутого:

int main()
{
    while (1)
    {

    }
}

Некоторые заметки:

  • Вы не пишете «эскиз» больше, не то, что вы когда - нибудь на самом деле сделать написать эскиз. Вы пишете программы . Период. Мне все равно, что хотят сказать ардуино, они не могут переопределить условия.
  • Все управление прерываниями осуществляется вручную. Это означает, что нет milis()или подобное.
  • Вы все еще можете использовать последовательные библиотеки Arduino и так далее, если хотите. Вы должны #include <Arduino.h>.
  • Вы определяете main. Вы никогда не вернетесь из main. Если вы хотите что-то настроить, он идет до while (1).
Коннор Вольф
источник
@jfpoilpret Вы называете это IDE? Больше похоже на блокнот с макросами ...
Рон
@ Ron-E Я не называю это IDE, Arduino IDE - это его имя, поэтому я просто использовал его, хотя оно того не стоит.
jfpoilpret
2
@FakeName Плохой язык не разрешен на сайтах Stack Exchange (см .: stackoverflow.com/help/behavior ). Я отредактировал это в этом случае, но, пожалуйста, постарайтесь в будущем воздерживаться от использования ругательств на этом сайте. Спасибо.
Питер Блумфилд
2

Хотя это зависит от вашего эскиза, вы можете несколько уменьшить размер, повторно используя код с методами.

Возьми этот код:

int led = 13;
int val;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  val = digitalRead(10);
}

1322 байта на Arduino Uno. Теперь давайте немного его уменьшим:

int led = 13;
int val;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  for(uint8_t i = 0; i < 8; i++) {
    blink(HIGH);
    blink(LOW);
  }    
  val = digitalRead(10);
}

void blink(uint8_t state) {
  digitalWrite(led, state);   // turn the LED to the right state
  delay(1000);                // wait for a second
}

1194 байта. Это примерно на 10% меньше!

В любом случае, хотя это не сильно сокращает эскиз, иногда это может быть самый простой маршрут, когда вы превышаете ограничение на два байта, или просто хотите сделать более компактный эскиз для начала без потери функциональности. Это не для каждой ситуации, но иногда я нахожу это полезным.

Анонимный пингвин
источник
Как правило, если вы извлекаете код в функции, компилятор выполнит тяжелую работу и сделает все остальное именно для вас.
Cybergibbons
@Cybergibbons Вы можете определить это [для пользователей, которые не знакомы с этим]?
Анонимный Пингвин
3
Если вы разбиваете код на функцию, и она неэффективна, обычно компилятор встроит ее для вас. Однако компилятор никогда не разбивает код на функции. Поэтому почти всегда лучше писать больше функций.
Cybergibbons
1
Кроме того, использование кода в функциях значительно облегчает чтение и понимание
При использовании прямого доступа к порту размер уменьшается до 646 байт. Используя только avr-libc (без ядра Arduino), он уменьшается до 220 байт.
Эдгар Бонет
0

@annonomus penguin, конечно, мы можем Хотя код компилируется во флэш-память 1180 байт + 13 байт оперативной памяти для uno на моем компьютере, мы можем улучшить его :), поэтому мы приняли вызов для игры в гольф, а также несколько полезных советов, поскольку мы находимся в бизнесе обучение.

Шаг 1: уменьшить переменные требования. Использование int для светодиодного порта кажется излишним, у нас, конечно, нет 65535 адресуемых портов ввода-вывода на Arduino :). Поэтому мы изменим его на байт просто для удовольствия. Позже мы изменим его на #define, чтобы показать влияние использования слишком больших типов переменных.

byte led = 13;
int val;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  blink();
  val = digitalRead(10);
}

void blink() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

Компилируется в 1172 байта + 13 байтов ОЗУ. Это экономит 8 байт флэш-памяти благодаря меньшему количеству необходимых операций для байта вместо целого числа. Я ожидал бы 12 байтов оперативной памяти, но хорошо. Не так много, но каждый сохраненный байт - это хорошо.

Шаг 2: измените переменную на определяет, когда это имеет смысл. Например, светодиодный байт не нужен, вывод не распаяется.

#define LED 13
int val;

void setup() {                
  pinMode(LED, OUTPUT);     
}

void loop() {
  blink();
  val = digitalRead(10);
}

void blink() {
  digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

Компилируется в 1142 байта flash + 11 байтов оперативной памяти. Уже 38 байтов сохранено. Это связано с меньшим количеством операций регистра, необходимых для получения значения int. Также мы сохранили 2 байта из оперативной памяти. (все еще удивляюсь, почему байт не скомпилирован в 1 байт оперативной памяти .....)

Шаг 3: оптимизировать код. Я вижу 2 задержки. Интересно, если бы я изменил его на 1 задержку, это бы сэкономило место, но я должен выяснить значение светодиода и переключить (инвертировать) его. Мы можем сделать это с помощью digitalRead (), но сэкономит ли это место?

#define LED 13
int val;
void setup() {                
  pinMode(LED, OUTPUT);     
}
void loop() {
  blink();
  val = digitalRead(10);
}
void blink() {
  digitalWrite(LED, !digitalRead(LED));   // toggle the led based on read value
  delay(1000);               // wait for a second and spare yourself the other delay
}

Компилируется в 1134 байта + 11 байтов оперативной памяти. Ура! еще 8 байтов. Это составляет в общей сложности 46 байтов и на 2 строки кода меньше.

Также еще один общий совет по уменьшению размера кода. Не используйте класс String. Это ОГРОМНО, узнайте, как обращаться с массивами символов, strcpy (), strcmp (). Если все, что у вас есть, это некоторые базовые строковые операции, то использование класса String в основном просто тратит пространство как на флэш-память, так и на RAM.

Патрик Дилман
источник