スケッチを本当に縮小する方法


9

テスト目的で、できるだけ小さいスケッチを作成したいと思います。問題は、BareMinimumスケッチを(空のセットアップとループを使用して)コンパイルすると、Unoに466バイト、Leonardoになんと4,242バイトを取得することです。余分な関数を持たない独自のコード(つまり、millis()およびのTimer0 delay())を作成する方法はありますか?また、Leonardoのキーボード/マウス機能を無効にできるようにしたいと思います。


4
これはレオではなくレオナルドとタグ付けしないでください(そして1つのボードに焦点を当てます)?これらは別の質問です。
asheeshr

空白のコンパイルされたスケッチが多くのボード、特にネイティブのUSBベースのボードにとって大きいことを指摘しています
TheDoctor

また、Leonardoのキーボード/マウス機能を無効にできるようにしたいと思います。2番目の質問です。
asheeshr

回答:


3

https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specificationに従って、カスタムboards.txtファイルを使用して独自のボード定義を作成できるはずです。私が見るように、レオナルドの定義にはいくつかのUSB機能があります。4Kのコンパイルのインクルードがプロセッサのタイプではなく、これらのフラグに基づいていることを願っています。

boards.txtがアップロードを使用する場所、Leonardoのブートローダーセクション、およびunoのビルド。

これは、コアライブラリビルドがプロセッサ固有のフラグを使用してUSB関数を含めないことを前提としています。

あなたがそのような働きをするなら。ポストバック、私は他の人がそのようなことに興味を持っていると確信しています。


私は最近、実際にUNOを使い果たしたため、ライブラリデモでこの4K使用制限に遭遇しました。

#if !defined(__AVR_ATmega32U4__)
...

レオナルドに合うように、スケッチの追加機能の大きなチャンクの周り。

この4Kは、LeoのUSBのCDCを介してSerial.printがまだ含まれているためであると(誤って)想定していました。しかし、私は空のスケッチのメモリダンプの後で、それらがまだそこにあるのを見ます。

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

それは理にかなっています。Leonardoは、リモート再起動をストロークするためにAVR-DUDEから1200ボー接続を検出するために、USB-CDCクライアント(4K)を必要とします。


したがって、ビルドでUSBなしでカスタムboards.txtを作成するには、

leonardo.upload.use_1200bps_touch=true

削除されました。

ターゲットにロードされたら、アップロードをターゲットの手動リセットと同期する必要があります。リモート再起動する機能が失われるので。


Serial.printが省略されている場合でも、4Kが引き続きコンパイルされる理由について更新されました。
mpflaga

3

私は最近、まさにこれをやりたかったのです。そうするための良い方法がないので、これを正確に行うためにStino sublime-text arduinoプラグイン用のパッチ作成しました。それはその後受け入れられたので、最新のStinoインストールに含まれるはずです。

これにより、Stinoに新しいオプションが追加されます。

ここに画像の説明を入力してください

このモードを使用すると、次のようなコンパイル結果が生成されます。

Unoの場合:

バイナリスケッチサイズ:172バイト(最大32256バイト、0.53パーセント)。
推定メモリ使用量:0バイト(最大1024バイトのうち、0.00%)。

レオナルドのために

バイナリスケッチサイズ:240バイト(最大28672バイトのうち、0.84%)。
推定メモリ使用量:0バイト(最大2560バイトのうち、0.00%)。

上記のコンパイルされた出力を使用して実際にレオナルドをプログラミングすること、自動リセット機能を破壊する可能性があるため、おそらく悪い考えです、必要に応じて可能です。mpflagaの回答でこれを指摘したことに対するヒント。

メモリレポートは実際には正しくありませんが、それは別の問題です。

上記に使用されるコードは次のとおりです。

int main()
{
    while (1)
    {

    }
}

いくつかのメモ:

  • あなたは、あなたが実際にはないことを、もはや「スケッチ」を書いていないスケッチを書きます。あなたはプログラムを書きます。限目。私はArduinoワッコが何を言いたいのか気にしません、彼らは条件を再定義することができません。
  • すべての割り込み管理は手動です。これは、まったくmilis()または類似しないことを意味します。
  • あなたは、することができますしたい場合は、まだ、などのArduinoシリアルライブラリを使用しています。あなたはする必要があり#include <Arduino.h>ます。
  • あなたが定義しますmain。から戻ることはありませんmain。あなたがセットアップのものを望むなら、それはの前に行きますwhile (1)

@jfpoilpretそれをIDEと呼びますか?マクロ付きのメモ帳に似ています...
Ron

@ Ron-E はそれをIDEとは呼びません。ArduinoIDEはその名前です。そのため、その名前に値しないとしても、その名前を使用しました。
jfpoilpret 14

2
@FakeName悪い言語はStack Exchangeサイトでは許可されていません(stackoverflow.com/help/behaviorを参照)。この場合は編集しましたが、今後はこのサイトでの虚辞の使用を控えてください。ありがとう。
Peter Bloomfield

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);
}

Arduino Unoで1,322バイト。それを少し縮小しましょう:

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
}

1,194バイト。これは約10%の減少です。

とにかく、それはスケッチを大きく縮小しませんが、制限を2バイト超えている場合や、機能を失うことなく最初からよりコンパクトなスケッチを作成したい場合は、これが最も簡単なルートになることがあります。すべての状況に対応できるわけではありませんが、役立つ場合もあります。


一般に、コードを関数にプルアウトすると、コンパイラーが面倒な作業を行い、残りを正しく実行します。
Cyber​​gibbons 2014年

@Cyber​​gibbons [これに慣れていないユーザーのために]定義できますか?
匿名ペンギン

3
コードを関数に分解しても効率が悪い場合は、通常、コンパイラーがインライン化します。ただし、コンパイラはコードを関数に分解することはありません。したがって、ほとんどの場合、より多くの関数を記述する方が適切です。
Cyber​​gibbons 2014年

1
さらに、コードを関数に入れると、読みやすく、理解しやすくなります

ダイレクトポートアクセスを使用すると、サイズが646バイトに減少します。avr-libcのみ(Arduinoコアなし)を使用すると、220バイトになります。
Edgar Bonet

0

@annonomusペンギン、できます。コードは1180バイトのフラッシュと13バイトのRAMにコンパイルされますが、コンピュータ上でunoを実現できますが、それを改善することができます。学習。

ステップ1:変動要件を減らす。LEDポートにintを使用するのは少々やり過ぎに思われますが、arduinoには65535のアドレス可能なIOポートがないのは確かです。後で#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バイトのRAMにコンパイルします。これにより、整数の代わりにバイトに必要な操作が少なくなるため、8バイトのフラッシュが節約されます。12バイトのRAMが必要ですが、大丈夫です。それほど多くはありませんが、保存されたすべてのバイトは良好です。

ステップ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バイトのフラッシュ+ 11バイトのRAMにコンパイルします。すでに38バイトが保存されています。これは、int値をフェッチするために必要なレジスタ操作が少ないためです。また、RAMから2バイトを節約しました。(バイトが1バイト少ないRAMにコンパイルされなかった理由はまだ疑問です...)

ステップ3:コードを最適化します。2つの遅延が発生します。スペースを節約するために1遅延に変更するかどうかは疑問ですが、LEDピンの値を把握し、トグル(反転)する必要があります。それは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バイトのRAMにコンパイルします。わーい!さらに8バイト。これにより、合計で46バイト、コードが2行少なくなります。

コードサイズを小さくするためのもう1つの一般的なヒント。Stringクラスは使用しないでください。それは巨大です、char配列、strcpy()、strcmp()を処理する方法を学びます。基本的な文字列操作がすべてある場合、Stringクラスの使用は、ほとんどの場合、フラッシュとRAMの両方のスペースを無駄にするだけです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.