mirror of
				https://github.com/Klipper3d/klipper.git
				synced 2025-10-31 02:15:52 +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/ |   https://github.com/codazoda/hub-ctrl.c/ | ||||||
| revision 42095e522859059e8a5f4ec05c1e3def01a870a9. | revision 42095e522859059e8a5f4ec05c1e3def01a870a9. | ||||||
|  |  | ||||||
|  | The bossac directory contains code from: | ||||||
|  |   https://github.com/shumatech/BOSSA | ||||||
|  | version 1.9 (b176eeef918fc810045c832348590595120187b4). | ||||||
|  |  | ||||||
| The pru_rpmsg directory contains code from: | The pru_rpmsg directory contains code from: | ||||||
|   https://github.com/dinuxbg/pru-gcc-examples |   https://github.com/dinuxbg/pru-gcc-examples | ||||||
| revision 425a42d82006cf0aa24be27b483d2f6a41607489. The code is taken | 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