aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/README4
-rw-r--r--lib/bossac/LICENSE24
-rw-r--r--lib/bossac/Makefile347
-rw-r--r--lib/bossac/src/Applet.cpp64
-rw-r--r--lib/bossac/src/Applet.h65
-rw-r--r--lib/bossac/src/CmdOpts.cpp159
-rw-r--r--lib/bossac/src/CmdOpts.h88
-rw-r--r--lib/bossac/src/D2xNvmFlash.cpp347
-rw-r--r--lib/bossac/src/D2xNvmFlash.h76
-rw-r--r--lib/bossac/src/D5xNvmFlash.cpp352
-rw-r--r--lib/bossac/src/D5xNvmFlash.h79
-rw-r--r--lib/bossac/src/Device.cpp692
-rw-r--r--lib/bossac/src/Device.h104
-rw-r--r--lib/bossac/src/EefcFlash.cpp363
-rw-r--r--lib/bossac/src/EefcFlash.h88
-rw-r--r--lib/bossac/src/EfcFlash.cpp295
-rw-r--r--lib/bossac/src/EfcFlash.h83
-rw-r--r--lib/bossac/src/FileError.h94
-rw-r--r--lib/bossac/src/Flash.cpp106
-rw-r--r--lib/bossac/src/Flash.h180
-rw-r--r--lib/bossac/src/Flasher.cpp373
-rw-r--r--lib/bossac/src/Flasher.h110
-rw-r--r--lib/bossac/src/LinuxPortFactory.cpp109
-rw-r--r--lib/bossac/src/LinuxPortFactory.h60
-rw-r--r--lib/bossac/src/PortFactory.h68
-rw-r--r--lib/bossac/src/PosixSerialPort.cpp332
-rw-r--r--lib/bossac/src/PosixSerialPort.h66
-rw-r--r--lib/bossac/src/Samba.cpp672
-rw-r--r--lib/bossac/src/Samba.h115
-rw-r--r--lib/bossac/src/SerialPort.h82
-rw-r--r--lib/bossac/src/WordCopyApplet.cpp62
-rw-r--r--lib/bossac/src/WordCopyApplet.h49
-rw-r--r--lib/bossac/src/WordCopyArm.asm47
-rw-r--r--lib/bossac/src/WordCopyArm.cpp25
-rw-r--r--lib/bossac/src/WordCopyArm.h18
-rw-r--r--lib/bossac/src/bossac.cpp489
36 files changed, 6287 insertions, 0 deletions
diff --git a/lib/README b/lib/README
index c785c7de..00f888e2 100644
--- a/lib/README
+++ b/lib/README
@@ -50,6 +50,10 @@ The hub-ctrl directory contains code from:
https://github.com/codazoda/hub-ctrl.c/
revision 42095e522859059e8a5f4ec05c1e3def01a870a9.
+The bossac directory contains code from:
+ https://github.com/shumatech/BOSSA
+version 1.9 (b176eeef918fc810045c832348590595120187b4).
+
The pru_rpmsg directory contains code from:
https://github.com/dinuxbg/pru-gcc-examples
revision 425a42d82006cf0aa24be27b483d2f6a41607489. The code is taken
diff --git a/lib/bossac/LICENSE b/lib/bossac/LICENSE
new file mode 100644
index 00000000..da4f48cd
--- /dev/null
+++ b/lib/bossac/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2011-2016, ShumaTech
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the <organization> nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/lib/bossac/Makefile b/lib/bossac/Makefile
new file mode 100644
index 00000000..35fe857a
--- /dev/null
+++ b/lib/bossac/Makefile
@@ -0,0 +1,347 @@
+.DEFAULT_GOAL := all
+
+#
+# Version
+#
+VERSION=1.9
+WXVERSION=3.0
+
+#
+# Source files
+#
+COMMON_SRCS=Samba.cpp Flash.cpp D5xNvmFlash.cpp D2xNvmFlash.cpp EfcFlash.cpp EefcFlash.cpp Applet.cpp WordCopyApplet.cpp Flasher.cpp Device.cpp
+APPLET_SRCS=WordCopyArm.asm
+BOSSA_SRCS=BossaForm.cpp BossaWindow.cpp BossaAbout.cpp BossaApp.cpp BossaBitmaps.cpp BossaInfo.cpp BossaThread.cpp BossaProgress.cpp
+BOSSA_BMPS=BossaLogo.bmp BossaIcon.bmp ShumaTechLogo.bmp
+BOSSAC_SRCS=bossac.cpp CmdOpts.cpp
+BOSSASH_SRCS=bossash.cpp Shell.cpp Command.cpp
+
+#
+# Build directories
+#
+BINDIR=bin
+OBJDIR=obj
+SRCDIR=src
+RESDIR=res
+INSTALLDIR=install
+
+#
+# Determine OS
+#
+OS:=$(shell uname -s | cut -c -7)
+
+#
+# Windows rules
+#
+ifeq ($(OS),MINGW32)
+# Use wxWindows development branch to work around font scaling issues on Windows
+WXVERSION=3.1
+EXE=.exe
+COMMON_SRCS+=WinSerialPort.cpp WinPortFactory.cpp
+COMMON_LDFLAGS=-Wl,--enable-auto-import -static -static-libstdc++ -static-libgcc
+COMMON_LIBS=-ltermcap -Wl,--as-needed -lsetupapi
+BOSSA_RC=BossaRes.rc
+WIXDIR="C:\Program Files (x86)\WiX Toolset v3.10\bin"
+CODE_SIGN=$(INSTALLDIR)\\code_sign.p12
+TIMESTAMP=http://timestamp.comodoca.com/authenticode
+SIGNTOOL="C:\Program Files (x86)\Windows Kits\10\bin\x64\signtool.exe"
+INF2CAT="C:\Program Files (x86)\Windows Kits\10\bin\x86\Inf2Cat.exe"
+
+define bossa_msi
+$(OBJDIR)\\bossa-$(1)-$(VERSION).wixobj: $(INSTALLDIR)\\bossa.wxs
+ $(WIXDIR)\\candle.exe -dVersion=$(VERSION) -arch $(1) -out $$@ -ext $(WIXDIR)\\WixUIExtension.dll -ext $(WIXDIR)\\WixDifxAppExtension.dll $$<
+
+$(BINDIR)\\bossa-$(1)-$(VERSION).msi: $(OBJDIR)\\bossa-$(1)-$(VERSION).wixobj
+ $(WIXDIR)\\light.exe -cultures:null -out $$@ -pdbout $(OBJDIR)\\bossa.wixpdb -sice:ICE57 -ext $(WIXDIR)\\WixUIExtension.dll -ext $(WIXDIR)\\WixDifxAppExtension.dll $(WIXDIR)\\difxapp_$(1).wixlib $$<
+ $$(Q)read -p "Password:" -rs PASSWORD; \
+ cmd /C '$(SIGNTOOL) sign /v /fd sha256 /f $(CODE_SIGN) -t $(TIMESTAMP) /p '$$$$PASSWORD' $$@'
+endef
+
+$(eval $(call bossa_msi,x86))
+$(eval $(call bossa_msi,x64))
+
+$(INSTALLDIR)\\bossa.cat: $(INSTALLDIR)\\bossa.inf
+ export TMP=$$(mktemp -d); \
+ cp $< $$TMP; \
+ cmd /C '$(INF2CAT) /v /driver:'$$(cygpath -w $$TMP)' /os:XP_X86,Vista_X86,Vista_X64,7_X86,7_X64,8_X86,8_X64,6_3_X86,6_3_X64,10_x86,10_x64'; \
+ mv $$TMP/bossa.cat $@; \
+ rm -rf $$TMP; \
+ read -p "Password:" -rs PASSWORD; \
+ cmd /C '$(SIGNTOOL) sign /v /fd sha256 /f $(CODE_SIGN) -t $(TIMESTAMP) /p '$$PASSWORD' $@'
+
+bossa.cat: $(INSTALLDIR)\\bossa.cat
+
+install32: $(BINDIR)\\bossa-x86-$(VERSION).msi
+install64: $(BINDIR)\\bossa-x64-$(VERSION).msi
+.PHONY: install
+install: strip install32 install64
+
+endif
+
+#
+# Linux rules
+#
+ifeq ($(OS),Linux)
+COMMON_SRCS+=PosixSerialPort.cpp LinuxPortFactory.cpp
+COMMON_LIBS=-Wl,--as-needed
+COMMON_CXXFLAGS=-std=c++11
+WX_LIBS+=-lX11
+
+MACHINE:=$(shell uname -m)
+
+install: strip
+ tar cvzf $(BINDIR)/bossa-$(MACHINE)-$(VERSION).tgz -C $(BINDIR) bossa$(EXE) bossac$(EXE) bossash$(EXE)
+endif
+
+#
+# OS X rules
+#
+ifeq ($(OS),Darwin)
+COMMON_SRCS+=PosixSerialPort.cpp OSXPortFactory.cpp
+COMMON_CXXFLAGS=-arch x86_64 -mmacosx-version-min=10.9
+COMMON_LDFLAGS=-arch x86_64 -mmacosx-version-min=10.9
+APP=BOSSA.app
+DMG=bossa-$(VERSION).dmg
+VOLUME=BOSSA
+BACKGROUND=$(INSTALLDIR)/background.png
+.PHONY: install
+app:
+ mkdir -p $(BINDIR)/$(APP)/Contents/MacOS
+ mkdir -p $(BINDIR)/$(APP)/Contents/Resources
+ cp -f $(INSTALLDIR)/Info.plist $(BINDIR)/$(APP)/Contents
+ echo -n "APPL????" > $(BINDIR)/$(APP)/Contents/PkgInfo
+ ln -f $(BINDIR)/bossa $(BINDIR)/$(APP)/Contents/MacOS/bossa
+ cp -f $(RESDIR)/BossaIcon.icns $(BINDIR)/$(APP)/Contents/Resources
+install: strip app
+ hdiutil create -ov -megabytes 5 -fs HFS+ -volname $(VOLUME) $(BINDIR)/$(DMG)
+ hdiutil attach -noautoopen $(BINDIR)/$(DMG)
+ cp -R $(BINDIR)/$(APP) /Volumes/$(VOLUME)/
+ cp $(BINDIR)/bossac$(EXE) /Volumes/$(VOLUME)/
+ cp $(BINDIR)/bossash$(EXE) /Volumes/$(VOLUME)/
+ ln -s /Applications /Volumes/$(VOLUME)/Applications
+ ln -s /usr/local/bin /Volumes/$(VOLUME)/bin
+ mkdir /Volumes/$(VOLUME)/.background
+ cp $(BACKGROUND) /Volumes/$(VOLUME)/.background
+ osascript < $(INSTALLDIR)/dmgwin.osa
+ hdiutil detach /Volumes/$(VOLUME)/
+ hdiutil convert -format UDBZ -o $(BINDIR)/tmp$(DMG) $(BINDIR)/$(DMG)
+ mv -f $(BINDIR)/tmp$(DMG) $(BINDIR)/$(DMG)
+endif
+
+#
+# OpenBSD rules
+# (This is likely to work without changes, but not tested, on other BSDs)
+#
+ifeq ($(OS),OpenBSD)
+
+COMMON_SRCS+=PosixSerialPort.cpp BSDPortFactory.cpp
+
+# This is only needed for bossash, but we can't add it to BOSSASH_LIBS here
+# because that one is redefined later.
+COMMON_LIBS+=-ltermcap
+
+# As of 5.7, OpenBSD packages WxWidgets 2.8
+# bossa builds, runs, and appears to play nicely with this version,
+# but fails to do anything useful on systems that don't have hardware
+# serial ports because of USB detection problems.
+# (The SAM's USB programming port doesn't get recognized as a ucom
+# device, and a USB serial adaptor attached to the UART gets detected
+# by bossa as a USB interface and doesn't fall back to the serial
+# programming protocol.)
+WXVERSION=2.8
+
+endif
+
+ifeq (${OS},FreeBSD)
+
+# This is only needed for bossash, but we can't add it to BOSSASH_LIBS here
+# because that one is redefined later.
+COMMON_SRCS+=PosixSerialPort.cpp BSDPortFactory.cpp
+
+endif
+
+#
+# Object files
+#
+COMMON_OBJS=$(foreach src,$(COMMON_SRCS),$(OBJDIR)/$(src:%.cpp=%.o))
+APPLET_OBJS=$(foreach src,$(APPLET_SRCS),$(OBJDIR)/$(src:%.asm=%.o))
+BOSSA_OBJS=$(APPLET_OBJS) $(COMMON_OBJS) $(foreach src,$(BOSSA_SRCS),$(OBJDIR)/$(src:%.cpp=%.o))
+ifdef BOSSA_RC
+BOSSA_OBJS+=$(OBJDIR)/$(BOSSA_RC:%.rc=%.o)
+endif
+BOSSAC_OBJS=$(APPLET_OBJS) $(COMMON_OBJS) $(foreach src,$(BOSSAC_SRCS),$(OBJDIR)/$(src:%.cpp=%.o))
+BOSSASH_OBJS=$(APPLET_OBJS) $(COMMON_OBJS) $(foreach src,$(BOSSASH_SRCS),$(OBJDIR)/$(src:%.cpp=%.o))
+
+#
+# Dependencies
+#
+DEPENDS=$(COMMON_SRCS:%.cpp=$(OBJDIR)/%.d)
+DEPENDS+=$(APPLET_SRCS:%.asm=$(OBJDIR)/%.d)
+DEPENDS+=$(BOSSA_SRCS:%.cpp=$(OBJDIR)/%.d)
+DEPENDS+=$(BOSSAC_SRCS:%.cpp=$(OBJDIR)/%.d)
+DEPENDS+=$(BOSSASH_SRCS:%.cpp=$(OBJDIR)/%.d)
+
+#
+# Tools
+#
+Q?=@
+CXX?=g++
+ARM=arm-none-eabi-
+ARMAS=$(ARM)as
+ARMOBJCOPY=$(ARM)objcopy
+
+#
+# CXX Flags
+#
+# COMMON_CXXFLAGS+=-Wall -Werror -MT $@ -MD -MP -MF $(@:%.o=%.d) -DVERSION=\"$(VERSION)\" -g -O2
+COMMON_CXXFLAGS+=-Wall -MT $@ -MD -MP -MF $(@:%.o=%.d) -DVERSION=\"$(VERSION)\" -g -O2 $(CXXFLAGS)
+WX_CXXFLAGS:=$(shell wx-config --cxxflags --version=$(WXVERSION)) -DWX_PRECOMP -Wno-ctor-dtor-privacy -O2 -fno-strict-aliasing
+BOSSA_CXXFLAGS=$(COMMON_CXXFLAGS) $(WX_CXXFLAGS)
+BOSSAC_CXXFLAGS=$(COMMON_CXXFLAGS)
+BOSSASH_CXXFLAGS=$(COMMON_CXXFLAGS)
+
+#
+# LD Flags
+#
+COMMON_LDFLAGS+=-g $(LDFLAGS)
+BOSSA_LDFLAGS=$(COMMON_LDFLAGS)
+BOSSAC_LDFLAGS=$(COMMON_LDFLAGS)
+BOSSASH_LDFLAGS=$(COMMON_LDFLAGS)
+
+#
+# Libs
+#
+COMMON_LIBS+=
+WX_LIBS:=$(shell wx-config --libs --version=$(WXVERSION)) $(WX_LIBS)
+BOSSA_LIBS=$(COMMON_LIBS) $(WX_LIBS)
+BOSSAC_LIBS=$(COMMON_LIBS)
+BOSSASH_LIBS=-lreadline $(COMMON_LIBS)
+
+#
+# Main targets
+#
+all: $(BINDIR)/bossa$(EXE) $(BINDIR)/bossac$(EXE) $(BINDIR)/bossash$(EXE)
+
+#
+# Common rules
+#
+define common_obj
+$(OBJDIR)/$(1:%.cpp=%.o): $(SRCDIR)/$(1)
+ @echo CPP COMMON $$<
+ $$(Q)$$(CXX) $$(COMMON_CXXFLAGS) -c -o $$@ $$<
+endef
+$(foreach src,$(COMMON_SRCS),$(eval $(call common_obj,$(src))))
+
+#
+# Applet rules
+#
+define applet_obj
+$(SRCDIR)/$(1:%.asm=%.cpp): $(SRCDIR)/$(1)
+ @echo APPLET $(1:%.asm=%)
+ $$(Q)$$(ARMAS) -o $$(@:$(SRCDIR)/%.cpp=$(OBJDIR)/%.obj) $$<
+ $$(Q)$$(ARMOBJCOPY) -O binary $$(@:$(SRCDIR)/%.cpp=$(OBJDIR)/%.obj) $$(@:$(SRCDIR)/%.cpp=$(OBJDIR)/%.bin)
+ $$(Q)./appletgen $(1:%.asm=%) $(SRCDIR) $(OBJDIR)
+$(OBJDIR)/$(1:%.asm=%.o): $(SRCDIR)/$(1:%.asm=%.cpp)
+ @echo CPP APPLET $$<
+ $$(Q)$$(CXX) $$(COMMON_CXXFLAGS) -c -o $$(@) $$(<:%.asm=%.cpp)
+endef
+$(foreach src,$(APPLET_SRCS),$(eval $(call applet_obj,$(src))))
+
+#
+# BOSSA rules
+#
+define bossa_obj
+$(OBJDIR)/$(1:%.cpp=%.o): $(SRCDIR)/$(1)
+ @echo CPP BOSSA $$<
+ $$(Q)$$(CXX) $$(BOSSA_CXXFLAGS) -c -o $$@ $$<
+endef
+$(foreach src,$(BOSSA_SRCS),$(eval $(call bossa_obj,$(src))))
+
+#
+# Resource rules
+#
+ifeq ($(OS),MINGW32)
+$(OBJDIR)/$(BOSSA_RC:%.rc=%.o): $(RESDIR)/$(BOSSA_RC)
+ @echo RC $<
+ $(Q)`wx-config --rescomp --version=$(WXVERSION)` -o $@ $<
+endif
+
+#
+# BOSSAC rules
+#
+define bossac_obj
+$(OBJDIR)/$(1:%.cpp=%.o): $(SRCDIR)/$(1)
+ @echo CPP BOSSAC $$<
+ $$(Q)$$(CXX) $$(BOSSAC_CXXFLAGS) -c -o $$@ $$<
+endef
+$(foreach src,$(BOSSAC_SRCS),$(eval $(call bossac_obj,$(src))))
+
+#
+# BOSSASH rules
+#
+define bossash_obj
+$(OBJDIR)/$(1:%.cpp=%.o): $(SRCDIR)/$(1)
+ @echo CPP BOSSASH $$<
+ $$(Q)$$(CXX) $$(BOSSASH_CXXFLAGS) -c -o $$@ $$<
+endef
+$(foreach src,$(BOSSASH_SRCS),$(eval $(call bossash_obj,$(src))))
+
+#
+# BMP rules
+#
+define bossa_bmp
+$(SRCDIR)/$(1:%.bmp=%.cpp): $(RESDIR)/$(1)
+ @echo BIN2C $$<
+ $(Q)bin2c $$< $$@
+endef
+$(foreach bmp,$(BOSSA_BMPS),$(eval $(call bossa_bmp,$(bmp))))
+
+#
+# Directory rules
+#
+$(OBJDIR):
+ @mkdir $@
+
+$(BINDIR):
+ @mkdir $@
+
+#
+# Target rules
+#
+$(BOSSA_OBJS): | $(OBJDIR)
+$(BINDIR)/bossa$(EXE): $(foreach bmp,$(BOSSA_BMPS),$(SRCDIR)/$(bmp:%.bmp=%.cpp)) $(BOSSA_OBJS) | $(BINDIR)
+ @echo LD $@
+ $(Q)$(CXX) $(BOSSA_LDFLAGS) -o $@ $(BOSSA_OBJS) $(BOSSA_LIBS)
+
+$(BOSSAC_OBJS): | $(OBJDIR)
+$(BINDIR)/bossac$(EXE): $(BOSSAC_OBJS) | $(BINDIR)
+ @echo LD $@
+ $(Q)$(CXX) $(BOSSAC_LDFLAGS) -o $@ $(BOSSAC_OBJS) $(BOSSAC_LIBS)
+
+$(BOSSASH_OBJS): | $(OBJDIR)
+$(BINDIR)/bossash$(EXE): $(BOSSASH_OBJS) | $(BINDIR)
+ @echo LD $@
+ $(Q)$(CXX) $(BOSSASH_LDFLAGS) -o $@ $(BOSSASH_OBJS) $(BOSSASH_LIBS)
+
+strip-bossa: $(BINDIR)/bossa$(EXE)
+ @echo STRIP $^
+ $(Q)strip $^
+
+strip-bossac: $(BINDIR)/bossac$(EXE)
+ @echo STRIP $^
+ $(Q)strip $^
+
+strip-bossash: $(BINDIR)/bossash$(EXE)
+ @echo STRIP $^
+ $(Q)strip $^
+
+strip: strip-bossa strip-bossac strip-bossash
+
+clean:
+ @echo CLEAN
+ $(Q)rm -rf $(BINDIR) $(OBJDIR)
+
+#
+# Include dependencies
+#
+-include $(DEPENDS)
diff --git a/lib/bossac/src/Applet.cpp b/lib/bossac/src/Applet.cpp
new file mode 100644
index 00000000..7bba24bb
--- /dev/null
+++ b/lib/bossac/src/Applet.cpp
@@ -0,0 +1,64 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#include "Applet.h"
+
+Applet::Applet(Samba& samba,
+ uint32_t addr,
+ uint8_t* code,
+ uint32_t size,
+ uint32_t start,
+ uint32_t stack,
+ uint32_t reset) :
+ _samba(samba), _addr(addr), _size(size), _start(start), _stack(stack), _reset(reset)
+{
+ _samba.write(addr, code, size);
+}
+
+void
+Applet::setStack(uint32_t stack)
+{
+ _samba.writeWord(_stack, stack);
+}
+
+void
+Applet::run()
+{
+ // Add one to the start address for Thumb mode
+ _samba.go(_start + 1);
+}
+
+void
+Applet::runv()
+{
+ // Add one to the start address for Thumb mode
+ _samba.writeWord(_reset, _start + 1);
+
+ // The stack is the first reset vector
+ _samba.go(_stack);
+}
diff --git a/lib/bossac/src/Applet.h b/lib/bossac/src/Applet.h
new file mode 100644
index 00000000..4acb504a
--- /dev/null
+++ b/lib/bossac/src/Applet.h
@@ -0,0 +1,65 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#ifndef _APPLET_H
+#define _APPLET_H
+
+#include <stdint.h>
+
+#include "Samba.h"
+
+class Applet
+{
+public:
+ Applet(Samba& samba,
+ uint32_t addr,
+ uint8_t* code,
+ uint32_t size,
+ uint32_t start,
+ uint32_t stack,
+ uint32_t reset);
+ virtual ~Applet() {}
+
+ virtual uint32_t size() { return _size; }
+ virtual uint32_t addr() { return _addr; }
+
+ virtual void setStack(uint32_t stack);
+
+ virtual void run(); // To be used for Thumb-1 based devices (ARM7TDMI, ARM9)
+ virtual void runv(); // To be used for Thumb-2 based devices (Cortex-Mx)
+
+protected:
+ Samba& _samba;
+ uint32_t _addr; // Address in device SRAM where will be placed the applet
+ uint32_t _size; // Applet size
+ uint32_t _start; //
+ uint32_t _stack; // Applet stack address in device SRAM
+ uint32_t _reset;
+};
+
+#endif // _APPLET_H
diff --git a/lib/bossac/src/CmdOpts.cpp b/lib/bossac/src/CmdOpts.cpp
new file mode 100644
index 00000000..675f7e1d
--- /dev/null
+++ b/lib/bossac/src/CmdOpts.cpp
@@ -0,0 +1,159 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include <assert.h>
+
+#include "CmdOpts.h"
+
+CmdOpts::CmdOpts(int argc, char* argv[], int numOpts, Option* opts) :
+ _argc(argc), _argv(argv), _numOpts(numOpts), _opts(opts)
+{
+}
+
+CmdOpts::~CmdOpts()
+{
+}
+
+void
+CmdOpts::usage(FILE* out)
+{
+ int optIdx;
+ char name[40];
+ const char* start;
+ const char* end;
+
+ for (optIdx = 0; optIdx < _numOpts; optIdx++)
+ {
+ if (_opts[optIdx].arg.has == ArgOptional)
+ snprintf(name, sizeof(name), " -%c, --%s[=%s]",
+ _opts[optIdx].letter,
+ _opts[optIdx].name,
+ _opts[optIdx].arg.name);
+ else if (_opts[optIdx].arg.has == ArgRequired)
+ snprintf(name, sizeof(name), " -%c, --%s=%s",
+ _opts[optIdx].letter,
+ _opts[optIdx].name,
+ _opts[optIdx].arg.name);
+ else
+ snprintf(name, sizeof(name), " -%c, --%s",
+ _opts[optIdx].letter,
+ _opts[optIdx].name);
+
+ fprintf(out, "%-23s ", name);
+
+ start = _opts[optIdx].help;
+ while ((end = strchr(start, '\n')))
+ {
+ fwrite(start, end - start + 1, 1, out);
+ fprintf(out, "%24s", "");
+ start = end + 1;
+ }
+ fprintf(out, "%s\n", start);
+ }
+}
+
+int
+CmdOpts::parse()
+{
+ struct option long_opts[_numOpts + 1];
+ char optstring[_numOpts * 3 + 1];
+ char* optPtr = optstring;
+ int optIdx;
+ int rc;
+
+ for (optIdx = 0; optIdx < _numOpts; optIdx++)
+ {
+ *_opts[optIdx].present = false;
+
+ *optPtr++ = _opts[optIdx].letter;
+ long_opts[optIdx].name = _opts[optIdx].name;
+ switch (_opts[optIdx].arg.has)
+ {
+ default:
+ case ArgNone:
+ long_opts[optIdx].has_arg = no_argument;
+ break;
+ case ArgOptional:
+ long_opts[optIdx].has_arg = optional_argument;
+ *optPtr++ = ':';
+ *optPtr++ = ':';
+ break;
+ case ArgRequired:
+ long_opts[optIdx].has_arg = required_argument;
+ *optPtr++ = ':';
+ break;
+ }
+ long_opts[optIdx].flag = NULL;
+ long_opts[optIdx].val = 0;
+ }
+
+ memset(&long_opts[_numOpts], 0, sizeof(long_opts[_numOpts]));
+ *optPtr = '\0';
+ optIdx = 0;
+ while ((rc = getopt_long(_argc, _argv, optstring, long_opts, &optIdx)) != -1)
+ {
+ if (rc == '?')
+ return -1;
+
+ if (rc != 0)
+ optIdx = find(rc);
+
+ assert(optIdx >= 0 && optIdx < _numOpts);
+ *_opts[optIdx].present = true;
+ if (_opts[optIdx].arg.has != ArgNone && optarg)
+ {
+ switch (_opts[optIdx].arg.type)
+ {
+ case ArgInt:
+ *_opts[optIdx].arg.value.intPtr = strtol(optarg, NULL, 0);
+ break;
+ default:
+ case ArgString:
+ *_opts[optIdx].arg.value.strPtr = optarg;
+ break;
+ }
+ }
+ }
+
+ return optind;
+}
+
+int
+CmdOpts::find(char letter)
+{
+ int optIdx;
+
+ for (optIdx = 0; optIdx < _numOpts; optIdx++)
+ if (_opts[optIdx].letter == letter)
+ break;
+
+ return optIdx;
+}
diff --git a/lib/bossac/src/CmdOpts.h b/lib/bossac/src/CmdOpts.h
new file mode 100644
index 00000000..f752a5df
--- /dev/null
+++ b/lib/bossac/src/CmdOpts.h
@@ -0,0 +1,88 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#ifndef _OPTION_H
+#define _OPTION_H
+
+#include <string>
+#include <stdio.h>
+
+typedef enum
+{
+ ArgNone,
+ ArgOptional,
+ ArgRequired
+} ArgHas;
+
+typedef enum
+{
+ ArgInt,
+ ArgString
+} ArgType;
+
+typedef struct
+{
+ ArgHas has;
+ ArgType type;
+ const char* name;
+ union
+ {
+ void* voidPtr;
+ int* intPtr;
+ std::string* strPtr;
+ } value;
+} OptArg;
+
+typedef struct
+{
+ char letter;
+ const char* name;
+ bool* present;
+ OptArg arg;
+ const char* help;
+} Option;
+
+class CmdOpts
+{
+public:
+ CmdOpts(int argc, char* argv[], int numOpts, Option* opts);
+ virtual ~CmdOpts();
+
+ void usage(FILE* out);
+ int parse();
+
+private:
+ int _argc;
+ char** _argv;
+ int _numOpts;
+ Option* _opts;
+
+ int find(char letter);
+};
+
+#endif // _OPTION_H
diff --git a/lib/bossac/src/D2xNvmFlash.cpp b/lib/bossac/src/D2xNvmFlash.cpp
new file mode 100644
index 00000000..0974936c
--- /dev/null
+++ b/lib/bossac/src/D2xNvmFlash.cpp
@@ -0,0 +1,347 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2018, ShumaTech
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+///////////////////////////////////////////////////////////////////////////////
+
+#include "D2xNvmFlash.h"
+
+// CMDEX field should be 0xA5 to allow execution of any command.
+#define CMDEX_KEY 0xa500
+
+// NVM ready bit mask
+#define NVM_INT_STATUS_READY_MASK 0x1
+
+// NVM status mask
+#define NVM_CTRL_STATUS_MASK 0xFFEB
+
+#define NVM_REG_BASE 0x41004000
+
+#define NVM_REG_CTRLA 0x00
+#define NVM_REG_CTRLB 0x04
+#define NVM_REG_INTFLAG 0x14
+#define NVM_REG_STATUS 0x18
+#define NVM_REG_ADDR 0x1c
+#define NVM_REG_LOCK 0x20
+
+#define NVM_CMD_ER 0x02
+#define NVM_CMD_WP 0x04
+#define NVM_CMD_EAR 0x05
+#define NVM_CMD_WAP 0x06
+#define NVM_CMD_LR 0x40
+#define NVM_CMD_UR 0x41
+#define NVM_CMD_SSB 0x45
+#define NVM_CMD_PBC 0x44
+
+#define ERASE_ROW_PAGES 4 // pages
+
+// NVM User Row
+#define NVM_UR_ADDR 0x804000
+#define NVM_UR_SIZE (_size * ERASE_ROW_PAGES)
+#define NVM_UR_BOD33_ENABLE_OFFSET 0x1
+#define NVM_UR_BOD33_ENABLE_MASK 0x6
+#define NVM_UR_BOD33_RESET_OFFSET 0x1
+#define NVM_UR_BOD33_RESET_MASK 0x7
+#define NVM_UR_NVM_LOCK_OFFSET 0x6
+
+D2xNvmFlash::D2xNvmFlash(
+ Samba& samba,
+ const std::string& name,
+ uint32_t pages,
+ uint32_t size,
+ uint32_t user,
+ uint32_t stack)
+ :
+ Flash(samba, name, 0, pages, size, 1, 16, user, stack), _eraseAuto(true)
+{
+}
+
+D2xNvmFlash::~D2xNvmFlash()
+{
+}
+
+void
+D2xNvmFlash::erase(uint32_t offset, uint32_t size)
+{
+ uint32_t eraseSize = _size * ERASE_ROW_PAGES;
+
+ // Offset must be a multiple of the erase size
+ if (offset % eraseSize)
+ throw FlashEraseError();
+
+ // Offset and size must be in range
+ if (offset + size > totalSize())
+ throw FlashEraseError();
+
+ uint32_t eraseEnd = (offset + size + eraseSize - 1) / eraseSize;
+
+ // Erase each erase size set of pages
+ for (uint32_t eraseNum = offset / eraseSize; eraseNum < eraseEnd; eraseNum++)
+ {
+ waitReady();
+
+ // Clear error bits
+ uint16_t statusReg = readReg(NVM_REG_STATUS);
+ writeReg(NVM_REG_STATUS, statusReg | NVM_CTRL_STATUS_MASK);
+
+ // Issue erase command
+ uint32_t wordAddr = (eraseNum * eraseSize) / 2;
+ writeReg(NVM_REG_ADDR, wordAddr);
+ command(NVM_CMD_ER);
+ }
+}
+
+void
+D2xNvmFlash::eraseAll(uint32_t offset)
+{
+ // Use the extended Samba command if available
+ if (_samba.canChipErase())
+ {
+ _samba.chipErase(offset);
+ }
+ else
+ {
+ erase(offset, totalSize() - offset);
+ }
+}
+
+void
+D2xNvmFlash::eraseAuto(bool enable)
+{
+ _eraseAuto = enable;
+}
+
+std::vector<bool>
+D2xNvmFlash::getLockRegions()
+{
+ uint8_t lockBits = 0;
+ uint32_t addr = NVM_UR_ADDR + NVM_UR_NVM_LOCK_OFFSET;
+ std::vector<bool> regions(_lockRegions);
+
+ for (uint32_t region = 0; region < _lockRegions; region++)
+ {
+ if (region % 8 == 0)
+ lockBits = _samba.readByte(addr++);
+ regions[region] = (lockBits & (1 << (region % 8))) == 0;
+ }
+
+ return regions;
+}
+
+bool
+D2xNvmFlash::getSecurity()
+{
+ return (readReg(NVM_REG_STATUS) & 0x100) != 0;
+}
+
+bool
+D2xNvmFlash::getBod()
+{
+ uint8_t byte = _samba.readByte(NVM_UR_ADDR + NVM_UR_BOD33_ENABLE_OFFSET);
+
+ return (byte & NVM_UR_BOD33_ENABLE_MASK) != 0;
+}
+
+bool
+D2xNvmFlash::getBor()
+{
+ uint8_t byte = _samba.readByte(NVM_UR_ADDR + NVM_UR_BOD33_RESET_OFFSET);
+
+ return (byte & NVM_UR_BOD33_RESET_MASK) != 0;
+}
+
+bool
+D2xNvmFlash::getBootFlash()
+{
+ return true;
+}
+
+void
+D2xNvmFlash::readUserRow(std::unique_ptr<uint8_t[]>& userRow)
+{
+ if (!userRow)
+ {
+ userRow.reset(new uint8_t[NVM_UR_SIZE]);
+ _samba.read(NVM_UR_ADDR, userRow.get(), NVM_UR_SIZE);
+ }
+}
+
+void
+D2xNvmFlash::writeOptions()
+{
+ std::unique_ptr<uint8_t[]> userRow;
+
+ if (canBor() && _bor.isDirty() && _bor.get() != getBor())
+ {
+ readUserRow(userRow);
+ if (_bor.get())
+ userRow[NVM_UR_BOD33_RESET_OFFSET] |= NVM_UR_BOD33_RESET_MASK;
+ else
+ userRow[NVM_UR_BOD33_RESET_OFFSET] &= ~NVM_UR_BOD33_RESET_MASK;
+ }
+ if (canBod() && _bod.isDirty() && _bod.get() != getBod())
+ {
+ readUserRow(userRow);
+ if (_bod.get())
+ userRow[NVM_UR_BOD33_ENABLE_OFFSET] |= NVM_UR_BOD33_ENABLE_MASK;
+ else
+ userRow[NVM_UR_BOD33_ENABLE_OFFSET] &= ~NVM_UR_BOD33_ENABLE_MASK;
+ }
+ if (_regions.isDirty())
+ {
+ // Check if any lock bits are different from the current set
+ std::vector<bool> current = getLockRegions();
+ if (!equal(_regions.get().begin(), _regions.get().end(), current.begin()))
+ {
+ readUserRow(userRow);
+
+ uint8_t* lockBits = &userRow[NVM_UR_NVM_LOCK_OFFSET];
+ for (uint32_t region = 0; region < _regions.get().size(); region++)
+ {
+ if (_regions.get()[region])
+ lockBits[region / 8] &= ~(1 << (region % 8));
+ else
+ lockBits[region / 8] |= (1 << (region % 8));
+ }
+ }
+ }
+
+ // Erase and write the user row if modified
+ if (userRow)
+ {
+ // Disable cache and configure manual page write
+ writeReg(NVM_REG_CTRLB, readReg(NVM_REG_CTRLB) | (0x1 << 18) | (0x1 << 7));
+
+ // Erase user row
+ writeReg(NVM_REG_ADDR, NVM_UR_ADDR / 2);
+ command(NVM_CMD_EAR);
+
+ // Write user row in page chunks
+ for (uint32_t offset = 0; offset < NVM_UR_SIZE; offset += _size)
+ {
+ // Load the buffer with the page
+ loadBuffer(&userRow[offset], _size);
+
+ // Clear page buffer
+ command(NVM_CMD_PBC);
+
+ // Copy page to page buffer
+ _wordCopy.setDstAddr(NVM_UR_ADDR + offset);
+ _wordCopy.setSrcAddr(_onBufferA ? _pageBufferA : _pageBufferB);
+ _onBufferA = !_onBufferA;
+ waitReady();
+ _wordCopy.runv();
+
+ // Write the page
+ writeReg(NVM_REG_ADDR, (NVM_UR_ADDR + offset) / 2);
+ command(NVM_CMD_WAP);
+ }
+ }
+
+ // Always do security last
+ if (_security.isDirty() && _security.get() == true && _security.get() != getSecurity())
+ {
+ command(NVM_CMD_SSB);
+ }
+}
+
+void
+D2xNvmFlash::writePage(uint32_t page)
+{
+ if (page >= _pages)
+ {
+ throw FlashPageError();
+ }
+
+ // Disable cache and configure manual page write
+ writeReg(NVM_REG_CTRLB, readReg(NVM_REG_CTRLB) | (0x1 << 18) | (0x1 << 7));
+
+ // Auto-erase if writing at the start of the erase page
+ if (_eraseAuto && page % ERASE_ROW_PAGES == 0)
+ erase(page * _size, ERASE_ROW_PAGES * _size);
+
+ // Clear page buffer
+ command(NVM_CMD_PBC);
+
+ // Compute the start address.
+ uint32_t addr = _addr + (page * _size);
+
+ _wordCopy.setDstAddr(addr);
+ _wordCopy.setSrcAddr(_onBufferA ? _pageBufferA : _pageBufferB);
+ _onBufferA = !_onBufferA;
+ waitReady();
+ _wordCopy.runv();
+
+ writeReg(NVM_REG_ADDR, addr / 2);
+ command(NVM_CMD_WP);
+}
+
+void
+D2xNvmFlash::waitReady()
+{
+ while ((readReg(NVM_REG_INTFLAG) & 0x1) == 0);
+}
+
+void
+D2xNvmFlash::readPage(uint32_t page, uint8_t* buf)
+{
+ if (page >= _pages)
+ {
+ throw FlashPageError();
+ }
+
+ _samba.read(_addr + (page * _size), buf, _size);
+}
+
+uint32_t
+D2xNvmFlash::readReg(uint8_t reg)
+{
+ return _samba.readWord(NVM_REG_BASE + reg);
+}
+
+void
+D2xNvmFlash::writeReg(uint8_t reg, uint32_t value)
+{
+ _samba.writeWord(NVM_REG_BASE + reg, value);
+}
+
+void
+D2xNvmFlash::command(uint8_t cmd)
+{
+ waitReady();
+
+ writeReg(NVM_REG_CTRLA, CMDEX_KEY | cmd);
+
+ waitReady();
+
+ if (readReg(NVM_REG_INTFLAG) & 0x2)
+ {
+ // Clear the error bit
+ writeReg(NVM_REG_INTFLAG, 0x2);
+ throw FlashCmdError();
+ }
+}
+
+void
+D2xNvmFlash::writeBuffer(uint32_t dst_addr, uint32_t size)
+{
+ // Auto-erase if enabled
+ if (_eraseAuto)
+ erase(dst_addr, size);
+
+ // Call the base class method
+ Flash::writeBuffer(dst_addr, size);
+}
diff --git a/lib/bossac/src/D2xNvmFlash.h b/lib/bossac/src/D2xNvmFlash.h
new file mode 100644
index 00000000..d7c36948
--- /dev/null
+++ b/lib/bossac/src/D2xNvmFlash.h
@@ -0,0 +1,76 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2018, ShumaTech
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _D2XNVMFLASH_H
+#define _D2XNVMFLASH_H
+
+#include <stdint.h>
+#include <exception>
+
+#include "Flash.h"
+
+class D2xNvmFlash : public Flash
+{
+public:
+ D2xNvmFlash(
+ Samba& samba,
+ const std::string& name,
+ uint32_t pages,
+ uint32_t size,
+ uint32_t user,
+ uint32_t stack);
+
+ virtual ~D2xNvmFlash();
+
+ void eraseAll(uint32_t offset);
+ void eraseAuto(bool enable);
+
+ std::vector<bool> getLockRegions();
+
+ bool getSecurity();
+
+ bool getBod();
+ bool canBod() { return true; }
+
+ bool getBor();
+ bool canBor() { return true; }
+
+ bool getBootFlash();
+ bool canBootFlash() { return false; }
+
+ void writeOptions();
+
+ void writePage(uint32_t page);
+ void readPage(uint32_t page, uint8_t* data);
+
+ void writeBuffer(uint32_t dst_addr, uint32_t size);
+
+protected:
+ bool _eraseAuto;
+
+ uint32_t readReg(uint8_t reg);
+ void writeReg(uint8_t reg, uint32_t value);
+
+ void waitReady();
+ void command(uint8_t cmd);
+ void erase(uint32_t offset, uint32_t size);
+ void readUserRow(std::unique_ptr<uint8_t[]>& userRow);
+};
+
+#endif // _D2XNVMFLASH_H
diff --git a/lib/bossac/src/D5xNvmFlash.cpp b/lib/bossac/src/D5xNvmFlash.cpp
new file mode 100644
index 00000000..81e5583f
--- /dev/null
+++ b/lib/bossac/src/D5xNvmFlash.cpp
@@ -0,0 +1,352 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2018, ShumaTech
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+///////////////////////////////////////////////////////////////////////////////
+
+#include "D5xNvmFlash.h"
+
+
+#define CMDEX_KEY 0xa500
+
+#define NVM_REG_BASE 0x41004000
+
+#define NVM_REG_CTRLA 0x00
+#define NVM_REG_CTRLB 0x04
+#define NVM_REG_INTFLAG 0x10
+#define NVM_REG_STATUS 0x12
+#define NVM_REG_ADDR 0x14
+#define NVM_REG_RUNLOCK 0x18
+
+#define NVM_CMD_EP 0x00
+#define NVM_CMD_EB 0x01
+#define NVM_CMD_WP 0x03
+#define NVM_CMD_WQW 0x04
+#define NVM_CMD_LR 0x11
+#define NVM_CMD_UR 0x12
+#define NVM_CMD_SSB 0x16
+#define NVM_CMD_PBC 0x15
+
+#define ERASE_BLOCK_PAGES 16 // pages
+
+// NVM User Page
+#define NVM_UP_ADDR 0x804000
+#define NVM_UP_SIZE (_size)
+#define NVM_UP_BOD33_DISABLE_OFFSET 0x0
+#define NVM_UP_BOD33_DISABLE_MASK 0x1
+#define NVM_UP_BOD33_RESET_OFFSET 0x1
+#define NVM_UP_BOD33_RESET_MASK 0x2
+#define NVM_UP_NVM_LOCK_OFFSET 0x8
+
+D5xNvmFlash::D5xNvmFlash(
+ Samba& samba,
+ const std::string& name,
+ uint32_t pages,
+ uint32_t size,
+ uint32_t user,
+ uint32_t stack)
+ :
+ Flash(samba, name, 0, pages, size, 1, 32, user, stack), _eraseAuto(true)
+{
+}
+
+D5xNvmFlash::~D5xNvmFlash()
+{
+}
+
+void
+D5xNvmFlash::erase(uint32_t offset, uint32_t size)
+{
+ uint32_t eraseSize = _size * ERASE_BLOCK_PAGES;
+
+ // Offset must be a multiple of the erase size
+ if (offset % eraseSize)
+ throw FlashEraseError();
+
+ // Offset and size must be in range
+ if (offset + size > totalSize())
+ throw FlashEraseError();
+
+ uint32_t eraseEnd = (offset + size + eraseSize - 1) / eraseSize;
+
+ // Erase each erase size set of pages
+ for (uint32_t eraseNum = offset / eraseSize; eraseNum < eraseEnd; eraseNum++)
+ {
+ // Issue erase command
+ writeRegU32(NVM_REG_ADDR, eraseNum * eraseSize);
+ command(NVM_CMD_EB);
+ }
+}
+
+void
+D5xNvmFlash::eraseAll(uint32_t offset)
+{
+ // Use the extended Samba command if available
+ if (_samba.canChipErase())
+ {
+ _samba.chipErase(offset);
+ }
+ else
+ {
+ erase(offset, totalSize() - offset);
+ }
+}
+
+void
+D5xNvmFlash::waitReady()
+{
+ while ((readRegU16(NVM_REG_STATUS) & 0x1) == 0);
+}
+
+void
+D5xNvmFlash::eraseAuto(bool enable)
+{
+ _eraseAuto = enable;
+}
+
+std::vector<bool>
+D5xNvmFlash::getLockRegions()
+{
+ uint8_t lockBits = 0;
+ uint32_t addr = NVM_UP_ADDR + NVM_UP_NVM_LOCK_OFFSET;
+ std::vector<bool> regions(_lockRegions);
+
+ for (uint32_t region = 0; region < _lockRegions; region++)
+ {
+ if (region % 8 == 0)
+ lockBits = _samba.readByte(addr++);
+ regions[region] = (lockBits & (1 << (region % 8))) == 0;
+ }
+
+ return regions;
+}
+
+bool
+D5xNvmFlash::getSecurity()
+{
+ // There doesn't seem to be a way to read this
+ return false;
+}
+
+bool
+D5xNvmFlash::getBod()
+{
+ uint8_t byte = _samba.readByte(NVM_UP_ADDR + NVM_UP_BOD33_DISABLE_OFFSET);
+
+ return (byte & NVM_UP_BOD33_DISABLE_MASK) == 0;
+}
+
+bool
+D5xNvmFlash::getBor()
+{
+ uint8_t byte = _samba.readByte(NVM_UP_ADDR + NVM_UP_BOD33_RESET_OFFSET);
+
+ return (byte & NVM_UP_BOD33_RESET_MASK) != 0;
+}
+
+bool
+D5xNvmFlash::getBootFlash()
+{
+ return true;
+}
+
+void
+D5xNvmFlash::readUserPage(std::unique_ptr<uint8_t[]>& userPage)
+{
+ if (!userPage)
+ {
+ userPage.reset(new uint8_t[NVM_UP_SIZE]);
+ _samba.read(NVM_UP_ADDR, userPage.get(), NVM_UP_SIZE);
+ }
+}
+
+void
+D5xNvmFlash::writeOptions()
+{
+ std::unique_ptr<uint8_t[]> userPage;
+
+ if (canBor() && _bor.isDirty() && _bor.get() != getBor())
+ {
+ readUserPage(userPage);
+ if (_bor.get())
+ userPage[NVM_UP_BOD33_RESET_OFFSET] |= NVM_UP_BOD33_RESET_MASK;
+ else
+ userPage[NVM_UP_BOD33_RESET_OFFSET] &= ~NVM_UP_BOD33_RESET_MASK;
+ }
+ if (canBod() && _bod.isDirty() && _bod.get() != getBod())
+ {
+ readUserPage(userPage);
+ if (_bod.get())
+ userPage[NVM_UP_BOD33_DISABLE_OFFSET] &= ~NVM_UP_BOD33_DISABLE_MASK;
+ else
+ userPage[NVM_UP_BOD33_DISABLE_OFFSET] |= NVM_UP_BOD33_DISABLE_MASK;
+ }
+ if (_regions.isDirty())
+ {
+ // Check if any lock bits are different from the current set
+ std::vector<bool> current = getLockRegions();
+ if (!equal(_regions.get().begin(), _regions.get().end(), current.begin()))
+ {
+ readUserPage(userPage);
+
+ uint8_t* lockBits = &userPage[NVM_UP_NVM_LOCK_OFFSET];
+ for (uint32_t region = 0; region < _regions.get().size(); region++)
+ {
+ if (_regions.get()[region])
+ lockBits[region / 8] &= ~(1 << (region % 8));
+ else
+ lockBits[region / 8] |= (1 << (region % 8));
+ }
+ }
+ }
+
+ // Erase and write the user page if modified
+ if (userPage)
+ {
+ // Configure manual page write and disable caches
+ writeRegU16(NVM_REG_CTRLA, (readRegU16(NVM_REG_CTRLA) | (0x3 << 14)) & 0xffcf);
+
+ // Erase user page
+ writeRegU32(NVM_REG_ADDR, NVM_UP_ADDR);
+ command(NVM_CMD_EP);
+
+ // Write user page in quad-word chunks
+ for (uint32_t offset = 0; offset < NVM_UP_SIZE; offset += 16)
+ {
+ // Load the buffer with the quad word
+ loadBuffer(&userPage[offset], 16);
+
+ // Clear page buffer
+ command(NVM_CMD_PBC);
+
+ // Copy quad word to page buffer
+ _wordCopy.setDstAddr(NVM_UP_ADDR + offset);
+ _wordCopy.setSrcAddr(_onBufferA ? _pageBufferA : _pageBufferB);
+ _wordCopy.setWords(4);
+ _onBufferA = !_onBufferA;
+ waitReady();
+ _wordCopy.runv();
+
+ // Write the quad word
+ writeRegU32(NVM_REG_ADDR, NVM_UP_ADDR + offset);
+ command(NVM_CMD_WQW);
+ }
+ }
+
+ // Always do security last
+ if (_security.isDirty() && _security.get() == true && _security.get() != getSecurity())
+ {
+ command(NVM_CMD_SSB);
+ }
+}
+
+void
+D5xNvmFlash::writePage(uint32_t page)
+{
+ if (page >= _pages)
+ {
+ throw FlashPageError();
+ }
+
+ // Configure manual page write and disable caches
+ writeRegU16(NVM_REG_CTRLA, (readRegU16(NVM_REG_CTRLA) | (0x3 << 14)) & 0xffcf);
+
+ // Auto-erase if writing at the start of the erase page
+ if (_eraseAuto && page % ERASE_BLOCK_PAGES == 0)
+ {
+ erase(page * _size, ERASE_BLOCK_PAGES * _size);
+ }
+
+ // Clear page bur
+ command(NVM_CMD_PBC);
+
+ uint32_t addr = _addr + (page * _size );
+
+ _wordCopy.setDstAddr(addr);
+ _wordCopy.setSrcAddr(_onBufferA ? _pageBufferA : _pageBufferB);
+ _wordCopy.setWords(_size / sizeof(uint32_t));
+ _onBufferA = !_onBufferA;
+ waitReady();
+ _wordCopy.runv();
+
+ writeRegU32(NVM_REG_ADDR, addr);
+ command(NVM_CMD_WP);
+}
+
+void
+D5xNvmFlash::readPage(uint32_t page, uint8_t* buf)
+{
+ if (page >= _pages)
+ {
+ throw FlashPageError();
+ }
+
+ _samba.read(_addr + (page * _size), buf, _size);
+}
+
+uint16_t
+D5xNvmFlash::readRegU16(uint8_t reg)
+{
+ return (uint16_t) _samba.readByte(NVM_REG_BASE + reg) |
+ (_samba.readByte(NVM_REG_BASE + reg + 1) << 8);
+}
+
+void
+D5xNvmFlash::writeRegU16(uint8_t reg, uint16_t value)
+{
+ _samba.writeByte(NVM_REG_BASE + reg, value & 0xff);
+ _samba.writeByte(NVM_REG_BASE + reg + 1, value >> 8);
+}
+
+uint32_t
+D5xNvmFlash::readRegU32(uint8_t reg)
+{
+ return _samba.readWord(NVM_REG_BASE + reg);
+}
+
+void
+D5xNvmFlash::writeRegU32(uint8_t reg, uint32_t value)
+{
+ _samba.writeWord(NVM_REG_BASE + reg, value);
+}
+
+void
+D5xNvmFlash::command(uint8_t cmd)
+{
+ waitReady();
+
+ writeRegU32(NVM_REG_CTRLB, CMDEX_KEY | cmd);
+
+ waitReady();
+
+ if (readRegU16(NVM_REG_INTFLAG) & 0xce)
+ {
+ // Clear the error bits
+ writeRegU16(NVM_REG_INTFLAG, 0xce);
+ throw FlashCmdError();
+ }
+}
+
+void
+D5xNvmFlash::writeBuffer(uint32_t dst_addr, uint32_t size)
+{
+ // Auto-erase if writing at the start of the erase page
+ if (_eraseAuto && ((dst_addr / _size) % ERASE_BLOCK_PAGES == 0))
+ erase(dst_addr, size);
+
+ // Call the base class method
+ Flash::writeBuffer(dst_addr, size);
+}
diff --git a/lib/bossac/src/D5xNvmFlash.h b/lib/bossac/src/D5xNvmFlash.h
new file mode 100644
index 00000000..d266f588
--- /dev/null
+++ b/lib/bossac/src/D5xNvmFlash.h
@@ -0,0 +1,79 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2018, ShumaTech
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _D5XNVMFLASH_H
+#define _D5XNVMFLASH_H
+
+#include <stdint.h>
+#include <exception>
+
+#include "Flash.h"
+
+class D5xNvmFlash : public Flash
+{
+public:
+ D5xNvmFlash(
+ Samba& samba,
+ const std::string& name,
+ uint32_t pages,
+ uint32_t size,
+ uint32_t user,
+ uint32_t stack);
+
+ virtual ~D5xNvmFlash();
+
+ void eraseAll(uint32_t offset);
+ void eraseAuto(bool enable);
+
+ std::vector<bool> getLockRegions();
+
+ bool getSecurity();
+
+ bool getBod();
+ bool canBod() { return true; }
+
+ bool getBor();
+ bool canBor() { return true; }
+
+ bool getBootFlash();
+ bool canBootFlash() { return false; }
+
+ void writeOptions();
+
+ void writePage(uint32_t page);
+ void readPage(uint32_t page, uint8_t* data);
+
+ void writeBuffer(uint32_t dst_addr, uint32_t size);
+
+protected:
+ bool _eraseAuto;
+
+ uint16_t readRegU16(uint8_t reg);
+ void writeRegU16(uint8_t reg, uint16_t value);
+ uint32_t readRegU32(uint8_t reg);
+ void writeRegU32(uint8_t reg, uint32_t value);
+
+ void waitReady();
+ void command(uint8_t cmd);
+ void erase(uint32_t offset, uint32_t size);
+ void checkError();
+ void readUserPage(std::unique_ptr<uint8_t[]>& userPage);
+};
+
+#endif // _D5XNVMFLASH_H
diff --git a/lib/bossac/src/Device.cpp b/lib/bossac/src/Device.cpp
new file mode 100644
index 00000000..457570ec
--- /dev/null
+++ b/lib/bossac/src/Device.cpp
@@ -0,0 +1,692 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#include "Device.h"
+#include "EfcFlash.h"
+#include "EefcFlash.h"
+#include "D2xNvmFlash.h"
+#include "D5xNvmFlash.h"
+
+void
+Device::readChipId(uint32_t& chipId, uint32_t& extChipId)
+{
+ if ((chipId = _samba.readWord(0x400e0740)) != 0)
+ {
+ extChipId = _samba.readWord(0x400e0744);
+ }
+ else if ((chipId = _samba.readWord(0x400e0940)) != 0)
+ {
+ extChipId = _samba.readWord(0x400e0944);
+ }
+}
+
+void
+Device::create()
+{
+ Flash* flashPtr;
+ uint32_t chipId = 0;
+ uint32_t cpuId = 0;
+ uint32_t extChipId = 0;
+ uint32_t deviceId = 0;
+
+ // Device identification must be performed carefully to avoid reading from
+ // addresses that devices do not support which will lock up the CPU
+
+ // All devices support addresss 0 as the ARM reset vector so if the vector is
+ // a ARM7TDMI branch, then assume we have an Atmel SAM7/9 CHIPID register
+ if ((_samba.readWord(0x0) & 0xff000000) == 0xea000000)
+ {
+ chipId = _samba.readWord(0xfffff240);
+ }
+ else
+ {
+ // Next try the ARM CPUID register since all Cortex-M devices support it
+ cpuId = _samba.readWord(0xe000ed00) & 0x0000fff0;
+
+ // Cortex-M0+
+ if (cpuId == 0xC600)
+ {
+ // These should support the ARM device ID register
+ deviceId = _samba.readWord(0x41002018);
+ }
+ // Cortex-M4
+ else if (cpuId == 0xC240)
+ {
+ // SAM4 processors have a reset vector to the SAM-BA ROM
+ if ((_samba.readWord(0x4) & 0xfff00000) == 0x800000)
+ {
+ readChipId(chipId, extChipId);
+ }
+ // Else we should have a device that supports the ARM device ID register
+ else
+ {
+ deviceId = _samba.readWord(0x41002018);
+ }
+ }
+ // For all other Cortex versions try the Atmel chip ID registers
+ else
+ {
+ readChipId(chipId, extChipId);
+ }
+ }
+
+ // Instantiate the proper flash for the device
+ switch (chipId & 0x7fffffe0)
+ {
+ //
+ // SAM7SE
+ //
+ case 0x272a0a40:
+ _family = FAMILY_SAM7SE;
+ flashPtr = new EfcFlash(_samba, "AT91SAM7SE512", 0x100000, 2048, 256, 2, 32, 0x202000, 0x208000, true);
+ break;
+ case 0x272a0940:
+ _family = FAMILY_SAM7SE;
+ flashPtr = new EfcFlash(_samba, "AT91SAM7SE256", 0x100000, 1024, 256, 1, 16, 0x202000, 0x208000, true);
+ break;
+ case 0x272a0340:
+ _family = FAMILY_SAM7SE;
+ flashPtr = new EfcFlash(_samba, "AT91SAM7SE32", 0x100000, 256, 128, 1, 8, 0x201400, 0x201C00, true);
+ break;
+ //
+ // SAM7S
+ //
+ case 0x270b0a40:
+ _family = FAMILY_SAM7S;
+ flashPtr = new EfcFlash(_samba, "AT91SAM7S512", 0x100000, 2048, 256, 2, 32, 0x202000, 0x210000, false);
+ break;
+ case 0x270d0940: // A
+ case 0x270b0940: // B/C
+ _family = FAMILY_SAM7S;
+ flashPtr = new EfcFlash(_samba, "AT91SAM7S256", 0x100000, 1024, 256, 1, 16, 0x202000, 0x210000, false);
+ break;
+ case 0x270c0740: // A
+ case 0x270a0740: // B/C
+ _family = FAMILY_SAM7S;
+ flashPtr = new EfcFlash(_samba, "AT91SAM7S128", 0x100000, 512, 256, 1, 8, 0x202000, 0x208000, false);
+ break;
+ case 0x27090540:
+ _family = FAMILY_SAM7S;
+ flashPtr = new EfcFlash(_samba, "AT91SAM7S64", 0x100000, 512, 128, 1, 16, 0x202000, 0x204000, false);
+ break;
+ case 0x27080340:
+ _family = FAMILY_SAM7S;
+ flashPtr = new EfcFlash(_samba, "AT91SAM7S32", 0x100000, 256, 128, 1, 8, 0x201400, 0x202000, false);
+ break;
+ case 0x27050240:
+ _family = FAMILY_SAM7S;
+ flashPtr = new EfcFlash(_samba, "AT91SAM7S16", 0x100000, 256, 64, 1, 8, 0x200000, 0x200e00, false);
+ break;
+ //
+ // SAM7XC
+ //
+ case 0x271c0a40:
+ _family = FAMILY_SAM7XC;
+ flashPtr = new EfcFlash(_samba, "AT91SAMXC512", 0x100000, 2048, 256, 2, 32, 0x202000, 0x220000, true);
+ break;
+ case 0x271b0940:
+ _family = FAMILY_SAM7XC;
+ flashPtr = new EfcFlash(_samba, "AT91SAMXC256", 0x100000, 1024, 256, 1, 16, 0x202000, 0x210000, true);
+ break;
+ case 0x271a0740:
+ _family = FAMILY_SAM7XC;
+ flashPtr = new EfcFlash(_samba, "AT91SAMXC128", 0x100000, 512, 256, 1, 8, 0x202000, 0x208000, true);
+ break;
+ //
+ // SAM7X
+ //
+ case 0x275c0a40:
+ _family = FAMILY_SAM7X;
+ flashPtr = new EfcFlash(_samba, "AT91SAMX512", 0x100000, 2048, 256, 2, 32, 0x202000, 0x220000, true);
+ break;
+ case 0x275b0940:
+ _family = FAMILY_SAM7X;
+ flashPtr = new EfcFlash(_samba, "AT91SAMX256", 0x100000, 1024, 256, 1, 16, 0x202000, 0x210000, true);
+ break;
+ case 0x275a0740:
+ _family = FAMILY_SAM7X;
+ flashPtr = new EfcFlash(_samba, "AT91SAMX128", 0x100000, 512, 256, 1, 8, 0x202000, 0x208000, true);
+ break;
+ //
+ // SAM4S
+ //
+ case 0x29870ee0: // A
+ case 0x29970ee0: // B
+ case 0x29A70ee0: // C
+ _family = FAMILY_SAM4S;
+ flashPtr = new EefcFlash(_samba, "ATSAM4SD32", 0x400000, 4096, 512, 2, 256, 0x20001000, 0x20010000, 0x400e0a00, false);
+ break;
+ case 0x29870c30: // A
+ case 0x29970c30: // B
+ case 0x29a70c30: // C
+ _family = FAMILY_SAM4S;
+ flashPtr = new EefcFlash(_samba, "ATSAM4SD16", 0x400000, 2048, 512, 2, 256, 0x20001000, 0x20010000, 0x400e0a00, false);
+ break;
+ case 0x28870ce0: // A
+ case 0x28970ce0: // B
+ case 0x28A70ce0: // C
+ _family = FAMILY_SAM4S;
+ flashPtr = new EefcFlash(_samba, "ATSAM4SA16", 0x400000, 2048, 512, 1, 256, 0x20001000, 0x20010000, 0x400e0a00, false);
+ break;
+ case 0x288c0ce0 : // A
+ case 0x289c0ce0 : // B
+ case 0x28ac0ce0 : // C
+ _family = FAMILY_SAM4S;
+ flashPtr = new EefcFlash(_samba, "ATSAM4S16", 0x400000, 2048, 512, 1, 128, 0x20001000, 0x20020000, 0x400e0a00, false);
+ break;
+ case 0x288c0ae0 : // A
+ case 0x289c0ae0 : // B
+ case 0x28ac0ae0 : // C
+ _family = FAMILY_SAM4S;
+ flashPtr = new EefcFlash(_samba, "ATSAM4S8", 0x400000, 1024, 512, 1, 64, 0x20001000, 0x20020000, 0x400e0a00, false);
+ break;
+ case 0x288b09e0 : // A
+ case 0x289b09e0 : // B
+ case 0x28ab09e0 : // C
+ _family = FAMILY_SAM4S;
+ flashPtr = new EefcFlash(_samba, "ATSAM4S4", 0x400000, 512, 512, 1, 16, 0x20001000, 0x20010000, 0x400e0a00, false);
+ break;
+ case 0x288b07e0 : // A
+ case 0x289b07e0 : // B
+ case 0x28ab07e0 : // C
+ _family = FAMILY_SAM4S;
+ flashPtr = new EefcFlash(_samba, "ATSAM4S2", 0x400000, 256, 512, 1, 16, 0x20001000, 0x20010000, 0x400e0a00, false);
+ break;
+ //
+ // SAM3N
+ //
+ case 0x29340960 : // A
+ case 0x29440960 : // B
+ case 0x29540960 : // C
+ _family = FAMILY_SAM3N;
+ flashPtr = new EefcFlash(_samba, "ATSAM3N4", 0x400000, 1024, 256, 1, 16, 0x20001000, 0x20006000, 0x400e0a00, false);
+ break;
+ case 0x29390760 : // A
+ case 0x29490760 : // B
+ case 0x29590760 : // C
+ _family = FAMILY_SAM3N;
+ flashPtr = new EefcFlash(_samba, "ATSAM3N2", 0x400000, 512, 256, 1, 8, 0x20001000, 0x20004000, 0x400e0a00, false);
+ break;
+ case 0x29380560 : // A
+ case 0x29480560 : // B
+ case 0x29580560 : // C
+ _family = FAMILY_SAM3N;
+ flashPtr = new EefcFlash(_samba, "ATSAM3N1", 0x400000, 256, 256, 1, 4, 0x20000800, 0x20002000, 0x400e0a00, false);
+ break;
+ case 0x29380360 : // A
+ case 0x29480360 : // B
+ case 0x29580360 : // C
+ _family = FAMILY_SAM3N;
+ flashPtr = new EefcFlash(_samba, "ATSAM3N0", 0x400000, 128, 256, 1, 1, 0x20000800, 0x20002000, 0x400e0a00, false);
+ break;
+ //
+ // SAM3S
+ //
+ case 0x299b0a60 : // B
+ case 0x29ab0a60 : // C
+ _family = FAMILY_SAM3S;
+ flashPtr = new EefcFlash(_samba, "ATSAM3SD8", 0x400000, 2048, 256, 1, 16, 0x20001000, 0x20010000, 0x400e0a00, false);
+ break;
+ case 0x289b0a60 : // B
+ case 0x28ab0a60 : // C
+ _family = FAMILY_SAM3S;
+ flashPtr = new EefcFlash(_samba, "ATSAM3S8", 0x400000, 2048, 256, 1, 16, 0x20001000, 0x20010000, 0x400e0a00, false);
+ break;
+ case 0x28800960 : // A
+ case 0x28900960 : // B
+ case 0x28a00960 : // C
+ _family = FAMILY_SAM3S;
+ flashPtr = new EefcFlash(_samba, "ATSAM3S4", 0x400000, 1024, 256, 1, 16, 0x20001000, 0x2000c000, 0x400e0a00, false);
+ break;
+ case 0x288a0760 : // A
+ case 0x289a0760 : // B
+ case 0x28aa0760 : // C
+ _family = FAMILY_SAM3S;
+ flashPtr = new EefcFlash(_samba, "ATSAM3S2", 0x400000, 512, 256, 1, 8, 0x20000800, 0x20008000, 0x400e0a00, false);
+ break;
+ case 0x288a0560 : // A
+ case 0x289a0560 : // B
+ case 0x28aa0560 : // C
+ _family = FAMILY_SAM3S;
+ flashPtr = new EefcFlash(_samba, "ATSAM3S1", 0x400000, 256, 256, 1, 4, 0x20000800, 0x20004000, 0x400e0a00, false);
+ break;
+ //
+ // SAM3U
+ //
+ case 0x28000960 : // C
+ case 0x28100960 : // E
+ _family = FAMILY_SAM3U;
+ flashPtr = new EefcFlash(_samba, "ATSAM3U4", 0xE0000, 1024, 256, 2, 32, 0x20001000, 0x20008000, 0x400e0800, false);
+ break;
+ case 0x280a0760 : // C
+ case 0x281a0760 : // E
+ _family = FAMILY_SAM3U;
+ flashPtr = new EefcFlash(_samba, "ATSAM3U2", 0x80000, 512, 256, 1, 16, 0x20001000, 0x20004000, 0x400e0800, false);
+ break;
+ case 0x28090560 : // C
+ case 0x28190560 : // E
+ _family = FAMILY_SAM3U;
+ flashPtr = new EefcFlash(_samba, "ATSAM3U1", 0x80000, 256, 256, 1, 8, 0x20001000, 0x20002000, 0x400e0800, false);
+ break;
+ //
+ // SAM3X
+ //
+ case 0x286e0a60 : // 8H
+ case 0x285e0a60 : // 8E
+ case 0x284e0a60 : // 8C
+ _family = FAMILY_SAM3X;
+ flashPtr = new EefcFlash(_samba, "ATSAM3X8", 0x80000, 2048, 256, 2, 32, 0x20001000, 0x20010000, 0x400e0a00, false);
+ break;
+ case 0x285b0960 : // 4E
+ case 0x284b0960 : // 4C
+ _family = FAMILY_SAM3X;
+ flashPtr = new EefcFlash(_samba, "ATSAM3X4", 0x80000, 1024, 256, 2, 16, 0x20001000, 0x20008000, 0x400e0a00, false);
+ break;
+ //
+ // SAM3A
+ //
+ case 0x283e0A60 : // 8C
+ _family = FAMILY_SAM3A;
+ flashPtr = new EefcFlash(_samba, "ATSAM3A8", 0x80000, 2048, 256, 2, 32, 0x20001000, 0x20010000, 0x400e0a00, false);
+ break;
+ case 0x283b0960 : // 4C
+ _family = FAMILY_SAM3A;
+ flashPtr = new EefcFlash(_samba, "ATSAM3A4", 0x80000, 1024, 256, 2, 16, 0x20001000, 0x20008000, 0x400e0a00, false);
+ break;
+ //
+ // SAM7L
+ //
+ case 0x27330740 :
+ _family = FAMILY_SAM7L;
+ flashPtr = new EefcFlash(_samba, "ATSAM7L128", 0x100000, 512, 256, 1, 16, 0x2ffb40, 0x300700, 0xffffff60, false);
+ break;
+ case 0x27330540 :
+ _family = FAMILY_SAM7L;
+ flashPtr = new EefcFlash(_samba, "ATSAM7L64", 0x100000, 256, 256, 1, 8, 0x2ffb40, 0x300700, 0xffffff60, false);
+ break;
+ //
+ // SAM9XE
+ //
+ case 0x329aa3a0 :
+ _family = FAMILY_SAM9XE;
+ flashPtr = new EefcFlash(_samba, "ATSAM9XE512", 0x200000, 1024, 512, 1, 32, 0x300000, 0x307000, 0xfffffa00, true);
+ break;
+ case 0x329a93a0 :
+ _family = FAMILY_SAM9XE;
+ flashPtr = new EefcFlash(_samba, "ATSAM9XE256", 0x200000, 512, 512, 1, 16, 0x300000, 0x307000, 0xfffffa00, true);
+ break;
+ case 0x329973a0 :
+ _family = FAMILY_SAM9XE;
+ flashPtr = new EefcFlash(_samba, "ATSAM9XE128", 0x200000, 256, 512, 1, 8, 0x300000, 0x303000, 0xfffffa00, true);
+ break;
+ //
+ // SAM4E
+ //
+ case 0x23cc0ce0:
+ switch (extChipId)
+ {
+ case 0x00120200: // E
+ case 0x00120201: // C
+ _family = FAMILY_SAM4E;
+ flashPtr = new EefcFlash(_samba, "ATSAM4E16", 0x400000, 2048, 512, 1, 128, 0x20001000, 0x20020000, 0x400e0a00, false);
+ break;
+ case 0x00120208: // E
+ case 0x00120209: // C
+ _family = FAMILY_SAM4E;
+ flashPtr = new EefcFlash(_samba, "ATSAM4E8", 0x400000, 1024, 512, 1, 64, 0x20001000, 0x20020000, 0x400e0a00, false);
+ break;
+ }
+ break;
+ //
+ // SAME70
+ //
+ case 0x210d0a00:
+ _family = FAMILY_SAME70;
+ flashPtr = new EefcFlash(_samba, "ATSAME70x19", 0x400000, 1024, 512, 1, 32, 0x20401000, 0x20404000, 0x400e0c00, false);
+ break;
+ case 0x21020c00:
+ _family = FAMILY_SAME70;
+ flashPtr = new EefcFlash(_samba, "ATSAME70x20", 0x400000, 2048, 512, 1, 64, 0x20401000, 0x20404000, 0x400e0c00, false);
+ break;
+ case 0x21020e00:
+ _family = FAMILY_SAME70;
+ flashPtr = new EefcFlash(_samba, "ATSAME70x21", 0x400000, 4096, 512, 1, 128, 0x20401000, 0x20404000, 0x400e0c00, false);
+ break;
+ //
+ // SAMS70
+ //
+ case 0x211d0a00:
+ _family = FAMILY_SAMS70;
+ flashPtr = new EefcFlash(_samba, "ATSAMS70x19", 0x400000, 1024, 512, 1, 32, 0x20401000, 0x20404000, 0x400e0c00, false);
+ break;
+ case 0x21120c00:
+ _family = FAMILY_SAMS70;
+ flashPtr = new EefcFlash(_samba, "ATSAMS70x20", 0x400000, 2048, 512, 1, 64, 0x20401000, 0x20404000, 0x400e0c00, false);
+ break;
+ case 0x21120e00:
+ _family = FAMILY_SAMS70;
+ flashPtr = new EefcFlash(_samba, "ATSAMS70x21", 0x400000, 4096, 512, 1, 128, 0x20401000, 0x20404000, 0x400e0c00, false);
+ break;
+ //
+ // SAMV70
+ //
+ case 0x213d0a00:
+ _family = FAMILY_SAMV70;
+ flashPtr = new EefcFlash(_samba, "ATSAMV70x19", 0x400000, 1024, 512, 1, 32, 0x20401000, 0x20404000, 0x400e0c00, false);
+ break;
+ case 0x21320c00:
+ _family = FAMILY_SAMV70;
+ flashPtr = new EefcFlash(_samba, "ATSAMV70x20", 0x400000, 2048, 512, 1, 64, 0x20401000, 0x20404000, 0x400e0c00, false);
+ break;
+ //
+ // SAMV71
+ //
+ case 0x212d0a00:
+ _family = FAMILY_SAMV71;
+ flashPtr = new EefcFlash(_samba, "ATSAMV71x19", 0x400000, 1024, 512, 1, 32, 0x20401000, 0x20404000, 0x400e0c00, false);
+ break;
+ case 0x21220c00:
+ _family = FAMILY_SAMV71;
+ flashPtr = new EefcFlash(_samba, "ATSAMV71x20", 0x400000, 2048, 512, 1, 64, 0x20401000, 0x20404000, 0x400e0c00, false);
+ break;
+ case 0x21220e00:
+ _family = FAMILY_SAMV71;
+ flashPtr = new EefcFlash(_samba, "ATSAMV71x21", 0x400000, 4096, 512, 1, 128, 0x20401000, 0x20404000, 0x400e0c00, false);
+ break;
+ //
+ // No CHIPID devices
+ //
+ case 0:
+ switch (deviceId & 0xffff00ff)
+ {
+ //
+ // SAMD21
+ //
+ case 0x10010003: // J15A
+ case 0x10010008: // G15A
+ case 0x1001000d: // E15A
+ case 0x10010021: // J15B
+ case 0x10010024: // G15B
+ case 0x10010027: // E15B
+ case 0x10010056: // E15B WLCSP
+ case 0x10010063: // E15C WLCSP
+ _family = FAMILY_SAMD21;
+ flashPtr = new D2xNvmFlash(_samba, "ATSAMD21x15", 512, 64, 0x20000800, 0x20001000) ;
+ break;
+
+ case 0x10010002: // J16A
+ case 0x10010007: // G16A
+ case 0x1001000c: // E16A
+ case 0x10010020: // J16B
+ case 0x10010023: // G16B
+ case 0x10010026: // E16B
+ case 0x10010055: // E16B WLCSP
+ case 0x10010062: // E16C WLCSP
+ _family = FAMILY_SAMD21;
+ flashPtr = new D2xNvmFlash(_samba, "ATSAMD21x16", 1024, 64, 0x20001000, 0x20002000) ;
+ break;
+
+ case 0x10010001: // J17A
+ case 0x10010006: // G17A
+ case 0x1001000b: // E17A
+ case 0x10010010: // G17A WLCSP
+ _family = FAMILY_SAMD21;
+ flashPtr = new D2xNvmFlash(_samba, "ATSAMD21x17", 2048, 64, 0x20002000, 0x20004000) ;
+ break;
+
+ case 0x10010000: // J18A
+ case 0x10010005: // G18A
+ case 0x1001000a: // E18A
+ case 0x1001000f: // G18A WLCSP
+ _family = FAMILY_SAMD21;
+ flashPtr = new D2xNvmFlash(_samba, "ATSAMD21x18", 4096, 64, 0x20004000, 0x20008000) ;
+ break;
+
+ //
+ // SAMR21
+ //
+ case 0x1001001e: // E16A
+ case 0x1001001b: // G16A
+ _family = FAMILY_SAMR21;
+ flashPtr = new D2xNvmFlash(_samba, "ATSAMR21x16", 1024, 64, 0x20001000, 0x20002000) ;
+ break;
+
+ case 0x1001001d: // E17A
+ case 0x1001001a: // G17A
+ _family = FAMILY_SAMR21;
+ flashPtr = new D2xNvmFlash(_samba, "ATSAMR21x17", 2048, 64, 0x20002000, 0x20004000) ;
+ break;
+
+ case 0x1001001c: // E18A
+ case 0x10010019: // G18A
+ _family = FAMILY_SAMR21;
+ flashPtr = new D2xNvmFlash(_samba, "ATSAMR21x18", 4096, 64, 0x20004000, 0x20008000) ;
+ break;
+
+ case 0x10010018: // E19A
+ _family = FAMILY_SAMR21;
+ flashPtr = new D2xNvmFlash(_samba, "ATSAMR21x19", 4096, 64, 0x20004000, 0x20008000) ;
+ break;
+
+ //
+ // SAML21
+ //
+ case 0x1081000d: // E15A
+ case 0x1081001c: // E15B
+ _family = FAMILY_SAMD21;
+ flashPtr = new D2xNvmFlash(_samba, "ATSAML21x15", 512, 64, 0x20000800, 0x20001000) ;
+ break;
+
+ case 0x10810002: // J16A
+ case 0x10810007: // G16A
+ case 0x1081000c: // E16A
+ case 0x10810011: // J16B
+ case 0x10810016: // G16B
+ case 0x1081001b: // E16B
+ _family = FAMILY_SAML21;
+ flashPtr = new D2xNvmFlash(_samba, "ATSAML21x16", 1024, 64, 0x20001000, 0x20002000) ;
+ break;
+
+ case 0x10810001: // J17A
+ case 0x10810006: // G17A
+ case 0x1081000b: // E17A
+ case 0x10810010: // J17B
+ case 0x10810015: // G17B
+ case 0x1081001a: // E17B
+ _family = FAMILY_SAML21;
+ flashPtr = new D2xNvmFlash(_samba, "ATSAML21x17", 2048, 64, 0x20002000, 0x20004000) ;
+ break;
+
+ case 0x10810000: // J18A
+ case 0x10810005: // G18A
+ case 0x1081000a: // E18A
+ case 0x1081000f: // J18B
+ case 0x10810014: // G18B
+ case 0x10810019: // E18B
+ _family = FAMILY_SAML21;
+ flashPtr = new D2xNvmFlash(_samba, "ATSAML21x18", 4096, 64, 0x20004000, 0x20008000) ;
+ break;
+
+ //
+ // SAMD51
+ //
+ case 0x60060006: // J18A
+ case 0x60060008: // G18A
+ _family = FAMILY_SAMD51;
+ flashPtr = new D5xNvmFlash(_samba, "ATSAMD51x18", 512, 512, 0x20004000, 0x20008000) ;
+ break;
+
+ case 0x60060001: // P19A
+ case 0x60060003: // N19A
+ case 0x60060005: // J19A
+ case 0x60060007: // G19A
+ _family = FAMILY_SAMD51;
+ flashPtr = new D5xNvmFlash(_samba, "ATSAMD51x19", 1024, 512, 0x20004000, 0x20008000) ;
+ break;
+
+ case 0x60060000: // P20A
+ case 0x60060002: // N20A
+ case 0x60060004: // J20A
+ _family = FAMILY_SAMD51;
+ flashPtr = new D5xNvmFlash(_samba, "ATSAMD51x20", 2048, 512, 0x20004000, 0x20008000) ;
+ break;
+
+ //
+ // SAME51
+ //
+ case 0x61810003: // J18A
+ _family = FAMILY_SAME51;
+ flashPtr = new D5xNvmFlash(_samba, "ATSAME51x18", 512, 512, 0x20004000, 0x20008000) ;
+ break;
+
+ case 0x61810002: // J19A
+ case 0x61810001: // N19A
+ _family = FAMILY_SAME51;
+ flashPtr = new D5xNvmFlash(_samba, "ATSAME51x19", 1024, 512, 0x20004000, 0x20008000) ;
+ break;
+
+ case 0x61810004: // J20A
+ case 0x61810000: // N20A
+ _family = FAMILY_SAME51;
+ flashPtr = new D5xNvmFlash(_samba, "ATSAME51x20", 2048, 512, 0x20004000, 0x20008000) ;
+ break;
+
+ //
+ // SAME53
+ //
+ case 0x61830006: // J18A
+ _family = FAMILY_SAME53;
+ flashPtr = new D5xNvmFlash(_samba, "ATSAME53x18", 512, 512, 0x20004000, 0x20008000) ;
+ break;
+
+ case 0x61830005: // J19A
+ case 0x61830003: // N19A
+ _family = FAMILY_SAME53;
+ flashPtr = new D5xNvmFlash(_samba, "ATSAME53x19", 1024, 512, 0x20004000, 0x20008000) ;
+ break;
+
+ case 0x61830004: // J20A
+ case 0x61830002: // N20A
+ _family = FAMILY_SAME53;
+ flashPtr = new D5xNvmFlash(_samba, "ATSAME53x20", 2048, 512, 0x20004000, 0x20008000) ;
+ break;
+
+ //
+ // SAME54
+ //
+ case 0x61840001: // P19A
+ case 0x61840003: // N19A
+ _family = FAMILY_SAME54;
+ flashPtr = new D5xNvmFlash(_samba, "ATSAME54x19", 1024, 512, 0x20004000, 0x20008000) ;
+ break;
+
+ case 0x61840000: // P20A
+ case 0x61840002: // N20A
+ _family = FAMILY_SAME54;
+ flashPtr = new D5xNvmFlash(_samba, "ATSAME54x20", 2048, 512, 0x20004000, 0x20008000) ;
+ break;
+
+ //
+ // Unknown
+ //
+ default:
+ throw DeviceUnsupportedError();
+ break;
+ }
+ break;
+
+ //
+ // Unsupported device
+ //
+ default:
+ throw DeviceUnsupportedError();
+ break;
+ }
+
+ _flash = std::unique_ptr<Flash>(flashPtr);
+}
+
+void
+Device::reset()
+{
+ try
+ {
+ switch (_family)
+ {
+ case FAMILY_SAMD21:
+ case FAMILY_SAMR21:
+ case FAMILY_SAML21:
+ case FAMILY_SAMD51:
+ case FAMILY_SAME51:
+ case FAMILY_SAME53:
+ case FAMILY_SAME54:
+ case FAMILY_SAME70:
+ case FAMILY_SAMS70:
+ case FAMILY_SAMV70:
+ case FAMILY_SAMV71:
+ _samba.writeWord(0xE000ED0C, 0x05FA0004);
+ break;
+
+ case FAMILY_SAM3X:
+ case FAMILY_SAM3S:
+ case FAMILY_SAM3A:
+ _samba.writeWord(0x400E1A00, 0xA500000D);
+ break;
+
+ case FAMILY_SAM3U:
+ _samba.writeWord(0x400E1200, 0xA500000D);
+ break;
+
+ case FAMILY_SAM3N:
+ case FAMILY_SAM4S:
+ _samba.writeWord(0x400E1400, 0xA500000D);
+ break;
+
+ case FAMILY_SAM4E:
+ _samba.writeWord(0x400E1800, 0xA500000D);
+ break;
+
+ case FAMILY_SAM7S:
+ case FAMILY_SAM7SE:
+ case FAMILY_SAM7X:
+ case FAMILY_SAM7XC:
+ case FAMILY_SAM7L:
+ case FAMILY_SAM9XE:
+ _samba.writeWord(0xFFFFFD00, 0xA500000D);
+ break;
+
+ default:
+ break;
+ }
+ }
+ catch (std::exception& expected)
+ { // writeWord will most likely throw an exception when the CPU is reset
+ }
+}
+
+
diff --git a/lib/bossac/src/Device.h b/lib/bossac/src/Device.h
new file mode 100644
index 00000000..5475c557
--- /dev/null
+++ b/lib/bossac/src/Device.h
@@ -0,0 +1,104 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#ifndef _DEVICE_H
+#define _DEVICE_H
+
+#include <exception>
+
+#include "Samba.h"
+#include "Flash.h"
+
+class DeviceUnsupportedError : public std::exception
+{
+public:
+ DeviceUnsupportedError() : exception() {};
+ const char* what() const throw() { return "Device unsupported"; }
+};
+
+class Device
+{
+public:
+ enum Family {
+ FAMILY_NONE,
+
+ FAMILY_SAM7S,
+ FAMILY_SAM7SE,
+ FAMILY_SAM7X,
+ FAMILY_SAM7XC,
+ FAMILY_SAM7L,
+
+ FAMILY_SAM3N,
+ FAMILY_SAM3S,
+ FAMILY_SAM3U,
+ FAMILY_SAM3X,
+ FAMILY_SAM3A,
+
+ FAMILY_SAM4S,
+ FAMILY_SAM4E,
+
+ FAMILY_SAM9XE,
+
+ FAMILY_SAMD21,
+ FAMILY_SAMR21,
+ FAMILY_SAML21,
+
+ FAMILY_SAMD51,
+ FAMILY_SAME51,
+ FAMILY_SAME53,
+ FAMILY_SAME54,
+
+ FAMILY_SAME70,
+ FAMILY_SAMS70,
+ FAMILY_SAMV70,
+ FAMILY_SAMV71,
+ };
+
+ Device(Samba& samba) : _samba(samba), _flash(nullptr), _family(FAMILY_NONE) {}
+ virtual ~Device() {}
+
+ void create();
+
+ Family getFamily() { return _family; }
+
+ typedef std::unique_ptr<Flash> const FlashPtr;
+
+ FlashPtr& getFlash() { return _flash; }
+
+ void reset();
+
+private:
+ Samba& _samba;
+ std::unique_ptr<Flash> _flash;
+ Family _family;
+
+ void readChipId(uint32_t& chipId, uint32_t& extChipId);
+};
+
+#endif // _DEVICE_H
+
diff --git a/lib/bossac/src/EefcFlash.cpp b/lib/bossac/src/EefcFlash.cpp
new file mode 100644
index 00000000..988c3b7e
--- /dev/null
+++ b/lib/bossac/src/EefcFlash.cpp
@@ -0,0 +1,363 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#include "EefcFlash.h"
+
+#include <assert.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define EEFC_KEY 0x5a
+
+#define EEFC0_FMR (_regs + 0x00)
+#define EEFC0_FCR (_regs + 0x04)
+#define EEFC0_FSR (_regs + 0x08)
+#define EEFC0_FRR (_regs + 0x0C)
+
+#define EEFC1_FMR (_regs + 0x200)
+#define EEFC1_FCR (_regs + 0x204)
+#define EEFC1_FSR (_regs + 0x208)
+#define EEFC1_FRR (_regs + 0x20C)
+
+#define EEFC_FCMD_GETD 0x0
+#define EEFC_FCMD_WP 0x1
+#define EEFC_FCMD_WPL 0x2
+#define EEFC_FCMD_EWP 0x3
+#define EEFC_FCMD_EWPL 0x4
+#define EEFC_FCMD_EA 0x5
+#define EEFC_FCMD_EPA 0x7
+#define EEFC_FCMD_SLB 0x8
+#define EEFC_FCMD_CLB 0x9
+#define EEFC_FCMD_GLB 0xa
+#define EEFC_FCMD_SGPB 0xb
+#define EEFC_FCMD_CGPB 0xc
+#define EEFC_FCMD_GGPB 0xd
+
+const uint32_t
+EefcFlash::PagesPerErase = 8;
+
+EefcFlash::EefcFlash(Samba& samba,
+ const std::string& name,
+ uint32_t addr,
+ uint32_t pages,
+ uint32_t size,
+ uint32_t planes,
+ uint32_t lockRegions,
+ uint32_t user,
+ uint32_t stack,
+ uint32_t regs,
+ bool canBrownout)
+ : Flash(samba, name, addr, pages, size, planes, lockRegions, user, stack),
+ _regs(regs), _canBrownout(canBrownout), _eraseAuto(true)
+{
+ assert(planes == 1 || planes == 2);
+ assert(pages <= 4096);
+ assert(lockRegions <= 256);
+
+ // SAM3 Errata (FWS must be 6)
+ _samba.writeWord(EEFC0_FMR, 0x6 << 8);
+ if (planes == 2)
+ _samba.writeWord(EEFC1_FMR, 0x6 << 8);
+}
+
+EefcFlash::~EefcFlash()
+{
+}
+
+void
+EefcFlash::eraseAll(uint32_t offset)
+{
+ // Do a full chip erase if the offset is 0
+ if (offset == 0)
+ {
+ waitFSR();
+ writeFCR0(EEFC_FCMD_EA, 0);
+ if (_planes == 2)
+ {
+ waitFSR();
+ writeFCR1(EEFC_FCMD_EA, 0);
+ }
+
+ // Erase all can take an exceptionally long time on some devices
+ // so wait on FSR for up to 30 seconds
+ waitFSR(30);
+ }
+ // Else we must do it by pages
+ else
+ {
+ // Offset must be on an erase page boundary
+ if (offset % (_size * PagesPerErase))
+ throw FlashEraseError();
+
+ // Erase each PagesPerErase set of pages
+ for (uint32_t pageNum = offset / _size; pageNum < _pages; pageNum += PagesPerErase)
+ {
+ if (_planes == 1 || pageNum < _pages / 2)
+ {
+ waitFSR();
+ writeFCR0(EEFC_FCMD_EPA, pageNum | 0x1);
+ }
+ else
+ {
+ waitFSR();
+ writeFCR1(EEFC_FCMD_EPA, (pageNum % (_pages / 2)) | 0x1);
+ }
+ }
+ }
+}
+
+void
+EefcFlash::eraseAuto(bool enable)
+{
+ _eraseAuto = enable;
+}
+
+std::vector<bool>
+EefcFlash::getLockRegions()
+{
+ std::vector<bool> regions(_lockRegions);
+ uint32_t frr;
+ uint32_t bit;
+
+ waitFSR();
+ for (uint32_t region = 0; region < _lockRegions; region++)
+ {
+ if (_planes == 2 && region >= _lockRegions / 2)
+ {
+ bit = region - _lockRegions / 2;
+ writeFCR1(EEFC_FCMD_GLB, 0);
+ waitFSR();
+ frr = readFRR1();
+ while (bit >= 32)
+ {
+ frr = readFRR1();
+ bit -= 32;
+ }
+ regions[region] = (frr & (1 << bit)) != 0;
+ }
+ else
+ {
+ bit = region;
+ writeFCR0(EEFC_FCMD_GLB, 0);
+ waitFSR();
+ frr = readFRR0();
+ while (bit >= 32)
+ {
+ frr = readFRR0();
+ bit -= 32;
+ }
+ regions[region] = (frr & (1 << bit)) != 0;
+ }
+ }
+
+ return regions;
+}
+
+bool
+EefcFlash::getSecurity()
+{
+ waitFSR();
+ writeFCR0(EEFC_FCMD_GGPB, 0);
+ waitFSR();
+ return (readFRR0() & (1 << 0));
+}
+
+bool
+EefcFlash::getBod()
+{
+ if (!_canBrownout)
+ return false;
+
+ waitFSR();
+ writeFCR0(EEFC_FCMD_GGPB, 0);
+ waitFSR();
+ return (readFRR0() & (1 << 1));
+}
+
+bool
+EefcFlash::getBor()
+{
+ if (!_canBrownout)
+ return false;
+
+ waitFSR();
+ writeFCR0(EEFC_FCMD_GGPB, 0);
+ waitFSR();
+ return (readFRR0() & (1 << 2));
+}
+
+bool
+EefcFlash::getBootFlash()
+{
+ waitFSR();
+ writeFCR0(EEFC_FCMD_GGPB, 0);
+ waitFSR();
+ return (readFRR0() & (1 << (_canBrownout ? 3 : 1)));
+}
+
+void
+EefcFlash::writeOptions()
+{
+ if (canBootFlash() && _bootFlash.isDirty() && _bootFlash.get() != getBootFlash())
+ {
+ waitFSR();
+ writeFCR0(_bootFlash.get() ? EEFC_FCMD_SGPB : EEFC_FCMD_CGPB, (canBod() ? 3 : 1));
+ }
+ if (canBor() && _bor.isDirty() && _bor.get() != getBor())
+ {
+ waitFSR();
+ writeFCR0(_bor.get() ? EEFC_FCMD_SGPB : EEFC_FCMD_CGPB, 2);
+ }
+ if (canBod() && _bod.isDirty() && _bod.get() != getBod())
+ {
+ waitFSR();
+ writeFCR0(_bod.get() ? EEFC_FCMD_SGPB : EEFC_FCMD_CGPB, 1);
+ }
+ if (_regions.isDirty())
+ {
+ uint32_t page;
+ std::vector<bool> current;
+
+ if (_regions.get().size() >= _lockRegions)
+ throw FlashRegionError();
+
+ current = getLockRegions();
+
+ for (uint32_t region = 0; region < _lockRegions; region++)
+ {
+ if (_regions.get()[region] != current[region])
+ {
+ if (_planes == 2 && region >= _lockRegions / 2)
+ {
+ page = (region - _lockRegions / 2) * _pages / _lockRegions;
+ waitFSR();
+ writeFCR1(_regions.get()[region] ? EEFC_FCMD_SLB : EEFC_FCMD_CLB, page);
+ }
+ else
+ {
+ page = region * _pages / _lockRegions;
+ waitFSR();
+ writeFCR0(_regions.get()[region] ? EEFC_FCMD_SLB : EEFC_FCMD_CLB, page);
+ }
+ }
+ }
+ }
+ if (_security.isDirty() && _security.get() == true && _security.get() != getSecurity())
+ {
+ waitFSR();
+ writeFCR0(EEFC_FCMD_SGPB, 0);
+ }
+}
+
+void
+EefcFlash::writePage(uint32_t page)
+{
+ if (page >= _pages)
+ throw FlashPageError();
+
+ _wordCopy.setDstAddr(_addr + page * _size);
+ _wordCopy.setSrcAddr(_onBufferA ? _pageBufferA : _pageBufferB);
+ _onBufferA = !_onBufferA;
+ waitFSR();
+ _wordCopy.runv();
+ if (_planes == 2 && page >= _pages / 2)
+ writeFCR1(_eraseAuto ? EEFC_FCMD_EWP : EEFC_FCMD_WP, page - _pages / 2);
+ else
+ writeFCR0(_eraseAuto ? EEFC_FCMD_EWP : EEFC_FCMD_WP, page);
+}
+
+void
+EefcFlash::readPage(uint32_t page, uint8_t* data)
+{
+ if (page >= _pages)
+ throw FlashPageError();
+
+ // The SAM3 firmware has a bug where it returns all zeros for reads
+ // directly from the flash so instead, we copy the flash page to
+ // SRAM and read it from there.
+ _wordCopy.setDstAddr(_onBufferA ? _pageBufferA : _pageBufferB);
+ _wordCopy.setSrcAddr(_addr + page * _size);
+ waitFSR();
+ _wordCopy.runv();
+ _samba.read(_onBufferA ? _pageBufferA : _pageBufferB, data, _size);
+}
+
+void
+EefcFlash::waitFSR(int seconds)
+{
+ int tries = seconds * 1000;
+ uint32_t fsr0;
+ uint32_t fsr1 = 0x1;
+
+ while (tries-- > 0)
+ {
+ fsr0 = _samba.readWord(EEFC0_FSR);
+ if (fsr0 & 0x2)
+ throw FlashCmdError();
+ if (fsr0 & 0x4)
+ throw FlashLockError();
+
+ if (_planes == 2)
+ {
+ fsr1 = _samba.readWord(EEFC1_FSR);
+ if (fsr1 & 0x2)
+ throw FlashCmdError();
+ if (fsr1 & 0x4)
+ throw FlashLockError();
+ }
+ if (fsr0 & fsr1 & 0x1)
+ break;
+ usleep(1000);
+ }
+ if (tries == 0)
+ throw FlashTimeoutError();
+}
+
+void
+EefcFlash::writeFCR0(uint8_t cmd, uint32_t arg)
+{
+ _samba.writeWord(EEFC0_FCR, (EEFC_KEY << 24) | (arg << 8) | cmd);
+}
+
+void
+EefcFlash::writeFCR1(uint8_t cmd, uint32_t arg)
+{
+ _samba.writeWord(EEFC1_FCR, (EEFC_KEY << 24) | (arg << 8) | cmd);
+}
+
+uint32_t
+EefcFlash::readFRR0()
+{
+ return _samba.readWord(EEFC0_FRR);
+}
+
+uint32_t
+EefcFlash::readFRR1()
+{
+ return _samba.readWord(EEFC1_FRR);
+}
diff --git a/lib/bossac/src/EefcFlash.h b/lib/bossac/src/EefcFlash.h
new file mode 100644
index 00000000..40fabc1a
--- /dev/null
+++ b/lib/bossac/src/EefcFlash.h
@@ -0,0 +1,88 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#ifndef _EEFCFLASH_H
+#define _EEFCFLASH_H
+
+#include <stdint.h>
+#include <exception>
+
+#include "Flash.h"
+
+class EefcFlash : public Flash
+{
+public:
+ EefcFlash(Samba& samba,
+ const std::string& name,
+ uint32_t addr,
+ uint32_t pages,
+ uint32_t size,
+ uint32_t planes,
+ uint32_t lockRegions,
+ uint32_t user,
+ uint32_t stack,
+ uint32_t regs,
+ bool canBrownout);
+ virtual ~EefcFlash();
+
+ void eraseAll(uint32_t offset);
+ void eraseAuto(bool enable);
+
+ std::vector<bool> getLockRegions();
+
+ bool getSecurity();
+
+ bool getBod();
+ bool canBod() { return _canBrownout; }
+
+ bool getBor();
+ bool canBor() { return _canBrownout; }
+
+ bool getBootFlash();
+ bool canBootFlash() { return true; }
+
+ void writeOptions();
+
+ void writePage(uint32_t page);
+ void readPage(uint32_t page, uint8_t* data);
+
+ static const uint32_t PagesPerErase;
+
+private:
+ uint32_t _regs;
+ bool _canBrownout;
+ bool _eraseAuto;
+
+ void waitFSR(int seconds = 1);
+ void writeFCR0(uint8_t cmd, uint32_t arg);
+ void writeFCR1(uint8_t cmd, uint32_t arg);
+ uint32_t readFRR0();
+ uint32_t readFRR1();
+};
+
+#endif // _EEFCFLASH_H
diff --git a/lib/bossac/src/EfcFlash.cpp b/lib/bossac/src/EfcFlash.cpp
new file mode 100644
index 00000000..9b212385
--- /dev/null
+++ b/lib/bossac/src/EfcFlash.cpp
@@ -0,0 +1,295 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#include "EfcFlash.h"
+
+#include <assert.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define EFC_KEY 0x5a
+
+#define EFC0_FMR 0xffffff60
+#define EFC0_FCR 0xffffff64
+#define EFC0_FSR 0xffffff68
+
+#define EFC1_FMR 0xffffff70
+#define EFC1_FCR 0xffffff74
+#define EFC1_FSR 0xffffff78
+
+#define EFC_FCMD_WP 0x1
+#define EFC_FCMD_SLB 0x2
+#define EFC_FCMD_WPL 0x3
+#define EFC_FCMD_CLB 0x4
+#define EFC_FCMD_EA 0x8
+#define EFC_FCMD_SGPB 0xb
+#define EFC_FCMD_CGPB 0xd
+#define EFC_FCMD_SSB 0xf
+
+EfcFlash::EfcFlash(Samba& samba,
+ const std::string& name,
+ uint32_t addr,
+ uint32_t pages,
+ uint32_t size,
+ uint32_t planes,
+ uint32_t lockRegions,
+ uint32_t user,
+ uint32_t stack,
+ bool canBootFlash)
+ : Flash(samba, name, addr, pages, size, planes, lockRegions, user, stack),
+ _canBootFlash(canBootFlash)
+{
+ assert(planes == 1 || planes == 2);
+ assert(pages <= planes * 1024);
+ assert(lockRegions <= 32);
+
+ eraseAuto(true);
+}
+
+EfcFlash::~EfcFlash()
+{
+}
+
+void
+EfcFlash::eraseAll(uint32_t offset)
+{
+ if (offset != 0)
+ throw FlashEraseError();
+
+ waitFSR();
+ writeFCR0(EFC_FCMD_EA, 0);
+ if (_planes == 2)
+ {
+ waitFSR();
+ writeFCR0(EFC_FCMD_EA, _pages / 2);
+ }
+}
+
+void
+EfcFlash::eraseAuto(bool enable)
+{
+ uint32_t fmr;
+
+ waitFSR();
+ fmr = _samba.readWord(EFC0_FMR);
+ if (enable)
+ fmr &= ~(1 << 7);
+ else
+ fmr |= (1 << 7);
+
+ _samba.writeWord(EFC0_FMR, fmr);
+ if (_planes == 2)
+ {
+ waitFSR();
+ _samba.writeWord(EFC1_FMR, fmr);
+ }
+}
+
+std::vector<bool>
+EfcFlash::getLockRegions()
+{
+ std::vector<bool> regions(_lockRegions);
+ uint32_t fsr0;
+ uint32_t fsr1;
+
+ fsr0 = readFSR0();
+ if (_planes == 2)
+ fsr1 = readFSR1();
+ else
+ fsr1 = 0;
+
+ for (uint32_t region = 0; region < _lockRegions; region++)
+ {
+ if (_planes == 2 && region >= _lockRegions / 2)
+ regions[region] = (fsr1 & (1 << (16 + region - _lockRegions / 2))) != 0;
+ else
+ regions[region] = (fsr0 & (1 << (16 + region))) != 0;
+ }
+
+ return regions;
+}
+
+bool
+EfcFlash::getSecurity()
+{
+ return (readFSR0() & (1 << 4));
+}
+
+bool
+EfcFlash::getBod()
+{
+ return (readFSR0() & (1 << 8));
+}
+
+bool
+EfcFlash::getBor()
+{
+ return (readFSR0() & (2 << 8));
+}
+
+bool
+EfcFlash::getBootFlash()
+{
+ if (!_canBootFlash)
+ return false;
+
+ return (readFSR0() & (1 << 10));
+}
+
+void
+EfcFlash::writeOptions()
+{
+ if (canBootFlash() && _bootFlash.isDirty() && _bootFlash.get() != getBootFlash())
+ {
+ waitFSR();
+ writeFCR0(_bootFlash.get() ? EFC_FCMD_SGPB : EFC_FCMD_CGPB, 2);
+ }
+ if (canBor() && _bor.isDirty() && _bor.get() != getBor())
+ {
+ waitFSR();
+ writeFCR0(_bor.get() ? EFC_FCMD_SGPB : EFC_FCMD_CGPB, 1);
+ }
+ if (canBod() && _bod.isDirty() && _bod.get() != getBod())
+ {
+ waitFSR();
+ writeFCR0(_bod.get() ? EFC_FCMD_SGPB : EFC_FCMD_CGPB, 0);
+ }
+ if (_regions.isDirty())
+ {
+ uint32_t page;
+ std::vector<bool> current;
+
+ current = getLockRegions();
+
+ for (uint32_t region = 0; region < _regions.get().size(); region++)
+ {
+ if (_regions.get()[region] != current[region])
+ {
+ if (_planes == 2 && region >= _lockRegions / 2)
+ {
+ page = (region - _lockRegions / 2) * _pages / _lockRegions;
+ waitFSR();
+ writeFCR1(_regions.get()[region] ? EFC_FCMD_SLB : EFC_FCMD_CLB, page);
+ }
+ else
+ {
+ page = region * _pages / _lockRegions;
+ waitFSR();
+ writeFCR0(_regions.get()[region] ? EFC_FCMD_SLB : EFC_FCMD_CLB, page);
+ }
+ }
+ }
+ }
+ if (_security.isDirty() && _security.get() == true && _security.get() != getSecurity())
+ {
+ waitFSR();
+ writeFCR0(EFC_FCMD_SSB, 0);
+ }
+}
+
+void
+EfcFlash::writePage(uint32_t page)
+{
+ if (page >= _pages)
+ throw FlashPageError();
+
+ _wordCopy.setDstAddr(_addr + page * _size);
+ _wordCopy.setSrcAddr(_onBufferA ? _pageBufferA : _pageBufferB);
+ _onBufferA = !_onBufferA;
+ waitFSR();
+ _wordCopy.run();
+ if (_planes == 2 && page >= _pages / 2)
+ writeFCR1(EFC_FCMD_WP, page - _pages / 2);
+ else
+ writeFCR0(EFC_FCMD_WP, page);
+}
+
+void
+EfcFlash::readPage(uint32_t page, uint8_t* data)
+{
+ if (page >= _pages)
+ throw FlashPageError();
+
+ waitFSR();
+ _samba.read(_addr + page * _size, data, _size);
+}
+
+void
+EfcFlash::waitFSR(int seconds)
+{
+ int tries = seconds * 1000;
+ uint32_t fsr0;
+ uint32_t fsr1 = 0x1;
+
+ while (tries-- > 0)
+ {
+ fsr0 = readFSR0();
+ if (fsr0 & 0x2)
+ throw FlashCmdError();
+ if (fsr0 & 0x4)
+ throw FlashLockError();
+
+ if (_planes == 2)
+ {
+ fsr1 = readFSR1();
+ if (fsr1 & 0x2)
+ throw FlashCmdError();
+ if (fsr1 & 0x4)
+ throw FlashLockError();
+ }
+ if (fsr0 & fsr1 & 0x1)
+ break;
+ usleep(1000);
+ }
+ if (tries == 0)
+ throw FlashTimeoutError();
+}
+
+void
+EfcFlash::writeFCR0(uint8_t cmd, uint32_t arg)
+{
+ _samba.writeWord(EFC0_FCR, (EFC_KEY << 24) | (arg << 8) | cmd);
+}
+
+void
+EfcFlash::writeFCR1(uint8_t cmd, uint32_t arg)
+{
+ _samba.writeWord(EFC1_FCR, (EFC_KEY << 24) | (arg << 8) | cmd);
+}
+
+uint32_t
+EfcFlash::readFSR0()
+{
+ return _samba.readWord(EFC0_FSR);
+}
+
+uint32_t
+EfcFlash::readFSR1()
+{
+ return _samba.readWord(EFC1_FSR);
+}
diff --git a/lib/bossac/src/EfcFlash.h b/lib/bossac/src/EfcFlash.h
new file mode 100644
index 00000000..cf22f0b8
--- /dev/null
+++ b/lib/bossac/src/EfcFlash.h
@@ -0,0 +1,83 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#ifndef _EFCFLASH_H
+#define _EFCFLASH_H
+
+#include <stdint.h>
+#include <exception>
+
+#include "Flash.h"
+
+class EfcFlash : public Flash
+{
+public:
+ EfcFlash(Samba& samba,
+ const std::string& name,
+ uint32_t addr,
+ uint32_t pages,
+ uint32_t size,
+ uint32_t planes,
+ uint32_t lockRegions,
+ uint32_t user,
+ uint32_t stack,
+ bool canBootFlash);
+ virtual ~EfcFlash();
+
+ void eraseAll(uint32_t offset);
+ void eraseAuto(bool enable);
+
+ std::vector<bool> getLockRegions();
+
+ bool getSecurity();
+
+ bool getBod();
+ bool canBod() { return true; }
+
+ bool getBor();
+ bool canBor() { return true; }
+
+ bool getBootFlash();
+ bool canBootFlash() { return _canBootFlash; }
+
+ void writeOptions();
+
+ void writePage(uint32_t page);
+ void readPage(uint32_t page, uint8_t* data);
+
+private:
+ bool _canBootFlash;
+
+ void waitFSR(int seconds = 1);
+ void writeFCR0(uint8_t cmd, uint32_t arg);
+ void writeFCR1(uint8_t cmd, uint32_t arg);
+ uint32_t readFSR0();
+ uint32_t readFSR1();
+};
+
+#endif // _EFCFLASH_H
diff --git a/lib/bossac/src/FileError.h b/lib/bossac/src/FileError.h
new file mode 100644
index 00000000..ff2fb284
--- /dev/null
+++ b/lib/bossac/src/FileError.h
@@ -0,0 +1,94 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#ifndef _FILEERROR_H
+#define _FILEERROR_H
+
+#include <exception>
+#include <errno.h>
+#include <string.h>
+
+#include "Flash.h"
+#include "Samba.h"
+
+class FileError : public std::exception
+{
+public:
+ FileError() : std::exception() {}
+};
+
+class FileOpenError : public FileError
+{
+public:
+ FileOpenError() : FileError(), _errnum(0) {};
+ FileOpenError(int errnum) : FileError(), _errnum(errnum) {};
+ const char* what() const throw()
+ {
+ if (_errnum == 0)
+ return "Unable to open file";
+ else
+ return strerror(_errnum);
+ }
+private:
+ int _errnum;
+};
+
+class FileIoError : public FileError
+{
+public:
+ FileIoError() : FileError(), _errnum(0) {};
+ FileIoError(int errnum) : FileError(), _errnum(errnum) {};
+ const char* what() const throw()
+ {
+ if (_errnum == 0)
+ return "File I/O operation failed";
+ else
+ return strerror(_errnum);
+ }
+private:
+ int _errnum;
+};
+
+class FileShortError : public FileError
+{
+public:
+ FileShortError() : FileError() {};
+ const char* what() const throw()
+ {
+ return "Operation ended with a short write";
+ }
+};
+
+class FileSizeError : public FileError
+{
+public:
+ FileSizeError() {};
+ const char* what() const throw() { return "File operation exceeds flash size"; }
+};
+
+#endif // _FILEERROR_H
diff --git a/lib/bossac/src/Flash.cpp b/lib/bossac/src/Flash.cpp
new file mode 100644
index 00000000..b00dfa0e
--- /dev/null
+++ b/lib/bossac/src/Flash.cpp
@@ -0,0 +1,106 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#include "Flash.h"
+
+#include <assert.h>
+
+Flash::Flash(Samba& samba,
+ const std::string& name,
+ uint32_t addr,
+ uint32_t pages,
+ uint32_t size,
+ uint32_t planes,
+ uint32_t lockRegions,
+ uint32_t user,
+ uint32_t stack)
+ : _samba(samba), _name(name), _addr(addr), _pages(pages), _size(size),
+ _planes(planes), _lockRegions(lockRegions), _user(user), _wordCopy(samba, user)
+{
+ assert((size & (size - 1)) == 0);
+ assert((pages & (pages - 1)) == 0);
+ assert((lockRegions & (lockRegions - 1)) == 0);
+
+ _wordCopy.setWords(size / sizeof(uint32_t));
+ _wordCopy.setStack(stack);
+
+ _onBufferA = true;
+
+ // page buffers will have the size of a physical page and will be situated right after the applet
+ _pageBufferA = ((_user + _wordCopy.size() + 3) / 4) * 4; // we need to avoid non 32bits aligned access on Cortex-M0+
+ _pageBufferB = _pageBufferA + size;
+}
+
+void
+Flash::setLockRegions(const std::vector<bool>& regions)
+{
+ if (regions.size() > _lockRegions)
+ throw FlashRegionError();
+
+ _regions.set(regions);
+}
+
+void
+Flash::setSecurity()
+{
+ _security.set(true);
+}
+
+void
+Flash::setBor(bool enable)
+{
+ if (canBor())
+ _bor.set(enable);
+}
+
+void
+Flash::setBod(bool enable)
+{
+ if (canBod())
+ _bod.set(enable);
+}
+
+void
+Flash::setBootFlash(bool enable)
+{
+ if (canBootFlash())
+ _bootFlash.set(enable);
+}
+
+void
+Flash::loadBuffer(const uint8_t* data, uint16_t bufferSize)
+{
+ _samba.write(_onBufferA ? _pageBufferA : _pageBufferB, data, bufferSize);
+}
+
+void
+Flash::writeBuffer(uint32_t dst_addr, uint32_t size)
+{
+ _samba.writeBuffer(_onBufferA ? _pageBufferA : _pageBufferB, dst_addr + _addr, size);
+}
+
diff --git a/lib/bossac/src/Flash.h b/lib/bossac/src/Flash.h
new file mode 100644
index 00000000..5d3a37b3
--- /dev/null
+++ b/lib/bossac/src/Flash.h
@@ -0,0 +1,180 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#ifndef _FLASH_H
+#define _FLASH_H
+
+#include <stdint.h>
+#include <vector>
+#include <memory>
+#include <exception>
+
+#include "Samba.h"
+#include "WordCopyApplet.h"
+
+class FlashPageError : public std::exception
+{
+public:
+ FlashPageError() : exception() {};
+ const char* what() const throw() { return "Invalid flash page"; }
+};
+
+class FlashRegionError : public std::exception
+{
+public:
+ FlashRegionError() : exception() {};
+ const char* what() const throw() { return "Invalid lock region"; }
+};
+
+class FlashLockError : public std::exception
+{
+public:
+ FlashLockError() : exception() {};
+ const char* what() const throw() { return "Flash page is locked"; }
+};
+
+class FlashCmdError : public std::exception
+{
+public:
+ FlashCmdError() : exception() {};
+ const char* what() const throw() { return "Flash command failed"; }
+};
+
+class FlashTimeoutError : public std::exception
+{
+public:
+ FlashTimeoutError() : exception() {};
+ const char* what() const throw() { return "Flash command timeout"; }
+};
+
+class BootFlashError : public std::exception
+{
+public:
+ BootFlashError() : exception() {};
+ const char* what() const throw() { return "Unable to clear boot flash for this device"; }
+
+};
+
+class FlashEraseError : public std::exception
+{
+public:
+ FlashEraseError() : exception() {};
+ const char* what() const throw() { return "Flash erase failed"; }
+
+};
+
+template<class T>
+class FlashOption
+{
+public:
+ FlashOption() : _dirty(false) {}
+ virtual ~FlashOption() {}
+ void set(const T& value) { _value = value; _dirty = true; }
+ const T& get() { return _value; }
+ bool isDirty() { return _dirty; }
+
+private:
+ T _value;
+ bool _dirty;
+};
+
+class Flash
+{
+public:
+ Flash(Samba& samba,
+ const std::string& name,
+ uint32_t addr, // Flash base address
+ uint32_t pages, // Number of pages
+ uint32_t size, // Page size in bytes
+ uint32_t planes, // Number of flash planes
+ uint32_t lockRegions, // Number of flash lock regions
+ uint32_t user, // Address in SRAM where the applet and buffers will be placed
+ uint32_t stack); // Address in SRAM where the applet stack will be placed
+ virtual ~Flash() {}
+
+ const std::string& name() { return _name; }
+
+ virtual uint32_t address() { return _addr; }
+ virtual uint32_t pageSize() { return _size; }
+ virtual uint32_t numPages() { return _pages; }
+ virtual uint32_t numPlanes() { return _planes; }
+ virtual uint32_t totalSize() { return _size * _pages; }
+ virtual uint32_t lockRegions() { return _lockRegions; }
+
+ virtual void eraseAll(uint32_t offset) = 0;
+ virtual void eraseAuto(bool enable) = 0;
+
+ virtual std::vector<bool> getLockRegions() = 0;
+ virtual void setLockRegions(const std::vector<bool>& regions);
+
+ virtual bool getSecurity() = 0;
+ virtual void setSecurity();
+
+ virtual bool getBod() = 0;
+ virtual void setBod(bool enable);
+ virtual bool canBod() = 0;
+
+ virtual bool getBor() = 0;
+ virtual void setBor(bool enable);
+ virtual bool canBor() = 0;
+
+ virtual bool getBootFlash() = 0;
+ virtual void setBootFlash(bool enable);
+ virtual bool canBootFlash() = 0;
+
+ virtual void writeOptions() = 0;
+
+ virtual void writePage(uint32_t page) = 0;
+ virtual void readPage(uint32_t page, uint8_t* data) = 0;
+
+ virtual void writeBuffer(uint32_t dst_addr, uint32_t size);
+ virtual void loadBuffer(const uint8_t* data, uint16_t size);
+
+protected:
+ Samba& _samba;
+ std::string _name;
+ uint32_t _addr;
+ uint32_t _pages;
+ uint32_t _size;
+ uint32_t _planes;
+ uint32_t _lockRegions;
+ uint32_t _user;
+ WordCopyApplet _wordCopy;
+
+ FlashOption<bool> _bootFlash;
+ FlashOption< std::vector<bool> > _regions;
+ FlashOption<bool> _bod;
+ FlashOption<bool> _bor;
+ FlashOption<bool> _security;
+
+ bool _onBufferA;
+ uint32_t _pageBufferA;
+ uint32_t _pageBufferB;
+};
+
+#endif // _FLASH_H
diff --git a/lib/bossac/src/Flasher.cpp b/lib/bossac/src/Flasher.cpp
new file mode 100644
index 00000000..7591cf9f
--- /dev/null
+++ b/lib/bossac/src/Flasher.cpp
@@ -0,0 +1,373 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#include <string>
+#include <exception>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "Flasher.h"
+
+using namespace std;
+
+void
+FlasherInfo::print()
+{
+ bool first;
+
+ printf("Device : %s\n", name.c_str());
+ printf("Version : %s\n", version.c_str());
+ printf("Address : 0x%x\n", address);
+ printf("Pages : %d\n", numPages);
+ printf("Page Size : %d bytes\n", pageSize);
+ printf("Total Size : %dKB\n", totalSize / 1024);
+ printf("Planes : %d\n", numPlanes);
+ printf("Lock Regions : %zd\n", lockRegions.size());
+ printf("Locked : ");
+ first = true;
+ for (uint32_t region = 0; region < lockRegions.size(); region++)
+ {
+ if (lockRegions[region])
+ {
+ printf("%s%d", first ? "" : ",", region);
+ first = false;
+ }
+ }
+ printf("%s\n", first ? "none" : "");
+ printf("Security : %s\n", security ? "true" : "false");
+ if (canBootFlash)
+ printf("Boot Flash : %s\n", bootFlash ? "true" : "false");
+ if (canBod)
+ printf("BOD : %s\n", bod ? "true" : "false");
+ if (canBor)
+ printf("BOR : %s\n", bor ? "true" : "false");
+}
+
+void
+Flasher::erase(uint32_t foffset)
+{
+ _observer.onStatus("Erase flash\n");
+ _flash->eraseAll(foffset);
+ _flash->eraseAuto(false);
+}
+
+void
+Flasher::write(const char* filename, uint32_t foffset)
+{
+ FILE* infile;
+ uint32_t pageSize = _flash->pageSize();
+ uint32_t pageNum = 0;
+ uint32_t numPages;
+ long fsize;
+ size_t fbytes;
+
+ if (foffset % pageSize != 0 || foffset >= _flash->totalSize())
+ throw FlashOffsetError();
+
+ infile = fopen(filename, "rb");
+ if (!infile)
+ throw FileOpenError(errno);
+
+ try
+ {
+ if (fseek(infile, 0, SEEK_END) != 0 || (fsize = ftell(infile)) < 0)
+ throw FileIoError(errno);
+
+ rewind(infile);
+
+ numPages = (fsize + pageSize - 1) / pageSize;
+ if (numPages > _flash->numPages())
+ throw FileSizeError();
+
+ _observer.onStatus("Write %ld bytes to flash (%u pages)\n", fsize, numPages);
+
+ if (_samba.canWriteBuffer())
+ {
+ uint32_t offset = 0;
+ uint32_t bufferSize = _samba.writeBufferSize();
+ uint8_t buffer[bufferSize];
+
+ while ((fbytes = fread(buffer, 1, bufferSize, infile)) > 0)
+ {
+ _observer.onProgress(offset / pageSize, numPages);
+
+ if (fbytes < bufferSize)
+ {
+ memset(buffer + fbytes, 0, bufferSize - fbytes);
+ fbytes = (fbytes + pageSize - 1) / pageSize * pageSize;
+ }
+
+ _flash->loadBuffer(buffer, fbytes);
+ _flash->writeBuffer(foffset + offset, fbytes);
+ offset += fbytes;
+ }
+
+ }
+ else
+ {
+ uint8_t buffer[pageSize];
+ uint32_t pageOffset = foffset / pageSize;
+
+ while ((fbytes = fread(buffer, 1, pageSize, infile)) > 0)
+ {
+ _observer.onProgress(pageNum, numPages);
+
+ _flash->loadBuffer(buffer, fbytes);
+ _flash->writePage(pageOffset + pageNum);
+
+ pageNum++;
+ if (pageNum == numPages || fbytes != pageSize)
+ break;
+ }
+
+ }
+ }
+ catch(...)
+ {
+ fclose(infile);
+ throw;
+ }
+
+ fclose(infile);
+ _observer.onProgress(numPages, numPages);
+}
+
+bool
+Flasher::verify(const char* filename, uint32_t& pageErrors, uint32_t& totalErrors, uint32_t foffset)
+{
+ FILE* infile;
+ uint32_t pageSize = _flash->pageSize();
+ uint8_t bufferA[pageSize];
+ uint8_t bufferB[pageSize];
+ uint32_t pageNum = 0;
+ uint32_t numPages;
+ uint32_t pageOffset;
+ uint32_t byteErrors = 0;
+ uint16_t calcCrc = 0;
+ uint16_t flashCrc;
+ long fsize;
+ size_t fbytes;
+
+ pageErrors = 0;
+ totalErrors = 0;
+
+ if (foffset % pageSize != 0 || foffset >= _flash->totalSize())
+ throw FlashOffsetError();
+
+ pageOffset = foffset / pageSize;
+
+ infile = fopen(filename, "rb");
+ if (!infile)
+ throw FileOpenError(errno);
+
+ try
+ {
+ if (fseek(infile, 0, SEEK_END) != 0 || (fsize = ftell(infile)) < 0)
+ throw FileIoError(errno);
+
+ rewind(infile);
+
+ numPages = (fsize + pageSize - 1) / pageSize;
+ if (numPages > _flash->numPages())
+ throw FileSizeError();
+
+ _observer.onStatus("Verify %ld bytes of flash\n", fsize);
+
+ while ((fbytes = fread(bufferA, 1, pageSize, infile)) > 0)
+ {
+ byteErrors = 0;
+
+ _observer.onProgress(pageNum, numPages);
+
+ if (_samba.canChecksumBuffer())
+ {
+ for (uint32_t i = 0; i < fbytes; i++)
+ calcCrc = _samba.checksumCalc(bufferA[i], calcCrc);
+
+ flashCrc = _samba.checksumBuffer((pageOffset + pageNum) * pageSize, fbytes);
+
+ if (flashCrc != calcCrc)
+ {
+ _flash->readPage(pageOffset + pageNum, bufferB);
+
+ for (uint32_t i = 0; i < fbytes; i++)
+ {
+ if (bufferA[i] != bufferB[i])
+ byteErrors++;
+ }
+ }
+ }
+ else
+ {
+ _flash->readPage(pageOffset + pageNum, bufferB);
+
+ for (uint32_t i = 0; i < fbytes; i++)
+ {
+ if (bufferA[i] != bufferB[i])
+ byteErrors++;
+ }
+ }
+
+ if (byteErrors != 0)
+ {
+ pageErrors++;
+ totalErrors += byteErrors;
+ }
+
+ pageNum++;
+ if (pageNum == numPages || fbytes != pageSize)
+ break;
+ }
+ }
+ catch(...)
+ {
+ fclose(infile);
+ throw;
+ }
+
+ fclose(infile);
+
+ _observer.onProgress(numPages, numPages);
+
+ if (pageErrors != 0)
+ return false;
+
+ return true;
+}
+
+void
+Flasher::read(const char* filename, uint32_t fsize, uint32_t foffset)
+{
+ FILE* outfile;
+ uint32_t pageSize = _flash->pageSize();
+ uint8_t buffer[pageSize];
+ uint32_t pageNum = 0;
+ uint32_t pageOffset;
+ uint32_t numPages;
+ size_t fbytes;
+
+ if (foffset % pageSize != 0 || foffset >= _flash->totalSize())
+ throw FlashOffsetError();
+
+ pageOffset = foffset / pageSize;
+
+ if (fsize == 0)
+ fsize = pageSize * (_flash->numPages() - pageOffset);
+
+ numPages = (fsize + pageSize - 1) / pageSize;
+ if (pageOffset + numPages > _flash->numPages())
+ throw FileSizeError();
+
+ outfile = fopen(filename, "wb");
+ if (!outfile)
+ throw FileOpenError(errno);
+
+ _observer.onStatus("Read %d bytes from flash\n", fsize);
+
+ try
+ {
+ for (pageNum = 0; pageNum < numPages; pageNum++)
+ {
+ _observer.onProgress(pageNum, numPages);
+
+ _flash->readPage(pageOffset + pageNum, buffer);
+
+ if (pageNum == numPages - 1 && fsize % pageSize > 0)
+ pageSize = fsize % pageSize;
+ fbytes = fwrite(buffer, 1, pageSize, outfile);
+ if (fbytes != pageSize)
+ throw FileShortError();
+ }
+ }
+ catch(...)
+ {
+ fclose(outfile);
+ throw;
+ }
+
+ _observer.onProgress(numPages, numPages);
+
+ fclose(outfile);
+}
+
+void
+Flasher::lock(string& regionArg, bool enable)
+{
+ if (regionArg.empty())
+ {
+ _observer.onStatus("%s all regions\n", enable ? "Lock" : "Unlock");
+ std::vector<bool> regions(_flash->lockRegions(), enable);
+ _flash->setLockRegions(regions);
+ }
+ else
+ {
+ size_t pos = 0;
+ size_t delim;
+ uint32_t region;
+ string sub;
+ std::vector<bool> regions = _flash->getLockRegions();
+
+ do
+ {
+ delim = regionArg.find(',', pos);
+ sub = regionArg.substr(pos, delim - pos);
+ region = strtol(sub.c_str(), NULL, 0);
+ _observer.onStatus("%s region %d\n", enable ? "Lock" : "Unlock", region);
+ regions[region] = enable;
+ pos = delim + 1;
+ } while (delim != string::npos);
+
+ _flash->setLockRegions(regions);
+ }
+}
+
+void
+Flasher::info(FlasherInfo& info)
+{
+ info.name = _flash->name();
+ info.version = _samba.version();
+ info.address = _flash->address();
+ info.numPages = _flash->numPages();
+ info.pageSize = _flash->pageSize();
+ info.totalSize = _flash->numPages() * _flash->pageSize();
+ info.numPlanes = _flash->numPlanes();
+ info.security = _flash->getSecurity();
+ info.bootFlash = _flash->getBootFlash();
+ info.bod = _flash->getBod();
+ info.bor = _flash->getBor();
+
+ info.canBootFlash = _flash->canBootFlash();
+ info.canBod = _flash->canBod();
+ info.canBor = _flash->canBor();
+ info.canChipErase = _samba.canChipErase();
+ info.canWriteBuffer = _samba.canWriteBuffer();
+ info.canChecksumBuffer = _samba.canChecksumBuffer();
+ info.lockRegions = _flash->getLockRegions();
+}
diff --git a/lib/bossac/src/Flasher.h b/lib/bossac/src/Flasher.h
new file mode 100644
index 00000000..c926fb36
--- /dev/null
+++ b/lib/bossac/src/Flasher.h
@@ -0,0 +1,110 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#ifndef _FLASHER_H
+#define _FLASHER_H
+
+#include <string>
+#include <exception>
+#include <vector>
+
+#include "Device.h"
+#include "Flash.h"
+#include "Samba.h"
+#include "FileError.h"
+
+class FlashOffsetError : public std::exception
+{
+public:
+ FlashOffsetError() : std::exception() {};
+ virtual const char* what() const throw() { return "Flash offset is invalid"; }
+};
+
+class FlasherObserver
+{
+public:
+ FlasherObserver() {}
+ virtual ~FlasherObserver() {}
+
+ virtual void onStatus(const char *message, ...) = 0;
+ virtual void onProgress(int num, int div) = 0;
+};
+
+class FlasherInfo
+{
+public:
+ FlasherInfo() {}
+ virtual ~FlasherInfo() {}
+
+ void print();
+
+ std::string name;
+ uint32_t chipId;
+ uint32_t extChipId;
+ std::string version;
+ uint32_t address;
+ uint32_t numPages;
+ uint32_t pageSize;
+ uint32_t totalSize;
+ uint32_t numPlanes;
+
+ bool security;
+ bool bootFlash;
+ bool bod;
+ bool bor;
+
+ bool canBootFlash;
+ bool canBod;
+ bool canBor;
+ bool canChipErase;
+ bool canWriteBuffer;
+ bool canChecksumBuffer;
+
+ std::vector<bool> lockRegions;
+};
+
+class Flasher
+{
+public:
+ Flasher(Samba& samba, Device& device, FlasherObserver& observer) : _samba(samba), _flash(device.getFlash()), _observer(observer) {}
+ virtual ~Flasher() {}
+
+ void erase(uint32_t foffset);
+ void write(const char* filename, uint32_t foffset = 0);
+ bool verify(const char* filename, uint32_t& pageErrors, uint32_t& totalErrors, uint32_t foffset = 0);
+ void read(const char* filename, uint32_t fsize, uint32_t foffset = 0);
+ void lock(std::string& regionArg, bool enable);
+ void info(FlasherInfo& info);
+
+private:
+ Samba& _samba;
+ Device::FlashPtr& _flash;
+ FlasherObserver& _observer;
+};
+
+#endif // _FLASHER_H
diff --git a/lib/bossac/src/LinuxPortFactory.cpp b/lib/bossac/src/LinuxPortFactory.cpp
new file mode 100644
index 00000000..80499bf9
--- /dev/null
+++ b/lib/bossac/src/LinuxPortFactory.cpp
@@ -0,0 +1,109 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#include "LinuxPortFactory.h"
+#include "PosixSerialPort.h"
+
+#include <string.h>
+#include <stdio.h>
+
+#include <string>
+
+LinuxPortFactory::LinuxPortFactory()
+{
+ _dir = opendir("/dev");
+}
+
+LinuxPortFactory::~LinuxPortFactory()
+{
+ if (_dir)
+ closedir(_dir);
+}
+
+SerialPort::Ptr
+LinuxPortFactory::create(const std::string& name)
+{
+ bool isUsb = false;
+
+ if (name.find("ttyUSB") != std::string::npos ||
+ name.find("ttyACM") != std::string::npos)
+ isUsb = true;
+
+ return create(name, isUsb);
+}
+
+SerialPort::Ptr
+LinuxPortFactory::create(const std::string& name, bool isUsb)
+{
+ return SerialPort::Ptr(new PosixSerialPort(name, isUsb));
+}
+
+std::string
+LinuxPortFactory::begin()
+{
+ if (!_dir)
+ return end();
+
+ rewinddir(_dir);
+
+ return next();
+}
+
+std::string
+LinuxPortFactory::next()
+{
+ struct dirent* entry;
+
+ if (!_dir)
+ return end();
+
+ while ((entry = readdir(_dir)))
+ {
+ if (strncmp("ttyUSB", entry->d_name, sizeof("ttyUSB") - 1) == 0)
+ return std::string(entry->d_name);
+ else if (strncmp("ttyACM", entry->d_name, sizeof("ttyACM") - 1) == 0)
+ return std::string(entry->d_name);
+ else if (strncmp("ttyS", entry->d_name, sizeof("ttyS") - 1) == 0)
+ return std::string(entry->d_name);
+ }
+
+ return end();
+}
+
+std::string
+LinuxPortFactory::end()
+{
+ return std::string();
+}
+
+std::string
+LinuxPortFactory::def()
+{
+ return std::string("/dev/ttyACM0");
+}
+
diff --git a/lib/bossac/src/LinuxPortFactory.h b/lib/bossac/src/LinuxPortFactory.h
new file mode 100644
index 00000000..50f60f95
--- /dev/null
+++ b/lib/bossac/src/LinuxPortFactory.h
@@ -0,0 +1,60 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#ifndef _LINUXPORTFACTORY_H
+#define _LINUXPORTFACTORY_H
+
+class LinuxPortFactory;
+#include "PortFactory.h"
+
+#include <sys/types.h>
+#include <dirent.h>
+
+#include <string>
+
+
+class LinuxPortFactory : public PortFactoryBase
+{
+public:
+ LinuxPortFactory();
+ virtual ~LinuxPortFactory();
+
+ virtual std::string begin();
+ virtual std::string end();
+ virtual std::string next();
+ virtual std::string def();
+
+ virtual SerialPort::Ptr create(const std::string& name);
+ virtual SerialPort::Ptr create(const std::string& name, bool isUsb);
+
+private:
+ std::string _empty;
+ DIR* _dir;
+};
+
+#endif // _LINUXPORTFACTORY_H
diff --git a/lib/bossac/src/PortFactory.h b/lib/bossac/src/PortFactory.h
new file mode 100644
index 00000000..3b3b631e
--- /dev/null
+++ b/lib/bossac/src/PortFactory.h
@@ -0,0 +1,68 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#ifndef _PORTFACTORY_H
+#define _PORTFACTORY_H
+
+#include <string>
+
+#include "SerialPort.h"
+
+class PortFactoryBase
+{
+public:
+ PortFactoryBase() {}
+ virtual ~PortFactoryBase() {}
+
+ virtual std::string begin() = 0;
+ virtual std::string end() = 0;
+ virtual std::string next() = 0;
+ virtual std::string def() = 0;
+
+ virtual SerialPort::Ptr create(const std::string& name) = 0;
+ virtual SerialPort::Ptr create(const std::string& name, bool isUsb) = 0;
+};
+
+#if defined(__WIN32__)
+#include "WinPortFactory.h"
+typedef WinPortFactory PortFactory;
+#elif defined(__linux__)
+#include "LinuxPortFactory.h"
+typedef LinuxPortFactory PortFactory;
+#elif defined(__APPLE__)
+#include "OSXPortFactory.h"
+typedef OSXPortFactory PortFactory;
+#elif defined(__OpenBSD__) || defined(__FreeBSD__)
+// This is likely to work (but not tested) for the other BSDs as well
+#include "BSDPortFactory.h"
+typedef BSDPortFactory PortFactory;
+#else
+#error "Platform is not supported"
+#endif
+
+#endif // _PORTFACTORY_H
diff --git a/lib/bossac/src/PosixSerialPort.cpp b/lib/bossac/src/PosixSerialPort.cpp
new file mode 100644
index 00000000..45eaca9c
--- /dev/null
+++ b/lib/bossac/src/PosixSerialPort.cpp
@@ -0,0 +1,332 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#include "PosixSerialPort.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <termios.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+#include <string>
+
+#ifndef B460800
+#define B460800 460800
+#endif
+#ifndef B921600
+#define B921600 921600
+#endif
+
+PosixSerialPort::PosixSerialPort(const std::string& name, bool isUsb) :
+ SerialPort(name), _devfd(-1), _isUsb(isUsb), _timeout(0),
+ _autoFlush(false)
+{
+}
+
+PosixSerialPort::~PosixSerialPort()
+{
+ if (_devfd >= 0)
+ ::close(_devfd);
+}
+
+bool
+PosixSerialPort::open(int baud,
+ int data,
+ SerialPort::Parity parity,
+ SerialPort::StopBit stop)
+{
+ struct termios options;
+ speed_t speed;
+ // Try opening port assuming _name is full path. If it fails
+ // try "/dev/" + _name
+ _devfd = ::open(_name.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
+ if (_devfd == -1)
+ {
+ std::string dev("/dev/");
+ dev += _name;
+ _devfd = ::open(dev.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
+ if (_devfd == -1)
+ return false;
+ }
+
+ if (tcgetattr(_devfd, &options) == -1)
+ {
+ close();
+ return false;
+ }
+
+ switch (baud)
+ {
+ case 1200:
+ speed = B1200;
+ break;
+ case 9600:
+ speed = B9600;
+ break;
+ case 19200:
+ speed = B19200;
+ break;
+ case 38400:
+ speed = B38400;
+ break;
+ case 57600:
+ speed = B57600;
+ break;
+ case 115200:
+ speed = B115200;
+ break;
+ case 230400:
+ speed = B230400;
+ break;
+ case 460800:
+ speed = B460800;
+ break;
+ case 921600:
+ speed = B921600;
+ break;
+ default:
+ close();
+ return false;
+ }
+
+ if (cfsetispeed(&options, speed) || cfsetospeed(&options, speed))
+ {
+ close();
+ return false;
+ }
+
+ options.c_cflag |= (CLOCAL | CREAD);
+
+ switch (data)
+ {
+ case 8:
+ options.c_cflag &= ~CSIZE;
+ options.c_cflag |= CS8;
+ break;
+ case 7:
+ options.c_cflag &= ~CSIZE;
+ options.c_cflag |= CS7;
+ break;
+ default:
+ close();
+ return false;
+ }
+
+ switch (parity)
+ {
+ case SerialPort::ParityNone:
+ options.c_cflag &= ~PARENB;
+ options.c_cflag &= ~PARODD;
+ options.c_iflag &= ~(INPCK | ISTRIP);
+ break;
+ case SerialPort::ParityOdd:
+ options.c_cflag |= PARENB;
+ options.c_cflag |= PARODD;
+ options.c_iflag |= (INPCK | ISTRIP);
+ break;
+ case SerialPort::ParityEven:
+ options.c_cflag |= PARENB;
+ options.c_cflag &= ~PARODD;
+ options.c_iflag |= (INPCK | ISTRIP);
+ break;
+ default:
+ close();
+ return false;
+ }
+
+ switch (stop)
+ {
+ case StopBitOne:
+ options.c_cflag &= ~CSTOPB;
+ break;
+ case StopBitTwo:
+ options.c_cflag |= CSTOPB;
+ break;
+ default:
+ close();
+ return false;
+ }
+
+ // No hardware flow control
+ options.c_cflag &= ~CRTSCTS;
+
+ // No software flow control
+ options.c_iflag &= ~(IXON | IXOFF | IXANY);
+
+ // Raw input
+ options.c_iflag &= ~(BRKINT | ICRNL);
+ options.c_lflag &= ~(ICANON | IEXTEN | ECHO | ECHOE | ISIG);
+
+ // Raw output
+ options.c_oflag &= ~OPOST;
+
+ // No wait time
+ options.c_cc[VMIN] = 0;
+ options.c_cc[VTIME] = 0;
+
+ if (tcsetattr(_devfd, TCSANOW, &options))
+ {
+ close();
+ return false;
+ }
+
+ return true;
+}
+
+void
+PosixSerialPort::close()
+{
+ if (_devfd >= 0)
+ ::close(_devfd);
+ _devfd = -1;
+}
+
+int
+PosixSerialPort::read(uint8_t* buffer, int len)
+{
+ fd_set fds;
+ struct timeval tv;
+ int numread = 0;
+ int retval;
+
+ if (_devfd == -1)
+ return -1;
+
+ while (numread < len)
+ {
+ FD_ZERO(&fds);
+ FD_SET(_devfd, &fds);
+
+ tv.tv_sec = _timeout / 1000;
+ tv.tv_usec = (_timeout % 1000) * 1000;
+
+ retval = select(_devfd + 1, &fds, NULL, NULL, &tv);
+
+ if (retval < 0)
+ {
+ return -1;
+ }
+ else if (retval == 0)
+ {
+ return numread;
+ }
+ else if (FD_ISSET(_devfd, &fds))
+ {
+ retval = ::read(_devfd, (uint8_t*) buffer + numread, len - numread);
+ if (retval < 0)
+ return -1;
+ numread += retval;
+ }
+ }
+
+ return numread;
+}
+
+int
+PosixSerialPort::write(const uint8_t* buffer, int len)
+{
+ if (_devfd == -1)
+ return -1;
+
+ int res = ::write(_devfd, buffer, len);
+ // Used on macos to avoid upload errors
+ if (_autoFlush)
+ flush();
+ return res;
+}
+
+int
+PosixSerialPort::get()
+{
+ uint8_t byte;
+
+ if (_devfd == -1)
+ return -1;
+
+ if (read(&byte, 1) != 1)
+ return -1;
+
+ return byte;
+}
+
+int
+PosixSerialPort::put(int c)
+{
+ uint8_t byte;
+
+ byte = c;
+ return write(&byte, 1);
+}
+
+void
+PosixSerialPort::flush()
+{
+ // There isn't a reliable way to flush on a file descriptor
+ // so we just wait it out. One millisecond is the USB poll
+ // interval so that should cover it.
+ usleep(1000);
+}
+
+bool
+PosixSerialPort::timeout(int millisecs)
+{
+ _timeout = millisecs;
+ return true;
+}
+
+void
+PosixSerialPort::setDTR(bool dtr)
+{
+ if (_devfd == -1)
+ return;
+
+ int iFlags = TIOCM_DTR;
+
+ ioctl(_devfd, (dtr ? TIOCMBIS : TIOCMBIC), &iFlags);
+}
+
+void
+PosixSerialPort::setRTS(bool rts)
+{
+ if (_devfd == -1)
+ return;
+
+ int iFlags = TIOCM_RTS;
+
+ ioctl(_devfd, (rts ? TIOCMBIS : TIOCMBIC), &iFlags);
+}
+
+void
+PosixSerialPort::setAutoFlush(bool autoflush)
+{
+ _autoFlush = autoflush;
+}
diff --git a/lib/bossac/src/PosixSerialPort.h b/lib/bossac/src/PosixSerialPort.h
new file mode 100644
index 00000000..a79fe889
--- /dev/null
+++ b/lib/bossac/src/PosixSerialPort.h
@@ -0,0 +1,66 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#ifndef _POSIXSERIALPORT_H
+#define _POSIXSERIALPORT_H
+
+#include "SerialPort.h"
+
+class PosixSerialPort : public SerialPort
+{
+public:
+ PosixSerialPort(const std::string& name, bool isUsb);
+ virtual ~PosixSerialPort();
+
+ bool open(int baud = 115200,
+ int data = 8,
+ SerialPort::Parity parity = SerialPort::ParityNone,
+ SerialPort::StopBit stop = SerialPort::StopBitOne);
+ void close();
+
+ bool isUsb() { return _isUsb; };
+
+ int read(uint8_t* data, int size);
+ int write(const uint8_t* data, int size);
+ int get();
+ int put(int c);
+
+ bool timeout(int millisecs);
+ void flush();
+ void setDTR(bool dtr);
+ void setRTS(bool rts);
+ void setAutoFlush(bool autoflush);
+
+private:
+ int _devfd;
+ bool _isUsb;
+ int _timeout;
+ bool _autoFlush;
+};
+
+#endif // _POSIXSERIALPORT_H
diff --git a/lib/bossac/src/Samba.cpp b/lib/bossac/src/Samba.cpp
new file mode 100644
index 00000000..490e3936
--- /dev/null
+++ b/lib/bossac/src/Samba.cpp
@@ -0,0 +1,672 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#include "Samba.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+
+using namespace std;
+
+// XMODEM definitions
+#define BLK_SIZE 128
+#define MAX_RETRIES 5
+#define SOH 0x01
+#define EOT 0x04
+#define ACK 0x06
+#define NAK 0x15
+#define CAN 0x18
+#define START 'C'
+
+#define TIMEOUT_QUICK 100
+#define TIMEOUT_NORMAL 1000
+#define TIMEOUT_LONG 5000
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+Samba::Samba() :
+ _canChipErase(false),
+ _canWriteBuffer(false),
+ _canChecksumBuffer(false),
+ _readBufferSize(0),
+ _debug(false),
+ _isUsb(false)
+{
+}
+
+Samba::~Samba()
+{
+}
+
+bool
+Samba::init()
+{
+ uint8_t cmd[3];
+
+ _port->timeout(TIMEOUT_QUICK);
+
+ // Flush garbage
+ uint8_t dummy[1024];
+ _port->read(dummy, sizeof(dummy));
+
+ if (!_isUsb)
+ {
+ if (_debug)
+ printf("Send auto-baud\n");
+
+ // RS-232 auto-baud sequence
+ _port->put(0x80);
+ _port->get();
+ _port->put(0x80);
+ _port->get();
+ _port->put('#');
+ _port->read(cmd, 3);
+ }
+
+ // Set binary mode
+ if (_debug)
+ printf("Set binary mode\n");
+ cmd[0] = 'N';
+ cmd[1] = '#';
+ _port->write(cmd, 2);
+ _port->read(cmd, 2);
+
+ std::string ver;
+ try
+ {
+ ver = version();
+ }
+ catch(SambaError& err)
+ {
+ return false;
+ }
+
+ std::size_t extIndex = ver.find("[Arduino:");
+ if (extIndex != string::npos)
+ {
+ extIndex += 9;
+ while (ver[extIndex] != ']')
+ {
+ switch (ver[extIndex])
+ {
+ case 'X': _canChipErase = true; break;
+ case 'Y': _canWriteBuffer = true; break;
+ case 'Z': _canChecksumBuffer = true; break;
+ }
+ extIndex++;
+ }
+
+ // All SAMD-based Arduino/AdaFruit boards have a bug in their bootloader
+ // that trying to read 64 bytes or more over USB corrupts the data.
+ // We must limit these boards to read chunks of 63 bytes.
+ if (_isUsb)
+ _readBufferSize = 63;
+ }
+
+ _port->timeout(TIMEOUT_NORMAL);
+
+ return true;
+}
+
+bool
+Samba::connect(SerialPort::Ptr port, int bps)
+{
+ _port = move(port);
+
+ // Try to connect at a high speed if USB
+ _isUsb = _port->isUsb();
+ if (_isUsb)
+ {
+ if (_port->open(921600) && init())
+ {
+ if (_debug)
+ printf("Connected at 921600 baud\n");
+ return true;
+ }
+ else
+ {
+ _port->close();
+ }
+ }
+ _isUsb = false;
+
+ // Try the serial port at slower speed
+ if (_port->open(bps) && init())
+ {
+ if (_debug)
+ printf("Connected at %d baud\n", bps);
+ return true;
+ }
+
+ disconnect();
+ return false;
+}
+
+void
+Samba::disconnect()
+{
+ _port->close();
+ _port.release();
+}
+
+void
+Samba::writeByte(uint32_t addr, uint8_t value)
+{
+ uint8_t cmd[14];
+
+ if (_debug)
+ printf("%s(addr=%#x,value=%#x)\n", __FUNCTION__, addr, value);
+
+ snprintf((char*) cmd, sizeof(cmd), "O%08X,%02X#", addr, value);
+ if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
+ throw SambaError();
+
+ // The SAM firmware has a bug that if the command and binary data
+ // are received in the same USB data packet, then the firmware
+ // gets confused. Even though the writes are separated in the code,
+ // USB drivers often do write combining which can put them together
+ // in the same USB data packet. To avoid this, we call the serial
+ // port object's flush method before writing the data.
+ if (_isUsb)
+ _port->flush();
+}
+
+uint8_t
+Samba::readByte(uint32_t addr)
+{
+ uint8_t cmd[13];
+ uint8_t value;
+
+ snprintf((char*) cmd, sizeof(cmd), "o%08X,4#", addr);
+ if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
+ throw SambaError();
+ if (_port->read(cmd, sizeof(uint8_t)) != sizeof(uint8_t))
+ throw SambaError();
+
+ value = cmd[0];
+
+ if (_debug)
+ printf("%s(addr=%#x)=%#x\n", __FUNCTION__, addr, value);
+
+ return value;
+}
+
+
+void
+Samba::writeWord(uint32_t addr, uint32_t value)
+{
+ uint8_t cmd[20];
+
+ if (_debug)
+ printf("%s(addr=%#x,value=%#x)\n", __FUNCTION__, addr, value);
+
+ snprintf((char*) cmd, sizeof(cmd), "W%08X,%08X#", addr, value);
+ if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
+ throw SambaError();
+
+ // The SAM firmware has a bug that if the command and binary data
+ // are received in the same USB data packet, then the firmware
+ // gets confused. Even though the writes are sperated in the code,
+ // USB drivers often do write combining which can put them together
+ // in the same USB data packet. To avoid this, we call the serial
+ // port object's flush method before writing the data.
+ if (_isUsb)
+ _port->flush();
+}
+
+
+uint32_t
+Samba::readWord(uint32_t addr)
+{
+ uint8_t cmd[13];
+ uint32_t value;
+
+ snprintf((char*) cmd, sizeof(cmd), "w%08X,4#", addr);
+ if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
+ throw SambaError();
+ if (_port->read(cmd, sizeof(uint32_t)) != sizeof(uint32_t))
+ throw SambaError();
+
+ value = (cmd[3] << 24 | cmd[2] << 16 | cmd[1] << 8 | cmd[0] << 0);
+
+ if (_debug)
+ printf("%s(addr=%#x)=%#x\n", __FUNCTION__, addr, value);
+
+ return value;
+}
+
+static const uint16_t crc16Table[256] = {
+ 0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
+ 0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
+ 0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,
+ 0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
+ 0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,
+ 0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
+ 0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,
+ 0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
+ 0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,
+ 0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,
+ 0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
+ 0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,
+ 0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,
+ 0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,
+ 0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
+ 0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,
+ 0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
+ 0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,
+ 0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
+ 0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,
+ 0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,
+ 0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
+ 0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,
+ 0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,
+ 0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,
+ 0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,
+ 0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,
+ 0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,
+ 0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,
+ 0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,
+ 0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,
+ 0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0
+};
+
+uint16_t
+Samba::crc16Calc(const uint8_t *data, int len)
+{
+ uint16_t crc16 = 0;
+
+ while (len-- > 0)
+ crc16 = (crc16 << 8) ^ crc16Table[((crc16 >> 8) ^ *(uint8_t*) data++) & 0xff];
+ return crc16;
+}
+
+bool
+Samba::crc16Check(const uint8_t *blk)
+{
+ uint16_t crc16;
+
+ crc16 = blk[BLK_SIZE + 3] << 8 | blk[BLK_SIZE + 4];
+ return (crc16Calc(&blk[3], BLK_SIZE) == crc16);
+}
+
+void
+Samba::crc16Add(uint8_t *blk)
+{
+ uint16_t crc16;
+
+ crc16 = crc16Calc(&blk[3], BLK_SIZE);
+ blk[BLK_SIZE + 3] = (crc16 >> 8) & 0xff;
+ blk[BLK_SIZE + 4] = crc16 & 0xff;
+}
+
+uint16_t
+Samba::checksumCalc(uint8_t data, uint16_t crc16) {
+ return (crc16 << 8) ^ crc16Table[((crc16 >> 8) ^ data) & 0xff];
+}
+
+void
+Samba::readXmodem(uint8_t* buffer, int size)
+{
+ uint8_t blk[BLK_SIZE + 5];
+ uint32_t blkNum = 1;
+ int retries;
+ int bytes;
+
+ while (size > 0)
+ {
+ for (retries = 0; retries < MAX_RETRIES; retries++)
+ {
+ if (blkNum == 1)
+ _port->put(START);
+
+ bytes = _port->read(blk, sizeof(blk));
+ if (bytes == sizeof(blk) &&
+ blk[0] == SOH &&
+ blk[1] == (blkNum & 0xff) &&
+ crc16Check(blk))
+ break;
+
+ if (blkNum != 1)
+ _port->put(NAK);
+ }
+ if (retries == MAX_RETRIES)
+ throw SambaError();
+
+ _port->put(ACK);
+
+ memmove(buffer, &blk[3], min(size, BLK_SIZE));
+ buffer += BLK_SIZE;
+ size -= BLK_SIZE;
+ blkNum++;
+ }
+
+ for (retries = 0; retries < MAX_RETRIES; retries++)
+ {
+ if (_port->get() == EOT)
+ {
+ _port->put(ACK);
+ break;
+ }
+ _port->put(NAK);
+ }
+ if (retries == MAX_RETRIES)
+ throw SambaError();
+}
+
+void
+Samba::writeXmodem(const uint8_t* buffer, int size)
+{
+ uint8_t blk[BLK_SIZE + 5];
+ uint32_t blkNum = 1;
+ int retries;
+ int bytes;
+
+ for (retries = 0; retries < MAX_RETRIES; retries++)
+ {
+ if (_port->get() == START)
+ break;
+ }
+ if (retries == MAX_RETRIES)
+ throw SambaError();
+
+ while (size > 0)
+ {
+ blk[0] = SOH;
+ blk[1] = (blkNum & 0xff);
+ blk[2] = ~(blkNum & 0xff);
+ memmove(&blk[3], buffer, min(size, BLK_SIZE));
+ if (size < BLK_SIZE)
+ memset(&blk[3] + size, 0, BLK_SIZE - size);
+ crc16Add(blk);
+
+ for (retries = 0; retries < MAX_RETRIES; retries++)
+ {
+ bytes = _port->write(blk, sizeof(blk));
+ if (bytes != sizeof(blk))
+ throw SambaError();
+
+ if (_port->get() == ACK)
+ break;
+ }
+
+ if (retries == MAX_RETRIES)
+ throw SambaError();
+
+ buffer += BLK_SIZE;
+ size -= BLK_SIZE;
+ blkNum++;
+ }
+
+ for (retries = 0; retries < MAX_RETRIES; retries++)
+ {
+ _port->put(EOT);
+ if (_port->get() == ACK)
+ break;
+ }
+ if (retries == MAX_RETRIES)
+ throw SambaError();
+}
+
+void
+Samba::readBinary(uint8_t* buffer, int size)
+{
+ if (_port->read(buffer, size) != size)
+ throw SambaError();
+}
+
+void
+Samba::writeBinary(const uint8_t* buffer, int size)
+{
+ while (size)
+ {
+ int written = _port->write(buffer, size);
+ if (written <= 0)
+ throw SambaError();
+ buffer += written;
+ size -= written;
+ }
+}
+
+void
+Samba::read(uint32_t addr, uint8_t* buffer, int size)
+{
+ uint8_t cmd[20];
+ int chunk;
+
+ if (_debug)
+ printf("%s(addr=%#x,size=%#x)\n", __FUNCTION__, addr, size);
+
+ // The SAM firmware has a bug reading powers of 2 over 32 bytes
+ // via USB. If that is the case here, then read the first byte
+ // with a readByte and then read one less than the requested size.
+ if (_isUsb && _readBufferSize == 0 && size > 32 && !(size & (size - 1)))
+ {
+ *buffer = readByte(addr);
+ addr++;
+ buffer++;
+ size--;
+ }
+
+ while (size > 0)
+ {
+ // Handle any limitations on the size of the read
+ if (_readBufferSize > 0 && size > _readBufferSize)
+ chunk = _readBufferSize;
+ else
+ chunk = size;
+
+ snprintf((char*) cmd, sizeof(cmd), "R%08X,%08X#", addr, chunk);
+ if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
+ throw SambaError();
+
+ if (_isUsb)
+ readBinary(buffer, chunk);
+ else
+ readXmodem(buffer, chunk);
+
+ size -= chunk;
+ addr += chunk;
+ buffer += chunk;
+ }
+}
+
+void
+Samba::write(uint32_t addr, const uint8_t* buffer, int size)
+{
+ uint8_t cmd[20];
+
+ if (_debug)
+ printf("%s(addr=%#x,size=%#x)\n", __FUNCTION__, addr, size);
+
+ snprintf((char*) cmd, sizeof(cmd), "S%08X,%08X#", addr, size);
+ if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
+ throw SambaError();
+
+ // The SAM firmware has a bug that if the command and binary data
+ // are received in the same USB data packet, then the firmware
+ // gets confused. Even though the writes are separated in the code,
+ // USB drivers often do write combining which can put them together
+ // in the same USB data packet. To avoid this, we call the serial
+ // port object's flush method before writing the data.
+ if (_isUsb)
+ {
+ _port->flush();
+ writeBinary(buffer, size);
+ }
+ else
+ {
+ writeXmodem(buffer, size);
+ }
+}
+
+void
+Samba::go(uint32_t addr)
+{
+ uint8_t cmd[11];
+
+ if (_debug)
+ printf("%s(addr=%#x)\n", __FUNCTION__, addr);
+
+ snprintf((char*) cmd, sizeof(cmd), "G%08X#", addr);
+ if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
+ throw SambaError();
+
+ // The SAM firmware can get confused if another command is
+ // received in the same USB data packet as the go command
+ // so we flush after writing the command over USB.
+ if (_isUsb)
+ _port->flush();
+}
+
+std::string
+Samba::version()
+{
+ uint8_t cmd[256];
+ char* str;
+ int size;
+ int pos;
+
+ cmd[0] = 'V';
+ cmd[1] = '#';
+ _port->write(cmd, 2);
+
+ _port->timeout(TIMEOUT_QUICK);
+ size = _port->read(cmd, sizeof(cmd) - 1);
+ _port->timeout(TIMEOUT_NORMAL);
+ if (size <= 0)
+ throw SambaError();
+
+ str = (char*) cmd;
+ for (pos = 0; pos < size; pos++)
+ {
+ if (!isprint(str[pos]))
+ break;
+ }
+ str[pos] = '\0';
+
+ std::string ver(str);
+
+ if (_debug)
+ printf("%s()=%s\n", __FUNCTION__, ver.c_str());
+
+ return ver;
+}
+
+void
+Samba::chipErase(uint32_t start_addr)
+{
+ if (!_canChipErase)
+ throw SambaError();
+
+ uint8_t cmd[64];
+
+ if (_debug)
+ printf("%s(addr=%#x)\n", __FUNCTION__, start_addr);
+
+ int l = snprintf((char*) cmd, sizeof(cmd), "X%08X#", start_addr);
+ if (_port->write(cmd, l) != l)
+ throw SambaError();
+ _port->timeout(TIMEOUT_LONG);
+ _port->read(cmd, 3); // Expects "X\n\r"
+ _port->timeout(TIMEOUT_NORMAL);
+ if (cmd[0] != 'X')
+ throw SambaError();
+}
+
+void
+Samba::writeBuffer(uint32_t src_addr, uint32_t dst_addr, uint32_t size)
+{
+ if (!_canWriteBuffer)
+ throw SambaError();
+
+ if (size > checksumBufferSize())
+ throw SambaError();
+
+ if (_debug)
+ printf("%s(scr_addr=%#x, dst_addr=%#x, size=%#x)\n", __FUNCTION__, src_addr, dst_addr, size);
+
+ uint8_t cmd[64];
+ int l = snprintf((char*) cmd, sizeof(cmd), "Y%08X,0#", src_addr);
+ if (_port->write(cmd, l) != l)
+ throw SambaError();
+ _port->timeout(TIMEOUT_QUICK);
+ cmd[0] = 0;
+ _port->read(cmd, 3); // Expects "Y\n\r"
+ _port->timeout(TIMEOUT_NORMAL);
+ if (cmd[0] != 'Y')
+ throw SambaError();
+
+ l = snprintf((char*) cmd, sizeof(cmd), "Y%08X,%08X#", dst_addr, size);
+ if (_port->write(cmd, l) != l)
+ throw SambaError();
+ _port->timeout(TIMEOUT_LONG);
+ cmd[0] = 0;
+ _port->read(cmd, 3); // Expects "Y\n\r"
+ _port->timeout(TIMEOUT_NORMAL);
+ if (cmd[0] != 'Y')
+ throw SambaError();
+}
+
+uint16_t
+Samba::checksumBuffer(uint32_t start_addr, uint32_t size)
+{
+ if (!_canChecksumBuffer)
+ throw SambaError();
+
+ if (size > checksumBufferSize())
+ throw SambaError();
+
+ if (_debug)
+ printf("%s(start_addr=%#x, size=%#x) = ", __FUNCTION__, start_addr, size);
+
+ uint8_t cmd[64];
+ int l = snprintf((char*) cmd, sizeof(cmd), "Z%08X,%08X#", start_addr, size);
+ if (_port->write(cmd, l) != l)
+ throw SambaError();
+ _port->timeout(TIMEOUT_LONG);
+ cmd[0] = 0;
+ _port->read(cmd, 12); // Expects "Z00000000#\n\r"
+ _port->timeout(TIMEOUT_NORMAL);
+ if (cmd[0] != 'Z')
+ throw SambaError();
+
+ cmd[9] = 0;
+ errno = 0;
+ uint32_t res = strtol((char*) &cmd[1], NULL, 16);
+ if (errno != 0)
+ throw SambaError();
+ if (_debug)
+ printf("%x\n", res);
+ return res;
+}
+
diff --git a/lib/bossac/src/Samba.h b/lib/bossac/src/Samba.h
new file mode 100644
index 00000000..84bea406
--- /dev/null
+++ b/lib/bossac/src/Samba.h
@@ -0,0 +1,115 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _SAMBA_H
+#define _SAMBA_H
+
+#include <string>
+#include <stdint.h>
+#include <exception>
+#include <memory>
+
+#include "SerialPort.h"
+
+class SambaError : public std::exception
+{
+public:
+ SambaError() : exception() {};
+ const char* what() const throw() { return "SAM-BA operation failed"; }
+};
+
+
+
+class Samba
+{
+public:
+ Samba();
+ virtual ~Samba();
+
+ bool connect(SerialPort::Ptr port, int bps = 115200);
+ void disconnect();
+
+ void writeByte(uint32_t addr, uint8_t value);
+ uint8_t readByte(uint32_t addr);
+
+ void writeWord(uint32_t addr, uint32_t value);
+ uint32_t readWord(uint32_t addr);
+
+ void write(uint32_t addr, const uint8_t* buffer, int size);
+ void read(uint32_t addr, uint8_t* buffer, int size);
+
+ void go(uint32_t addr);
+
+ std::string version();
+
+ void chipId(uint32_t& chipId, uint32_t& extChipId);
+
+ void setDebug(bool debug) { _debug = debug; }
+
+ const SerialPort& getSerialPort() { return *_port; }
+
+ void reset();
+
+ // Extended SAM-BA functions
+ bool canChipErase() { return _canChipErase; }
+ void chipErase(uint32_t start_addr);
+
+ bool canWriteBuffer() { return _canWriteBuffer; }
+ void writeBuffer(uint32_t src_addr, uint32_t dst_addr, uint32_t size);
+ uint32_t writeBufferSize() { return 4096; }
+
+ bool canChecksumBuffer() { return _canChecksumBuffer; }
+ uint16_t checksumBuffer(uint32_t start_addr, uint32_t size);
+ uint32_t checksumBufferSize() { return 4096; }
+ uint16_t checksumCalc(uint8_t c, uint16_t crc);
+
+private:
+ bool _canChipErase;
+ bool _canWriteBuffer;
+ bool _canChecksumBuffer;
+ int _readBufferSize;
+ bool _debug;
+ bool _isUsb;
+ SerialPort::Ptr _port;
+
+ bool init();
+
+ uint16_t crc16Calc(const uint8_t *data, int len);
+ bool crc16Check(const uint8_t *blk);
+ void crc16Add(uint8_t *blk);
+ void writeXmodem(const uint8_t* buffer, int size);
+ void readXmodem(uint8_t* buffer, int size);
+
+ void writeBinary(const uint8_t* buffer, int size);
+ void readBinary(uint8_t* buffer, int size);
+
+};
+
+
+#endif // _SAMBA_H
diff --git a/lib/bossac/src/SerialPort.h b/lib/bossac/src/SerialPort.h
new file mode 100644
index 00000000..6ebbcc7b
--- /dev/null
+++ b/lib/bossac/src/SerialPort.h
@@ -0,0 +1,82 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#ifndef _SERIALPORT_H
+#define _SERIALPORT_H
+
+#include <string>
+#include <memory>
+#include <stdint.h>
+
+class SerialPort
+{
+public:
+ SerialPort(const std::string& name) : _name(name) {}
+ virtual ~SerialPort() {}
+
+ enum Parity
+ {
+ ParityNone,
+ ParityOdd,
+ ParityEven,
+ };
+
+ enum StopBit
+ {
+ StopBitOne,
+ StopBitOneFive,
+ StopBitTwo,
+ };
+
+ virtual bool open(int baud = 115200,
+ int data = 8,
+ Parity parity = ParityNone,
+ StopBit stop = StopBitOne) = 0;
+ virtual void close() = 0;
+
+ virtual bool isUsb() = 0;
+
+ virtual int read(uint8_t* data, int size) = 0;
+ virtual int write(const uint8_t* data, int size) = 0;
+ virtual int get() = 0;
+ virtual int put(int c) = 0;
+
+ virtual bool timeout(int millisecs) = 0;
+ virtual void flush() = 0;
+ virtual void setDTR(bool dtr) = 0;
+ virtual void setRTS(bool rts) = 0;
+
+ virtual std::string name() const { return _name; }
+
+ typedef std::unique_ptr<SerialPort> Ptr;
+
+protected:
+ std::string _name;
+};
+
+#endif // _SERIALPORT_H
diff --git a/lib/bossac/src/WordCopyApplet.cpp b/lib/bossac/src/WordCopyApplet.cpp
new file mode 100644
index 00000000..39741d96
--- /dev/null
+++ b/lib/bossac/src/WordCopyApplet.cpp
@@ -0,0 +1,62 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#include "WordCopyApplet.h"
+
+WordCopyApplet::WordCopyApplet(Samba& samba, uint32_t addr)
+ : Applet(samba,
+ addr,
+ applet.code,
+ sizeof(applet.code),
+ addr + applet.start,
+ addr + applet.stack,
+ addr + applet.reset)
+{
+}
+
+WordCopyApplet::~WordCopyApplet()
+{
+}
+
+void
+WordCopyApplet::setDstAddr(uint32_t dstAddr)
+{
+ _samba.writeWord(_addr + applet.dst_addr, dstAddr);
+}
+
+void
+WordCopyApplet::setSrcAddr(uint32_t srcAddr)
+{
+ _samba.writeWord(_addr + applet.src_addr, srcAddr);
+}
+
+void
+WordCopyApplet::setWords(uint32_t words)
+{
+ _samba.writeWord(_addr + applet.words, words);
+}
diff --git a/lib/bossac/src/WordCopyApplet.h b/lib/bossac/src/WordCopyApplet.h
new file mode 100644
index 00000000..7f6ac95c
--- /dev/null
+++ b/lib/bossac/src/WordCopyApplet.h
@@ -0,0 +1,49 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#ifndef _WORDCOPYAPPLET_H
+#define _WORDCOPYAPPLET_H
+
+#include "Applet.h"
+#include "WordCopyArm.h"
+
+class WordCopyApplet : public Applet
+{
+public:
+ WordCopyApplet(Samba& samba, uint32_t addr);
+ virtual ~WordCopyApplet();
+
+ void setDstAddr(uint32_t dstAddr);
+ void setSrcAddr(uint32_t srcAddr);
+ void setWords(uint32_t words);
+
+private:
+ static WordCopyArm applet;
+};
+
+#endif // _WORDCOPYAPPLET_H
diff --git a/lib/bossac/src/WordCopyArm.asm b/lib/bossac/src/WordCopyArm.asm
new file mode 100644
index 00000000..b9f291d0
--- /dev/null
+++ b/lib/bossac/src/WordCopyArm.asm
@@ -0,0 +1,47 @@
+ .global start
+ .global stack
+ .global reset
+ .global dst_addr
+ .global src_addr
+ .global words
+
+ .text
+ .thumb
+ .align 0
+
+start:
+ ldr r0, dst_addr
+ ldr r1, src_addr
+ ldr r2, words
+ b check
+
+copy:
+ ldmia r1!, {r3}
+ stmia r0!, {r3}
+ sub r2, #1
+
+check:
+ cmp r2, #0
+ bne copy
+
+ @ Fix for SAM-BA stack bug
+ ldr r0, reset
+ cmp r0, #0
+ bne return
+ ldr r0, stack
+ mov sp, r0
+
+return:
+ bx lr
+
+ .align 0
+stack:
+ .word 0
+reset:
+ .word 0
+dst_addr:
+ .word 0
+src_addr:
+ .word 0
+words:
+ .word 0
diff --git a/lib/bossac/src/WordCopyArm.cpp b/lib/bossac/src/WordCopyArm.cpp
new file mode 100644
index 00000000..09bb1175
--- /dev/null
+++ b/lib/bossac/src/WordCopyArm.cpp
@@ -0,0 +1,25 @@
+// WARNING!!! DO NOT EDIT - FILE GENERATED BY APPLETGEN
+#include "WordCopyArm.h"
+#include "WordCopyApplet.h"
+
+WordCopyArm WordCopyApplet::applet = {
+// dst_addr
+0x00000028,
+// reset
+0x00000024,
+// src_addr
+0x0000002c,
+// stack
+0x00000020,
+// start
+0x00000000,
+// words
+0x00000030,
+// code
+{
+0x09, 0x48, 0x0a, 0x49, 0x0a, 0x4a, 0x02, 0xe0, 0x08, 0xc9, 0x08, 0xc0, 0x01, 0x3a, 0x00, 0x2a,
+0xfa, 0xd1, 0x04, 0x48, 0x00, 0x28, 0x01, 0xd1, 0x01, 0x48, 0x85, 0x46, 0x70, 0x47, 0xc0, 0x46,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00,
+}
+};
diff --git a/lib/bossac/src/WordCopyArm.h b/lib/bossac/src/WordCopyArm.h
new file mode 100644
index 00000000..d3975e83
--- /dev/null
+++ b/lib/bossac/src/WordCopyArm.h
@@ -0,0 +1,18 @@
+// WARNING!!! DO NOT EDIT - FILE GENERATED BY APPLETGEN
+#ifndef _WORDCOPYARM_H
+#define _WORDCOPYARM_H
+
+#include <stdint.h>
+
+typedef struct
+{
+ uint32_t dst_addr;
+ uint32_t reset;
+ uint32_t src_addr;
+ uint32_t stack;
+ uint32_t start;
+ uint32_t words;
+ uint8_t code[52];
+} WordCopyArm;
+
+#endif // _WORDCOPYARM_H
diff --git a/lib/bossac/src/bossac.cpp b/lib/bossac/src/bossac.cpp
new file mode 100644
index 00000000..450d0fa1
--- /dev/null
+++ b/lib/bossac/src/bossac.cpp
@@ -0,0 +1,489 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#include <string>
+#include <exception>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/time.h>
+
+#include "CmdOpts.h"
+#include "Samba.h"
+#include "PortFactory.h"
+#include "Device.h"
+#include "Flasher.h"
+
+using namespace std;
+
+class BossaConfig
+{
+public:
+ BossaConfig();
+ virtual ~BossaConfig() {}
+
+ bool erase;
+ bool write;
+ bool read;
+ bool verify;
+ bool offset;
+ bool reset;
+ bool port;
+ bool boot;
+ bool bor;
+ bool bod;
+ bool lock;
+ bool unlock;
+ bool security;
+ bool info;
+ bool debug;
+ bool help;
+ bool usbPort;
+ bool arduinoErase;
+
+ int readArg;
+ int offsetArg;
+ string portArg;
+ int bootArg;
+ int bodArg;
+ int borArg;
+ string lockArg;
+ string unlockArg;
+ bool usbPortArg;
+};
+
+BossaConfig::BossaConfig()
+{
+ erase = false;
+ write = false;
+ read = false;
+ verify = false;
+ port = false;
+ boot = false;
+ bod = false;
+ bor = false;
+ lock = false;
+ security = false;
+ info = false;
+ help = false;
+ usbPort = false;
+ arduinoErase = false;
+
+ readArg = 0;
+ offsetArg = 0;
+ bootArg = 1;
+ bodArg = 1;
+ borArg = 1;
+ usbPortArg=1;
+
+ reset = false;
+}
+
+class BossaObserver : public FlasherObserver
+{
+public:
+ BossaObserver() : _lastTicks(-1) {}
+ virtual ~BossaObserver() {}
+
+ virtual void onStatus(const char *message, ...);
+ virtual void onProgress(int num, int div);
+private:
+ int _lastTicks;
+};
+
+void
+BossaObserver::onStatus(const char *message, ...)
+{
+ va_list ap;
+
+ va_start(ap, message);
+ vprintf(message, ap);
+ va_end(ap);
+}
+
+void
+BossaObserver::onProgress(int num, int div)
+{
+ int ticks;
+ int bars = 30;
+
+ ticks = num * bars / div;
+
+ if (ticks == _lastTicks)
+ return;
+
+ printf("\r[");
+ while (ticks-- > 0)
+ {
+ putchar('=');
+ bars--;
+ }
+ while (bars-- > 0)
+ {
+ putchar(' ');
+ }
+ printf("] %d%% (%d/%d pages)", num * 100 / div, num, div);
+ fflush(stdout);
+
+ _lastTicks = 0;
+}
+
+static BossaConfig config;
+static Option opts[] =
+{
+ {
+ 'e', "erase", &config.erase,
+ { ArgNone },
+ "erase the entire flash starting at the offset"
+ },
+ {
+ 'w', "write", &config.write,
+ { ArgNone },
+ "write FILE to the flash; accelerated when\n"
+ "combined with erase option"
+ },
+ {
+ 'r', "read", &config.read,
+ { ArgOptional, ArgInt, "SIZE", { &config.readArg } },
+ "read SIZE from flash and store in FILE;\n"
+ "read entire flash if SIZE not specified"
+ },
+ {
+ 'v', "verify", &config.verify,
+ { ArgNone },
+ "verify FILE matches flash contents"
+ },
+ {
+ 'o', "offset", &config.offset,
+ { ArgRequired, ArgInt, "OFFSET", { &config.offsetArg } },
+ "start erase/write/read/verify operation at flash OFFSET;\n"
+ "OFFSET must be aligned to a flash page boundary"
+ },
+ {
+ 'p', "port", &config.port,
+ { ArgRequired, ArgString, "PORT", { &config.portArg } },
+ "use serial PORT to communicate to device;\n"
+ "default behavior is to use first serial port"
+ },
+ {
+ 'b', "boot", &config.boot,
+ { ArgOptional, ArgInt, "BOOL", { &config.bootArg } },
+ "boot from ROM if BOOL is 0;\n"
+ "boot from FLASH if BOOL is 1 [default];\n"
+ "option is ignored on unsupported devices"
+ },
+ {
+ 'c', "bod", &config.bod,
+ { ArgOptional, ArgInt, "BOOL", { &config.bodArg } },
+ "no brownout detection if BOOL is 0;\n"
+ "brownout detection is on if BOOL is 1 [default]"
+ },
+ {
+ 't', "bor", &config.bor,
+ { ArgOptional, ArgInt, "BOOL", { &config.borArg } },
+ "no brownout reset if BOOL is 0;\n"
+ "brownout reset is on if BOOL is 1 [default]"
+ },
+ {
+ 'l', "lock", &config.lock,
+ { ArgOptional, ArgString, "REGION", { &config.lockArg } },
+ "lock the flash REGION as a comma-separated list;\n"
+ "lock all if not given [default]"
+ },
+ {
+ 'u', "unlock", &config.unlock,
+ { ArgOptional, ArgString, "REGION", { &config.unlockArg } },
+ "unlock the flash REGION as a comma-separated list;\n"
+ "unlock all if not given [default]"
+ },
+ {
+ 's', "security", &config.security,
+ { ArgNone },
+ "set the flash security flag"
+ },
+ {
+ 'i', "info", &config.info,
+ { ArgNone },
+ "display device information"
+ },
+ {
+ 'd', "debug", &config.debug,
+ { ArgNone },
+ "print debug messages"
+ },
+ {
+ 'h', "help", &config.help,
+ { ArgNone },
+ "display this help text"
+ },
+ {
+ 'U', "usb-port", &config.usbPort,
+ { ArgOptional, ArgInt, "BOOL", { &config.usbPortArg } },
+ "force serial port detection to USB if BOOL is 1 [default]\n"
+ "or to RS-232 if BOOL is 0"
+ },
+ {
+ 'R', "reset", &config.reset,
+ { ArgNone },
+ "reset CPU (if supported)"
+ },
+ {
+ 'a', "arduino-erase", &config.arduinoErase,
+ { ArgNone },
+ "erase and reset via Arduino 1200 baud hack"
+ }
+};
+
+int
+help(const char* program)
+{
+ fprintf(stderr, "Try '%s -h' or '%s --help' for more information\n", program, program);
+ return 1;
+}
+
+static struct timeval start_time;
+
+void
+timer_start()
+{
+ gettimeofday(&start_time, NULL);
+}
+
+float
+timer_stop()
+{
+ struct timeval end;
+ gettimeofday(&end, NULL);
+ return (end.tv_sec - start_time.tv_sec) + (end.tv_usec - start_time.tv_usec) / 1000000.0;
+}
+
+int
+main(int argc, char* argv[])
+{
+ int args;
+ char* pos;
+ CmdOpts cmd(argc, argv, sizeof(opts) / sizeof(opts[0]), opts);
+
+ if ((pos = strrchr(argv[0], '/')) || (pos = strrchr(argv[0], '\\')))
+ argv[0] = pos + 1;
+
+ if (argc <= 1)
+ {
+ fprintf(stderr, "%s: you must specify at least one option\n", argv[0]);
+ return help(argv[0]);
+ }
+
+ args = cmd.parse();
+ if (args < 0)
+ return help(argv[0]);
+
+ if (config.read && (config.write || config.verify))
+ {
+ fprintf(stderr, "%s: read option is exclusive of write or verify\n", argv[0]);
+ return help(argv[0]);
+ }
+
+ if (config.read || config.write || config.verify)
+ {
+ if (args == argc)
+ {
+ fprintf(stderr, "%s: missing file\n", argv[0]);
+ return help(argv[0]);
+ }
+ argc--;
+ }
+ if (args != argc)
+ {
+ fprintf(stderr, "%s: extra arguments found\n", argv[0]);
+ return help(argv[0]);
+ }
+
+ if (config.help)
+ {
+ printf("Usage: %s [OPTION...] [FILE]\n", argv[0]);
+ printf("Basic Open Source SAM-BA Application (BOSSA) Version " VERSION "\n"
+ "Flash programmer for Atmel SAM devices.\n"
+ "Copyright (c) 2011-2018 ShumaTech (http://www.shumatech.com)\n"
+ "\n"
+ "Examples:\n"
+ " bossac -e -w -v -b image.bin # Erase flash, write flash with image.bin,\n"
+ " # verify the write, and set boot from flash\n"
+ " bossac -r0x10000 image.bin # Read 64KB from flash and store in image.bin\n"
+ );
+ printf("\nOptions:\n");
+ cmd.usage(stdout);
+ printf("\nReport bugs to <bugs@shumatech.com>\n");
+ return 1;
+ }
+
+ try
+ {
+ Samba samba;
+ PortFactory portFactory;
+
+ if (config.debug)
+ samba.setDebug(true);
+
+ if (!config.port)
+ config.portArg = portFactory.def();
+
+ if (config.arduinoErase)
+ {
+ SerialPort::Ptr port;
+ port = portFactory.create(config.portArg, config.usbPortArg != 0);
+
+ if(!port->open(1200))
+ {
+ fprintf(stderr, "Failed to open port at 1200bps\n");
+ return 1;
+ }
+
+ port->setRTS(true);
+ port->setDTR(false);
+ port->close();
+ }
+
+ if (config.portArg.empty())
+ {
+ fprintf(stderr, "No serial ports available\n");
+ return 1;
+ }
+
+ bool res;
+ if (config.usbPort)
+ res = samba.connect(portFactory.create(config.portArg, config.usbPortArg != 0));
+ else
+ res = samba.connect(portFactory.create(config.portArg));
+ if (!res)
+ {
+ fprintf(stderr, "No device found on %s\n", config.portArg.c_str());
+ return 1;
+ }
+
+ Device device(samba);
+ device.create();
+
+ Device::FlashPtr& flash = device.getFlash();
+
+ BossaObserver observer;
+ Flasher flasher(samba, device, observer);
+
+ if (config.info)
+ {
+ FlasherInfo info;
+ flasher.info(info);
+ info.print();
+ }
+
+ if (config.unlock)
+ flasher.lock(config.unlockArg, false);
+
+ if (config.erase)
+ {
+ timer_start();
+ flasher.erase(config.offsetArg);
+ printf("\nDone in %5.3f seconds\n", timer_stop());
+ }
+
+ if (config.write)
+ {
+ timer_start();
+ flasher.write(argv[args], config.offsetArg);
+ printf("\nDone in %5.3f seconds\n", timer_stop());
+ }
+
+ if (config.verify)
+ {
+ uint32_t pageErrors;
+ uint32_t totalErrors;
+
+ timer_start();
+ if (!flasher.verify(argv[args], pageErrors, totalErrors, config.offsetArg))
+ {
+ printf("\nVerify failed\nPage errors: %d\nByte errors: %d\n",
+ pageErrors, totalErrors);
+ return 2;
+ }
+
+ printf("\nVerify successful\nDone in %5.3f seconds\n", timer_stop());
+ }
+
+ if (config.read)
+ {
+ timer_start();
+ flasher.read(argv[args], config.readArg, config.offsetArg);
+ printf("\nDone in %5.3f seconds\n", timer_stop());
+ }
+
+ if (config.boot)
+ {
+ printf("Set boot flash %s\n", config.bootArg ? "true" : "false");
+ flash->setBootFlash(config.bootArg);
+ }
+
+ if (config.bod)
+ {
+ printf("Set brownout detect %s\n", config.bodArg ? "true" : "false");
+ flash->setBod(config.bodArg);
+ }
+
+ if (config.bor)
+ {
+ printf("Set brownout reset %s\n", config.borArg ? "true" : "false");
+ flash->setBor(config.borArg);
+ }
+
+ if (config.security)
+ {
+ printf("Set security\n");
+ flash->setSecurity();
+ }
+
+ if (config.lock)
+ flasher.lock(config.lockArg, true);
+
+ flash->writeOptions();
+
+ if (config.reset)
+ device.reset();
+ }
+ catch (exception& e)
+ {
+ fprintf(stderr, "\n%s\n", e.what());
+ return 1;
+ }
+ catch(...)
+ {
+ fprintf(stderr, "\nUnhandled exception\n");
+ return 1;
+ }
+
+ return 0;
+}
+