Avr-gcc no se compila correctamente sin optimizaciones, pero funciona (mal) con -Os

2

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)

    
pregunta student

1 respuesta

7

Deberá inspeccionar la salida de avr-objdump para ver qué instrucciones exactas se generaron para su código. Por cierto, sería útil incluir su código C en el desmontaje a través de avr-objdump -S main.elf > main.s . Dudo que todo el programa se vuelva diferente cuando reemplace la constante 0x1F por 0x3F , aislar las diferencias en la lista y analizarlas cuidadosamente sería su próximo paso.

Tal análisis es lo más lejos que se puede lograr sin las herramientas de desarrollo adecuadas. Obtener un depurador o un simulador le ahorraría mucho esfuerzo, lo que se requiere cuando está limitado al análisis de listas estáticas.

PS: Supongo que aquí no recibes ninguna advertencia del compilador durante la compilación. Si tiene alguno, corregirlos debe ser su primera prioridad. Los compiladores modernos hacen un buen trabajo al informarle sobre errores sutiles que pueden ser difíciles de encontrar de otra manera.

    
respondido por el Dmitry Grigoryev

Lea otras preguntas en las etiquetas