Skip to content

Commit

Permalink
SAMD Cortex M0 device support (Zero, MKR1000, etc)
Browse files Browse the repository at this point in the history
Compilation improvements by adding variant as other obj but not working on device

Arduino Zero devices with OpenOCD working

Created ARM_TOOLS_DIR and define arm toolchain executables in Sam.mk

Check avr-gcc on last AVR_TOOLS_DIR detect and indenting formatting

GDB debugging and programming added

Documentation updates and define ARDMK_VENDOR rather than include Sam.mk

Expand all parse_boards when defined rather than when used

Trim extra defines regex working on both macOS and Linux but need better fix

Print USB ids and added debug usage to readme

Add note on Arduino package dir and made board.txt work

Do ARM ARDUINO_ARCH define in Arduino.mk]

Add MZeroBlink to non-testable examples for now

Remove \B from extra defines grep

Add ARDUINO_PACKAGE_DIR for board support files

Fix a typo in the README

Fix typo in arduino-mk-vars.md

Prevent re-including Arduino.mk from Sam.mk when make restarts for upload

Add catrina to ARD_REST_OPTS if/else

Remove realpath in Sam.mk for cygwin compatability

SAMD bootloader support in ard-reset using --zero

Enters bootloader using open/close of port at 1200 BAUD, then polls the
attached devices for new port enumerating (bootloader). This is how the
Arduino IDE operates

Bossa support for Zero, MKR1000 etc

Re-word Arm README section after Native USB development

Reset for zero refactored like IDE

Zero bootloader reset tested on macOS and comments added

Re-word ARM bootloader and remove imports from testing

Patch changes ARDMK_VENDOR->ARCHITECHTURE, show_config_vars, ignore CORE_VER if emtpy

Common.mk header guard, openocd/bossac avoid separator, typos

Documentation update for patch changes

Move ARM tools to Sam.mk and auto-detect include

Correct accidental commit of Blink Makefile change

Lib fix with alternative core and documentation

Append zero to ARD_RESET_OPTS rather than set

Prioritise package ARM upload tools over path installed

Add note in README on ARM tools versions

Move openocd variant config script flag to OPTS
  • Loading branch information
tuna-f1sh committed Feb 24, 2018
1 parent a6d979e commit f804866
Show file tree
Hide file tree
Showing 13 changed files with 1,203 additions and 79 deletions.
188 changes: 136 additions & 52 deletions Arduino.mk
Expand Up @@ -261,7 +261,9 @@ else
endif

# include Common.mk now we know where it is
include $(ARDMK_DIR)/Common.mk
ifndef COMMON_INCLUDED
include $(ARDMK_DIR)/Common.mk
endif

# show_config_variable macro is available now. So let's print config details for ARDMK_DIR
ifndef ARDMK_DIR_MSG
Expand Down Expand Up @@ -317,11 +319,7 @@ else
ifeq ($(ARCHITECTURE),avr)
ARDUINO_ARCH_FLAG = -DARDUINO_ARCH_AVR
else
ifeq ($(ARCHITECTURE),sam)
ARDUINO_ARCH_FLAG = -DARDUINO_ARCH_SAM
else
ARDUINO_ARCH_FLAG = -DARDUINO_ARCH_$(shell echo $(ARCHITECTURE) | tr '[:lower:]' '[:upper:]')
endif
ARDUINO_ARCH_FLAG = -DARDUINO_ARCH_$(shell echo $(ARCHITECTURE) | tr '[:lower:]' '[:upper:]')
endif
endif

Expand Down Expand Up @@ -454,7 +452,14 @@ ifndef AVR_TOOLS_DIR
AVR_TOOLS_DIR = $(SYSTEMPATH_AVR_TOOLS_DIR)
$(call show_config_variable,AVR_TOOLS_DIR,[AUTODETECTED],(found in $$PATH))
else
echo $(error No AVR tools directory found)
# One last attempt using avr-gcc in case using arm
SYSTEMPATH_AVR_TOOLS_DIR := $(call dir_if_exists,$(abspath $(dir $(shell which $(avr-gcc)))/..))
ifdef SYSTEMPATH_AVR_TOOLS_DIR
AVR_TOOLS_DIR = $(SYSTEMPATH_AVR_TOOLS_DIR)
$(call show_config_variable,AVR_TOOLS_DIR,[AUTODETECTED],(found in $$PATH))
else
echo $(error No AVR tools directory found)
endif
endif # SYSTEMPATH_AVR_TOOLS_DIR

endif # BUNDLED_AVR_TOOLS_DIR
Expand Down Expand Up @@ -644,6 +649,9 @@ ifeq ($(strip $(NO_CORE)),)
USB_PID := $(call PARSE_BOARD,$(BOARD_TAG),menu.(chip|cpu).$(BOARD_SUB).build.pid)
endif
endif

# add caterina flag to ARD_RESET_OPTS
ARD_RESET_OPTS += --caterina
endif

# normal programming info
Expand Down Expand Up @@ -745,34 +753,21 @@ endif
# Reset

ifndef RESET_CMD
ARD_RESET_ARDUINO := $(shell which ard-reset-arduino 2> /dev/null)
ifndef ARD_RESET_ARDUINO
# same level as *.mk in bin directory when checked out from git
# or in $PATH when packaged
ARD_RESET_ARDUINO = $(ARDMK_DIR)/bin/ard-reset-arduino
endif
ifneq ($(CATERINA),)
ifneq (,$(findstring CYGWIN,$(shell uname -s)))
# confirm user is using default cygwin unix Python (which uses ttySx) and not Windows Python (which uses COMx)
ifeq ($(shell which python),/usr/bin/python)
RESET_CMD = $(ARD_RESET_ARDUINO) --caterina $(ARD_RESET_OPTS) $(DEVICE_PATH)
else
RESET_CMD = $(ARD_RESET_ARDUINO) --caterina $(ARD_RESET_OPTS) $(call get_monitor_port)
endif
else
RESET_CMD = $(ARD_RESET_ARDUINO) --caterina $(ARD_RESET_OPTS) $(call get_monitor_port)
endif
ARD_RESET_ARDUINO := $(shell which ard-reset-arduino 2> /dev/null)
ifndef ARD_RESET_ARDUINO
# same level as *.mk in bin directory when checked out from git
# or in $PATH when packaged
ARD_RESET_ARDUINO = $(ARDMK_DIR)/bin/ard-reset-arduino
endif
ifneq (,$(findstring CYGWIN,$(shell uname -s)))
# confirm user is using default cygwin unix Python (which uses ttySx) and not Windows Python (which uses COMx)
ifeq ($(shell which python),/usr/bin/python)
RESET_CMD = $(ARD_RESET_ARDUINO) $(ARD_RESET_OPTS) $(DEVICE_PATH)
else
RESET_CMD = $(ARD_RESET_ARDUINO) $(ARD_RESET_OPTS) $(call get_monitor_port)
endif
else
ifneq (,$(findstring CYGWIN,$(shell uname -s)))
# confirm user is using default cygwin unix Python (which uses ttySx) and not Windows Python (which uses COMx)
ifeq ($(shell which python),/usr/bin/python)
RESET_CMD = $(ARD_RESET_ARDUINO) $(ARD_RESET_OPTS) $(DEVICE_PATH)
else
RESET_CMD = $(ARD_RESET_ARDUINO) $(ARD_RESET_OPTS) $(call get_monitor_port)
endif
else
RESET_CMD = $(ARD_RESET_ARDUINO) $(ARD_RESET_OPTS) $(call get_monitor_port)
endif
RESET_CMD = $(ARD_RESET_ARDUINO) $(ARD_RESET_OPTS) $(call get_monitor_port)
endif
endif

Expand Down Expand Up @@ -815,7 +810,7 @@ ifeq ($(strip $(CHK_SOURCES)),)
$(call show_config_info,No .pde or .ino files found. If you are compiling .c or .cpp files then you need to explicitly include Arduino header files)
else
#TODO: Support more than one file. https://github.com/sudar/Arduino-Makefile/issues/49
$(error Need exactly one .pde or .ino file. This makefile doesn't support multiple .ino/.pde files yet)
$(error Need exactly one .pde or .ino file. This makefile doesn\'t support multiple .ino/.pde files yet)
endif
endif

Expand All @@ -830,13 +825,26 @@ ifeq ($(strip $(NO_CORE)),)
CORE_CPP_SRCS = $(wildcard $(ARDUINO_CORE_PATH)/*.cpp)
CORE_AS_SRCS = $(wildcard $(ARDUINO_CORE_PATH)/*.S)

# USB Core if samd or sam
ifeq ($(findstring sam, $(strip $(ARCHITECTURE))), sam)
CORE_C_SRCS += $(wildcard $(ARDUINO_CORE_PATH)/USB/*.c)
CORE_CPP_SRCS += $(wildcard $(ARDUINO_CORE_PATH)/USB/*.cpp)
endif

ifneq ($(strip $(NO_CORE_MAIN_CPP)),)
CORE_CPP_SRCS := $(filter-out %main.cpp, $(CORE_CPP_SRCS))
$(call show_config_info,NO_CORE_MAIN_CPP set so core library will not include main.cpp,[MANUAL])
endif

# Put alt core variant file for M0 devices in OTHER_OJBS
ifdef ALT_CORE_CPP_SRCS
ALT_CORE_OBJ_FILES = $(ALT_CORE_C_SRCS:.c=.c.o) $(ALT_CORE_CPP_SRCS:.cpp=.cpp.o) $(ALT_CORE_AS_SRCS:.S=.S.o)
OTHER_OBJS := $(patsubst $(ALTERNATE_CORE_PATH)/variants/$(VARIANT)/%, \
$(OBJDIR)/core/%,$(ALT_CORE_OBJ_FILES))
endif

CORE_OBJ_FILES = $(CORE_C_SRCS:.c=.c.o) $(CORE_CPP_SRCS:.cpp=.cpp.o) $(CORE_AS_SRCS:.S=.S.o)
CORE_OBJS = $(patsubst $(ARDUINO_CORE_PATH)/%, \
CORE_OBJS += $(patsubst $(ARDUINO_CORE_PATH)/%, \
$(OBJDIR)/core/%,$(CORE_OBJ_FILES))
endif
else
Expand Down Expand Up @@ -908,6 +916,7 @@ endif
TARGET_HEX = $(OBJDIR)/$(TARGET).hex
TARGET_ELF = $(OBJDIR)/$(TARGET).elf
TARGET_EEP = $(OBJDIR)/$(TARGET).eep
TARGET_BIN = $(OBJDIR)/$(TARGET).bin
CORE_LIB = $(OBJDIR)/libcore.a

# Names of executables - chipKIT needs to override all to set paths to PIC32
Expand Down Expand Up @@ -1023,6 +1032,7 @@ endif

# SoftwareSerial requires -Os (some delays are tuned for this optimization level)
%SoftwareSerial.cpp.o : OPTIMIZATION_FLAGS = -Os
%Uart.cpp.o : OPTIMIZATION_FLAGS = -Os

ifndef MCU_FLAG_NAME
MCU_FLAG_NAME = mmcu
Expand Down Expand Up @@ -1094,7 +1104,7 @@ ifeq ($(shell expr $(CC_VERNUM) '>' 490), 1)
endif
LDFLAGS += -$(MCU_FLAG_NAME)=$(MCU) -Wl,--gc-sections -O$(OPTIMIZATION_LEVEL)
ifeq ($(shell expr $(CC_VERNUM) '>' 490), 1)
LDFLAGS += -flto -fuse-linker-plugin
LDFLAGS += -flto -fuse-linker-plugin
endif
SIZEFLAGS ?= --mcu=$(MCU) -C

Expand Down Expand Up @@ -1302,7 +1312,24 @@ $(OBJDIR)/core/%.S.o: $(ARDUINO_CORE_PATH)/%.S $(COMMON_DEPS) | $(OBJDIR)
@$(MKDIR) $(dir $@)
$(CC) -MMD -c $(CPPFLAGS) $(ASFLAGS) $< -o $@

# alt core files
$(OBJDIR)/core/%.c.o: $(ALTERNATE_CORE_PATH)/variants/$(VARIANT)/%.c $(COMMON_DEPS) | $(OBJDIR)
@$(MKDIR) $(dir $@)
$(CC) -MMD -c $(CPPFLAGS) $(CFLAGS) $< -o $@

$(OBJDIR)/core/%.cpp.o: $(ALTERNATE_CORE_PATH)/variants/$(VARIANT)/%.cpp $(COMMON_DEPS) | $(OBJDIR)
@$(MKDIR) $(dir $@)
$(CXX) -MMD -c $(CPPFLAGS) $(CXXFLAGS) $< -o $@

$(OBJDIR)/core/%.S.o: $(ALTERNATE_CORE_PATH)/variants/$(VARIANT)/%.S $(COMMON_DEPS) | $(OBJDIR)
@$(MKDIR) $(dir $@)
$(CC) -MMD -c $(CPPFLAGS) $(ASFLAGS) $< -o $@

# various object conversions
$(OBJDIR)/%.bin: $(OBJDIR)/%.elf $(COMMON_DEPS)
@$(MKDIR) $(dir $@)
-$(OBJCOPY) -O binary $< $@

$(OBJDIR)/%.hex: $(OBJDIR)/%.elf $(COMMON_DEPS)
@$(MKDIR) $(dir $@)
$(OBJCOPY) -O ihex -R .eeprom $< $@
Expand Down Expand Up @@ -1442,12 +1469,21 @@ endif
# so we do not set it by default.
AVRDUDE_ISP_OPTS = -c $(ISP_PROG) -b $(AVRDUDE_ISP_BAUDRATE)

ifndef $(ISP_PORT)
ifndef ISP_PORT
ifneq ($(strip $(ISP_PROG)),$(filter $(ISP_PROG), atmelice_isp usbasp usbtiny gpio linuxgpio avrispmkii dragon_isp dragon_dw))
AVRDUDE_ISP_OPTS += -P $(call get_isp_port)
# switch for sam devices as bootloader will be on usb serial if using stk500_v2
ifeq ($(findstring sam, $(strip $(ARCHITECTURE))), sam)
AVRDUDE_ISP_OPTS += -P $(call get_monitor_port)
else
AVRDUDE_ISP_OPTS += -P $(call get_isp_port)
endif
endif
else
AVRDUDE_ISP_OPTS += -P $(call get_isp_port)
ifeq ($(CURRENT_OS), WINDOWS)
AVRDUDE_ISP_OPT += -P ISP_PORT
else
AVRDUDE_ISP_OPTS += -P $(call get_isp_port)
endif
endif

ifndef ISP_EEPROM
Expand All @@ -1465,7 +1501,7 @@ endif
########################################################################
# Explicit targets start here

all: $(TARGET_EEP) $(TARGET_HEX)
all: $(TARGET_EEP) $(TARGET_BIN) $(TARGET_HEX)

# Rule to create $(OBJDIR) automatically. All rules with recipes that
# create a file within it, but do not already depend on a file within it
Expand All @@ -1479,30 +1515,63 @@ $(OBJDIR): pre-build
pre-build:
$(call runscript_if_exists,$(PRE_BUILD_HOOK))

# copied from arduino with start-group, end-group
$(TARGET_ELF): $(LOCAL_OBJS) $(CORE_LIB) $(OTHER_OBJS)
# sam devices need start and end group
ifeq ($(findstring sam, $(strip $(ARCHITECTURE))), sam)
$(CC) $(LINKER_SCRIPTS) -Wl,-Map=$(OBJDIR)/$(TARGET).map -o $@ $(LOCAL_OBJS) $(OTHER_OBJS) $(OTHER_LIBS) $(LDFLAGS) $(CORE_LIB) -Wl,--end-group
# otherwise traditional
else
$(CC) $(LDFLAGS) -o $@ $(LOCAL_OBJS) $(CORE_LIB) $(OTHER_OBJS) $(OTHER_LIBS) -lc -lm $(LINKER_SCRIPTS)
endif

$(CORE_LIB): $(CORE_OBJS) $(LIB_OBJS) $(PLATFORM_LIB_OBJS) $(USER_LIB_OBJS)
$(AR) rcs $@ $(CORE_OBJS) $(LIB_OBJS) $(PLATFORM_LIB_OBJS) $(USER_LIB_OBJS)

error_on_caterina:
$(ERROR_ON_CATERINA)


# Use submake so we can guarantee the reset happens
# before the upload, even with make -j
upload: $(TARGET_HEX) verify_size
ifeq ($(findstring sam, $(strip $(ARCHITECTURE))), sam)
# do reset toggle at 1200 BAUD to enter bootloader if using avrdude or bossa
ifeq ($(strip $(UPLOAD_TOOL)), avrdude)
$(MAKE) reset
else ifeq ($(findstring bossac, $(strip $(UPLOAD_TOOL))), bossac)
$(MAKE) reset
endif
$(MAKE) do_sam_upload
else
$(MAKE) reset
$(MAKE) do_upload
endif

raw_upload: $(TARGET_HEX) verify_size
ifeq ($(findstring sam, $(strip $(ARCHITECTURE))), sam)
$(MAKE) do_sam_upload
else
$(MAKE) error_on_caterina
$(MAKE) do_upload
endif

do_upload:
$(AVRDUDE) $(AVRDUDE_COM_OPTS) $(AVRDUDE_ARD_OPTS) \
$(AVRDUDE_UPLOAD_HEX)

do_sam_upload: $(TARGET_BIN) verify_size
ifeq ($(findstring openocd, $(strip $(UPLOAD_TOOL))), openocd)
$(OPENOCD) $(OPENOCD_OPTS) -c "telnet_port disabled; program {{$(TARGET_BIN)}} verify reset $(BOOTLOADER_SIZE); shutdown"
else ifeq ($(findstring bossac, $(strip $(UPLOAD_TOOL))), bossac)
$(BOSSA) $(BOSSA_OPTS) $(TARGET_BIN)
else ifeq ($(findstring gdb, $(strip $(UPLOAD_TOOL))), gdb)
$(GDB) $(GDB_UPLOAD_OPTS)
else ifeq ($(strip $(UPLOAD_TOOL)), avrdude)
$(MAKE) ispload
else
@$(ECHO) "$(BOOTLOADER_UPLOAD_TOOL) not currently supported!\n\n"
endif

do_eeprom: $(TARGET_EEP) $(TARGET_HEX)
$(AVRDUDE) $(AVRDUDE_COM_OPTS) $(AVRDUDE_ARD_OPTS) \
$(AVRDUDE_UPLOAD_EEP)
Expand Down Expand Up @@ -1535,14 +1604,22 @@ ispload: $(TARGET_EEP) $(TARGET_HEX) verify_size
$(AVRDUDE_ISPLOAD_OPTS)

burn_bootloader:
ifneq ($(strip $(AVRDUDE_ISP_FUSES_PRE)),)
$(AVRDUDE) $(AVRDUDE_COM_OPTS) $(AVRDUDE_ISP_OPTS) -e $(AVRDUDE_ISP_FUSES_PRE)
endif
ifneq ($(strip $(AVRDUDE_ISP_BURN_BOOTLOADER)),)
$(AVRDUDE) $(AVRDUDE_COM_OPTS) $(AVRDUDE_ISP_OPTS) $(AVRDUDE_ISP_BURN_BOOTLOADER)
endif
ifneq ($(strip $(AVRDUDE_ISP_FUSES_POST)),)
$(AVRDUDE) $(AVRDUDE_COM_OPTS) $(AVRDUDE_ISP_OPTS) $(AVRDUDE_ISP_FUSES_POST)
ifeq ($(findstring sam, $(strip $(ARCHITECTURE))), sam)
ifeq ($(strip $(BOOTLOADER_UPLOAD_TOOL)), openocd)
$(OPENOCD) $(OPENOCD_OPTS) -c "telnet_port disabled; init; halt; $(BOOTLOADER_UNPROTECT); program {{$(BOOTLOADER_PARENT)/$(BOOTLOADER_FILE)}} verify reset; shutdown"
else
@$(ECHO) "$(BOOTLOADER_UPLOAD_TOOL) not currently supported!\n\n"
endif
else
ifneq ($(strip $(AVRDUDE_ISP_FUSES_PRE)),)
$(AVRDUDE) $(AVRDUDE_COM_OPTS) $(AVRDUDE_ISP_OPTS) -e $(AVRDUDE_ISP_FUSES_PRE)
endif
ifneq ($(strip $(AVRDUDE_ISP_BURN_BOOTLOADER)),)
$(AVRDUDE) $(AVRDUDE_COM_OPTS) $(AVRDUDE_ISP_OPTS) $(AVRDUDE_ISP_BURN_BOOTLOADER)
endif
ifneq ($(strip $(AVRDUDE_ISP_FUSES_POST)),)
$(AVRDUDE) $(AVRDUDE_COM_OPTS) $(AVRDUDE_ISP_OPTS) $(AVRDUDE_ISP_FUSES_POST)
endif
endif

set_fuses:
Expand Down Expand Up @@ -1580,6 +1657,12 @@ else
$(MONITOR_CMD) $(call get_monitor_port) $(MONITOR_BAUDRATE)
endif

debug_init:
$(OPENOCD)

debug:
$(GDB) $(GDB_OPTS)

disasm: $(OBJDIR)/$(TARGET).lss
@$(ECHO) "The compiled ELF file has been disassembled to $(OBJDIR)/$(TARGET).lss\n\n"

Expand All @@ -1599,7 +1682,6 @@ generate_assembly: $(OBJDIR)/$(TARGET).s
generated_assembly: generate_assembly
@$(ECHO) "\"generated_assembly\" target is deprecated. Use \"generate_assembly\" target instead\n\n"

.PHONY: tags
tags:
ifneq ($(words $(wildcard $(TAGS_FILE))), 0)
rm -f $(TAGS_FILE)
Expand Down Expand Up @@ -1634,6 +1716,8 @@ help:
make show_boards - list all the boards defined in boards.txt\n\
make show_submenu - list all board submenus defined in boards.txt\n\
make monitor - connect to the Arduino's serial port\n\
make debug_init - start openocd gdb server\n\
make debug - connect to gdb target and begin debugging\n\
make size - show the size of the compiled output (relative to\n\
resources, if you have a patched avr-size).\n\
make verify_size - verify that the size of the final file is less than\n\
Expand All @@ -1655,7 +1739,7 @@ help:

.PHONY: all upload raw_upload raw_eeprom error_on_caterina reset reset_stty ispload \
clean depends size show_boards monitor disasm symbol_sizes generated_assembly \
generate_assembly verify_size burn_bootloader help pre-build
generate_assembly verify_size burn_bootloader help pre-build tags debug debug_init

# added - in the beginning, so that we don't get an error if the file is not present
-include $(DEPS)
6 changes: 5 additions & 1 deletion Common.mk
@@ -1,3 +1,4 @@
COMMON_INCLUDED = TRUE
# Useful functions
# Returns the first argument (typically a directory), if the file or directory
# named by concatenating the first and optionally second argument
Expand Down Expand Up @@ -26,8 +27,11 @@ show_config_variable = $(call show_config_info,$(1) = $($(1)) $(3),$(2))
# Just a nice simple visual separator
show_separator = $(call arduino_output,-------------------------)

# Master Arduino Makefile include (after user Makefile)
ardmk_include = $(shell basename $(word 2,$(MAKEFILE_LIST)))

$(call show_separator)
$(call arduino_output,Arduino.mk Configuration:)
$(call arduino_output,$(call ardmk_include) Configuration:)

########################################################################
#
Expand Down
1 change: 1 addition & 0 deletions HISTORY.md
Expand Up @@ -18,6 +18,7 @@ I tried to give credit whenever possible. If I have missed anyone, kindly add it
- New: Add generation of tags file using ctags, which automatically includes project libs and Arduino core. (https://github.com/tuna-f1sh)
- New: Add template Makefile and project boilerplate initialise script, `ardmk-init`. (https://github.com/tuna-f1sh)
- New: Support atmelice_isp JTAG tool as ISP programmer. (https://github.com/tuna-f1sh)
- New: Support Arduino ARM-based (SAM/SAMD) devices. (https://github.com/tuna-f1sh)

### 1.6.0 (2017-07-11)
- Fix: Allowed for SparkFun's weird usb pid/vid submenu shenanigans (issue #499). (https://github.com/sej7278)
Expand Down

0 comments on commit f804866

Please sign in to comment.