Cara mengecilkan sketsa

9

Saya ingin membuat sketsa yang sekecil mungkin, untuk keperluan pengujian. Masalahnya adalah, ketika saya mengkompilasi sketsa BareMinimum (dengan setup dan loop kosong), saya mendapatkan 466 byte untuk Uno dan 4.242 kekalahan untuk Leonardo. Apakah ada cara untuk menulis kode Anda sendiri yang tidak memiliki fungsi tambahan (yaitu Timer0 untuk millis()dan delay()). Saya juga ingin dapat menonaktifkan fungsi keyboard / mouse untuk Leonardo.

Dokter
sumber
4
Bukankah ini harus ditandai leonardo dan bukan uno (dan fokus pada satu papan)? Ini adalah pertanyaan terpisah.
asheeshr
Saya hanya menunjukkan bahwa sketsa yang dikompilasi kosong besar untuk banyak papan, terutama yang berbasis USB asli
TheDoctor
Saya juga ingin dapat menonaktifkan fungsi keyboard / mouse untuk Leonardo. adalah pertanyaan kedua.
asheeshr

Jawaban:

3

Anda harus dapat membuat definisi papan Anda sendiri dengan file boards.txt khusus sesuai https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification . Seperti yang saya lihat ada beberapa fitur usb dalam definisi leonardo. Saya berharap bahwa kompilasi inklusi 4K didasarkan dari flag-flag ini dan bukan tipe prosesor.

Di mana boards.txt akan menggunakan bagian unggahan, bootloader dari Leonardo dan build dari uno.

Ini semua dengan asumsi pustaka inti tidak menggunakan flag spesifik prosesor untuk menyertakan fungsi USB.

Jika Anda mendapatkan pekerjaan seperti itu. posting kembali, saya yakin orang lain akan tertarik seperti itu.


Saya baru-baru ini mengalami keterbatasan 4K yang digunakan pada demo perpustakaan yang benar-benar memaksimalkan UNO dan harus memasukkan

#if !defined(__AVR_ATmega32U4__)
...

sekitar sejumlah besar fitur tambahan di sketsa agar sesuai pada Leonardo.

Saya telah berasumsi (salah) bahwa 4K ini adalah karena saya masih menyertakan Serial.print yang ketika melalui CDC USB pada Leo. Tapi saya melihat setelah memori dump dari sketsa kosong mereka masih ada di sana.

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

Itu masuk akal. Karena Leonardo masih memerlukan klien USB-CDC (4K) untuk mendeteksi sambungan 1200 Baud dari AVR-DUDE untuk menggerakkan reboot jarak jauh.


Karenanya membuat custom boards.txt tanpa USB di build, juga perlu dimiliki

leonardo.upload.use_1200bps_touch=true

dihapus.

Setelah dimuat pada target, ini akan membutuhkan unggahan untuk disinkronkan dengan reset manual target. Karena kemampuan untuk reboot jarak jauh hilang.

mpflaga
sumber
diperbarui mengapa 4K masih dikompilasi, bahkan jika Serial.print dihilangkan.
mpflaga
3

Saya baru-baru ini ingin melakukan ini. Karena tidak ada cara yang baik untuk melakukannya, saya akhirnya menulis sebuah tambalan untuk Stino luhur-teks Arduino plugin untuk melakukan hal ini. Ini kemudian diterima, jadi itu harus dalam pemasangan Stino terbaru.

Ini menambahkan opsi baru ke Stino:

masukkan deskripsi gambar di sini

Menggunakan mode ini menghasilkan hasil kompilasi seperti berikut:

Untuk Uno:

Ukuran sketsa biner: 172 byte (dari maksimum 32256 byte, 0,53 persen).
Penggunaan memori diperkirakan: 0 byte (dari maksimum 1024 byte, 0,00 persen).

Untuk seorang leonardo

Ukuran sketsa biner: 240 byte (dari maksimum 28672 byte, 0,84 persen).
Diperkirakan penggunaan memori: 0 byte (dari maksimum 2560 byte, 0,00 persen).

Sebenarnya pemrograman leonardo dengan output yang dikompilasi di atas mungkin merupakan ide yang buruk, karena mungkin merusak fungsi reset otomatis, tetapi Anda bisa , jika Anda mau. Hat-tip untuk mpflaga karena mencatat ini dalam jawabannya.

Perhatikan bahwa laporan memori sebenarnya salah, tapi itu masalah terpisah .

Kode yang digunakan untuk di atas adalah:

int main()
{
    while (1)
    {

    }
}

Beberapa catatan:

  • Anda tidak lagi menulis "Sketsa", bukan berarti Anda pernah benar - benar menulis sketsa. Anda menulis program . Titik. Saya tidak peduli apa yang ingin dikatakan oleh orang Arduino, mereka tidak bisa mendefinisikan ulang istilah.
  • Semua manajemen interupsi bersifat manual. Ini berarti tidak ada milis()atau serupa.
  • Anda masih dapat menggunakan pustaka arduino serial dan sebagainya, jika Anda mau. Anda harus melakukannya#include <Arduino.h> .
  • Anda mendefinisikan main. Anda tidak pernah kembali main. Jika Anda ingin mengatur barang, itu berjalan sebelum while (1).
Connor Wolf
sumber
@ jfpoilpret Anda menyebutnya IDE? Lebih mirip notepad dengan makro ...
Ron
@ Ron-E Saya tidak menyebutnya IDE, Arduino IDE adalah namanya, jadi saya hanya menggunakan namanya, meskipun itu tidak sebanding dengan nama itu.
jfpoilpret
2
@FakeName Bahasa buruk tidak diizinkan di situs Stack Exchange (lihat: stackoverflow.com/help/behavior ). Saya sudah mengeditnya dalam kasus ini, tapi tolong jangan menahan diri untuk menggunakan kata-kata kasar di situs ini di masa depan. Terima kasih.
Peter Bloomfield
2

Meskipun tergantung pada sketsa Anda, Anda dapat mengurangi ukurannya dengan menggunakan kembali kode dengan metode.

Ambil kode ini:

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

1.322 byte pada Arduino Uno. Sekarang mari kita mengecilkannya sedikit:

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 byte. Itu tentang penurunan 10%!

Bagaimanapun juga, meskipun sketsa itu tidak terlalu menyusut, kadang-kadang bisa menjadi rute termudah ketika Anda dua byte melebihi batas, atau hanya ingin membuat sketsa yang lebih ringkas untuk memulai tanpa kehilangan fungsionalitas apa pun. Ini tidak untuk setiap situasi, tetapi saya kadang-kadang merasa berguna.

Penguin Anonim
sumber
Secara umum, jika Anda menarik kode ke fungsi, kompiler akan melakukan kerja keras dan mendapatkan sisanya tepat untuk Anda.
Cybergibbons
@Cybergibbons Bisakah Anda mendefinisikannya [untuk pengguna yang tidak terbiasa dengan itu]?
Penguin Anonim
3
Jika Anda memecah kode menjadi suatu fungsi dan itu tidak efisien, umumnya kompiler akan in-line untuk Anda. Namun, kompiler tidak akan pernah memecah kode menjadi fungsi. Oleh karena itu, hampir selalu lebih baik untuk menulis lebih banyak fungsi.
Cybergibbons
1
Ditambah menempatkan kode ke dalam fungsi membuatnya lebih mudah untuk dibaca dan dipahami
Menggunakan akses port langsung, ukurannya dikurangi menjadi 646 byte. Hanya menggunakan avr-libc (tanpa inti Arduino), ia turun ke 220 byte.
Edgar Bonet
0

@annonomus penguin, pasti kita bisa. Walaupun kode mengkompilasi menjadi 1180 byte flash + 13 byte RAM untuk uno di komputer saya, kami dapat meningkatkannya :) jadi tantangan golf diterima dan juga beberapa tips bermanfaat karena kami berada dalam bisnis belajar.

Langkah 1: kurangi persyaratan variabel. Menggunakan int untuk port yang dipimpin tampaknya sedikit berlebihan, kita tentu saja tidak memiliki 65535 port IO yang dapat dialamatkan pada arduino :) Jadi kita mengubahnya ke byte hanya untuk bersenang-senang. Kami akan mengubahnya ke #define nanti, tetapi untuk menunjukkan dampak penggunaan tipe variabel yang terlalu besar.

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
}

Kompilasi menjadi 1172 byte + 13 byte RAM. Ini menghemat 8 byte flash karena operasi yang dibutuhkan lebih sedikit untuk byte daripada integer. Saya harapkan 12 byte ram, tapi oke. Tidak banyak, tetapi setiap byte yang disimpan baik.

Langkah 2: ubah variabel menjadi definisi ketika itu masuk akal. Misalnya, byte yang dipimpin tidak diperlukan, pin tidak akan lepas sendiri.

#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
}

Kompilasi menjadi 1142 byte byte + ram 11 byte. Sudah 38 byte disimpan. Ini karena lebih sedikit operasi register yang diperlukan untuk mengambil nilai int. Kami juga menyimpan 2 byte dari RAM. (masih bertanya-tanya mengapa byte tidak dikompilasi menjadi 1 byte kurang ram .....)

Langkah 3: optimalkan kode. Saya melihat 2 penundaan. Saya ingin tahu apakah saya mengubahnya ke 1 penundaan akan menghemat ruang, tetapi saya harus mencari tahu nilai pin LED dan beralih (invert) itu. Kita dapat melakukannya dengan digitalRead (), tetapi apakah itu akan menghemat ruang?

#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
}

Kompilasi menjadi 1134 bytes + 11 bytes ram. Yay! 8 byte lainnya. Itu membuat total 46 byte dan 2 baris kode lebih sedikit.

Juga tip umum lain untuk mengurangi kodeisasi. Jangan gunakan kelas String. Ini BESAR, pelajari cara berurusan dengan array char, strcpy (), strcmp (). Jika semua yang Anda miliki adalah beberapa operasi string dasar, penggunaan kelas String sebagian besar hanya membuang ruang pada flash dan RAM.

Patrick Deelman
sumber