Estoy tratando de escribir un programa para ATTiny13. Mi problema es que tiene enormes restricciones de tamaño. Bueno, cuando hice mi primer programa Hello World, ¡se necesitaron 100 bytes de espacio de programa para hacer que una luz se encendiera y se apagara! ¿Hay alguna opción que pueda darle a avr-gcc para reducir este tamaño? Además, ¿qué hay en el crt0? No estoy muy interesado en el montaje de AVR, así que no lo entiendo mucho.
No quiero tener que dejar de ensamblar para este proyecto..
crt0 es la rutina de inicio para el uC. Las rutinas realizan la configuración de los registros y también la inicialización de los datos.
¿Los 100 bytes incluyen la tabla de vectores de interrupción? No estoy seguro sobre el ATtiny13 pero el ATtiny25/45/85 tiene 15 vectores de interrupción. Esto ocuparía 30 bytes.
gcc tiene una opción para vincular en su crt0. Puede tomar el archivo AVR crt0.S y modificarlo. No es muy largo por lo que no debería ser difícil de hacer.
/avr-libc-1.6.7/avr/lib/avr2/attiny13/crttn13.S
Puede usar avr-objdump -d .elf para ver lo que se genera:
Analicémoslo 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 insistiera y prometiera 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 un poco redundante. (podrías prometer que nunca volverás de main)
00000020 <__bad_interrupt>:
20: ef cf rjmp .-34 ; 0x0 <__vectors>
Procedimiento de interrupción predeterminado para aquellas interrupciones que no tienen una sobrescrita en C. (mismas reglas que para __vectores)
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>
Su proceso principal. Ajustado.
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 sea requerido por el estándar C y __stop_program es necesario para que funcione como debería.
¿Cuál es su 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 avr-libc C. Contiene cosas como el manejo de pilas para que pueda usar funciones con argumentos y valores devueltos.
100 bytes para la configuración de C incrustado no es tan malo y tiene un tamaño constante. Duplicar las líneas de la lógica del programa no necesariamente lo hará de 200 bytes. ¿A qué nivel de optimización estás 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 que se muestra a continuación ocupa 62 bytes en un ATtiny13 con "-Os" en el avr-gcc 4.3.3. de CrossPack-AVR:
#incluye <avr/io.h> #incluir <avr/retraso.h> int principal (vacío) { DDRB |= _BV( PB3 ); mientras ( 1 ) { PUERTOB |= _BV( PB3 ); _retraso_ms(200); PUERTOB &=~ _BV(PB3); _retraso_ms(200); } }
Eliminar las llamadas _delay_ms() lo convierte en 46 bytes.
Un ejemplo más grande en el ATtiny13 son mis prototipos Smart LED . Este código contiene un PWM de software de 3 canales, una conversión de color de HSV a RGB, una máquina de estado y lee dos botones. No está particularmente bien escrito y tiene un tamaño de 864 bytes. Bajo avr-gcc 3.x era aún más pequeño. (por alguna razón, avr-gcc 4 ha hecho que casi todos los programas crezcan unos pocos bytes)
avr-gcc -std=c99 -Wall -Os -mmcu=attiny13 -o hello.out helloworld.c
es la línea relevante en mi archivo MAKE (autocreado). y uso un código casi idéntico excepto para voltear el LED que uso PORTB &= ~(1 << LED);
y talSi tiene poco espacio, pruebe 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 es suficiente para ATTiny y probablemente una mejor optimización que gcc
Los dispositivos como ese 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.
johan
condez