mirror of
				https://github.com/Klipper3d/klipper.git
				synced 2025-10-29 17:26:14 +01:00 
			
		
		
		
	lib: Add bossac 1.9 code to lib directory
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
		| @@ -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 | ||||
|   | ||||
							
								
								
									
										24
									
								
								lib/bossac/LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								lib/bossac/LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -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. | ||||
							
								
								
									
										347
									
								
								lib/bossac/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										347
									
								
								lib/bossac/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -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) | ||||
							
								
								
									
										64
									
								
								lib/bossac/src/Applet.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								lib/bossac/src/Applet.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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); | ||||
| } | ||||
							
								
								
									
										65
									
								
								lib/bossac/src/Applet.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								lib/bossac/src/Applet.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										159
									
								
								lib/bossac/src/CmdOpts.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								lib/bossac/src/CmdOpts.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||
| } | ||||
							
								
								
									
										88
									
								
								lib/bossac/src/CmdOpts.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								lib/bossac/src/CmdOpts.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										347
									
								
								lib/bossac/src/D2xNvmFlash.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										347
									
								
								lib/bossac/src/D2xNvmFlash.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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); | ||||
| } | ||||
							
								
								
									
										76
									
								
								lib/bossac/src/D2xNvmFlash.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								lib/bossac/src/D2xNvmFlash.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										352
									
								
								lib/bossac/src/D5xNvmFlash.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										352
									
								
								lib/bossac/src/D5xNvmFlash.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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); | ||||
| } | ||||
							
								
								
									
										79
									
								
								lib/bossac/src/D5xNvmFlash.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								lib/bossac/src/D5xNvmFlash.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										692
									
								
								lib/bossac/src/Device.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										692
									
								
								lib/bossac/src/Device.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										104
									
								
								lib/bossac/src/Device.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								lib/bossac/src/Device.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
|  | ||||
							
								
								
									
										363
									
								
								lib/bossac/src/EefcFlash.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										363
									
								
								lib/bossac/src/EefcFlash.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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); | ||||
| } | ||||
							
								
								
									
										88
									
								
								lib/bossac/src/EefcFlash.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								lib/bossac/src/EefcFlash.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										295
									
								
								lib/bossac/src/EfcFlash.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										295
									
								
								lib/bossac/src/EfcFlash.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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); | ||||
| } | ||||
							
								
								
									
										83
									
								
								lib/bossac/src/EfcFlash.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								lib/bossac/src/EfcFlash.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										94
									
								
								lib/bossac/src/FileError.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								lib/bossac/src/FileError.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										106
									
								
								lib/bossac/src/Flash.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								lib/bossac/src/Flash.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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); | ||||
| } | ||||
|  | ||||
							
								
								
									
										180
									
								
								lib/bossac/src/Flash.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								lib/bossac/src/Flash.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										373
									
								
								lib/bossac/src/Flasher.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										373
									
								
								lib/bossac/src/Flasher.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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(); | ||||
| } | ||||
							
								
								
									
										110
									
								
								lib/bossac/src/Flasher.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								lib/bossac/src/Flasher.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										109
									
								
								lib/bossac/src/LinuxPortFactory.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								lib/bossac/src/LinuxPortFactory.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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"); | ||||
| } | ||||
|  | ||||
							
								
								
									
										60
									
								
								lib/bossac/src/LinuxPortFactory.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								lib/bossac/src/LinuxPortFactory.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										68
									
								
								lib/bossac/src/PortFactory.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								lib/bossac/src/PortFactory.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										332
									
								
								lib/bossac/src/PosixSerialPort.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										332
									
								
								lib/bossac/src/PosixSerialPort.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||
| } | ||||
							
								
								
									
										66
									
								
								lib/bossac/src/PosixSerialPort.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								lib/bossac/src/PosixSerialPort.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										672
									
								
								lib/bossac/src/Samba.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										672
									
								
								lib/bossac/src/Samba.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||
| } | ||||
|  | ||||
							
								
								
									
										115
									
								
								lib/bossac/src/Samba.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								lib/bossac/src/Samba.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										82
									
								
								lib/bossac/src/SerialPort.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								lib/bossac/src/SerialPort.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										62
									
								
								lib/bossac/src/WordCopyApplet.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								lib/bossac/src/WordCopyApplet.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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); | ||||
| } | ||||
							
								
								
									
										49
									
								
								lib/bossac/src/WordCopyApplet.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								lib/bossac/src/WordCopyApplet.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										47
									
								
								lib/bossac/src/WordCopyArm.asm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								lib/bossac/src/WordCopyArm.asm
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										25
									
								
								lib/bossac/src/WordCopyArm.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								lib/bossac/src/WordCopyArm.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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, | ||||
| } | ||||
| }; | ||||
							
								
								
									
										18
									
								
								lib/bossac/src/WordCopyArm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lib/bossac/src/WordCopyArm.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										489
									
								
								lib/bossac/src/bossac.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										489
									
								
								lib/bossac/src/bossac.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user