aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Arduino.mk188
-rw-r--r--Common.mk6
-rw-r--r--HISTORY.md1
-rw-r--r--README.md69
-rw-r--r--Sam.mk481
-rw-r--r--Teensy.mk2
-rw-r--r--arduino-mk-vars.md347
-rwxr-xr-xbin/ard-reset-arduino90
-rw-r--r--examples/MZeroBlink/MZeroBlink.ino19
-rw-r--r--examples/MZeroBlink/Makefile24
-rw-r--r--examples/ZeroBlink/Makefile30
-rw-r--r--examples/ZeroBlink/ZeroBlink.ino19
-rwxr-xr-xtests/script/runtests.sh2
13 files changed, 1201 insertions, 77 deletions
diff --git a/Arduino.mk b/Arduino.mk
index 3473166..865b0ef 100644
--- a/Arduino.mk
+++ b/Arduino.mk
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 $< $@
@@ -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
@@ -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
@@ -1479,8 +1515,15 @@ $(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)
@@ -1488,21 +1531,47 @@ $(CORE_LIB): $(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)
@@ -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:
@@ -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"
@@ -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)
@@ -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\
@@ -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)
diff --git a/Common.mk b/Common.mk
index a8bd46a..5f30fba 100644
--- a/Common.mk
+++ b/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
@@ -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:)
########################################################################
#
diff --git a/HISTORY.md b/HISTORY.md
index a6aa14f..b4f4200 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -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)
diff --git a/README.md b/README.md
index 777fe2f..f3b5e20 100644
--- a/README.md
+++ b/README.md
@@ -7,6 +7,8 @@ This is a very simple Makefile which knows how to build Arduino sketches. It def
- Very robust
- Highly customizable
- Supports all official AVR-based Arduino boards
+- Supports official ARM-based Arduino boards using Atmel SAM chip family
+ (Cortex M0) and includes on-device debugging targets.
- Supports chipKIT
- Supports Teensy 3.x (via Teensyduino)
- Works on all three major OS (Mac, Linux, Windows)
@@ -313,6 +315,72 @@ See examples/BlinkOpenCM for example usage.
For large Robotis projects, [libmaple](https://github.com/Rhoban/Maple) may be more appropriate, as the OpenCM IDE uses a very old compiler release.
+## Arduino ARM Boards
+
+For Arduino boards using ARM architechure, specifically the Atmel SAM series
+(Arduino M0 [Pro], Zero, MKR1000, Feather M0, etc.), first
+install the board support package from the IDE or other distribution channels.
+
+Define`ARDUINO_PACKAGE_DIR` as the root path containing the ARM support
+package (the manufacturer folder) and the `BOARD_TAG` (see `make show_boards`
+for help) within your project Makefile. Include 'Sam.mk' rather than
+ 'Arduino.mk' at the end of your file - see examples/ZeroBlink and
+ examples/MZeroBlink for example usage.
+
+**Note**: The Arduino IDE does not install board support packages to
+the base Arduino installation directory (the directory that will work with AVR
+Makefiles). They are generally installed to a '.arduino15/packages' folder in
+the users home directory. This is the reason for the new `ARDUINO_PACKAGE_DIR`
+define. On Windows, the package directory is often in the user home directory
+so advice is to create a symblic link to avoid slash/space in path problems.
+You can also manually install support packages in your Sketchbook 'hardware'
+folder, then define ARDUINO_PACKAGE_DIR as this path.
+
+If using a SAM board from a manufacturer other than Arduino, one must still
+install the Arduino board support as above (unless using externally defined
+toolchain) and then define the location of the manufacturer board support core
+using the ALTERNATIVE_CORE_PATH define. For example: `ALTERNATE_CORE_PATH =
+$(ARDUINO_SKETCHBOOK)/hardware/sparkfun/samd`
+
+The programing method will auto-detect based on the `BOARD_TAG` settings read
+from boards.txt:
+
+Programming using OpenOCD CMSIS-DAP with the Programming/debug USB is
+currently supported (the same method used by the IDE), including burning
+bootloaders. External CMSIS tools such as Atmel Ice will also work with this
+method. Black Magic Probe (BMP) support is also included using GDB for both
+uploading and debugging.
+
+Native USB programing using Bossa (Zero, MKR1000, Feather style bootloaders)
+and avrdude (M0 bootloaders) is supported. The bootloaders on these devices
+requires a double press of the reset button or open/closing the serial port at
+1200 BAUD. The automatic entry of the bootloader is attempted using
+`ard-reset-arduino` when using the general `make upload` target by polling
+attached devices until the bootloader port re-attaches (same method as the
+IDE). On Windows, the USB enumerates as differnt COM ports for the CDC Serial
+and bootloader and these must be defined. On encountering problems, one can
+manually enter the bootloader then upload using the `make raw_upload` target.
+Note that the `make reset` target will enter the bootloader on these devices;
+there is no way to reset over USB.
+
+If using system installed tools, be aware that `openocd` and `bossa` were
+orginally forked for Arduino support and system distributions may not be up
+to date with merged changes. `bossa` must be version 1.7->. `openocd` should
+work but there may be problems at run time
+[ref](https://github.com/pda/arduino-zero-without-ide). Ideally, use the
+support packaged version or compile and install the Arduino fork.
+
+With the ARM chipset and using a CMSIS-DAP tool, on-device debugging is made available:
+
+* `debug_init` and `debug` targets for on-device debugging using GDB. To use
+ this, one must start the GDB server with `make debug_init &`, followed by
+ connecting to the target with `make debug`. If using a Black Magic Probe,
+ one can just use `make debug`. At the moment, a system wide `arm-none-eabi-gdb` must be
+ installed as the one supplied with the Arduino toolchain
+ does not appear to work.
+* Example usage: https://asciinema.org/a/Jarz7Pr3gD6mqaZvCACQBzqix
+* See the examples/MZeroBlink Makefile for a commented example.
+
## Versioning
The current version of the makefile is `1.6.0`. You can find the full history in the [HISTORY.md](HISTORY.md) file
@@ -334,7 +402,6 @@ If you are looking for ideas to work on, then check out the following TODO items
## Limitations / Known Issues / TODO's
-- Doesn't support SAM boards yet.
- Since it doesn't do any pre processing like Arduino IDE, you have to declare all methods before you use them ([issue #59](https://github.com/sudar/Arduino-Makefile/issues/59))
- More than one .ino or .pde file is not supported yet ([issue #49](https://github.com/sudar/Arduino-Makefile/issues/49))
- When you compile for the first time, it builds all libs inside Arduino directory even if it is not needed. But while linking only the relevant files are linked. ([issue #29](https://github.com/sudar/Arduino-Makefile/issues/29)). Even Arduino IDE does the same thing though.
diff --git a/Sam.mk b/Sam.mk
new file mode 100644
index 0000000..8b93ee4
--- /dev/null
+++ b/Sam.mk
@@ -0,0 +1,481 @@
+########################################################################
+#
+# Support for Arduino Atmel SAM boards (sam and samd)
+#
+# You must install a SAM board hardware support package (such as Arduino Zero)
+# to use this, then define ARDUINO_PACKAGE_DIR as the path to the root
+# directory containing the support package.
+#
+# 2018 John Whittington @j_whittington
+#
+########################################################################
+
+arduino_output =
+# When output is not suppressed and we're in the top-level makefile,
+# running for the first time (i.e., not after a restart after
+# regenerating the dependency file), then output the configuration.
+ifndef ARDUINO_QUIET
+ ifeq ($(MAKE_RESTARTS),)
+ ifeq ($(MAKELEVEL),0)
+ arduino_output = $(info $(1))
+ endif
+ endif
+endif
+
+ifndef ARDMK_DIR
+ ARDMK_DIR := $(realpath $(dir $(realpath $(lastword $(MAKEFILE_LIST)))))
+endif
+
+# include Common.mk now we know where it is
+ifndef COMMON_INCLUDED
+ include $(ARDMK_DIR)/Common.mk
+endif
+
+ifndef ARDUINO_PACKAGE_DIR
+ # attempt to find based on Linux, macOS and Windows default
+ ARDUINO_PACKAGE_DIR := $(firstword \
+ $(call dir_if_exists,$(HOME)/.arduino15/packages) \
+ $(call dir_if_exists,$(ARDUINO_DIR)/packages) \
+ $(call dir_if_exists,$(HOME)/Library/Arduino15/packages) \
+ $(call dir_if_exists,$(USERPROFILE)/AppData/Local/Arduino15/packages) )
+ $(call show_config_variable,ARDUINO_PACKAGE_DIR,[AUTODETECTED],(from DEFAULT))
+else
+ $(call show_config_variable,ARDUINO_PACKAGE_DIR,[USER])
+endif
+
+ifndef ARDMK_VENDOR
+ ARDMK_VENDOR := arduino
+endif
+
+ifndef ARCHITECTURE
+ ARCHITECTURE := samd
+endif
+
+ifndef CORE_VER
+ CORE_VER := $(wildcard $(ARDUINO_PACKAGE_DIR)/$(ARDMK_VENDOR)/hardware/$(ARCHITECTURE)/1.*)
+ ifdef CORE_VER
+ CORE_VER := $(shell basename $(CORE_VER))
+ $(call show_config_variable,CORE_VER,[AUTODETECTED],(from ARDUINO_PACKAGE_DIR))
+ endif
+else
+ $(call show_config_variable,CORE_VER,[USER])
+endif
+
+ifndef CMSIS_VER
+ CMSIS_VER := $(shell basename $(wildcard $(ARDUINO_PACKAGE_DIR)/$(ARDMK_VENDOR)/tools/CMSIS/4.*))
+ $(call show_config_variable,CMSIS_VER,[AUTODETECTED],(from ARDUINO_PACKAGE_DIR))
+else
+ $(call show_config_variable,CMSIS_VER,[USER])
+endif
+
+ifndef CMSIS_ATMEL_VER
+ CMSIS_ATMEL_VER := $(shell basename $(wildcard $(ARDUINO_PACKAGE_DIR)/$(ARDMK_VENDOR)/tools/CMSIS-Atmel/1.*))
+ $(call show_config_variable,CMSIS_ATMEL_VER,[AUTODETECTED],(from ARDUINO_PACKAGE_DIR))
+else
+ $(call show_config_variable,CMSIS_ATMEL_VER,[USER])
+endif
+
+ifndef CMSIS_DIR
+ CMSIS_DIR := $(ARDUINO_PACKAGE_DIR)/$(ARDMK_VENDOR)/tools/CMSIS/$(CMSIS_VER)/CMSIS
+ $(call show_config_variable,CMSIS_DIR,[AUTODETECTED],(from ARDUINO_PACKAGE_DIR))
+else
+ $(call show_config_variable,CMSIS_DIR,[USER])
+endif
+
+ifndef CMSIS_ATMEL_DIR
+ CMSIS_ATMEL_DIR := $(ARDUINO_PACKAGE_DIR)/$(ARDMK_VENDOR)/tools/CMSIS-Atmel/$(CMSIS_ATMEL_VER)/CMSIS
+ $(call show_config_variable,CMSIS_ATMEL_DIR,[AUTODETECTED],(from ARDUINO_PACKAGE_DIR))
+else
+ $(call show_config_variable,CMSIS_ATMEL_DIR,[USER])
+endif
+
+# Arduino Settings (will get shown in Arduino.mk as computed)
+ifndef ALTERNATE_CORE_PATH
+ ifdef CORE_VER
+ ALTERNATE_CORE_PATH = $(ARDUINO_PACKAGE_DIR)/$(ARDMK_VENDOR)/hardware/$(ARCHITECTURE)/$(CORE_VER)
+ else
+ ALTERNATE_CORE_PATH = $(ARDUINO_PACKAGE_DIR)/$(ARDMK_VENDOR)/hardware/$(ARCHITECTURE)
+ endif
+endif
+ifndef ARDUINO_CORE_PATH
+ ARDUINO_CORE_PATH = $(ALTERNATE_CORE_PATH)/cores/arduino
+endif
+ifndef BOARD_TXT
+ BOARDS_TXT = $(ALTERNATE_CORE_PATH)/boards.txt
+endif
+
+# Check boards file exists before continuing as parsing non-existant file can create problems
+ifneq ($(findstring boards.txt, $(wildcard $(ALTERNATE_CORE_PATH)/*.txt)), boards.txt)
+ echo $(error $(CORE_VER) Cannot find boards file $(BOARDS_TXT). Check ARDUINO_PACKAGE_DIR path: $(ARDUINO_PACKAGE_DIR) and board support installed)
+endif
+
+# add CMSIS includes
+CPPFLAGS += -I$(CMSIS_DIR)/Include/
+CPPFLAGS += -I$(CMSIS_ATMEL_DIR)/Device/ATMEL
+# path for Cortex library
+LIB_PATH = $(CMSIS_DIR)/Lib/GCC
+BOOTLOADER_PARENT = $(ALTERNATE_CORE_PATH)/bootloaders
+
+# Utility from ard-mk to parse boards.txt for flags
+ifndef PARSE_BOARD
+ PARSE_BOARD = $(shell grep -Ev '^\#' $(BOARDS_TXT) | grep -E '^[ \t]*$(1).$(2)=' | cut -d = -f 2 | cut -d : -f 2)
+endif
+
+ifndef VARIANT
+ VARIANT := $(call PARSE_BOARD,$(BOARD_TAG),menu.(chip|cpu).$(BOARD_SUB).build.variant)
+ ifndef VARIANT
+ VARIANT := $(call PARSE_BOARD,$(BOARD_TAG),build.variant)
+ endif
+endif
+
+# grab any sources in the variant core path (variant.cpp defines pin/port mapping on SAM devices)
+ALT_CORE_C_SRCS := $(wildcard $(ALTERNATE_CORE_PATH)/variants/$(VARIANT)/*.c)
+ALT_CORE_CPP_SRCS := $(wildcard $(ALTERNATE_CORE_PATH)/variants/$(VARIANT)/*.cpp)
+ALT_CORE_S_SRCS := $(wildcard $(ALTERNATE_CORE_PATH)/variants/$(VARIANT)/*.S)
+
+# Use arm-toolchain from Arduino install if exists and user has not defined global version
+ifndef ARM_TOOLS_DIR
+ ARM_TOOLS_DIR = $(call dir_if_exists,$(wildcard $(ARDUINO_PACKAGE_DIR)/$(ARDMK_VENDOR)/tools/arm-none-eabi-gcc/*))
+ $(call show_config_variable,ARM_TOOLS_DIR,[COMPUTED],(from ARDUINO_PACKAGE_DIR))
+else
+ $(call show_config_variable,ARM_TOOLS_DIR,[USER])
+endif
+
+# define plaform lib dir from Arduino ARM support
+ifndef ARDUINO_PLATFORM_LIB_PATH
+ ARDUINO_PLATFORM_LIB_PATH := $(ALTERNATE_CORE_PATH)/libraries
+ $(call show_config_variable,ARDUINO_PLATFORM_LIB_PATH,[COMPUTED],(from ARDUINO_PACKAGE_DIR))
+endif
+
+########################################################################
+# command names
+
+ifndef CC_NAME
+ CC_NAME := $(call PARSE_BOARD,$(BOARD_TAG),build.command.gcc)
+ ifndef CC_NAME
+ CC_NAME := arm-none-eabi-gcc
+ else
+ $(call show_config_variable,CC_NAME,[COMPUTED])
+ endif
+endif
+
+ifndef CXX_NAME
+ CXX_NAME := $(call PARSE_BOARD,$(BOARD_TAG),build.command.g++)
+ ifndef CXX_NAME
+ CXX_NAME := arm-none-eabi-g++
+ else
+ $(call show_config_variable,CXX_NAME,[COMPUTED])
+ endif
+endif
+
+ifndef AS_NAME
+ AS_NAME := $(call PARSE_BOARD,$(BOARD_TAG),build.command.as)
+ ifndef AS_NAME
+ AS_NAME := arm-none-eabi-gcc-as
+ else
+ $(call show_config_variable,AS_NAME,[COMPUTED])
+ endif
+endif
+
+ifndef OBJCOPY_NAME
+ OBJCOPY_NAME := $(call PARSE_BOARD,$(BOARD_TAG),build.command.objcopy)
+ ifndef OBJCOPY_NAME
+ OBJCOPY_NAME := arm-none-eabi-objcopy
+ else
+ $(call show_config_variable,OBJCOPY_NAME,[COMPUTED])
+ endif
+endif
+
+ifndef OBJDUMP_NAME
+ OBJDUMP_NAME := $(call PARSE_BOARD,$(BOARD_TAG),build.command.objdump)
+ ifndef OBJDUMP_NAME
+ OBJDUMP_NAME := arm-none-eabi-objdump
+ else
+ $(call show_config_variable,OBJDUMP_NAME,[COMPUTED])
+ endif
+endif
+
+ifndef AR_NAME
+ AR_NAME := $(call PARSE_BOARD,$(BOARD_TAG),build.command.ar)
+ ifndef AR_NAME
+ AR_NAME := arm-none-eabi-ar
+ else
+ $(call show_config_variable,AR_NAME,[COMPUTED])
+ endif
+endif
+
+ifndef SIZE_NAME
+ SIZE_NAME := $(call PARSE_BOARD,$(BOARD_TAG),build.command.size)
+ ifndef SIZE_NAME
+ SIZE_NAME := arm-none-eabi-size
+ else
+ $(call show_config_variable,SIZE_NAME,[COMPUTED])
+ endif
+endif
+
+ifndef NM_NAME
+ NM_NAME := $(call PARSE_BOARD,$(BOARD_TAG),build.command.nm)
+ ifndef NM_NAME
+ NM_NAME := arm-none-eabi-gcc-nm
+ else
+ $(call show_config_variable,NM_NAME,[COMPUTED])
+ endif
+endif
+
+ifndef GDB_NAME
+ GDB_NAME := $(call PARSE_BOARD,$(BOARD_TAG),build.command.gdb)
+ ifndef GDB_NAME
+ GDB_NAME := arm-none-eabi-gdb
+ else
+ $(call show_config_variable,GDB_NAME,[COMPUTED])
+ endif
+endif
+
+ifndef UPLOAD_TOOL
+ UPLOAD_TOOL := $(call PARSE_BOARD,$(BOARD_TAG),upload.tool)
+ ifndef UPLOAD_TOOL
+ UPLOAD_TOOL := openocd
+ else
+ $(call show_config_variable,UPLOAD_TOOL,[COMPUTED])
+ endif
+endif
+
+ifndef BOOTLOADER_UPLOAD_TOOL
+ BOOTLOADER_UPLOAD_TOOL := $(call PARSE_BOARD,$(BOARD_TAG),bootloader.tool)
+ ifndef BOOTLOADER_UPLOAD_TOOL
+ BOOTLOADER_UPLOAD_TOOL := openocd
+ else
+ $(call show_config_variable,BOOTLOADER_UPLOAD_TOOL,[COMPUTED])
+ endif
+endif
+
+# processor stuff
+ifndef MCU
+ MCU := $(call PARSE_BOARD,$(BOARD_TAG),build.mcu)
+endif
+
+ifndef MCU_FLAG_NAME
+ MCU_FLAG_NAME=mcpu
+endif
+
+# native port emulates an AVR chip to use AVRDUDE
+ifndef AVRDUDE_MCU
+ AVRDUDE_MCU := $(call PARSE_BOARD,$(BOARD_TAG),build.emu.mcu)
+endif
+
+# GDP settings
+ifndef GDB_PORT
+ # default to localhost default OpenOCD port
+ GDB_PORT = localhost:3333
+endif
+
+ifndef GDB_OPTS
+ # if using BMP do a scan and attach
+ ifeq ($(findstring /dev/tty, $(strip $(GDB_PORT))), /dev/tty)
+ GDB_OPTS = -ex "target extended-remote $(GDB_PORT)" -ex "monitor swdp_scan" -ex "attach 1" -ex "load" -d $(OBJDIR) $(TARGET_ELF)
+ else
+ GDB_OPTS = -ex "target extended-remote $(GDB_PORT)" -ex "load" -d $(OBJDIR) $(TARGET_ELF)
+ endif
+endif
+
+ifndef GDB_UPLOAD_OPTS
+ GDB_UPLOAD_OPTS = $(GDB_OPTS) -ex "set confirm off" -ex "set target-async off" -ex "set remotetimeout 30" -ex "detach" -ex "kill" -ex "quit"
+endif
+
+########################################################################
+# OpenOCD for SAM devices
+
+ifndef OPENOCD
+ BUNDLED_OPENOCD_DIR := $(call dir_if_exists,$(ARDUINO_PACKAGE_DIR)/$(ARDMK_VENDOR)/tools/openocd)
+ # Try Arduino support package first
+ ifdef BUNDLED_OPENOCD_DIR
+ OPENOCD_VER := $(shell basename $(wildcard $(BUNDLED_OPENOCD_DIR)/*))
+ OPENOCD = $(BUNDLED_OPENOCD_DIR)/$(OPENOCD_VER)/bin/openocd -s $(BUNDLED_OPENOCD_DIR)/$(OPENOCD_VER)/share/openocd/scripts/
+ $(call show_config_variable,OPENOCD,[AUTODETECTED],(from ARDUINO_PACKAGE_DIR))
+ else
+ # Otherwise look on user path
+ OPENOCD := $(shell which openocd 2>/dev/null)
+ ifdef OPENOCD
+ $(call show_config_variable,OPENOCD,[AUTODETECTED],(found in $$PATH))
+ endif
+ endif
+else
+ $(call show_config_variable,OPENOCD,[USER])
+endif
+
+ifndef OPENOCD_OPTS
+ OPENOCD_OPTS += -d2 -f $(ALTERNATE_CORE_PATH)/variants/$(VARIANT)/$(OPENOCD_SCRIPT)
+endif
+
+########################################################################
+# Bossa for SAM devices
+
+ifndef BOSSA
+ BUNDLED_BOSSA_DIR := $(call dir_if_exists,$(ARDUINO_PACKAGE_DIR)/$(ARDMK_VENDOR)/tools/bossac)
+ # Try Arduino support package first
+ ifdef BUNDLED_BOSSA_DIR
+ BOSSA_VER := $(shell basename $(wildcard $(BUNDLED_BOSSA_DIR)/*))
+ BOSSA = $(BUNDLED_BOSSA_DIR)/$(BOSSA_VER)/bossac
+ $(call show_config_variable,BOSSA,[AUTODETECTED],(from ARDUINO_PACKAGE_DIR))
+ else
+ # Otherwise look on user path
+ BOSSA := $(shell which bossac 2>/dev/null)
+ ifdef BOSSA
+ $(call show_config_variable,BOSSA,[AUTODETECTED],(found in $$PATH))
+ endif
+ endif
+else
+ $(call show_config_variable,BOSSA,[USER])
+endif
+
+ifndef BOSSA_OPTS
+ BOSSA_OPTS += -d --info --erase --write --verify --reset
+endif
+
+get_bootloader = $(shell $(RESET_CMD) | tail -1)
+
+# if not bootloader port defined (ISP_PORT), automatically grab first port after reset
+# if not on windows
+ifndef ISP_PORT
+ ifeq ($(CURRENT_OS), WINDOWS)
+ BOSSA_OPTS += --port=$(COM_STYLE_MONITOR_PORT)
+ else
+ BOSSA_OPTS += --port=$(call get_monitor_port)
+ endif
+else
+ BOSSA_OPTS += --port=$(ISP_PORT)
+endif
+
+########################################################################
+# EXECUTABLES
+# Define them here to use ARM_TOOLS_PATH and allow auto finding of AVR_TOOLS_PATH
+OVERRIDE_EXECUTABLES = 1
+
+ARM_TOOLS_PATH := $(ARM_TOOLS_DIR)/bin
+CC = $(ARM_TOOLS_PATH)/$(CC_NAME)
+CXX = $(ARM_TOOLS_PATH)/$(CXX_NAME)
+AS = $(ARM_TOOLS_PATH)/$(AS_NAME)
+OBJCOPY = $(ARM_TOOLS_PATH)/$(OBJCOPY_NAME)
+OBJDUMP = $(ARM_TOOLS_PATH)/$(OBJDUMP_NAME)
+AR = $(ARM_TOOLS_PATH)/$(AR_NAME)
+SIZE = $(ARM_TOOLS_PATH)/$(SIZE_NAME)
+NM = $(ARM_TOOLS_PATH)/$(NM_NAME)
+#GDB = $(ARM_TOOLS_PATH)/$(GDB_NAME)
+# Use system gdb for now as Arduino supplied has lib error?
+GDB = $(GDB_NAME)
+
+########################################################################
+# FLAGS
+
+ifndef USB_TYPE
+ USB_TYPE = USBCON
+endif
+
+ifndef USB_PRODUCT
+ USB_PRODUCT := $(call PARSE_BOARD,$(BOARD_TAG),build.usb_product)
+ ifdef USB_PRODUCT
+ $(call show_config_variable,USB_PRODUCT,[COMPUTED])
+ endif
+endif
+
+ifndef USB_MANUFACTURER
+ USB_MANUFACTURER := $(call PARSE_BOARD,$(BOARD_TAG),build.usb_manufacturer)
+ ifndef USB_MANUFACTURER
+ USB_MANUFACTURER = "Unknown"
+ else
+ $(call show_config_variable,USB_MANUFACTURER,[COMPUTED])
+ endif
+endif
+
+ifndef USB_VID
+ USB_VID := $(call PARSE_BOARD,$(BOARD_TAG),build.vid)
+ ifdef USB_VID
+ $(call show_config_variable,USB_VID,[COMPUTED])
+ endif
+endif
+
+ifndef USB_PID
+ USB_PID := $(call PARSE_BOARD,$(BOARD_TAG),build.pid)
+ ifdef USB_PID
+ $(call show_config_variable,USB_PID,[COMPUTED])
+ endif
+endif
+
+# Bootloader settings
+ifndef BOOTLOADER_SIZE
+ BOOTLOADER_SIZE := $(call PARSE_BOARD,$(BOARD_TAG),bootloader.size)
+ ifndef BOOTLOADER_SIZE
+ BOOTLOADER_SIZE := 0x2000
+ else
+ $(call show_config_variable,BOOTLOADER_SIZE,[COMPUTED])
+ endif
+endif
+
+ifndef BOOTLOADER_UNPROTECT
+ BOOTLOADER_UNPROTECT := $(call PARSE_BOARD,$(BOARD_TAG),bootloader.cmd_unprotect)
+ ifndef BOOTLOADER_UNPROTECT
+ BOOTLOADER_UNPROTECT := at91samd bootloader 0
+ else
+ $(call show_config_variable,BOOTLOADER_UNPROTECT,[COMPUTED])
+ endif
+endif
+
+ifndef BOOTLOADER_PROTECT
+ BOOTLOADER_PROTECT := $(call PARSE_BOARD,$(BOARD_TAG),bootloader.cmd_protect)
+ ifndef BOOTLOADER_PROTECT
+ BOOTLOADER_PROTECT := at91samd bootloader 16384
+ else
+ $(call show_config_variable,BOOTLOADER_PROTECT,[COMPUTED])
+ endif
+endif
+
+ifndef BOOTLOADER_PROTECT_VERIFY
+ BOOTLOADER_PROTECT_VERIFY := $(call PARSE_BOARD,$(BOARD_TAG),bootloader.cmd_protect_verify)
+ ifndef BOOTLOADER_PROTECT_VERIFY
+ BOOTLOADER_PROTECT_VERIFY := at91samd bootloader
+ else
+ $(call show_config_variable,BOOTLOADER_PROTECT_VERIFY,[COMPUTED])
+ endif
+endif
+
+# C99 with GNU extensions required for C sources using old compiler
+CC_VERNUM = $(shell $(CC) -dumpversion | sed 's/\.//g')
+ifneq ($(shell expr $(CC_VERNUM) '>' 490), 1)
+ CFLAGS_STD = -std=gnu99
+endif
+
+CPPFLAGS += -DMD -D$(USB_TYPE) '-DUSB_PRODUCT=$(USB_PRODUCT)' '-DUSB_MANUFACTURER=$(USB_MANUFACTURER)'
+
+# Get extra define flags from boards.txt
+EXFLAGS := $(shell echo $(call PARSE_BOARD,$(BOARD_TAG),build.extra_flags) | grep -oE '(-D)\w+')
+
+# Strip only defines from extra flags as boards file appends user {build.usb}
+CPPFLAGS += $(EXFLAGS)
+CPPFLAGS += -DUSB_VID=$(USB_VID)
+CPPFLAGS += -DUSB_PID=$(USB_PID)
+# Cortex compiler flags
+CPPFLAGS += -mthumb -nostdlib --param max-inline-insns-single=500 -fno-exceptions -Wl,-Map=$(OBJDIR)/$(TARGET).map
+CXXFLAGS += -fno-rtti -fno-threadsafe-statics -std=gnu++11
+
+AMCU := $(call PARSE_BOARD,$(BOARD_TAG),build.mcu)
+BOARD_LINKER_SCRIPT := $(call PARSE_BOARD,$(BOARD_TAG),build.ldscript)
+OPENOCD_SCRIPT := $(call PARSE_BOARD,$(BOARD_TAG),build.openocdscript)
+# TODO Hard defines Cortex M0 math lib - should be dynamic
+LDFLAGS += --specs=nano.specs --specs=nosys.specs -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group -L$(LIB_PATH) -larm_cortexM0l_math -lm
+LINKER_SCRIPTS := -T$(ALTERNATE_CORE_PATH)/variants/$(VARIANT)/$(BOARD_LINKER_SCRIPT)
+OTHER_LIBS := $(call PARSE_BOARD,$(BOARD_TAG),build.flags.libs)
+
+# OpenOCD reset command only for now
+ifeq ($(strip $(UPLOAD_TOOL)), openocd)
+ RESET_CMD = $(OPENOCD) $(OPENOCD_OPTS) -c "telnet_port disabled; init; targets; reset run; shutdown"
+else
+ # Set zero flag for ard-reset for 1200 baud boot to bootloader
+ ARD_RESET_OPTS += --zero
+endif
+
+########################################################################
+# automatially include Arduino.mk for the user
+
+$(call show_separator)
+$(call arduino_output,Arduino.mk Configuration:)
+include $(ARDMK_DIR)/Arduino.mk
diff --git a/Teensy.mk b/Teensy.mk
index 8bd822b..3d0114c 100644
--- a/Teensy.mk
+++ b/Teensy.mk
@@ -146,7 +146,7 @@ endif
# processor stuff
ifndef MCU
- MCU := $(call PARSE_TEENSY,$(BOARD_TAG),build.cpu)
+ MCU := $(call PARSE_TEENSY,$(BOARD_TAG),build.mcu)
endif
ifndef MCU_FLAG_NAME
diff --git a/arduino-mk-vars.md b/arduino-mk-vars.md
index b86496a..e3b6f07 100644
--- a/arduino-mk-vars.md
+++ b/arduino-mk-vars.md
@@ -11,6 +11,7 @@ The following are the different variables that can be overwritten in the user ma
* [Avrdude setting variables](#avrdude-setting-variables)
* [Bootloader variables](#bootloader-variables)
* [ChipKIT variables](#chipkit-variables)
+* [ARM variables](#arm-variables)
* [Ctags variables](#ctags-variables)
## Global variables
@@ -73,6 +74,29 @@ AVR_TOOLS_DIR = /usr/share/arduino/hardware/tools/avr
----
+### ARM_TOOLS_DIR
+
+**Description:**
+
+Directory where the arm toolchain is installed. `arm-none-eabi-*` should be
+within a /bin subdirectory.
+
+Can usually be detected from `$ARDUINO_PACKAGE_DIR` /tools subdirectory when ARM
+device support is installed.
+
+**Example:**
+
+```Makefile
+ARM_TOOLS_DIR = /usr
+# or
+ARM_TOOLS_DIR =
+/usr/share/arduino/hardware/tools/arm-none-eabi-gcc/VERSION
+```
+
+**Requirement:** *Optional*
+
+----
+
### RESET_CMD
**Description:**
@@ -114,6 +138,27 @@ ARDUINO_DIR = /Applications/Arduino.app/Contents/Java
----
+### ARDUINO_PACKAGE_DIR
+
+**Description:**
+
+Directory where the Arduino package support files are stored. Can auto-detect based on default OS IDE locations.
+
+**Example:**
+
+```Makefile
+# Linux
+ARDUINO_PACKAGE_DIR = $(HOME)/.arduino15/packages
+# Mac OS X
+ARDUINO_PACKAGE_DIR = $(HOME)/Library/Arduino15/packages
+# Windows
+ARDUINO_PACKAGE_DIR = $(USERPROFILE)/AppData/Local/Arduino15/packages
+```
+
+**Requirement:** *Optional*
+
+----
+
### ARDUINO_PLATFORM_LIB_PATH
**Description:**
@@ -155,12 +200,13 @@ ARDUINO_VERSION = 105
Architecture for Arduino 1.5+
-Defaults to unset for 1.0 or `avr` for 1.5+
+Defaults to unset for 1.0 or `avr` for 1.5+. This value is not literally the chip architecture but will often be
+the chip series within a vendor's 'hardware' folder. For example, will default to `samd` if using Sam.mk.
**Example:**
```Makefile
-ARCHITECTURE = sam
+ARCHITECTURE = arm
```
**Requirement:** *Optional*
@@ -171,9 +217,9 @@ ARCHITECTURE = sam
**Description:**
-Board vendor/maintainer.
+Board vendor/maintainer/series.
-Defaults to `arduino`
+Defaults to `arduino`.
**Example:**
@@ -658,7 +704,8 @@ ISP_PROG = stk500v1
**Description:**
-Device path to ArduinoISP. Not needed for hardware ISP's.
+Device path to ArduinoISP. Not needed for hardware ISP's. Also used to define
+bootloader port on SAMD devices.
**Example:**
@@ -871,6 +918,18 @@ NM_NAME = pic32-nm
----
+### GDB_NAME
+
+**Description:**
+
+GDB utility.
+
+Defaults to `arm-none-eabi-gdb`
+
+**Requirement:** *Optional*
+
+----
+
### OPTIMIZATION_LEVEL
**Description:**
@@ -1229,6 +1288,54 @@ ALTERNATE_CORE_PATH = $(HOME)/sketchbook/hardware/arduino-tiny/cores/tiny
----
+### CORE_VER
+
+**Description:**
+
+Alternate core release version. The Arduino board support packages are within
+a sub-directory indicated by this define.
+
+Defaults to package current release.
+
+**Example:**
+
+```Makefile
+CORE_VER = 1.6.17
+```
+
+**Requirement:** *Optional*
+
+----
+
+### CMSIS_DIR
+
+**Description:**
+
+Path to ARM CMSIS. Normally installed as part of ARM board support.
+
+Defaults to `ARDUINO_PACKAGE_DIR/tools/CMSIS/4.5.0/CMSIS`
+
+**Example:**
+
+```Makefile
+CMSIS_DIR = /usr/share/CMSIS
+```
+
+**Requirement:** *Optional*
+
+----
+
+### CMSIS_ATMEL_DIR
+
+**Description:**
+
+Path to CMSIS-Atmel directory. Installed with ARM support package.
+
+Defaults to `ARDUINO_PACKAGE_DIR/tools/CMSIS-Atmel/1.1.0/CMSIS`
+
+**Requirement:** *Optional*
+----
+
### BOARDS_TXT
**Description:**
@@ -1385,6 +1492,67 @@ Would result in an absolute path to the bootloader hex file of `$(HOME)/sketchbo
----
+### BOOTLOADER_SIZE
+
+**Description:**
+
+Size of bootloader on ARM devices, ensures correct start address when flashing
+application area. Normally parsed from boards.txt
+
+Defaults to `0x2000`
+
+**Requirement:** *Optional*
+
+----
+
+### BOOTLOADER_UNPROTECT
+
+**Description:**
+
+Bootloader unprotect sequence for upload tool. Normally parsed from boards.txt
+
+Defaults to `at91samd bootloader 0`
+
+**Requirement:** *Optional*
+
+----
+
+### BOOTLOADER_PROTECT
+
+**Description:**
+
+Bootloader protect sequence for upload tool. Normally parsed from boards.txt
+
+Defaults to `at91samd bootloader 16384`
+
+**Requirement:** *Optional*
+
+----
+
+### BOOTLOADER_PROTECT_VERIFY
+
+**Description:**
+
+Bootloader protect and verify sequence for upload tool. Normally parsed from boards.txt
+
+Defaults to `at91samd bootloader`
+
+**Requirement:** *Optional*
+
+----
+
+### BOOTLOADER_UPLOAD_TOOL
+
+**Description:**
+
+Bootloader upload binary to use. Normally parsed from boards.txt.
+
+Defaults to `openocd`
+
+**Requirement:** *Optional*
+
+----
+
## ChipKIT variables
### MPIDE_DIR
@@ -1405,69 +1573,208 @@ MPIDE_DIR = $(HOME)/mpide
----
-## Ctags variables
+### MPIDE_PREFERENCES_PATH
-### TAGS_FILE
+**Description:**
+
+Path to chipKIT `preferences.txt` file.
+
+Usually can be auto-detected as `AUTO_MPIDE_PREFERENCES_PATH` from the defaults `$(HOME)/.mpide/preferences.txt` (Linux) or `$(HOME)/Library/Mpide/preferences.txt` (OSX)
+
+**Example:**
+
+```Makefile
+MPIDE_PREFERENCES_PATH = $(HOME)/chipkit/preferences.txt
+```
+
+**Requirement:** *Optional*
+
+----
+
+## ARM variables
+
+### UPLOAD_TOOL
**Description:**
-Output file name for tags. Defaults to 'tags'.
+Tool to upload binary to device. Normally parsed from boards.txt.
+
+Defaults to `openocd`
**Example:**
```Makefile
-TAGS_FILE = .tags
+UPLOAD_TOOL = gdb
```
**Requirement:** *Optional*
----
-### CTAGS_OPTS
+### DEBUG
**Description:**
-Additional options to pass to `ctags` command.
+Define to set `DEBUG_FLAGS` and allow stepping of code using GDB.
+
+Defaults to undefined.
**Example:**
```Makefile
-# Run ctags in verbose mode
-CTAGS_OPTS = -V
+DEBUG = 1
```
**Requirement:** *Optional*
----
-### CTAGS_CMD
+### GDB_PORT
**Description:**
-Location of `ctags` binary. Defaults to user path.
+Server port to use for GDB debugging or upload. Default assumes server running
+on localhost but can re-define to use Black Magic Probe serial port.
+
+Defaults to `localhost:3333`
**Example:**
```Makefile
-CTAGS_CMD = /usr/local/bin/
+GDB_PORT = /dev/ttyACM0
```
**Requirement:** *Optional*
----
-### MPIDE_PREFERENCES_PATH
+### GDB_OPTS
**Description:**
-Path to chipKIT `preferences.txt` file.
+Optional arguments to parse to GDB command.
-Usually can be auto-detected as `AUTO_MPIDE_PREFERENCES_PATH` from the defaults `$(HOME)/.mpide/preferences.txt` (Linux) or `$(HOME)/Library/Mpide/preferences.txt` (OSX)
+Defaults to `-ex "target extended-remote $(GDB_PORT)" -ex "monitor swdp_scan" -ex "attach 1" -ex "load" -d $(OBJDIR) $(TARGET_ELF)`
+
+**Requirement:** *Optional*
+
+----
+
+### GDB_UPLOAD_OPTS
+
+**Description:**
+
+Optional arguments to parse to GDB command when uploading binary only.
+
+Defaults to `GDB_UPLOAD_OPTS = $(GDB_OPTS) -ex "set confirm off" -ex "set target-async off" -ex "set remotetimeout 30" -ex "detach" -ex "kill" -ex "quit"`
+
+**Requirement:** *Optional*
+
+----
+
+### BOSSA
+
+**Description:**
+
+Path to bossac binary.
+
+Can usually be detected from `$ARDUINO_PACKAGE_DIR` /tools subdirectory when ARM
+device support is installed.
+
+**Requirement:** *Optional*
+
+----
+
+### BOSSA_OPTS
+
+**Description:**
+
+Flags to pass to bossac command.
+
+Defaults to `-d --info --erase --write --verify --reset`
+
+**Requirement:** *Optional*
+
+----
+
+### OPENOCD
+
+**Description:**
+
+Path to openocd binary.
+
+Can usually be detected from `$ARDUINO_PACKAGE_DIR` /tools subdirectory when ARM
+device support is installed.
+
+**Requirement:** *Optional*
+
+----
+
+### OPENOCD_OPTS
+
+**Description:**
+
+Flags to pass to openocd command. If using openocd from non-Arduino
+distributions, one should define this with the path to the Arduino openocd script.
+
+Defaults to `-d2`
+
+Example:
+
+```Makefile
+OPENOCD_OPTS = $(ARDUINO_PACKAGE_DIR)/$(ARDMK_VENDOR)/tools/openocd/0.9.0-arduino6-static/share/openocd/scripts/ -f $(ARDUINO_PACKAGE_DIR)/$(ARDMK_VENDOR)/hardware/samd/1.6.17/variants/$(VARIANT)/$(OPENOCD_SCRIPT)
+```
+
+**Requirement:** *Optional*
+
+
+----
+
+## Ctags variables
+
+### TAGS_FILE
+
+**Description:**
+
+Output file name for tags. Defaults to 'tags'.
**Example:**
```Makefile
-MPIDE_PREFERENCES_PATH = $(HOME)/chipkit/preferences.txt
+TAGS_FILE = .tags
+```
+
+**Requirement:** *Optional*
+
+----
+
+### CTAGS_OPTS
+
+**Description:**
+
+Additional options to pass to `ctags` command.
+
+**Example:**
+
+```Makefile
+# Run ctags in verbose mode
+CTAGS_OPTS = -V
+```
+
+**Requirement:** *Optional*
+
+----
+
+### CTAGS_CMD
+
+**Description:**
+
+Location of `ctags` binary. Defaults to user path.
+
+**Example:**
+
+```Makefile
+CTAGS_CMD = /usr/local/bin/
```
**Requirement:** *Optional*
diff --git a/bin/ard-reset-arduino b/bin/ard-reset-arduino
index 1f2c7e9..d6f974f 100755
--- a/bin/ard-reset-arduino
+++ b/bin/ard-reset-arduino
@@ -2,6 +2,7 @@
from __future__ import print_function
import serial
+import serial.tools.list_ports
import os.path
import argparse
from time import sleep
@@ -13,13 +14,100 @@ except:
pyserial_version = 2 # less than 2.3
parser = argparse.ArgumentParser(description='Reset an Arduino')
+parser.add_argument('--zero', action='store_true', help='Reset Arduino Zero or similar Native USB to enter bootloader')
parser.add_argument('--caterina', action='store_true', help='Reset a Leonardo, Micro, Robot or LilyPadUSB.')
parser.add_argument('--verbose', action='store_true', help="Watch what's going on on STDERR.")
parser.add_argument('--period', default=0.1, help='Specify the DTR pulse width in seconds.')
parser.add_argument('port', nargs=1, help='Serial device e.g. /dev/ttyACM0')
args = parser.parse_args()
-if args.caterina:
+
+def list_ports(output=False):
+ """ Lists serial ports attached
+
+ :returns
+ A list of paths to serial ports on system
+ """
+ ports = serial.tools.list_ports.comports()
+ connected = [port[0] for port in ports]
+ if output:
+ print(connected)
+
+ return connected
+
+
+def new_port(old, new):
+ """ Checks if a new port has attached
+
+ Args:
+ old: previous list of ports to check
+ new: current list of ports to check
+ Returns:
+ index of port in 'new' if new port found, otherwise -1
+ """
+ new_port = -1
+
+ for port in new:
+ if port not in old:
+ new_port = new.index(port)
+ break
+
+ return new_port
+
+
+if args.zero:
+ # number of trys to attempt
+ zero_attempts = 20 # ~2 seconds
+ initial_ports = list_ports(args.verbose)
+
+ if args.verbose:
+ print('Attempting to enter bootloader using 1200 bps open/close on port %s' % args.port[0])
+
+ ser = serial.Serial(args.port[0], 57600)
+ ser.close()
+
+ if pyserial_version < 3:
+ ser.setBaudrate(1200)
+ else:
+ ser.baudrate = 1200
+
+ # do the open/close at 1200 BAUD
+ ser.open()
+ ser.close()
+
+ if args.verbose:
+ print('Done. Waiting for bootloader port to attach...')
+
+ # get new list of ports
+ reset_ports = list_ports(args.verbose)
+
+ # wait for new port or port to return
+ port_index = new_port(initial_ports, reset_ports)
+
+ # keep checking until new port appears or timeout
+ while port_index < 0:
+ # count down attempts and leave if expired
+ zero_attempts -= 1
+ if zero_attempts < 0:
+ break
+ sleep(0.1)
+ # get list of ports after bootloader toggle performed
+ reset_ports = list_ports(args.verbose)
+ # if a port drops, set initial ports to reset ports so that
+ # next attached device will be new port
+ if (len(reset_ports) < len(initial_ports)):
+ initial_ports = reset_ports
+ # check if a new port has attached and return the index if it has
+ port_index = new_port(initial_ports, reset_ports)
+ # return the new port if detected, otherwise return passed port
+ if port_index is -1:
+ bootloader_port = args.port[0]
+ else:
+ bootloader_port = reset_ports[port_index]
+
+ # print so that `tail -1` can be piped for bootloader port
+ print(bootloader_port)
+elif args.caterina:
if args.verbose: print('Forcing reset using 1200bps open/close on port %s' % args.port[0])
ser = serial.Serial(args.port[0], 57600)
ser.close()
diff --git a/examples/MZeroBlink/MZeroBlink.ino b/examples/MZeroBlink/MZeroBlink.ino
new file mode 100644
index 0000000..f9a59a9
--- /dev/null
+++ b/examples/MZeroBlink/MZeroBlink.ino
@@ -0,0 +1,19 @@
+/*
+ Blink
+ Turns on an LED on for one second, then off for one second, repeatedly.
+
+ This example code is in the public domain.
+ */
+
+void setup() {
+ // initialize the digital pin as an output.
+ // Pin 13 has an LED connected on most Arduino boards:
+ pinMode(13, OUTPUT);
+}
+
+void loop() {
+ digitalWrite(13, HIGH); // set the LED on
+ delay(1000); // wait for a second
+ digitalWrite(13, LOW); // set the LED off
+ delay(1000); // wait for a second
+}
diff --git a/examples/MZeroBlink/Makefile b/examples/MZeroBlink/Makefile
new file mode 100644
index 0000000..29cb90b
--- /dev/null
+++ b/examples/MZeroBlink/Makefile
@@ -0,0 +1,24 @@
+# Arduino M0 Pro Programming Port
+BOARD_TAG = mzero_pro_bl_dbg
+
+# Define debug if you want to use gdb
+#DEBUG = 1
+
+# Define port if using Black Magic Probe rather than default localhost:3333
+#GDB_PORT = /dev/ttyACM0
+
+# Define ARM toolchain dir if not using Arduino supplied
+#ARM_TOOLS_DIR = /usr
+
+# Define AVR toolchain dir if not using Arduino supplied and using native port
+#AVR_TOOLS_DIR = /usr
+
+# Define Arduino support package installation path where SAM device support has been installed
+# Linux
+# ARDUINO_PACKAGE_DIR := $(HOME)/.arduino15/packages
+# macOS
+# ARDUINO_PACKAGE_DIR := $(HOME)/Library/Arduino15/packages
+# Windows
+# ARDUINO_PACKAGE_DIR := "C:/Users/$(USER)/AppData/Local/Arduino15/packages"
+
+include ../../Sam.mk
diff --git a/examples/ZeroBlink/Makefile b/examples/ZeroBlink/Makefile
new file mode 100644
index 0000000..60c8435
--- /dev/null
+++ b/examples/ZeroBlink/Makefile
@@ -0,0 +1,30 @@
+# Arduino Zero Native Port (should work with Feather, MKR1000 etc.)
+# BOOTLOADER: The bootloader on these devices loaded when reset is pressed twice
+# or the port is opened/closed at 1200 BAUD. If there is no program on the device,
+# you may have to manually enter bootloader by toggling reset twice.
+# see http://www.avdweb.nl/arduino/samd21/virus.html
+BOARD_TAG = arduino_zero_native
+
+# Define alternative core path if using another board supplier
+#ALTERNATE_CORE_PATH = $(HOME)/Arduino/hardware/sparkfun/samd
+
+# Define monitor port and isp port (bootloader port).
+# Will automatically detect if Linux/macOS but MUST be defined on Windows
+#MONITOR_PORT = com40 # CDC serial
+#ISP_PORT = com39 # bootloader
+
+# Define ARM toolchain dir if not using Arduino supplied
+#ARM_TOOLS_DIR = /usr
+
+# Define AVR toolchain dir if not using Arduino supplied and using native port
+#AVR_TOOLS_DIR = /usr
+
+# Define Arduino support package installation path where SAM device support has been installed
+# Linux
+#ARDUINO_PACKAGE_DIR := $(HOME)/.arduino15/packages
+# macOS
+#ARDUINO_PACKAGE_DIR := $(HOME)/Library/Arduino15/packages
+# Windows
+#ARDUINO_PACKAGE_DIR := "C:/Users/$(USER)/AppData/Local/Arduino15/packages"
+
+include ../../Sam.mk
diff --git a/examples/ZeroBlink/ZeroBlink.ino b/examples/ZeroBlink/ZeroBlink.ino
new file mode 100644
index 0000000..f9a59a9
--- /dev/null
+++ b/examples/ZeroBlink/ZeroBlink.ino
@@ -0,0 +1,19 @@
+/*
+ Blink
+ Turns on an LED on for one second, then off for one second, repeatedly.
+
+ This example code is in the public domain.
+ */
+
+void setup() {
+ // initialize the digital pin as an output.
+ // Pin 13 has an LED connected on most Arduino boards:
+ pinMode(13, OUTPUT);
+}
+
+void loop() {
+ digitalWrite(13, HIGH); // set the LED on
+ delay(1000); // wait for a second
+ digitalWrite(13, LOW); // set the LED off
+ delay(1000); // wait for a second
+}
diff --git a/tests/script/runtests.sh b/tests/script/runtests.sh
index 7792186..648a0cf 100755
--- a/tests/script/runtests.sh
+++ b/tests/script/runtests.sh
@@ -7,7 +7,7 @@ failures=()
# These examples cannot be tested easily at the moment as they require
# alternate cores. The MakefileExample doesn't actually contain any source code
# to compile.
-NON_TESTABLE_EXAMPLES=(ATtinyBlink MakefileExample TinySoftWareSerial BlinkOpenCM BlinkTeensy BlinkNetworkRPi BlinkInAVRC)
+NON_TESTABLE_EXAMPLES=(ATtinyBlink MakefileExample TinySoftWareSerial BlinkOpenCM BlinkTeensy BlinkNetworkRPi BlinkInAVRC MZeroBlink ZeroBlink)
for dir in $TESTS_DIR/*/
do