Come ridurre davvero uno schizzo


9

Voglio fare uno schizzo il più piccolo possibile, a scopo di test. Il problema è che quando compilo lo schizzo BareMinimum (con un'impostazione e un loop vuoti), ottengo 466 byte per Uno e un enorme 4.242 per Leonardo. Esiste un modo per scrivere il proprio codice che non ha funzioni extra (vale a dire Timer0 per millis()e delay()). Vorrei anche poter disabilitare le funzioni tastiera / mouse per Leonardo.


4
Questo non dovrebbe essere etichettato leonardo e non uno (e concentrarsi su una scheda)? Queste sono domande separate.
asheeshr,

Sto solo sottolineando che uno schizzo compilato vuoto è grande per molte schede, in particolare quelle basate su USB native
TheDoctor

Vorrei anche poter disabilitare le funzioni tastiera / mouse per Leonardo. è la seconda domanda.
asheeshr,

Risposte:


3

Dovresti essere in grado di creare la tua definizione di board con un file boards.txt personalizzato come da https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification . Come vedo ci sono diverse funzionalità USB nella definizione di leonardo. Spero che l'inclusione delle compilazioni del 4K sia basata su questi flag e non sul tipo di processore.

Dove boards.txt userebbe le sezioni upload, bootloader di Leonardo e build da uno.

Tutto questo presuppone che la build della libreria principale non utilizzi flag specifici del processore per includere le funzioni USB.

Se riesci a farlo. post back, sono sicuro che altri sarebbero interessati a questo.


Di recente mi sono imbattuto in questa limitazione utilizzata da 4K in una demo della libreria che in realtà ha raggiunto il limite massimo dell'ONU e ha dovuto inserire un

#if !defined(__AVR_ATmega32U4__)
...

attorno a una grande porzione di funzioni extra nello schizzo per adattarsi al Leonardo.

Avevo supposto (errato) che questo 4K fosse perché includevo ancora Serial.print che quando si trovava sopra il CDC della USB sul Leo. Ma vedo che dopo un deposito di memoria di uno schizzo vuoto sono ancora lì.

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

Questo ha senso. Poiché Leonardo richiede ancora il client USB-CDC (il 4K) per rilevare la connessione 1200 Baud da AVR-DUDE per eseguire il riavvio remoto.


Quindi è necessario creare un boards.txt personalizzato senza USB nella build

leonardo.upload.use_1200bps_touch=true

rimosso.

Una volta caricato sulla destinazione, ciò richiederebbe la sincronizzazione del caricamento con un ripristino manuale della destinazione. Poiché la possibilità di riavvio remoto viene persa.


aggiornato sul motivo per cui 4K è ancora compilato, anche se Serial.print è omesso.
mpflaga,

3

Di recente ho voluto fare esattamente questo. Dato che non esiste un modo carino per farlo, ho finito per scrivere una patch per il plug-in Arduino con testo sublime di Stino per fare esattamente questo. Successivamente è stato accettato, quindi dovrebbe essere presente in tutte le installazioni Stino aggiornate.

Questo aggiunge una nuova opzione a Stino:

inserisci qui la descrizione dell'immagine

L'uso di questa modalità produce risultati di compilazione come i seguenti:

Per uno:

Dimensione dello schizzo binario: 172 byte (di un massimo di 32256 byte, 0,53 percento).
Utilizzo stimato della memoria: 0 byte (massimo 1024 byte, 0,00 percento).

Per un leonardo

Dimensione dello schizzo binario: 240 byte (di un massimo di 28672 byte, 0,84 percento).
Utilizzo stimato della memoria: 0 byte (massimo 2560 byte, 0,00 percento).

In realtà la programmazione Leonardo con l'uscita sopra compilato è probabilmente una cattiva idea, in quanto potrebbe interrompere la funzionalità auto-reset, ma si potrebbe , se si voleva. Punta di cappello a mpflaga per averlo notato nella sua risposta.

Si noti che i rapporti sulla memoria non sono corretti, ma si tratta di un problema separato .

Il codice utilizzato per quanto sopra è:

int main()
{
    while (1)
    {

    }
}

Alcune note:

  • Non sta scrivendo un "Schizzo" più, non che mai in realtà non scrive uno schizzo. Scrivi programmi . Periodo. Non mi importa cosa vogliono dire i pazzi di Arduino, non riescono a ridefinire i termini.
  • Tutta la gestione degli interrupt è manuale. Questo significa no milis()o simili.
  • È possibile comunque utilizzare le librerie seriale Arduino e così via, se si vuole. Devi #include <Arduino.h>.
  • Tu definisci main. Non torni mai da main. Se vuoi cose di installazione, va prima di while (1).

@jfpoilpret Lo chiami IDE? Più come un blocco note con macro ...
Ron,

@ Ron-E io non lo chiamo un IDE, Arduino IDE è il suo nome, così ho solo usato il suo nome, anche se non vale la pena di quel nome.
jfpoilpret,

2
@FakeName Non è consentita la lingua errata sui siti Stack Exchange (consultare: stackoverflow.com/help/behavior ). L'ho modificato in questo caso, ma per favore prova ad astenermi dall'utilizzare le imprecazioni su questo sito in futuro. Grazie.
Peter Bloomfield,

2

Anche se dipende dal tuo schizzo, puoi in qualche modo ridurre le dimensioni riutilizzando il codice con i metodi.

Prendi questo codice:

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 su Arduino Uno. Ora restringiamolo un po ':

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. È una riduzione di circa il 10%!

In ogni caso, sebbene non riduca notevolmente uno schizzo, a volte può essere il percorso più semplice quando si superano i due byte oltre il limite o si desidera semplicemente creare uno schizzo più compatto per iniziare senza perdere alcuna funzionalità. Non è per ogni situazione, ma lo trovo utile a volte.


Generalmente, se estrai il codice in funzioni, il compilatore farà il duro lavoro e farà il resto giusto per te.
Cybergibbons,

@Cybergibbons Puoi definirlo [per utenti che non lo conoscono]?
Anonimo Penguin

3
Se si suddivide il codice in una funzione e non è efficiente, in genere il compilatore lo inserirà per te. Tuttavia, un compilatore non suddividerà mai il codice in funzioni. Pertanto, è quasi sempre meglio scrivere più funzioni.
Cybergibbons

1
Inoltre, mettere il codice in funzioni rende molto più facile da leggere e comprendere

Utilizzando l'accesso diretto alla porta, la dimensione viene ridotta a 646 byte. Utilizzando solo avr-libc (nessun core Arduino), scende a 220 byte.
Edgar Bonet,

0

@annonomus penguin, certo che possiamo Sebbene il codice si compili in 1180 byte flash + 13 byte RAM per uno sul mio computer, possiamo migliorarlo :) quindi la sfida del golf è accettata e anche alcuni consigli utili dato che siamo nel business di apprendimento.

Passaggio 1: ridurre i requisiti variabili. L'uso di un int per una porta led sembra un po 'eccessivo, certamente non abbiamo 65535 porte IO indirizzabili sull'arduino :) Quindi lo cambiamo in un byte solo per divertirci. Lo cambieremo in un #define in seguito, ma per mostrare l'impatto dell'uso di tipi di variabili troppo grandi.

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
}

Compila in 1172 byte + 13 byte RAM. Ciò consente di risparmiare 8 byte di flash a causa di un minor numero di operazioni necessarie per il byte anziché un numero intero. Mi aspetterei 12 byte di RAM, ma va bene. Non molto, ma ogni byte salvato è buono.

Passaggio 2: passare alla variabile in definisce quando ha senso. Ad esempio, il byte led non è necessario, il pin non si dissalderà da solo.

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

Compila in 1142 byte flash + 11 byte RAM. Già 38 byte salvati. Ciò è dovuto al minor numero di operazioni di registro necessarie per recuperare il valore int. Inoltre abbiamo salvato 2 byte dalla RAM. (mi chiedo ancora perché il byte non sia stato compilato in 1 byte in meno di ram .....)

Passaggio 3: ottimizza il codice. Vedo 2 ritardi. Mi chiedo se lo cambio a 1 ritardo risparmierebbe spazio, ma devo capire il valore del pin LED e attivarlo (invertirlo). Possiamo farlo con digitalRead (), ma risparmierà spazio?

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

Compila in 1134 byte + 11 byte ram. Sìì! altri 8 byte. Ciò significa un totale di 46 byte e 2 righe di codice in meno.

Anche un altro consiglio generale sulla riduzione della dimensione del codice. Non usare la classe String. È ENORME, impara a gestire gli array di caratteri, strcpy (), strcmp (). Se tutto ciò che hai sono alcune operazioni di base sulle stringhe, l'uso della classe String consiste principalmente nello sprecare spazio sia su flash che su RAM.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.