Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/bossa
diff options
context:
space:
mode:
authorManuel <manuel@duet3d.com>2020-11-30 17:43:15 +0300
committerGitHub <noreply@github.com>2020-11-30 17:43:15 +0300
commit77d8e38c85b00c9a706d7bd8639fc6b4de813764 (patch)
tree6896ab66334e16f2ded63ced0ab51af5135cc2e6 /src/bossa
parent1acd66057d369a56fa9fa0a91ad68ee89356a9e3 (diff)
Implement flashing PanelDue v3 from Duet mainboards (#451)
* Implement flashing PanelDue v3 from Duet mainboards This uses the required code extracted from BOSSA * Remove unsused blocks with #if 0 ... #endif Initialize PanelDueUpdater on first use Simplify excpetion handling in PanelDueUpdater Undo some changes made to bossa code to keep it closer to original (except for removed parts)
Diffstat (limited to 'src/bossa')
-rw-r--r--src/bossa/Applet.cpp64
-rw-r--r--src/bossa/Applet.h65
-rw-r--r--src/bossa/Device.cpp701
-rw-r--r--src/bossa/Device.h100
-rw-r--r--src/bossa/EefcFlash.cpp371
-rw-r--r--src/bossa/EefcFlash.h90
-rw-r--r--src/bossa/Flash.cpp101
-rw-r--r--src/bossa/Flash.h136
-rw-r--r--src/bossa/Flasher.cpp294
-rw-r--r--src/bossa/Flasher.h75
-rw-r--r--src/bossa/Samba.cpp497
-rw-r--r--src/bossa/Samba.h102
-rw-r--r--src/bossa/SerialPort.h73
-rw-r--r--src/bossa/WordCopyApplet.cpp62
-rw-r--r--src/bossa/WordCopyApplet.h49
-rw-r--r--src/bossa/WordCopyArm.asm47
-rw-r--r--src/bossa/WordCopyArm.cpp25
-rw-r--r--src/bossa/WordCopyArm.h18
18 files changed, 2870 insertions, 0 deletions
diff --git a/src/bossa/Applet.cpp b/src/bossa/Applet.cpp
new file mode 100644
index 00000000..80b3fbd7
--- /dev/null
+++ b/src/bossa/Applet.cpp
@@ -0,0 +1,64 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#include "Applet.h"
+
+Applet::Applet(Samba& samba,
+ uint32_t addr,
+ uint8_t* code,
+ uint32_t size,
+ uint32_t start,
+ uint32_t stack,
+ uint32_t reset) :
+ _samba(samba), _addr(addr), _size(size), _start(start), _stack(stack), _reset(reset)
+{
+ _samba.write(addr, code, size);
+}
+
+void
+Applet::setStack(uint32_t stack)
+{
+ _samba.writeWord(_stack, stack);
+}
+
+void
+Applet::run()
+{
+ // Add one to the start address for Thumb mode
+ _samba.go(_start + 1);
+}
+
+void
+Applet::runv()
+{
+ // Add one to the start address for Thumb mode
+ _samba.writeWord(_reset, _start + 1);
+
+ // The stack is the first reset vector
+ _samba.go(_stack);
+}
diff --git a/src/bossa/Applet.h b/src/bossa/Applet.h
new file mode 100644
index 00000000..f0b6f5cb
--- /dev/null
+++ b/src/bossa/Applet.h
@@ -0,0 +1,65 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#ifndef _APPLET_H
+#define _APPLET_H
+
+#include <cstdint>
+
+#include "Samba.h"
+
+class Applet
+{
+public:
+ Applet(Samba& samba,
+ uint32_t addr,
+ uint8_t* code,
+ uint32_t size,
+ uint32_t start,
+ uint32_t stack,
+ uint32_t reset);
+ virtual ~Applet() {}
+
+ virtual uint32_t size() { return _size; }
+ virtual uint32_t addr() { return _addr; }
+
+ virtual void setStack(uint32_t stack);
+
+ virtual void run(); // To be used for Thumb-1 based devices (ARM7TDMI, ARM9)
+ virtual void runv(); // To be used for Thumb-2 based devices (Cortex-Mx)
+
+protected:
+ Samba& _samba;
+ uint32_t _addr; // Address in device SRAM where will be placed the applet
+ uint32_t _size; // Applet size
+ uint32_t _start; //
+ uint32_t _stack; // Applet stack address in device SRAM
+ uint32_t _reset;
+};
+
+#endif // _APPLET_H
diff --git a/src/bossa/Device.cpp b/src/bossa/Device.cpp
new file mode 100644
index 00000000..7cde03af
--- /dev/null
+++ b/src/bossa/Device.cpp
@@ -0,0 +1,701 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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 "EefcFlash.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;
+#if 0
+ 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)
+ {
+#if 0
+ //
+ // 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;
+#endif
+ case 0x288b09e0 : // A
+ case 0x289b09e0 : // B
+ case 0x28ab09e0 : // C
+#endif
+ _family = FAMILY_SAM4S;
+ flashPtr = new EefcFlash(_samba, "ATSAM4S4", 0x400000, 512, 512, 1, 16, 0x20001000, 0x20010000, 0x400e0a00, false);
+#if 0
+ break;
+#if 0
+ 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 0x28890560 : // A
+ case 0x28990560 : // B
+ case 0x28a90560 : // 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;
+#endif
+ //
+ // Unsupported device
+ //
+ default:
+ exceptionScratch.cat(" - Remote device unsupported: ");
+ exceptionScratch.catf("%08" PRIx32 " - %08" PRIx32 " - %08" PRIx32 "", chipId, cpuId, extChipId);
+ throw DeviceUnsupportedError(exceptionScratch.c_str());
+ break;
+ }
+#endif
+
+ _flash = flashPtr;
+}
+
+void
+Device::reset()
+{
+ try
+ {
+ switch (_family)
+ {
+#if 0
+ 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:
+#endif
+ case FAMILY_SAM4S:
+ _samba.writeWord(0x400E1400, 0xA500000D);
+ break;
+#if 0
+ 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;
+#endif
+
+ default:
+ break;
+ }
+ }
+ catch (...)
+ { // writeWord will most likely throw an exception when the CPU is reset
+ }
+}
+
+
diff --git a/src/bossa/Device.h b/src/bossa/Device.h
new file mode 100644
index 00000000..c0603c68
--- /dev/null
+++ b/src/bossa/Device.h
@@ -0,0 +1,100 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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 "Samba.h"
+#include "Flash.h"
+
+#include "GCodes/GCodeException.h"
+
+typedef GCodeException DeviceUnsupportedError;
+
+class Device
+{
+public:
+ enum Family {
+ FAMILY_NONE,
+#if 0
+
+ FAMILY_SAM7S,
+ FAMILY_SAM7SE,
+ FAMILY_SAM7X,
+ FAMILY_SAM7XC,
+ FAMILY_SAM7L,
+
+ FAMILY_SAM3N,
+ FAMILY_SAM3S,
+ FAMILY_SAM3U,
+ FAMILY_SAM3X,
+ FAMILY_SAM3A,
+#endif
+ FAMILY_SAM4S,
+#if 0
+ 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,
+#endif
+ };
+
+ Device(Samba& samba) : _samba(samba), _flash(nullptr), _family(FAMILY_NONE) {}
+ virtual ~Device() { delete _flash; }
+
+ void create();
+
+ Family getFamily() { return _family; }
+
+ Flash* getFlash() { return _flash; }
+
+ void reset();
+
+private:
+ Samba& _samba;
+ Flash* _flash;
+ Family _family;
+
+ void readChipId(uint32_t& chipId, uint32_t& extChipId);
+};
+
+#endif // _DEVICE_H
+
diff --git a/src/bossa/EefcFlash.cpp b/src/bossa/EefcFlash.cpp
new file mode 100644
index 00000000..b8063a74
--- /dev/null
+++ b/src/bossa/EefcFlash.cpp
@@ -0,0 +1,371 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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"
+
+#if 0
+#include <assert.h>
+#include <unistd.h>
+#include <stdio.h>
+#endif
+
+#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 char* 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)
+{
+#if 0
+ assert(planes == 1 || planes == 2);
+ assert(pages <= 4096);
+ assert(lockRegions <= 256);
+#endif
+
+ // 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("Flash erase error");
+
+ // 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;
+}
+
+Vector<bool, 16>
+EefcFlash::getLockRegions()
+{
+ Vector<bool, 16> regions(_lockRegions, false);
+ 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 0
+ 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);
+ }
+#endif
+ if (_regions.isDirty())
+ {
+ uint32_t page;
+ Vector<bool, 16> current;
+
+ if (_regions.get().Size() > _lockRegions)
+ throw FlashRegionError("EefcFlash::writeOptions: 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 0
+ if (_security.isDirty() && _security.get() == true && _security.get() != getSecurity())
+ {
+ waitFSR();
+ writeFCR0(EEFC_FCMD_SGPB, 0);
+ }
+#endif
+}
+
+void
+EefcFlash::writePage(uint32_t page)
+{
+ if (page >= _pages)
+ throw FlashPageError("EefcFlash::writePage: 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("EefcFlash::readPage: 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("EefcFlash::waitFSR: FlashCmdError 1");
+ if (fsr0 & 0x4)
+ throw FlashLockError("EefcFlash::waitFSR: FlashLockError 1");
+
+ if (_planes == 2)
+ {
+ fsr1 = _samba.readWord(EEFC1_FSR);
+ if (fsr1 & 0x2)
+ throw FlashCmdError("EefcFlash::waitFSR: FlashCmdError 2");
+ if (fsr1 & 0x4)
+ throw FlashLockError("EefcFlash::waitFSR: FlashLockError 2");
+ }
+ if (fsr0 & fsr1 & 0x1)
+ break;
+ delay(2);
+ }
+ if (tries == 0)
+ throw FlashTimeoutError("EefcFlash::waitFSR: FlashTimeoutError");
+}
+
+void
+EefcFlash::writeFCR0(uint8_t cmd, uint32_t arg)
+{
+ _samba.writeWord(EEFC0_FCR, (EEFC_KEY << 24) | (arg << 8) | cmd);
+}
+
+void
+EefcFlash::writeFCR1(uint8_t cmd, uint32_t arg)
+{
+ _samba.writeWord(EEFC1_FCR, (EEFC_KEY << 24) | (arg << 8) | cmd);
+}
+
+uint32_t
+EefcFlash::readFRR0()
+{
+ return _samba.readWord(EEFC0_FRR);
+}
+
+uint32_t
+EefcFlash::readFRR1()
+{
+ return _samba.readWord(EEFC1_FRR);
+}
diff --git a/src/bossa/EefcFlash.h b/src/bossa/EefcFlash.h
new file mode 100644
index 00000000..fa9a1e39
--- /dev/null
+++ b/src/bossa/EefcFlash.h
@@ -0,0 +1,90 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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 <cstdint>
+#if 0
+#include <exception>
+#endif
+
+#include "Flash.h"
+
+class EefcFlash : public Flash
+{
+public:
+ EefcFlash(Samba& samba,
+ const char* 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);
+
+ Vector<bool, 16> getLockRegions();
+
+ bool getSecurity();
+
+ bool getBod();
+ bool canBod() { return _canBrownout; }
+
+ bool getBor();
+ bool canBor() { return _canBrownout; }
+
+ bool getBootFlash();
+ bool canBootFlash() { return true; }
+
+ void writeOptions();
+
+ void writePage(uint32_t page);
+ void readPage(uint32_t page, uint8_t* data);
+
+ static const uint32_t PagesPerErase;
+
+private:
+ uint32_t _regs;
+ bool _canBrownout;
+ bool _eraseAuto;
+
+ void waitFSR(int seconds = 1);
+ void writeFCR0(uint8_t cmd, uint32_t arg);
+ void writeFCR1(uint8_t cmd, uint32_t arg);
+ uint32_t readFRR0();
+ uint32_t readFRR1();
+};
+
+#endif // _EEFCFLASH_H
diff --git a/src/bossa/Flash.cpp b/src/bossa/Flash.cpp
new file mode 100644
index 00000000..a71ee1b2
--- /dev/null
+++ b/src/bossa/Flash.cpp
@@ -0,0 +1,101 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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"
+
+Flash::Flash(Samba& samba,
+ const char* 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)
+{
+
+ _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 Vector<bool, 16>& regions)
+{
+ if (regions.Size() > _lockRegions)
+ throw FlashRegionError("Flash::setLockRegions: regions.Size() > _lockRegions");
+
+ _regions.set(regions);
+}
+
+void
+Flash::setSecurity()
+{
+ _security.set(true);
+}
+
+void
+Flash::setBor(bool enable)
+{
+ if (canBor())
+ _bor.set(enable);
+}
+
+void
+Flash::setBod(bool enable)
+{
+ if (canBod())
+ _bod.set(enable);
+}
+
+void
+Flash::setBootFlash(bool enable)
+{
+ if (canBootFlash())
+ _bootFlash.set(enable);
+}
+
+void
+Flash::loadBuffer(const uint8_t* data, uint16_t bufferSize)
+{
+ _samba.write(_onBufferA ? _pageBufferA : _pageBufferB, data, bufferSize);
+}
+
+void
+Flash::writeBuffer(uint32_t dst_addr, uint32_t size)
+{
+ _samba.writeBuffer(_onBufferA ? _pageBufferA : _pageBufferB, dst_addr + _addr, size);
+}
+
diff --git a/src/bossa/Flash.h b/src/bossa/Flash.h
new file mode 100644
index 00000000..9df828ed
--- /dev/null
+++ b/src/bossa/Flash.h
@@ -0,0 +1,136 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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 "General/Vector.hpp"
+
+#include "Samba.h"
+#include "WordCopyApplet.h"
+
+#include "GCodes/GCodeException.h"
+
+typedef GCodeException FlashPageError;
+typedef GCodeException FlashRegionError;
+typedef GCodeException FlashLockError;
+typedef GCodeException FlashCmdError;
+typedef GCodeException FlashTimeoutError;
+typedef GCodeException BootFlashError;
+typedef GCodeException FlashEraseError;
+
+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 char* 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 char* 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 Vector<bool, 16> getLockRegions() = 0;
+ virtual void setLockRegions(const Vector<bool, 16>& 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;
+ const char* _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<Vector<bool, 16>> _regions;
+ FlashOption<bool> _bod;
+ FlashOption<bool> _bor;
+ FlashOption<bool> _security;
+
+ bool _onBufferA;
+ uint32_t _pageBufferA;
+ uint32_t _pageBufferB;
+};
+
+#endif // _FLASH_H
diff --git a/src/bossa/Flasher.cpp b/src/bossa/Flasher.cpp
new file mode 100644
index 00000000..5e93c178
--- /dev/null
+++ b/src/bossa/Flasher.cpp
@@ -0,0 +1,294 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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 "Flasher.h"
+#include "RepRap.h"
+#include "Platform.h"
+#include "General/Vector.hpp"
+#if HAS_LINUX_INTERFACE
+# include "Linux/LinuxInterface.h"
+#endif
+
+void
+Flasher::erase(uint32_t foffset)
+{
+ _observer.onStatus("Erase flash\n");
+ _flash->eraseAll(foffset);
+ _flash->eraseAuto(false);
+}
+
+int Flasher::GetNextChunk(char* buffer, const uint32_t length, uint32_t& offset, const char* filename) noexcept
+{
+ uint32_t read = 0;
+#if HAS_LINUX_INTERFACE
+ if (!reprap.UsingLinuxInterface())
+#endif
+ {
+ read = infile->Read(buffer, length);
+ }
+#if HAS_LINUX_INTERFACE
+ else
+ {
+ read = length;
+ const bool success = reprap.GetLinuxInterface().GetFileChunk(filename, offset, (char*)buffer, read, fileSize);
+ if (!success) {
+ return -1;
+ }
+ }
+#endif
+ offset += read;
+ return read;
+}
+
+bool
+Flasher::write(const char* filename, uint32_t& foffset)
+{
+ uint32_t pageSize = _flash->pageSize();
+ uint32_t numPages;
+ size_t fbytes = 0;
+
+ if (foffset == 0)
+ {
+ pageNum = 0;
+ Platform& platform = reprap.GetPlatform();
+#if HAS_LINUX_INTERFACE
+ if (!reprap.UsingLinuxInterface())
+#endif
+ {
+ infile = MassStorage::OpenFile(filename, OpenMode::read, 0);
+ if (infile == nullptr)
+ {
+ platform.MessageF(ErrorMessage, "Failed to open file %s\n", filename);
+ throw GCodeException(nullptr);
+ }
+ fileSize = infile->Length();
+ }
+#if HAS_LINUX_INTERFACE
+ else
+ {
+ char dummyBuf[1];
+ uint32_t dummyLen = 0;
+ if (!reprap.GetLinuxInterface().GetFileChunk(filename, 0, dummyBuf, dummyLen, fileSize))
+ {
+ platform.MessageF(ErrorMessage, "Failed to open file %s\n", filename);
+ throw GCodeException(nullptr);
+ }
+ }
+#endif
+ if (fileSize == 0)
+ {
+ if (infile != nullptr)
+ {
+ infile->Close();
+ }
+ platform.MessageF(ErrorMessage, "Firmware file is empty %s\n", filename);
+ throw GCodeException(nullptr);
+ }
+ }
+
+ try
+ {
+
+ numPages = (fileSize + pageSize - 1) / pageSize;
+ if (foffset == 0)
+ {
+ if (numPages > _flash->numPages())
+ {
+ throw FileSizeError("Flasher::write: FileSizeError");
+ }
+
+ _observer.onStatus("Write %ld bytes to flash (%u pages)\n", fileSize, numPages);
+ }
+
+ uint8_t buffer[pageSize];
+ uint32_t pageOffset = foffset / pageSize;
+
+ if ((fbytes = GetNextChunk((char*)buffer, pageSize, foffset, filename)) > 0)
+ {
+ _observer.onProgress(pageNum, numPages);
+
+ _flash->loadBuffer(buffer, fbytes);
+ _flash->writePage(pageOffset /* + pageNum */);
+
+ pageNum++;
+ if (!(pageNum == numPages || fbytes != pageSize))
+ {
+ return false; // We get back in the next PanelDueFlasher::Spin() iteration
+ }
+ }
+ }
+ catch(...)
+ {
+ if (infile != nullptr)
+ {
+ infile->Close();
+ }
+
+ throw;
+ }
+
+ if (infile != nullptr)
+ {
+ infile->Close();
+ }
+ _observer.onProgress(numPages, numPages);
+ return true;
+}
+
+bool
+Flasher::verify(const char* filename, uint32_t& pageErrors, uint32_t& totalErrors, uint32_t& foffset)
+{
+ uint32_t pageSize = _flash->pageSize();
+ uint8_t bufferA[pageSize];
+ uint8_t bufferB[pageSize];
+ uint32_t numPages;
+ uint32_t pageOffset;
+ uint32_t byteErrors = 0;
+ size_t fbytes;
+
+ pageErrors = 0;
+ totalErrors = 0;
+
+
+ pageOffset = foffset / pageSize;
+
+ if (foffset == 0)
+ {
+ pageNum = 0;
+
+ // Note that we can skip all checks for file validity here since
+ // we would not get here from write() if any of these failed
+
+#if HAS_LINUX_INTERFACE
+ if (!reprap.UsingLinuxInterface())
+#endif
+ {
+ infile = MassStorage::OpenFile(filename, OpenMode::read, 0);
+ }
+ }
+
+ try
+ {
+
+ numPages = (fileSize + pageSize - 1) / pageSize;
+ if (foffset == 0)
+ {
+ if (numPages > _flash->numPages())
+ throw FileSizeError("Flasher::verify: FileSizeError");
+
+ _observer.onStatus("Verify %ld bytes of flash\n", fileSize);
+ }
+
+ if ((fbytes = GetNextChunk((char*)bufferA, pageSize, foffset, filename)) > 0)
+ {
+ byteErrors = 0;
+
+ _observer.onProgress(pageNum, numPages);
+
+ {
+ _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))
+ {
+ return false; // We get back in the next PanelDueFlasher::Spin() iteration
+ }
+ }
+ }
+ catch(...)
+ {
+ if (infile != nullptr)
+ {
+ infile->Close();
+ }
+ throw;
+ }
+
+ if (infile != nullptr)
+ {
+ infile->Close();
+ }
+
+ _observer.onProgress(numPages, numPages);
+
+#if 0 // This has to be checked outside because we use the return value now used to indicate if we finished
+ if (pageErrors != 0)
+ return false;
+#endif
+
+ return true;
+}
+
+void
+Flasher::lock(/* string& regionArg, */ bool enable)
+{
+#if 0
+ if (regionArg.empty())
+ {
+#endif
+ _observer.onStatus("%s all regions\n", enable ? "Lock" : "Unlock");
+ Vector<bool, 16> regions(_flash->lockRegions(), enable);
+ _flash->setLockRegions(regions);
+#if 0
+ }
+ 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);
+ }
+#endif
+}
diff --git a/src/bossa/Flasher.h b/src/bossa/Flasher.h
new file mode 100644
index 00000000..6c676ffc
--- /dev/null
+++ b/src/bossa/Flasher.h
@@ -0,0 +1,75 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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 "Device.h"
+#include "Flash.h"
+#include "Samba.h"
+
+#include "GCodes/GCodeException.h"
+
+typedef GCodeException FlashOffsetError;
+typedef GCodeException FileSizeError;
+
+class FlasherObserver
+{
+public:
+ FlasherObserver() {}
+ virtual ~FlasherObserver() {}
+
+ virtual void onStatus(const char *message, ...) = 0;
+ virtual void onProgress(int num, int div) = 0;
+};
+
+class Flasher
+{
+public:
+ Flasher(Samba& samba, Device& device, FlasherObserver& observer)
+ : _samba(samba), _flash(device.getFlash()), _observer(observer), pageNum(0), infile(nullptr), fileSize(0)
+ {}
+ virtual ~Flasher() {}
+
+ void erase(uint32_t foffset);
+ int GetNextChunk(char* buffer, const uint32_t amount, uint32_t& offset, const char* filename) noexcept;
+ bool write(const char* filename, uint32_t& foffset);
+ bool verify(const char* filename, uint32_t& pageErrors, uint32_t& totalErrors, uint32_t& foffset);
+ void lock(/* std::string& regionArg, */ bool enable);
+
+private:
+ Samba& _samba;
+ Flash* _flash;
+ FlasherObserver& _observer;
+
+ uint32_t pageNum;
+ FileStore * infile;
+ FilePosition fileSize;
+};
+
+#endif // _FLASHER_H
diff --git a/src/bossa/Samba.cpp b/src/bossa/Samba.cpp
new file mode 100644
index 00000000..6ee35a81
--- /dev/null
+++ b/src/bossa/Samba.cpp
@@ -0,0 +1,497 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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 "RepRapFirmware.h"
+
+// 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))
+
+#define printf debugPrintf
+
+Samba::Samba() :
+ _canChipErase(false),
+ _canWriteBuffer(false),
+ _canChecksumBuffer(false),
+ _readBufferSize(0),
+ _debug(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));
+
+ // Set binary mode
+ if (_debug)
+ printf("Set binary mode\n");
+ cmd[0] = 'N';
+ cmd[1] = '#';
+ _port->write(cmd, 2);
+ _port->read(cmd, 2);
+
+ _port->timeout(TIMEOUT_NORMAL);
+
+ return true;
+}
+
+bool
+Samba::connect(SerialPort* port, int bps)
+{
+ _port = port;
+
+ // 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();
+}
+
+void
+Samba::writeByte(uint32_t addr, uint8_t value)
+{
+ uint8_t cmd[14];
+
+ if (_debug)
+ printf("%s(addr=%#" PRIx32 ",value=%#" PRIx8 ")\n", __FUNCTION__, addr, value);
+
+ SafeSnprintf((char*) cmd, sizeof(cmd), "O%08" PRIX32 ",%02" PRIX8 "#", addr, value);
+ if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
+ throw SambaError("Samba::writeByte: _port->write failed");
+}
+
+uint8_t
+Samba::readByte(uint32_t addr)
+{
+ uint8_t cmd[13];
+ uint8_t value;
+
+ SafeSnprintf((char*) cmd, sizeof(cmd), "o%08" PRIX32 ",4#", addr);
+ if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
+ throw SambaError("Samba::readByte: _port->write failed");
+ if (_port->read(cmd, sizeof(uint8_t)) != sizeof(uint8_t))
+ throw SambaError("Samba::readByte: _port->read failed");
+
+ value = cmd[0];
+
+ if (_debug)
+ printf("%s(addr=%#" PRIx32 ")=%#" PRIx8 "\n", __FUNCTION__, addr, value);
+
+ return value;
+}
+
+
+void
+Samba::writeWord(uint32_t addr, uint32_t value)
+{
+ uint8_t cmd[20];
+
+ if (_debug)
+ printf("%s(addr=%#" PRIx32 ",value=%#" PRIx32 ")\n", __FUNCTION__, addr, value);
+
+ SafeSnprintf((char*) cmd, sizeof(cmd), "W%08" PRIX32 ",%08" PRIX32 "#", addr, value);
+ if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
+ throw SambaError("Samba::writeWord: _port->write failed");
+}
+
+
+uint32_t
+Samba::readWord(uint32_t addr)
+{
+ uint8_t cmd[13];
+ uint32_t value;
+
+ SafeSnprintf((char*) cmd, sizeof(cmd), "w%08" PRIX32 ",4#", addr);
+ if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
+ throw SambaError("Samba::readWord: _port->write failed");
+ if (_port->read(cmd, sizeof(uint32_t)) != sizeof(uint32_t))
+ throw SambaError("Samba::readWord: _port->read failed");
+
+ value = (cmd[3] << 24 | cmd[2] << 16 | cmd[1] << 8 | cmd[0] << 0);
+
+ if (_debug)
+ printf("%s(addr=%#" PRIx32 ")=%#" PRIx32 "\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("Samba::readXmodem: max retries reached 1");
+
+ _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("Samba::readXmodem: max retries reached 2");
+}
+
+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("Samba::writeXmodem: max retries reached getting START signal");
+
+ 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("Samba::writeXmodem: _port->write failed");
+
+ if (_port->get() == ACK)
+ break;
+ }
+
+ if (retries == MAX_RETRIES)
+ throw SambaError("Samba::writeXmodem: max retries reached 2");
+
+ 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("Samba::writeXmodem: max retries reached 3");
+}
+
+void
+Samba::read(uint32_t addr, uint8_t* buffer, int size)
+{
+ uint8_t cmd[20];
+ int chunk;
+
+ if (_debug)
+ printf("%s(addr=%#" PRIx32 ",size=%#x)\n", __FUNCTION__, addr, size);
+
+ while (size > 0)
+ {
+ // Handle any limitations on the size of the read
+ if (_readBufferSize > 0 && size > _readBufferSize)
+ chunk = _readBufferSize;
+ else
+ chunk = size;
+
+ SafeSnprintf((char*) cmd, sizeof(cmd), "R%08" PRIX32 ",%08X#", addr, chunk);
+ if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
+ throw SambaError("Samba::read: _port->write failed");
+
+ 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=%#" PRIx32 ",size=%#x)\n", __FUNCTION__, addr, size);
+
+ SafeSnprintf((char*) cmd, sizeof(cmd), "S%08" PRIX32 ",%08X#", addr, size);
+ if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
+ {
+ throw SambaError("Samba::write: _port->write failed");
+ }
+
+ writeXmodem(buffer, size);
+}
+
+void
+Samba::go(uint32_t addr)
+{
+ uint8_t cmd[11];
+
+ if (_debug)
+ printf("%s(addr=%#" PRIx32 ")\n", __FUNCTION__, addr);
+
+ SafeSnprintf((char*) cmd, sizeof(cmd), "G%08" PRIX32 "#", addr);
+ if (_port->write(cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1)
+ throw SambaError("Samba::go: _port->write failed");
+}
+
+void
+Samba::chipErase(uint32_t start_addr)
+{
+ if (!_canChipErase)
+ throw SambaError("Samba::chipErase: cannot erase chip");
+
+ uint8_t cmd[64];
+
+ if (_debug)
+ printf("%s(addr=%#" PRIx32 ")\n", __FUNCTION__, start_addr);
+
+ int l = SafeSnprintf((char*) cmd, sizeof(cmd), "X%08" PRIX32 "#", start_addr);
+ if (_port->write(cmd, l) != l)
+ throw SambaError("Samba::chipErase: _port->write failed");
+ _port->timeout(TIMEOUT_LONG);
+ _port->read(cmd, 3); // Expects "X\n\r"
+ _port->timeout(TIMEOUT_NORMAL);
+ if (cmd[0] != 'X')
+ throw SambaError("Samba::chipErase: unexpected response (expected: 'X')");
+}
+
+void
+Samba::writeBuffer(uint32_t src_addr, uint32_t dst_addr, uint32_t size)
+{
+ if (!_canWriteBuffer)
+ throw SambaError("Samba::writeBuffer: cannot write buffer");
+
+ if (size > checksumBufferSize())
+ throw SambaError("Samba::writeBuffer: size > checksumBufferSize()");
+
+ if (_debug)
+ printf("%s(scr_addr=%#" PRIx32 ", dst_addr=%#" PRIx32 ", size=%#" PRIx32 ")\n", __FUNCTION__, src_addr, dst_addr, size);
+
+ uint8_t cmd[64];
+ int l = SafeSnprintf((char*) cmd, sizeof(cmd), "Y%08" PRIX32 ",0#", src_addr);
+ if (_port->write(cmd, l) != l)
+ throw SambaError("Samba::writeBuffer: _port->write 1 failed");
+ _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("Samba::writeBuffer: unexpected response (expected: 'Y')");
+
+ l = SafeSnprintf((char*) cmd, sizeof(cmd), "Y%08" PRIX32 ",%08" PRIX32 "#", dst_addr, size);
+ if (_port->write(cmd, l) != l)
+ throw SambaError("Samba::writeBuffer: _port->write 2 failed");
+ _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("Samba::writeBuffer: unexpected response (expected: 'Y')");
+}
+
+uint16_t
+Samba::checksumBuffer(uint32_t start_addr, uint32_t size)
+{
+ if (!_canChecksumBuffer)
+ throw SambaError("Samba::checksumBuffer: cannot checksum buffer");
+
+ if (size > checksumBufferSize())
+ throw SambaError("Samba::checksumBuffer: size > checksumBufferSize()");
+
+ if (_debug)
+ printf("%s(start_addr=%#" PRIx32 ", size=%#" PRIx32 ") = ", __FUNCTION__, start_addr, size);
+
+ uint8_t cmd[64];
+ int l = SafeSnprintf((char*) cmd, sizeof(cmd), "Z%08" PRIX32 ",%08" PRIX32 "#", start_addr, size);
+ if (_port->write(cmd, l) != l)
+ throw SambaError("Samba::checksumBuffer: _port->write failed");
+ _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("Samba::checksumBuffer: unexpected response (expected: 'Z')");
+
+ cmd[9] = 0;
+ errno = 0;
+ uint32_t res = StrHexToU32((char*) &cmd[1], NULL);
+ if (errno != 0)
+ throw SambaError("Samba::checksumBuffer: cannot parse result");
+ if (_debug)
+ printf("%" PRIx32 "\n", res);
+ return res;
+}
+
diff --git a/src/bossa/Samba.h b/src/bossa/Samba.h
new file mode 100644
index 00000000..b972ca96
--- /dev/null
+++ b/src/bossa/Samba.h
@@ -0,0 +1,102 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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 "General/StringRef.h"
+
+#include "SerialPort.h"
+
+#include "GCodes/GCodeException.h"
+
+typedef GCodeException SambaError;
+
+
+class Samba
+{
+public:
+ Samba();
+ virtual ~Samba();
+
+ bool connect(SerialPort* 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);
+
+ 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;
+ SerialPort* _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);
+
+};
+
+
+#endif // _SAMBA_H
diff --git a/src/bossa/SerialPort.h b/src/bossa/SerialPort.h
new file mode 100644
index 00000000..3f8489c0
--- /dev/null
+++ b/src/bossa/SerialPort.h
@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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 <cstdint>
+
+class SerialPort
+{
+public:
+ SerialPort() {}
+ 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;
+};
+
+#endif // _SERIALPORT_H
diff --git a/src/bossa/WordCopyApplet.cpp b/src/bossa/WordCopyApplet.cpp
new file mode 100644
index 00000000..b076ea30
--- /dev/null
+++ b/src/bossa/WordCopyApplet.cpp
@@ -0,0 +1,62 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#include "WordCopyApplet.h"
+
+WordCopyApplet::WordCopyApplet(Samba& samba, uint32_t addr)
+ : Applet(samba,
+ addr,
+ applet.code,
+ sizeof(applet.code),
+ addr + applet.start,
+ addr + applet.stack,
+ addr + applet.reset)
+{
+}
+
+WordCopyApplet::~WordCopyApplet()
+{
+}
+
+void
+WordCopyApplet::setDstAddr(uint32_t dstAddr)
+{
+ _samba.writeWord(_addr + applet.dst_addr, dstAddr);
+}
+
+void
+WordCopyApplet::setSrcAddr(uint32_t srcAddr)
+{
+ _samba.writeWord(_addr + applet.src_addr, srcAddr);
+}
+
+void
+WordCopyApplet::setWords(uint32_t words)
+{
+ _samba.writeWord(_addr + applet.words, words);
+}
diff --git a/src/bossa/WordCopyApplet.h b/src/bossa/WordCopyApplet.h
new file mode 100644
index 00000000..becd02c3
--- /dev/null
+++ b/src/bossa/WordCopyApplet.h
@@ -0,0 +1,49 @@
+///////////////////////////////////////////////////////////////////////////////
+// BOSSA
+//
+// Copyright (c) 2011-2018, ShumaTech
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the <organization> nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+#ifndef _WORDCOPYAPPLET_H
+#define _WORDCOPYAPPLET_H
+
+#include "Applet.h"
+#include "WordCopyArm.h"
+
+class WordCopyApplet : public Applet
+{
+public:
+ WordCopyApplet(Samba& samba, uint32_t addr);
+ virtual ~WordCopyApplet();
+
+ void setDstAddr(uint32_t dstAddr);
+ void setSrcAddr(uint32_t srcAddr);
+ void setWords(uint32_t words);
+
+private:
+ static WordCopyArm applet;
+};
+
+#endif // _WORDCOPYAPPLET_H
diff --git a/src/bossa/WordCopyArm.asm b/src/bossa/WordCopyArm.asm
new file mode 100644
index 00000000..b9f291d0
--- /dev/null
+++ b/src/bossa/WordCopyArm.asm
@@ -0,0 +1,47 @@
+ .global start
+ .global stack
+ .global reset
+ .global dst_addr
+ .global src_addr
+ .global words
+
+ .text
+ .thumb
+ .align 0
+
+start:
+ ldr r0, dst_addr
+ ldr r1, src_addr
+ ldr r2, words
+ b check
+
+copy:
+ ldmia r1!, {r3}
+ stmia r0!, {r3}
+ sub r2, #1
+
+check:
+ cmp r2, #0
+ bne copy
+
+ @ Fix for SAM-BA stack bug
+ ldr r0, reset
+ cmp r0, #0
+ bne return
+ ldr r0, stack
+ mov sp, r0
+
+return:
+ bx lr
+
+ .align 0
+stack:
+ .word 0
+reset:
+ .word 0
+dst_addr:
+ .word 0
+src_addr:
+ .word 0
+words:
+ .word 0
diff --git a/src/bossa/WordCopyArm.cpp b/src/bossa/WordCopyArm.cpp
new file mode 100644
index 00000000..09bb1175
--- /dev/null
+++ b/src/bossa/WordCopyArm.cpp
@@ -0,0 +1,25 @@
+// WARNING!!! DO NOT EDIT - FILE GENERATED BY APPLETGEN
+#include "WordCopyArm.h"
+#include "WordCopyApplet.h"
+
+WordCopyArm WordCopyApplet::applet = {
+// dst_addr
+0x00000028,
+// reset
+0x00000024,
+// src_addr
+0x0000002c,
+// stack
+0x00000020,
+// start
+0x00000000,
+// words
+0x00000030,
+// code
+{
+0x09, 0x48, 0x0a, 0x49, 0x0a, 0x4a, 0x02, 0xe0, 0x08, 0xc9, 0x08, 0xc0, 0x01, 0x3a, 0x00, 0x2a,
+0xfa, 0xd1, 0x04, 0x48, 0x00, 0x28, 0x01, 0xd1, 0x01, 0x48, 0x85, 0x46, 0x70, 0x47, 0xc0, 0x46,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00,
+}
+};
diff --git a/src/bossa/WordCopyArm.h b/src/bossa/WordCopyArm.h
new file mode 100644
index 00000000..fab8ad76
--- /dev/null
+++ b/src/bossa/WordCopyArm.h
@@ -0,0 +1,18 @@
+// WARNING!!! DO NOT EDIT - FILE GENERATED BY APPLETGEN
+#ifndef _WORDCOPYARM_H
+#define _WORDCOPYARM_H
+
+#include <cstdint>
+
+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