¿Por qué el tamaño del flash depende del hardware de destino?

2

He estado escribiendo una aplicación para microcontroladores AVR. Tenía la intención de grabarlo en ATtiny13A (porque es barato, y de todas formas no usaría funciones complejas), pero en ese momento solo tenía ATmega328P disponible, así que lo usé para desarrollar el código. Sabiendo que el tamaño del flash de ATtiny13A es de solo 1kB, pasé bastante tiempo optimizando el código para el tamaño, haciéndolo 910B. Hoy, mi ATtiny13A ha llegado. Sin embargo, cuando recompilé el código para este hardware, el código tomó solo 772 B, ¡un 15% de diferencia! Si supiera esto antes, esperaría con esas optimizaciones. No uso ninguna función de biblioteca avanzada; los únicos archivos incluidos son: avr/io.h y util/delay.h . Por lo tanto, me pregunto qué causó la diferencia de tamaño: ¿eran esas suposiciones adicionales que el compilador podría usar para conocer la plataforma de destino? Si es así, ¿cuáles eran? ¿O tal vez los archivos incluidos en sí mismos contienen algún código repetitivo que varía entre las plataformas?

Nota: Estoy usando avr-gcc 4.8.1.

    
pregunta akrasuski1

3 respuestas

5

Observaciones de la comparación de desmontajes:

  1. Vectores de interrupción: aunque no uso interrupciones, los "talones" siguen ahí:

14: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt> .

ATmega328P tiene muchos más, y ATtiny usa instrucciones de 2 bytes rjmp allí.

  1. En un par de lugares, el código ATmega usa los códigos de operación call o jmp , mientras que ATtiny usa rcall o rjmp respectivamente. Por ejemplo:

8a: 0e 94 15 01 call 0x22a ; 0x22a <main> 8e: 0c 94 c0 01 jmp 0x380 ; 0x380 <_exit>

vs.

32: b5 d0 rcall .+362 ; 0x19e <main> 32: 60 c1 rjmp .+704 ; 0x2f6 <_exit>

Cada una de estas líneas guarda dos bytes.

  1. No tengo idea de por qué, pero el compilador a veces inserta instrucciones que son efectivas nop s:

b0: 00 c0 rjmp .+0 ; 0xb2 <ds18b20_reset+0x1c> b2: 00 00 nop

Las primeras instrucciones saltan a la siguiente (lo que ocurriría de todos modos, como incrementos de IP después de ejecutar cada instrucción), y la segunda es un nop literal. Esto sucede en el código ATmega, desperdiciando cuatro bytes cada vez.

  1. Hubo algunos compiladores de 'trucos' utilizados solo en ATtiny, por ejemplo, para desplazar r24 siete piezas restantes (x < < = 7;):

148: 20 e8 ldi r18, 0x80 14a: 82 9f mul r24, r18 14c: c0 01 movw r24, r0 14e: 11 24 eor r1, r1

vs.

d0: 87 95 ror r24 d2: 88 27 eor r24, r24 d4: 87 95 ror r24

No estoy seguro de si esto es exactamente equivalente, pero esto es lo que dijo el compilador.

En general, esos son desechos aproximados:

  1. Vectores de interrupción: en ATmega toman 0x68 bytes, en ATtiny 0x14. Diferencia = 84B, que es más de la mitad de la diferencia total.

  2. Número aproximado de jmp - > rjmp & call - > rcall cambia, sin contar los vectores de interrupción: 22, que multiplicado por dos bytes de guardado cada vez da 44B de guardados.

Las causas restantes son difíciles de contar debido a la falta de definición de la definición.

    
respondido por el akrasuski1
5

Porque son subarquitecturas diferentes (avr25 para el '13A, y avr5 para el' 328P) y tienen diferentes periféricos. Como tales, tienen conjuntos de instrucciones ligeramente diferentes y diferentes números de vectores de interrupción. Las interrupciones solas (10 frente a 26, 1 código de dirección frente a 2 por vector) dan como resultado una diferencia de 26 * 4-10 * 2 = 84 bytes.

La velocidad diferente entre los dispositivos también puede ser importante, ya que _delay_*() con un dispositivo más lento puede significar menos de 256/65536 bucles, mientras que un dispositivo más rápido necesitaría más de 256/65536 bucles. Esto puede significar una diferencia de 4 a 8 bytes cada vez se llama una de esas funciones.

    
respondido por el Ignacio Vazquez-Abrams
0

Técnicamente, es el tamaño compilado, no el tamaño "flash" al que se refiere. Estás en lo correcto. El compilador optimiza el código para la plataforma de destino a través del comando mmcu. Se ve en io.h y se dirige a la especificación ioxxxx.h para su chip. Por ejemplo, el número de puertos, etc. Es por eso que su código compilado varía de tamaño entre chips. Busque "avr io.h" en Google y debería obtener un enlace a los documentos donde se describe exactamente cómo funciona. Sólo fyi puede compilar para cualquier chip compatible. así que en el futuro puedes hacer tu desarrollo en uno y compilar el código para otro y, si tienes el estudio de atmel, simularlo para la depuración.

    
respondido por el BenG

Lea otras preguntas en las etiquetas