zevero / avr_boot

Arduino Bootloader to Flash from SD Card

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Can't compile for ATmega64A, 128, 128A, 32, 32A

per1234 opened this issue · comments

I wanted to try to add Arduino IDE support for more boards but ran into compiler errors with most of them.

These results are using the latest avr_boot with avr-gcc 6.1.0 but I've tried 4.8.1-arduino5, 4.9.2-atmel3.5.3-arduino2, and 5.1.0 and can't compile these MCUs with any of them. All the other MCUs I've tried compile fine, including ATmega64.

I modified asmfunc.S to define the pins as shown at: https://github.com/per1234/avr_boot/commit/7a4349fe525447cb3e338f00601b5dae8e907686

All makefile parameters other than MCU_TARGET and BOOT_ADR were left at the original values.

Any ideas? These are the last low hanging fruit for Arduino IDE support I'm aware of since they have a large enough boot size and established pin mappings(in the case of ATmega32/A, already included in the package).

With:

MCU_TARGET    = atmega64a
BOOT_ADR      = 0xF000

I get:

rm -rf *.o avr_boot.elf *.eps *.bak *.a *.bin
rm -rf pff/src/*.o uart/*.o
rm -rf *.lst *.map 
rm -rf avr_boot.hex
avr-gcc -gdwarf-2 -Wall -Os -mcall-prologues -ffunction-sections -fdata-sections -mmcu=atmega64a -std=c99 -DBOOT_ADR=0xF000 -DF_CPU=16000000   -DUSE_LED=0  -DUSE_UART=0  -DCS_PIN=4  -DVARIANT_1284P=0    -c -o main.o main.c
main.c: In function 'get_mcusr':
main.c:41:175: error: 'MCUSR' undeclared (first use in this function)
 uint8_t mcusr_mirror __attribute__ ((section (".noinit")));void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3")));void get_mcusr(void){mcusr_mirror = MCUSR;MCUSR = 0;wdt_disable();}
                                                                                                                                                                               ^~~~~
main.c:41:175: note: each undeclared identifier is reported only once for each function it appears in
make: *** [main.o] Error 1

With:

MCU_TARGET    = atmega128
BOOT_ADR      = 0x1F000

I get:

rm -rf *.o avr_boot.elf *.eps *.bak *.a *.bin
rm -rf pff/src/*.o uart/*.o
rm -rf *.lst *.map 
rm -rf avr_boot.hex
avr-gcc -gdwarf-2 -Wall -Os -mcall-prologues -ffunction-sections -fdata-sections -mmcu=atmega128 -std=c99 -DBOOT_ADR=0x1F000 -DF_CPU=16000000   -DUSE_LED=0  -DUSE_UART=0  -DCS_PIN=4  -DVARIANT_1284P=0    -c -o main.o main.c
main.c: In function 'get_mcusr':
main.c:41:175: error: attempt to use poisoned "MCUSR"
 uint8_t mcusr_mirror __attribute__ ((section (".noinit")));void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3")));void get_mcusr(void){mcusr_mirror = MCUSR;MCUSR = 0;wdt_disable();}
                                                                                                                                                                               ^
main.c:41:175: error: 'MCUSR' undeclared (first use in this function)
 uint8_t mcusr_mirror __attribute__ ((section (".noinit")));void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3")));void get_mcusr(void){mcusr_mirror = MCUSR;MCUSR = 0;wdt_disable();}
                                                                                                                                                                               ^~~~~
main.c:41:175: note: each undeclared identifier is reported only once for each function it appears in
main.c:41:181: error: attempt to use poisoned "MCUSR"
 uint8_t mcusr_mirror __attribute__ ((section (".noinit")));void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3")));void get_mcusr(void){mcusr_mirror = MCUSR;MCUSR = 0;wdt_disable();}
                                                                                                                                                                                     ^
make: *** [main.o] Error 1

With:

MCU_TARGET    = atmega128a
BOOT_ADR      = 0x1F000
rm -rf *.o avr_boot.elf *.eps *.bak *.a *.bin
rm -rf pff/src/*.o uart/*.o
rm -rf *.lst *.map 
rm -rf avr_boot.hex
avr-gcc -gdwarf-2 -Wall -Os -mcall-prologues -ffunction-sections -fdata-sections -mmcu=atmega128a -std=c99 -DBOOT_ADR=0x1F000 -DF_CPU=16000000   -DUSE_LED=0  -DUSE_UART=0  -DCS_PIN=4  -DVARIANT_1284P=0    -c -o main.o main.c
main.c: In function 'get_mcusr':
main.c:41:175: error: 'MCUSR' undeclared (first use in this function)
 uint8_t mcusr_mirror __attribute__ ((section (".noinit")));void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3")));void get_mcusr(void){mcusr_mirror = MCUSR;MCUSR = 0;wdt_disable();}
                                                                                                                                                                               ^~~~~
main.c:41:175: note: each undeclared identifier is reported only once for each function it appears in
make: *** [main.o] Error 1

With:

MCU_TARGET    = atmega32
BOOT_ADR      = 0x7000

I get:

rm -rf *.o avr_boot.elf *.eps *.bak *.a *.bin
rm -rf pff/src/*.o uart/*.o
rm -rf *.lst *.map 
rm -rf avr_boot.hex
avr-gcc -gdwarf-2 -Wall -Os -mcall-prologues -ffunction-sections -fdata-sections -mmcu=atmega32 -std=c99 -DBOOT_ADR=0x7000 -DF_CPU=16000000   -DUSE_LED=0  -DUSE_UART=0  -DCS_PIN=4  -DVARIANT_1284P=0    -c -o main.o main.c
avr-gcc -gdwarf-2 -Wall -Os -mcall-prologues -ffunction-sections -fdata-sections -mmcu=atmega32 -std=c99 -DBOOT_ADR=0x7000 -DF_CPU=16000000   -DUSE_LED=0  -DUSE_UART=0  -DCS_PIN=4  -DVARIANT_1284P=0    -c -o pff/src/pff.o pff/src/pff.c
pff/src/pff.c: In function 'get_fat':
pff/src/pff.c:379:3: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
   return LD_WORD(buf);
   ^~~~~~
pff/src/pff.c:384:3: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
   return LD_DWORD(buf) & 0x0FFFFFFF;
   ^~~~~~
pff/src/pff.c: In function 'pf_mount':
pff/src/pff.c:775:5: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
     bsect = LD_DWORD(&buf[8]); /* Partition offset in LBA */
     ^~~~~
avr-gcc -gdwarf-2 -Wall -Os -mcall-prologues -ffunction-sections -fdata-sections -mmcu=atmega32 -std=c99 -DBOOT_ADR=0x7000 -DF_CPU=16000000   -DUSE_LED=0  -DUSE_UART=0  -DCS_PIN=4  -DVARIANT_1284P=0    -c -o diskio.o diskio.c
avr-gcc -c -mmcu=atmega32 -I. -x assembler-with-cpp -Wa,-adhlns=asmfunc.lst,-gstabs -DBOOT_ADR=0x7000 -DF_CPU=16000000   -DUSE_LED=0  -DUSE_UART=0  -DCS_PIN=4  -DVARIANT_1284P=0  asmfunc.S -o asmfunc.o
avr-gcc -gdwarf-2 -Wall -Os -mcall-prologues -ffunction-sections -fdata-sections -mmcu=atmega32 -std=c99 -DBOOT_ADR=0x7000 -DF_CPU=16000000   -DUSE_LED=0  -DUSE_UART=0  -DCS_PIN=4  -DVARIANT_1284P=0  -Wl,-Map,avr_boot.map -Wl,--gc-sections -Wl,--section-start,.text=0x7000 -o avr_boot.elf main.o pff/src/pff.o diskio.o asmfunc.o 
asmfunc.o: In function `flash_erase':
asmfunc.S:366: undefined reference to `SPMCSR'
asmfunc.S:366: undefined reference to `SPMCSR'
asmfunc.S:366: undefined reference to `SPMCSR'
asmfunc.o: In function `flash_write':
asmfunc.S:399: undefined reference to `SPMCSR'
asmfunc.S:399: undefined reference to `SPMCSR'
asmfunc.o:asmfunc.S:399: more undefined references to `SPMCSR' follow
collect2.exe: error: ld returned 1 exit status
make: *** [avr_boot.elf] Error 1

With:

MCU_TARGET    = atmega32a
BOOT_ADR      = 0x7000

I get:

rm -rf *.o avr_boot.elf *.eps *.bak *.a *.bin
rm -rf pff/src/*.o uart/*.o
rm -rf *.lst *.map 
rm -rf avr_boot.hex
avr-gcc -gdwarf-2 -Wall -Os -mcall-prologues -ffunction-sections -fdata-sections -mmcu=atmega32a -std=c99 -DBOOT_ADR=0x7000 -DF_CPU=16000000   -DUSE_LED=0  -DUSE_UART=0  -DCS_PIN=4  -DVARIANT_1284P=0    -c -o main.o main.c
main.c: In function 'get_mcusr':
main.c:41:175: error: 'MCUSR' undeclared (first use in this function)
 uint8_t mcusr_mirror __attribute__ ((section (".noinit")));void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3")));void get_mcusr(void){mcusr_mirror = MCUSR;MCUSR = 0;wdt_disable();}
                                                                                                                                                                               ^~~~~
main.c:41:175: note: each undeclared identifier is reported only once for each function it appears in
make: *** [main.o] Error 1

As most errors origin in function 'get_mcusr' you may just try to comment out lines 40 and 41 and compile without disabling the watchdog (this is necessary if there was a restart by watchdog).

If that works, you may enable line 40 again but get rid of all those acrobatics in line 41 (only necessary to gain information on how the reboot occured - which we do not use anyway). Adding wdt_disable(); to the the first line of function 'main' should do the trick as well.

Commenting out lines 40 and 41 does solve the issue with MCUSR but disabling the watchdog is important and the avr-libc documentation says clearing MCUSR is required so I don't want to remove that either.

It turns out the problem is MCUSR isn't defined for those parts. For example, in iom64.h there is:

/* MCU Status Register */
#define MCUSR     _SFR_IO8(0x34) /* for backwards compatibility */
#define MCUCSR    _SFR_IO8(0x34) 

but in iom64a.h only:

#define MCUCSR  _SFR_IO8(0x34)

So I tried adding to main.c:

#ifndef MCUSR
#define MCUSR MCUCSR
#endif 

Now ATmega64A, 128A are compiling but with ATmega128 I get:

main.c:41:9: error: attempt to use poisoned "MCUSR"
 #ifndef MCUSR
         ^

So I changed my modification of main.c to:

#if defined(MCUCSR)
uint8_t mcusr_mirror __attribute__ ((section (".noinit")));void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3")));void get_mcusr(void){mcusr_mirror = MCUCSR;MCUCSR = 0;wdt_disable();}
#else
uint8_t mcusr_mirror __attribute__ ((section (".noinit")));void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3")));void get_mcusr(void){mcusr_mirror = MCUSR;MCUSR = 0;wdt_disable();}
#endif

That fixes all the MCUSR errors, now ATmega64A, 128, and 128A compile.

I'm really surprised I'm not finding any real information on this issue in my searches. It seems like it would be a common thing.

Next I hit another issue with ATmega32 and 32A:

asmfunc.o: In function `flash_erase':
asmfunc.S:373: undefined reference to `SPMCSR'
asmfunc.S:377: undefined reference to `SPMCSR'
asmfunc.S:383: undefined reference to `SPMCSR'
asmfunc.o: In function `flash_write':
asmfunc.S:413: undefined reference to `SPMCSR'
asmfunc.S:422: undefined reference to `SPMCSR'
asmfunc.o:asmfunc.S:426: more undefined references to `SPMCSR' follow

Sure enough there's no definition in iom32.h or iom32a.h. According to the datasheets the Store Program Memory Control Register is named SPMCR on those chips(why did they do that?). So I added to asmfunc.,S:

#ifndef SPMCSR
#define SPMCSR SPMCR
#endif

Now everything compiles. I don't own any of this hardware so I can't test but it still works correctly on the hardware I do own(ATmega328P, ATmega32U4, ATmega1284P). I do have a couple ATmega32A being shipped to me to play with(not much memory but $1.66/ea in single quantity is a great price for a DIP-40 AVR!).

Honestly I don't know what I'm doing here but would be happy to submit a pull request for these changes if they look correct. I don't want to add Arduino IDE support for any boards that require the user to modify the avr_boot source to build and I don't want to maintain multiple versions of the avr_boot source.

Thank you ... I can see how you solved the problem and I would do it the same as I do not know any better. Thank you for the link ... I would suggest to comment out the mcusr_mirror sections, as we do not use them.

Here is some information on wether we need to do MCUSR = 0
http://www.mikrocontroller.net/topic/276135
On the last post, someone states, that it is enough to reset the WDRF flag.

Would this help?