ATTiny13 - avr-gcc ¿Hello World usa más de 100 bytes?

9

Estoy tratando de escribir un programa para el ATTiny13. Mi problema es que tiene enormes limitaciones de tamaño. Bueno, al hacer mi primer programa Hello World, ¡se necesitaron 100 bytes de espacio de programa solo para encenderlo y apagarlo! ¿Hay alguna opción que pueda darle a avr-gcc para reducir este tamaño? Además, ¿qué hay en el crt0? No estoy demasiado interesado en el ensamblaje de AVR, por lo que no lo entiendo mucho ...

No quiero tener que ir a ensamblar para este proyecto ...

    
pregunta Earlz

5 respuestas

9

crt0 es la rutina de inicio para la unidad de usuario. Las rutinas realizan la configuración de los registros. y también la inicialización de datos.

¿Los 100 bytes incluyen la tabla de vectores de interrupción? No estoy seguro de la ATtiny13 pero el ATtiny25 / 45/85 tiene 15 vectores de interrupción. Esto tomaría 30 bytes.

gcc tiene una opción para enlazar en tu crt0. Podrías tomar el archivo AVR crt0.S y modificarlo. eso. No es muy largo, por lo que no debería ser difícil de hacer.

    
respondido por el jluciani
19

Puede usar avr-objdump -d .elf para ver qué se está generando:

Vamos a analizarlo un poco:

[jpc@jpc ~] avr-objdump -d avr.elf | sed -e 's/^/    /' | pbcopy

avr.elf:     file format elf32-avr

Disassembly of section .text:

00000000 <__vectors>:
   0:   09 c0           rjmp    .+18        ; 0x14 <__ctors_end>
   2:   0e c0           rjmp    .+28        ; 0x20 <__bad_interrupt>
   4:   0d c0           rjmp    .+26        ; 0x20 <__bad_interrupt>
   6:   0c c0           rjmp    .+24        ; 0x20 <__bad_interrupt>
   8:   0b c0           rjmp    .+22        ; 0x20 <__bad_interrupt>
   a:   0a c0           rjmp    .+20        ; 0x20 <__bad_interrupt>
   c:   09 c0           rjmp    .+18        ; 0x20 <__bad_interrupt>
   e:   08 c0           rjmp    .+16        ; 0x20 <__bad_interrupt>
  10:   07 c0           rjmp    .+14        ; 0x20 <__bad_interrupt>
  12:   06 c0           rjmp    .+12        ; 0x20 <__bad_interrupt>

Tabla de vectores de interrupción de 20 bytes (al menos algunas de las entradas podrían omitirse si usted insistió y prometió que nunca habilitaría las interrupciones correspondientes).

00000014 <__ctors_end>:
  14:   11 24           eor r1, r1
  16:   1f be           out 0x3f, r1    ; 63
  18:   cf e9           ldi r28, 0x9F   ; 159
  1a:   cd bf           out 0x3d, r28   ; 61
  1c:   02 d0           rcall   .+4         ; 0x22 <main>
  1e:   05 c0           rjmp    .+10        ; 0x2a <_exit>

Borra SREG (no estoy seguro de que esto sea realmente necesario), escribe 0x9f (RAMEND) en SPL (el puntero de pila) y salta a main. El último rjmp es algo redundante. (Podrías prometer no volver nunca de la página principal)

00000020 <__bad_interrupt>:
  20:   ef cf           rjmp    .-34        ; 0x0 <__vectors>

Procedimiento de interrupción predeterminado para esas interrupciones que no se ha sobrescrito en C. (las mismas reglas que para __vectors)

00000022 <main>:
  22:   bb 9a           sbi 0x17, 3 ; 23
  24:   c3 9a           sbi 0x18, 3 ; 24
  26:   c3 98           cbi 0x18, 3 ; 24
  28:   fd cf           rjmp    .-6         ; 0x24 <main+0x2>

Tu procedimiento principal. Apretado.

0000002a <_exit>:
  2a:   f8 94           cli

0000002c <__stop_program>:
  2c:   ff cf           rjmp    .-2         ; 0x2c <__stop_program>

Estos dos no son muy útiles. _exit probablemente es requerido por el estándar C y __stop_program es necesario para que funcione como debería.

    
respondido por el jpc
16

¿Cuál es tu eventual aplicación? Un ATtiny13 tiene 1kB de flash y puede hacer mucho con eso en C. El crt0 es el tiempo de ejecución de avr-libc C. Contiene cosas como el manejo de la pila para que pueda usar funciones con argumentos y valores de retorno.

100 bytes para la configuración de C incrustada no es tan malo, y es de tamaño constante. Duplicar las líneas de la lógica del programa no necesariamente lo hace 200 bytes. ¿En qué nivel de optimización está compilando? Deberías estar en "-Os". ¿Y cómo estás compilando esto? Los Makefiles en los proyectos de demostración disponibles en el sitio avr-libc son bastante buenos y completos.

El sencillo programa de encendido / apagado de LED a continuación toma 62 bytes en un ATtiny13 con "-Os" en el avr-gcc 4.3.3. de CrossPack-AVR:

#include <avr/io.h>
#include <avr/delay.h>

int main(void)
{
    DDRB |= _BV( PB3 );
    while( 1 ) { 
        PORTB |=  _BV( PB3 );
        _delay_ms(200);
        PORTB &=~ _BV( PB3 );
        _delay_ms(200);
    }
}

Eliminar las llamadas _delay_ms () hace que sean 46 bytes.

Un ejemplo más amplio en el ATtiny13 son mis prototipos LED inteligentes . Este código contiene un software PWM de 3 canales, una conversión de color de HSV a RGB, una máquina de estados y lee dos botones. No está escrito particularmente bien y llega a 864 bytes. Bajo avr-gcc 3.x era incluso más pequeño. (por alguna razón, avr-gcc 4 ha hecho que casi todos los programas crezcan unos pocos bytes)

    
respondido por el todbot
2

Si no tienes mucho espacio, prueba el banco de trabajo integrado de IAR: su versión gratuita 'kickstart' tiene un límite de tamaño de código de palabra de 4K, por lo que hay mucho para ATTiny, y probablemente una mejor optimización que gcc

    
respondido por el mikeselectricstuff
1

Los dispositivos de este tipo a menudo se programan en ensamblador, lo que da como resultado ejecutables más pequeños. Vale la pena hacer el esfuerzo y aprender a usarlo.

    
respondido por el Leon Heller

Lea otras preguntas en las etiquetas