I noticed the first PROGMEM in lss file gets marked as __trampolines_end opcodes, and the lss interprets the PROGMEM data as actual instructions in the disassembly, just the avr-objdump seems to label it as such, even though it is actually a string in PROGMEM or whatever...
tried on atmega168, attiny24, tinyavr1 series, all same result. I went back to some really old windows lss code from avr studio 4, and it was the same, seems like it has always been this way.
There is nothing wrong with actual code, it seems avr-objdump just does not identify the first PROGMEM as data, instead interprets it as opcodes.
everything I have tested ( the linux toolchain 3.5.4.1709 and 3.6.2.1759 and old windows avr studio 4 lss files ) all seem to do it...
I am using command... avr-objdump -h -S main.elf > main_test.lss
for example I see this...
00000022 <__trampolines_end>:
22: 54 68 ori r21, 0x84 ; 132
24: 69 73 andi r22, 0x39 ; 57
26: 20 69 ori r18, 0x90 ; 144
28: 73 20 and r7, r3
2a: 64 61 ori r22, 0x14 ; 20
2c: 74 61 ori r23, 0x14 ; 20
2e: 20 32 cpi r18, 0x20 ; 32
...
I expect to see this instead...
00000031 <test_bytes2>:
31: 54 68 69 73 20 69 73 20 64 61 74 61 20 31 00 This is data 2.
I am posting to see if anyone else has come across this before, and if you have, did you find a way to have the avr-objdump correctly interpret the first PROGMEM in the disassembly?
c code example (you should be able to paste this into avr studio in windows without any issues)
//includes #include <inttypes.h> #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include <avr/pgmspace.h> #include <stdlib.h> #include <string.h> #define TEST_DATA1 "This is data 1" #define TEST_DATA2 "This is data 2" //one of these below will be labeled as __trampolines_end in lss static const uint8_t test_bytes1[] PROGMEM __attribute__((used)) = { TEST_DATA1 }; static const uint8_t test_bytes2[] PROGMEM __attribute__((used)) = { TEST_DATA2 }; void main(void) __attribute__((noreturn)); void main(void) { const uint8_t* ptr = test_bytes1; uint8_t i=0; while( i < sizeof(test_bytes1) ) { uint8_t c = pgm_read_byte(ptr++); PORTB = c; } ptr = test_bytes2; i=0; while( i < sizeof(test_bytes2) ) { uint8_t c = pgm_read_byte(ptr++); PORTB = c; } while(1); }
lss output
main.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn 0 .text 0000005e 00000000 00000000 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .data 00000000 00800060 00800060 000000b2 2**0 CONTENTS, ALLOC, LOAD, DATA 2 .comment 00000030 00000000 00000000 000000b2 2**0 CONTENTS, READONLY 3 .note.gnu.avr.deviceinfo 0000003c 00000000 00000000 000000e4 2**2 CONTENTS, READONLY 4 .debug_aranges 00000020 00000000 00000000 00000120 2**0 CONTENTS, READONLY, DEBUGGING 5 .debug_info 0000053b 00000000 00000000 00000140 2**0 CONTENTS, READONLY, DEBUGGING 6 .debug_abbrev 000004ae 00000000 00000000 0000067b 2**0 CONTENTS, READONLY, DEBUGGING 7 .debug_line 000001d5 00000000 00000000 00000b29 2**0 CONTENTS, READONLY, DEBUGGING 8 .debug_frame 00000024 00000000 00000000 00000d00 2**2 CONTENTS, READONLY, DEBUGGING 9 .debug_str 000002ab 00000000 00000000 00000d24 2**0 CONTENTS, READONLY, DEBUGGING 10 .debug_loc 0000005a 00000000 00000000 00000fcf 2**0 CONTENTS, READONLY, DEBUGGING 11 .debug_ranges 00000010 00000000 00000000 00001029 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00000000 <__vectors>: 0: 1f c0 rjmp .+62 ; 0x40 <__ctors_end> 2: 24 c0 rjmp .+72 ; 0x4c <__bad_interrupt> 4: 23 c0 rjmp .+70 ; 0x4c <__bad_interrupt> 6: 22 c0 rjmp .+68 ; 0x4c <__bad_interrupt> 8: 21 c0 rjmp .+66 ; 0x4c <__bad_interrupt> a: 20 c0 rjmp .+64 ; 0x4c <__bad_interrupt> c: 1f c0 rjmp .+62 ; 0x4c <__bad_interrupt> e: 1e c0 rjmp .+60 ; 0x4c <__bad_interrupt> 10: 1d c0 rjmp .+58 ; 0x4c <__bad_interrupt> 12: 1c c0 rjmp .+56 ; 0x4c <__bad_interrupt> 14: 1b c0 rjmp .+54 ; 0x4c <__bad_interrupt> 16: 1a c0 rjmp .+52 ; 0x4c <__bad_interrupt> 18: 19 c0 rjmp .+50 ; 0x4c <__bad_interrupt> 1a: 18 c0 rjmp .+48 ; 0x4c <__bad_interrupt> 1c: 17 c0 rjmp .+46 ; 0x4c <__bad_interrupt> 1e: 16 c0 rjmp .+44 ; 0x4c <__bad_interrupt> 20: 15 c0 rjmp .+42 ; 0x4c <__bad_interrupt> 00000022 <__trampolines_end>: 22: 54 68 ori r21, 0x84 ; 132 24: 69 73 andi r22, 0x39 ; 57 26: 20 69 ori r18, 0x90 ; 144 28: 73 20 and r7, r3 2a: 64 61 ori r22, 0x14 ; 20 2c: 74 61 ori r23, 0x14 ; 20 2e: 20 32 cpi r18, 0x20 ; 32 ... 00000031 <test_bytes1>: 31: 54 68 69 73 20 69 73 20 64 61 74 61 20 31 00 This is data 1. 00000040 <__ctors_end>: 40: 11 24 eor r1, r1 42: 1f be out 0x3f, r1 ; 63 44: cf ed ldi r28, 0xDF ; 223 46: cd bf out 0x3d, r28 ; 61 48: 02 d0 rcall .+4 ; 0x4e <main> 4a: 07 c0 rjmp .+14 ; 0x5a <_exit> 0000004c <__bad_interrupt>: 4c: d9 cf rjmp .-78 ; 0x0 <__vectors> 0000004e <main>: //one of these below will be labeled as __trampolines_end in lss static const uint8_t test_bytes1[] PROGMEM __attribute__((used)) = { TEST_DATA1 }; static const uint8_t test_bytes2[] PROGMEM __attribute__((used)) = { TEST_DATA2 }; void main(void) __attribute__((noreturn)); void main(void) { 4e: e1 e3 ldi r30, 0x31 ; 49 50: f0 e0 ldi r31, 0x00 ; 0 const uint8_t* ptr = test_bytes1; uint8_t i=0; while( i < sizeof(test_bytes1) ) { uint8_t c = pgm_read_byte(ptr++); PORTB = c; } 52: 84 91 lpm r24, Z 54: 88 bb out 0x18, r24 ; 24 56: 31 96 adiw r30, 0x01 ; 1 58: fc cf rjmp .-8 ; 0x52 <main+0x4> 0000005a <_exit>: 5a: f8 94 cli 0000005c <__stop_program>: 5c: ff cf rjmp .-2 ; 0x5c <__stop_program>
compile script
#!/bin/bash #variables MCU=attiny24 OUT=$MCU USR=$USER TOOLCHAIN=/home/$USR/dev/lib_avr/avr8-gnu-toolchain-3.6.2.1759-linux_x86_64 GCC=$TOOLCHAIN/bin PAC=$TOOLCHAIN/PACKS/Atmel.ATtiny_DFP.1.3.172 PACB=$PAC/gcc/dev/$MCU/ PACI=$PAC/include/ PACS=-B $PACB -I $PACI CUR=$(pwd) #options OPT='-DF_CPU=8000000UL -Os -Wshadow -fpack-struct -fshort-enums -g2 -Wall -ffreestanding -finline-limit=3 -fno-inline-small-functions' #files to compile FILES=(main ) #make output directory if [ -e "$OUT" ]; then echo found existing bin directory else echo creating output directory mkdir $OUT fi #compile reset echo "__________________________________________________________" echo "STARTING COMPILE" cd $OUT #=========================================================== -std=gnu99 #reset object linking OL="" #compile to object file (if not compiling correctly, echo the command below and make sure all variables are set) FM=${FILES[0]} for FL in "${FILES[@]}" do $GCC/avr-gcc -x c -funsigned-char -funsigned-bitfields -DDEBUG -I $PACI $OPT -mmcu=$MCU -B $PACB -c -std=gnu99 -MD -MP -MF "$FL.d" -MT"$FL.d" -MT"$FL.o" -o "$FL.o" "$CUR/$FL.c" OL+="$FL.o " #prep the object linking done #compile objects to elf file $GCC/avr-gcc -o $FM.elf $OL -Wl,-Map="$FM.map" -Wl,--start-group -Wl,-lm -Wl,--end-group -Wl,--gc-sections -mmcu=$MCU -B $PACB #create hex from elf (must remove any extra data when dumping with -R) $GCC/avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures "$FM.elf" "$FM.hex" #create srec from elf $GCC/avr-objcopy -O srec -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures "$FM.elf" "$FM.srec" #create eeprom file from elf $GCC/avr-objcopy -j .eeprom --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0 --no-change-warnings -O ihex "$FM.elf" "$FM.eep" #compile objects to elf file again with source comments (must have -g switch to insert source code into elf file) $GCC/avr-gcc -g -o $FM.elf $OL -Wl,-Map="$FM.map" -Wl,--start-group -Wl,-lm -Wl,--end-group -Wl,--gc-sections -mmcu=$MCU -B $PACB #dump elf to assembly (must have elf that was generated with -g) $GCC/avr-objdump -h -S "$FM.elf" > "$FM.lss" #=========================================================== echo "COMPILE FINISHED" echo "__________________________________________________________" #display GCC version $GCC/avr-gcc --version #display code size echo "HEX SIZE USAGE" $GCC/avr-objdump -Pmem-usage $FM.elf $GCC/avr-size $FM.elf echo "__________________________________________________________" cd .. #===============================================================