3
\$\begingroup\$

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
asked May 1, 2014 at 12:48
\$\endgroup\$
8
  • 1
    \$\begingroup\$ What happens when you make the pwmtable volatile? \$\endgroup\$ Commented May 1, 2014 at 12:53
  • \$\begingroup\$ Same problem :-/ \$\endgroup\$ Commented May 1, 2014 at 12:54
  • \$\begingroup\$ What happens when you make fade volatile? (@TomL. is on the right track, wrong variable) \$\endgroup\$ Commented May 1, 2014 at 12:57
  • \$\begingroup\$ Looks like fade is already volatile \$\endgroup\$ Commented May 1, 2014 at 13:00
  • \$\begingroup\$ It is volatile (see first line of code sample :-)) \$\endgroup\$ Commented May 1, 2014 at 13:01

1 Answer 1

3
\$\begingroup\$

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

echox
2371 gold badge2 silver badges7 bronze badges
answered May 1, 2014 at 13:17
\$\endgroup\$
1
  • \$\begingroup\$ Thanks you are right! This works now. I edited your answer and added a reference to the documentation. :-) \$\endgroup\$ Commented May 1, 2014 at 13:23

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.