I have a ATmega328-PU chip which I have programmed with a bare minimum program which sets PB0 to output and then runs a function which sets the pin to HIGH. The problem is that the voltage output of the pin is at 10-20% of what it should be, identical to what it would be if the pin was set as input and the pull upp would be active. However if I set the function as static, it works as expected. I have tried this on 3 ATMega328-PU's with default fuse settings to minimize the things that could contribute to the problem.
I was hoping someone with better knowledge of avr-gcc could help me explain this behavior. My guess is that the instruction setting the pin to output is somehow never run so when setting the pin to HIGH it is actually in input mode and turns on the pull up resistor. But why? So, to get started. Here's the bare minimum program and makefile with information about the platform. I've included 3 different code examples of when the program behaves as expected. === // Bare minimum start (faulty behavior) === #include <avr/io.h> void turn_on_pb(void); int main(void) { DDRB |= (1 << PB0); turn_on_pb(); for (;;) { } return 0; } void turn_on_pb(void) { PORTB |= (1 << PB0); } --- --- Disassembly start --- --- 00000000 <turn_on_pb>: return 0; } void turn_on_pb(void) { PORTB |= (1 << PB0); 0: 28 9a sbi 0x05, 0 ; 5 } 2: 08 95 ret 00000004 <main>: void turn_on_pb(void); int main(void) { DDRB |= (1 << PB0); 4: 20 9a sbi 0x04, 0 ; 4 turn_on_pb(); 6: 0e 94 00 00 call 0 ; 0x0 <turn_on_pb> a: 00 c0 rjmp .+0 ; 0xc <main+0x8> --- --- Disassembly end --- --- === \\ Bare minimum end === Here's the code and disassembly of the function set to static which works as expected: === // Static bare minimum start (expected behavior) === #include <avr/io.h> static void turn_on_pb(void); int main(void) { DDRB |= (1 << PB0); turn_on_pb(); for (;;) { } return 0; } static void turn_on_pb(void) { PORTB |= (1 << PB0); } --- --- Disassembly start --- --- 00000000 <main>: static void turn_on_pb(void); int main(void) { DDRB |= (1 << PB0); 0: 20 9a sbi 0x04, 0 ; 4 return 0; } static void turn_on_pb(void) { PORTB |= (1 << PB0); 2: 28 9a sbi 0x05, 0 ; 5 4: 00 c0 rjmp .+0 ; 0x6 <__zero_reg__+0x5> --- --- Disassembly end --- --- === \\ Static bare minimum end === === // Bare minimum setting portb by hexadecimal begin (expected behaviour) === #include <avr/io.h> static void turn_on_pb(void); int main(void) { DDRB |= (1 << PB0); turn_on_pb(); for (;;) { } return 0; } static void turn_on_pb(void) { PORTB = 0xFF; } --- --- Disassembly start --- --- 00000000 <main>: static void turn_on_pb(void); int main(void) { DDRB |= (1 << PB0); 0: 20 9a sbi 0x04, 0 ; 4 return 0; } static void turn_on_pb(void) { PORTB = 0xFF; 2: 8f ef ldi r24, 0xFF ; 255 4: 85 b9 out 0x05, r24 ; 5 6: 00 c0 rjmp .+0 ; 0x8 <__zero_reg__+0x7> --- --- Disassembly end --- --- === \\ Bare minimum setting portb by hexadecimal end === === // Bare minimum setting portb in main begin (expected behaviour) === #include <avr/io.h> int main(void) { DDRB |= (1 << PB0); PORTB |= (1 << PB0); for (;;) { } return 0; } --- --- Disassembly start --- --- 00000000 <main>: #include <avr/io.h> int main(void) { DDRB |= (1 << PB0); 0: 20 9a sbi 0x04, 0 ; 4 PORTB |= (1 << PB0); 2: 28 9a sbi 0x05, 0 ; 5 4: 00 c0 rjmp .+0 ; 0x6 <__zero_reg__+0x5> --- --- Disassembly end --- --- === \\ Bare minimum setting portb in main end === The platform I use is OS X 10.7.3 with the following tools in the compilation and upload: - avr-gcc 4.5.1 - avr-objcopy 2.20.1.20100303 - avr-objdump 2.20.1.20100303 - avrdude 5.11.1 And here's my makefile: === // Make file begin === main: avr-gcc -g -Os -Wall -mmcu=atmega328 -c ../src/example.c elf: avr-gcc example.o -o example.elf hex: avr-objcopy -O ihex example.elf example.hex dump: avr-objdump -h -S example.o > example.lst upload: avrdude -p m328 -c avrispmkII -P usb -U flash:w:example.hex clean: rm -f *.o rm -f *.hex rm -f *.lst rm -f *.elf === \\ Make file end === And here's how I used the different commands to produce program, dump and upload program: make clean // remove old files make // compile make elf // run the linker make hex // turn in to hex to upload make dump // produce disassembly make upload // upload to the chip Thank you for taking time helping me _______________________________________________ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org https://lists.nongnu.org/mailman/listinfo/avr-gcc-list