Cómo realmente reducir un boceto

9

Quiero hacer un boceto que sea lo más pequeño posible, para fines de prueba. El problema es que cuando compilo el boceto BareMinimum (con una configuración y un bucle vacíos), obtengo 466 bytes para el Uno y 4.242 para Leonardo. ¿Hay alguna manera de escribir su propio código que no tenga funciones adicionales (es decir, Timer0 para millis()y delay())? También me gustaría poder desactivar las funciones de teclado / mouse para el Leonardo.

TheDoctor
fuente
44
¿No debería ser esto etiquetado leonardo y no uno (y centrarse en un tablero)? Estas son preguntas separadas.
asheeshr
Solo estoy señalando que un boceto compilado en blanco es grande para muchas placas, especialmente las nativas basadas en USB
TheDoctor
También me gustaría poder desactivar las funciones de teclado / mouse para el Leonardo. Es la segunda pregunta.
asheeshr

Respuestas:

3

Debería poder crear su propia definición de placa con un archivo boards.txt personalizado según https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification . Como veo, hay varias características usb en la definición de leonardo. Espero que la inclusión de compilaciones del 4K se base en estos indicadores y no en el tipo de procesador.

Donde boards.txt usaría la carga, las secciones del gestor de arranque del Leonardo y la compilación del uno.

Todo esto supone que la compilación de la biblioteca principal no utiliza indicadores específicos del procesador para incluir funciones USB.

Si te pones a trabajar. Publicar de nuevo, estoy seguro de que otros estarían interesados ​​en tal


Recientemente me encontré con esta limitación de 4K utilizada en una demostración de biblioteca que realmente maximizó la UNO y tuve que poner un

#if !defined(__AVR_ATmega32U4__)
...

alrededor de una gran cantidad de características adicionales en el boceto para encajar en el Leonardo.

Supuse (equivocado) que este 4K se debía a que todavía incluía Serial.print que cuando estaba sobre el CDC del USB en el Leo. Pero veo que después de un volcado de memoria de un boceto vacío todavía están allí.

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

Lo cual tiene sentido. Como el Leonardo todavía requiere el cliente USB-CDC (4K) para detectar la conexión de 1200 Baudios de AVR-DUDE y presionar el reinicio remoto.


Por lo tanto, hacer un tablero personalizado.txt sin USB en la compilación, también debe tener

leonardo.upload.use_1200bps_touch=true

remoto.

Una vez cargado en el objetivo, esto requeriría que la carga se sincronice con un reinicio manual del objetivo. Como la capacidad de reinicio remoto se pierde.

mpflaga
fuente
actualizado sobre por qué 4K todavía se compila, incluso si se omite Serial.print.
mpflaga
3

Hace poco quería hacer exactamente esto. Como no hay una buena manera de hacerlo, terminé escribiendo un parche para el complemento arduino de texto sublime Stino para hacer exactamente esto. Posteriormente se ha aceptado, por lo que debe estar en cualquier instalación actualizada de Stino.

Esto agrega una nueva opción a Stino:

ingrese la descripción de la imagen aquí

El uso de este modo produce resultados de compilación como los siguientes:

Para un uno:

Tamaño de boceto binario: 172 bytes (de un máximo de 32256 bytes, 0,53 por ciento).
Uso de memoria estimado: 0 bytes (de un máximo de 1024 bytes, 0.00 por ciento).

Por un leonardo

Tamaño de boceto binario: 240 bytes (de un máximo de 28672 bytes, 0,84 por ciento).
Uso de memoria estimado: 0 bytes (de un máximo de 2560 bytes, 0.00 por ciento).

En realidad, programar el leonardo con el resultado compilado anterior es probablemente una mala idea, ya que podría romper la funcionalidad de reinicio automático, pero podría hacerlo , si lo desea. Hat-tip a mpflaga por notar esto en su respuesta.

Tenga en cuenta que los informes de memoria son realmente incorrectos, pero ese es un problema separado .

El código utilizado para lo anterior es:

int main()
{
    while (1)
    {

    }
}

Algunas notas:

  • No está escribiendo un "bosquejo" nunca más, no es que alguna vez realmente qué escribir un boceto. Tú escribes programas . Período. No me importa lo que quieran decir los locos Arduino, no pueden redefinir los términos.
  • Toda la gestión de interrupciones es manual. Esto significa no milis()o similar.
  • Todavía puede usar las bibliotecas en serie de arduino, etc., si lo desea. Usted tiene que #include <Arduino.h>.
  • Usted define main. Nunca vuelves de main. Si quieres cosas de configuración, va antes que while (1).
Connor Wolf
fuente
@jfpoilpret ¿Llamas a eso un IDE? Más como un bloc de notas con macros ...
Ron
@ Ron-E No lo llamo un IDE, Arduino IDE es su nombre, así que simplemente usé su nombre, a pesar de que no vale ese nombre.
jfpoilpret
2
@FakeName No se permite lenguaje incorrecto en los sitios de Stack Exchange (consulte: stackoverflow.com/help/behavior ). Lo he editado en este caso, pero intente abstenerse de usar improperios en este sitio en el futuro. Gracias.
Peter Bloomfield
2

Aunque depende de su boceto, puede disminuir el tamaño reutilizando el código con métodos.

Toma este código:

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 bytes en Arduino Uno. Ahora reduzcamos un poco:

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 bytes. ¡Eso es una disminución del 10%!

De todos modos, aunque no reduce en gran medida un boceto, a veces puede ser la ruta más fácil cuando está dos bytes por encima del límite, o simplemente desea hacer un boceto más compacto para comenzar sin perder ninguna funcionalidad. No es para todas las situaciones, pero a veces me resulta útil.

Pingüino anónimo
fuente
En general, si extrae el código en las funciones, el compilador hará el trabajo duro y obtendrá el resto adecuado para usted.
Cybergibbons
@Cybergibbons ¿Puede definir eso [para usuarios que no están familiarizados con eso]?
Anonymous Penguin
3
Si divide el código en una función y no es eficiente, generalmente el compilador lo alineará por usted. Sin embargo, un compilador nunca dividirá el código en funciones. Por lo tanto, casi siempre es mejor escribir más funciones.
Cybergibbons
1
Además, poner el código en funciones hace que sea mucho más fácil de leer y comprender
Mediante el acceso directo al puerto, el tamaño se reduce a 646 bytes. Usando solo avr-libc (sin núcleo Arduino), se reduce a 220 bytes.
Edgar Bonet
0

@annonomus penguin, seguro que podemos Aunque el código se compila en 1180 bytes de flash + 13 bytes de RAM para uno en mi computadora, podemos mejorarlo :) así que aceptamos el desafío de golf y también algunos consejos útiles ya que estamos en el negocio de aprendizaje.

Paso 1: disminuir los requisitos variables. Usar un int para un puerto led parece un poco exagerado, ciertamente no tenemos 65535 puertos IO direccionables en el arduino :) Así que lo cambiamos a un byte solo por diversión. Lo cambiaremos a un #define más adelante, pero para mostrar el impacto de usar tipos de variables demasiado grandes.

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 en 1172 bytes + 13 bytes de RAM. Esto ahorra 8 bytes de flash debido a menos operaciones necesarias para el byte en lugar de un entero. Esperaría 12 bytes de ram, pero está bien. No tanto, pero cada byte guardado es bueno.

Paso 2: cambie la variable a define cuando tenga sentido. Por ejemplo, el byte dirigido no es necesario, el pin no se soldará.

#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 en 1142 bytes flash + 11 bytes ram. Ya se han guardado 38 bytes. Esto se debe a que se necesitan menos operaciones de registro para obtener el valor int. También guardamos 2 bytes de RAM. (Todavía me pregunto por qué el byte no se compiló en 1 byte menos de ram .....)

Paso 3: optimiza el código. Veo 2 retrasos. Me pregunto si lo cambio a 1 retraso, ahorraría espacio, pero tengo que calcular el valor del pin LED y alternarlo (invertirlo). Podemos hacer eso con digitalRead (), pero ¿ahorrará espacio?

#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 en 1134 bytes + 11 bytes de ram. ¡Hurra! otros 8 bytes Eso hace un total de 46 bytes y 2 líneas de código menos.

También otro consejo general sobre la disminución del tamaño del código. No uses la clase String. Es ENORME, aprende a lidiar con matrices de caracteres, strcpy (), strcmp (). Si todo lo que tiene son algunas operaciones básicas de cadena, el uso de la clase String es principalmente desperdiciar espacio en flash y RAM.

Patrick Deelman
fuente