Optiboot / optiboot

Small and Fast Bootloader for Arduino and other Atmel AVR chips
Other
1.08k stars 396 forks source link

Allow user defined CFLAGS? #297

Closed ctag closed 3 years ago

ctag commented 3 years ago

Hi,

To compile for atmega328pb on my distro I have to add "-D__AVR_DEV_LIB_NAME__=m328pb" to CFLAGS. But it appears CFLAGS it clobbered by the Makefile. Changing the syntax would allow custom flags such as this one to be added.

Reference at the bottom of this page: https://github.com/watterott/ATmega328PB-Testing/blob/master/hardware/tools/avr/lib/gcc/avr/4.9.2/device-specs/specs-atmega328pb

WestfW commented 3 years ago

It shouldn't be necessary to use AVR_DEV_LIB_NAME any more with the optiboot makefiles (we got rid of "-nostdlibs"):

 make atmega328pb LED=B5 UART=0

BAUD RATE CHECK: Desired: 115200, Real: 117647, UBRRL = 16, Difference=2.1%
avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=atmega328pb -DF_CPU=16000000L  -DBAUD_RATE=115200 -DLED_START_FLASHES=3    -DLED=B5        -DUART=0   -c -o optiboot.o optiboot.c
optiboot.c:386:6: warning: #warning BAUD_RATE off by greater than 2% [-Wcpp]

avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=atmega328pb -DF_CPU=16000000L  -DBAUD_RATE=115200 -DLED_START_FLASHES=3    -DLED=B5        -DUART=0 -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe -Wl,--relax -nostartfiles -o optiboot_atmega328pb_UART0__.elf optiboot.o 
avr-size optiboot_atmega328pb_UART0__.elf
   text    data     bss     dec     hex filename
    482       0       0     482     1e2 optiboot_atmega328pb_UART0__.elf
avr-objcopy -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex optiboot_atmega328pb_UART0__.elf optiboot_atmega328pb_UART0__.hex
avr-objdump -h -S optiboot_atmega328pb_UART0__.elf > optiboot_atmega328pb_UART0__.lst
rm optiboot.o

That said, optiboot should probably support mechanisms for adding additional CFLAGS, and for supporting the PACKS mechanism for new devices (the current makefiles require that new chips be merged manually into the compiler toolchain (which I've done, and Arduino has done, but isn't compatible with the way that Microchip looks like they'll be supporting avr-gcc in the future.))

ctag commented 3 years ago

Thanks WestfW. It may just be weirdness on my distro's packages then, but the atmega328pb compatibility package just drops the io file in the system and does not appear to inform avr-gcc. I'm not knowledgeable enough with any of these tools to know for sure what's going on.

Without that CFLAGS change:

[berocs@bns-kharselim optiboot]$ make atmega328pb LED=B5 UART=0
avr-gcc (GCC) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

BAUD RATE CHECK: Desired: 115200, Real: 117647, UBRRL = 16, Difference=2.1%
avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=atmega328pb -DF_CPU=16000000L  -DBAUD_RATE=115200 -DLED_START_FLASHES=3    -DLED=B5        -DUART=0   -c -o optiboot.o optiboot.c
In file included from optiboot.c:310:
/usr/avr/include/avr/io.h:623:6: warning: #warning "device type not defined" [-Wcpp]
  623 | #    warning "device type not defined"
      |      ^~~~~~~
In file included from optiboot.c:312:
/usr/avr/include/avr/eeprom.h:41:3: warning: #warning "Device does not have EEPROM available." [-Wcpp]
   41 | # warning "Device does not have EEPROM available."
      |   ^~~~~~~
In file included from boot_opt.h:2,
                 from optiboot.c:334:
/usr/avr/include/avr/boot.h:116:6: error: #error AVR processor does not provide bootloader support!
  116 | #    error AVR processor does not provide bootloader support!
      |      ^~~~~
/usr/avr/include/avr/boot.h:127:4: error: #error Cannot find SPM Enable bit definition!
  127 | #  error Cannot find SPM Enable bit definition!
      |    ^~~~~
In file included from optiboot.c:344:
pin_defs.h:67:3: error: #error UART == 0, but no UART0 on device
   67 | # error UART == 0, but no UART0 on device
      |   ^~~~~
pin_defs.h:1528:2: error: #error Unrecognized LED name. Should be like "B5"
 1528 | #error Unrecognized LED name.  Should be like "B5"
      |  ^~~~~
[...]
make: *** [<builtin>: optiboot.o] Error 1
WestfW commented 3 years ago

avr-gcc (GCC) 10.2.0

Wow. (considering that Microchip is shipping 5.4, and Arduino is using 7.3) What distribution are you using?

There are some instructions for merging "packs" into the main compiler tree here: https://www.avrfreaks.net/comment/2526416#comment-2526416

ctag commented 3 years ago

I'm using Archlinux.

Thank you for the link. I looked through the instructions and have gotten myself properly confused though. I now don't see how any avr-gcc can not use the compiler flag to target atmega328pb. I'll attempt to explain.

There are four relevant files in the Atmel pack for 328pb:

I originally was going to extract the files myself, but it turned out they were already on my system. The specs file is provided in the official avr-gcc package for Archlinux:

$ pacman -Ql avr-gcc | grep 328pb
avr-gcc /usr/lib/gcc/avr/10.2.0/device-specs/specs-atmega328pb

The other three are provided in an unofficial package avr-libc-atmel-atmega328pb

$ pacman -Ql avr-libc-atmel-atmega328pb 
avr-libc-atmel-atmega328pb /usr/
avr-libc-atmel-atmega328pb /usr/avr/
avr-libc-atmel-atmega328pb /usr/avr/include/
avr-libc-atmel-atmega328pb /usr/avr/include/avr/
avr-libc-atmel-atmega328pb /usr/avr/include/avr/iom328pb.h
avr-libc-atmel-atmega328pb /usr/avr/lib/
avr-libc-atmel-atmega328pb /usr/avr/lib/avr5/
avr-libc-atmel-atmega328pb /usr/avr/lib/avr5/crtatmega328pb.o
avr-libc-atmel-atmega328pb /usr/avr/lib/avr5/libatmega328pb.a

In the specs file it references how the iom328pb.h is included in a project:

# AVR-LibC's avr/io.h uses the device specifying macro to determine
# the name of the device header.  For example, -mmcu=atmega8a triggers
# the definition of __AVR_ATmega8A__ and avr/io.h includes the device
# header 'iom8a.h' by means of:
#
#     ...
#     #elif defined (__AVR_ATmega8A__)
#     #  include <avr/iom8a.h>
#     #elif ...
# 
# If no device macro is defined, AVR-LibC uses __AVR_DEV_LIB_NAME__
# as fallback to determine the name of the device header as
#
#     "avr/io" + __AVR_DEV_LIB_NAME__ + ".h"
#
# If you provide your own specs file for a device not yet known to
# AVR-LibC, you can now define the hook macro __AVR_DEV_LIB_NAME__
# as needed so that
#
#     #include <avr/io.h>
#
# will include the desired device header.  For ATmega8A the supplement
# to *cpp would read
#
#     -D__AVR_DEV_LIB_NAME__=m8a

But there is no reference at all to 328pb in my io.h file, nor in the upstream master from avr libc. So how is gcc finding the target on your machine?

WestfW commented 3 years ago

I think that the ability to automatically pick up a device-specs file based on the -mmcu option is an Atmel patch that isn't in the arch-linux distribution, or something like that? https://github.com/arduino/toolchain-avr/blob/master/avr-gcc-patches/atmel-patches-gcc.5.4.0.patch#L2257

(there are other patches, including internal knowledge of atmega328pb, in the arduino patches. But I don't believe those internal definitions are necessary if the proper device-spec patch is there.)

ctag commented 3 years ago

Thanks WestfW, that makes sense.

I wound up making a user package that fixes io.h so that I can target the 328pb with make.