lib: Add bossac 1.9 code to lib directory

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2018-08-16 17:03:23 -04:00
parent 79632878ac
commit 2b9124f3c0
36 changed files with 6287 additions and 0 deletions

View File

@ -50,6 +50,10 @@ The hub-ctrl directory contains code from:
https://github.com/codazoda/hub-ctrl.c/
revision 42095e522859059e8a5f4ec05c1e3def01a870a9.
The bossac directory contains code from:
https://github.com/shumatech/BOSSA
version 1.9 (b176eeef918fc810045c832348590595120187b4).
The pru_rpmsg directory contains code from:
https://github.com/dinuxbg/pru-gcc-examples
revision 425a42d82006cf0aa24be27b483d2f6a41607489. The code is taken

24
lib/bossac/LICENSE Normal file
View 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
View 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
View 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
View 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
View 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
View 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

View 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);
}

View 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

View 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);
}

View 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
View 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
View 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

View 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);
}

View 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
View 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
View 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

View 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
View 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
View 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
View 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
View 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

View 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");
}

View 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

View 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

View 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;
}

View 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
View 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
View 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

View 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

View 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);
}

View 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

View 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

View 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,
}
};

View 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
View 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;
}