Usando una variable como índice de matriz - ¿Error de optimización?

3

Descubrí un error en mi código que solo se activa si se utiliza la optimización avr-gcc.

¿Alguien puede explicar cuál es el problema aquí?

Soy consciente de que hay varias formas inteligentes de lograr algunos PWM, pero ese no es el punto aquí.

Información de fondo

Juego con un LED y lo atenúo con PWM. Para hacer una corrección gamma simple, utilizo una matriz predefinida con los valores correctos.

Código

Este es el código que uso, Main contiene solo el inicio de interrupción y un bucle while (1) vacío:

volatile size_t fade;
volatile uint16_t counter = 0;

const uint16_t PROGMEM pwmtable_10[64] = {
    0, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10,
    11, 12, 13, 15, 17, 19, 21, 23, 26, 29, 32, 36, 40, 44, 49, 55,
    61, 68, 76, 85, 94, 105, 117, 131, 146, 162, 181, 202, 225, 250,
    279, 311, 346, 386, 430, 479, 534, 595, 663, 739, 824, 918, 1023
};

ISR(TIMER0_OVF_vect) {
 // fade is set in the main loop or somewhere else
    if(counter < pwmtable_10[fade]) {
        counter=counter+1;
        PORTB = 0;
    } else {
        counter=0;
        PORTB |= RED;
    }
}

Un valor de 1 da una luz muy brillante, un valor de 1023 da una luz muy tenue. El valor 1023 es accesible a través del índice de matriz 63.

El problema

No importa a qué valor establezca fade, el LED siempre está brillante, si compilo mi código con avr-gcc -Os . Al utilizar avr-gcc -O0 , el código funciona.

El cambio de código no funciona incluso al configurar fade a 63 dentro de la interrupción:

ISR(TIMER0_OVF_vect) {
    fade=63;
    if(counter < pwmtable_10[fade]) {
    //[..]

Esto es lo que funciona:

  • Reemplazando pwmtable_10[fade] con 1023.
  • Reemplazando pwmtable_10[fade] con pwmtable_10[63]
  • Reemplazando fade con una nueva variable declarada directamente antes de la comparación

Información adicional

Plataforma: Atmega 168

% avr-gcc --version
avr-gcc (GCC) 4.8.2

Comandos para construir y flashear el código:

avr-gcc -Wall -Wextra -Os -mmcu=atmega168 -DF_CPU=16000000 -o moody.elf moody.c
avr-objcopy -j .text -j .data -O ihex moody.elf moody.hex
avrdude -b4 -c usbasp -v -p m168 -P usb -U flash:w:moody.hex
    
pregunta echox

1 respuesta

3

Creo que el problema está en el atributo PROGMEM que guarda la matriz constante en la memoria flash. Para obtener valores necesitas un memcpy_P () o algo así. Para acceso directo intente evitando el atributo PROGMEM. pwmtable_10 [fade] obtiene un valor RAM aleatorio.

Consulte enlace

    
respondido por el TMa

Lea otras preguntas en las etiquetas