Estoy desarrollando software para attiny88 con la cadena de herramientas avr-gcc. Este es un microcontrolador barato con memoria de programa de 8kB, 512B SRAM y 64B de memoria no volátil de datos EEPROM. Todo esto es suficiente para la tarea que se supone que debe manejar. No tengo un depurador para este chip.
El dispositivo actúa como esclavo SPI y le permite al maestro leer / programar la EEPROM y leer el estado del dispositivo (estado de algunas entradas analógicas y salidas digitales). El protocolo es simple: el primer databyte transporta la instrucción donde los dos bits más altos codifican la acción requerida (00-nada, 01-escritura eeprom, 10-lectura eeprom, 11-lectura estado) y el resto es dirección. El segundo byte siempre es cero, el tercer byte es el valor para leer o escribir, el cuarto byte siempre es cero.
El problema es que estoy obteniendo un comportamiento extraño del compilador. Es difícil señalar lo que está pasando, así que daré algunos ejemplos. Lo más sorprendente es que sin la optimización de -Os el dispositivo no responde a través de SPI. Esto no es por ninguna de las razones obvias: el programa se adapta a la memoria y la pila no debe ejecutarse en las secciones .bss / .data (el programa tiene ~ 700B, SRAM se asigna entre 0x100 y 0x2ff, donde .bss_end está en 0x109; el montón está vacío; no hay llamadas de función anidadas, ni interrupciones anidadas).
Si activo la optimización de -Os, el programa responde según lo previsto. Aquí está el código de trabajo para manejar el ISR:
unsigned char state[8];
volatile unsigned char data;
ISR(SPI_STC_vect)
{
switch(data>>6) {
case 0:
data = SPDR;
break;
case 1: /* write eeprom */
while(EECR & (1<<EEPE));
EECR = (0<<EEPM1)|(0<<EEPM0);
EEARL = 0;
EEDR = SPDR;
EECR |= (1<<EEMPE);
EECR |= (1<<EEPE);
data = 0;
break;
case 2: /* read eeprom */
EEARL = data & 0x1f; /* with 0x3f stops working (???) */
EECR |= (1<<EERE);
SPDR = EEDR;
data = 0;
break;
case 3: /* read state */
SPDR = state[data&7];
data = 0;
break;
}
}
Sin embargo, el programa se rompe cuando se escribe de forma semánticamente diferente:
-
Si cambio la línea "EEARL = data & 0x1f;" a "EEARL = data & 0x3f;", que es deseable ya que permitiría abordar todo el espacio de direcciones de EEPROM, la escritura / lectura de ERPROM deja de funcionar (no necesito 64B completo, por lo que lo dejé como está)
-
La lectura del estado (caso 3) se interrumpe si reemplazo la línea "SPDR = estado [datos & 7];" con construcción de conmutación de caso que devuelve el valor del registro PORTD / PORTB cuando la dirección es 0 y 1 respectivamente (la solución actual es mantener el estado [0] y el estado [1] sincronizados con PORTB / PORTD en el bucle principal).
¿Me estoy perdiendo algo importante? Me parece que el compilador se desordena, pero no he encontrado ningún informe de errores para avr-gcc o avr-libc (¿newlib?) Que se ajuste a la factura.
La cadena de herramientas se instaló desde el paquete gcc-avr actual en los repositorios de aptitude. El makefile es bastante básico:
all: main.hex main.s
main.elf: main.o
avr-gcc -g -mmcu=attiny88 -o main.elf main.o
main.s: main.elf
avr-objdump -d main.elf > main.s
main.hex: main.elf
avr-objcopy -O ihex main.elf main.hex
main.o: main.c
avr-gcc -mmcu=attiny88 -Os -c main.c -Wall
ACTUALIZACIÓN : Sigue con el mismo resultado con los últimos binutils, gcc y avr-libc (compilados de fuentes)