Take the 2-minute tour ×
Electrical Engineering Stack Exchange is a question and answer site for electronics and electrical engineering professionals, students, and enthusiasts. It's 100% free, no registration required.

I discovered a bug in my code which only turns up if avr-gcc optimization is used.

Can somebody explain whats the problem here?

I'm aware that there are several smart ways to achieve some PWM, but that is not the point here.

Background Information

I play around with an LED and dimming it with PWM. To do some simple gamma correction I use a predefined array with the right values.

Code

This is the code I use, Main contains just the interrupt init and an empty while(1) loop:

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;
    }
}

A value of 1 gives a very bright light, a value of 1023 gives a very dimmed light. The value 1023 is accessible through the array index 63.

The Problem

It doesn't matter which value I set fade to, the LED is always bright, if I compile my code with avr-gcc -Os. By using avr-gcc -O0 the code works.

Changing to code doesn't work even by setting fade to 63 inside the interrupt:

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

This is what works:

  • Replacing pwmtable_10[fade] with 1023.
  • Replacing pwmtable_10[fade] with pwmtable_10[63]
  • Replacing fade with a new variable directly declared before the compare

Additional Info

Platform: Atmega 168

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

Commands to build and flash the code:

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
share|improve this question
1  
What happens when you make the pwmtable volatile? –  Tom L. May 1 at 12:53
    
Same problem :-/ –  echox May 1 at 12:54
    
What happens when you make fade volatile? (@TomL. is on the right track, wrong variable) –  Dave Tweed May 1 at 12:57
    
Looks like fade is already volatile –  Scott Seidman May 1 at 13:00
    
It is volatile (see first line of code sample :-)) –  echox May 1 at 13:01
show 3 more comments

1 Answer 1

up vote 3 down vote accepted

I believe problem is in PROGMEM attribute which saves const array into flash memory. To get values you need a memcpy_P() or so. For direct access try avoiding PROGMEM attribute. pwmtable_10[fade] gets random RAM value.

See http://www.nongnu.org/avr-libc/user-manual/pgmspace.html

share|improve this answer
    
Thanks you are right! This works now. I edited your answer and added a reference to the documentation. :-) –  echox May 1 at 13:23
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.