diff --git a/Makefile b/Makefile index 63b2b017..650fa65d 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ 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 +COMMON_SRCS=Samba.cpp Flash.cpp D5xNvmFlash.cpp D2xNvmFlash.cpp EfcFlash.cpp EefcFlash.cpp CalwFlash.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 diff --git a/src/CalwFlash.cpp b/src/CalwFlash.cpp new file mode 100644 index 00000000..3e54d22f --- /dev/null +++ b/src/CalwFlash.cpp @@ -0,0 +1,210 @@ +/////////////////////////////////////////////////////////////////////////////// +// BOSSA +// +// Copyright (c) 2011-2020, 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 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 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 "CalwFlash.h" + +#include +#include +#include + +#define CALW_KEY 0xa5 + +#define CALW_FCR (_regs + 0x00) +#define CALW_FCMD (_regs + 0x04) +#define CALW_FSR (_regs + 0x08) +#define CALW_FPR (_regs + 0x0C) + +#define CALW_FCMD_NOP 0x00 +#define CALW_FCMD_WP 0x01 +#define CALW_FCMD_EP 0x02 +#define CALW_FCMD_CPB 0x03 +#define CALW_FCMD_LP 0x04 +#define CALW_FCMD_UP 0x05 +#define CALW_FCMD_EA 0x06 +#define CALW_FCMD_WGPB 0x07 +#define CALW_FCMD_EGPB 0x08 +#define CALW_FCMD_SSB 0x09 +#define CALW_FCMD_PGPFB 0x0a +#define CALW_FCMD_EAGPF 0x0b +#define CALW_FCMD_QPR 0x0c +#define CALW_FCMD_WUP 0x0d +#define CALW_FCMD_EUP 0x0e +#define CALW_FCMD_QPRUP 0x0f +#define CALW_FCMD_HSEN 0x10 +#define CALW_FCMD_HSDIS 0x11 + + /* SCS_BASE + SCB offset + AIRCR offset) */ +#define NVIC_SCB_AIRCR (0xE000E000UL + 0x0D00UL + 0x00CUL) +#define SCB_AIRCR_VECTKEY 0x5FAUL +#define SCB_AIRCR_VECTKEY_Pos 16U +#define SCB_AIRCR_SYSRESETREQ_Pos 2U +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) +#define SCB_AIRCR_RESET_CPU_VAL ((SCB_AIRCR_VECTKEY << \ + SCB_AIRCR_VECTKEY_Pos) | \ + SCB_AIRCR_SYSRESETREQ_Msk) + +CalwFlash::CalwFlash(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) + : Flash(samba, name, addr, pages, size, planes, lockRegions, user, stack), + _regs(regs) +{ + assert(planes == 1); + assert(pages <= 1024); + assert(lockRegions <= 16); + + // Force 1WS + writeFCR(0x40); +} + +CalwFlash::~CalwFlash() +{ +} + +void +CalwFlash::eraseAll(uint32_t offset) +{ + // Do NOT a full chip erase, SAM-BA bootloader resides at offset lower than 0x4000 + if (offset < 0x4000) + { + throw FlashOverrideSambaError(); + } + // Else we must do it by pages + else + { + // Offset must be on an erase page boundary + if (offset % _size) + throw FlashEraseError(); + + // Erase each PagesPerErase set of pages + for (uint32_t pageNum = offset / _size; pageNum < _pages; pageNum++) + { + waitFSR(); + writeFCMD(CALW_FCMD_EP, pageNum); + } + } +} + +std::vector +CalwFlash::getLockRegions() +{ + std::vector regions(_lockRegions); + uint32_t locks; + + waitFSR(); + locks = readFSR(); + locks >>= 16; + for (uint32_t region = 0; region < _lockRegions; region++) + { + regions[region] = locks & (1 << region); + } + + return regions; +} + +void +CalwFlash::writePage(uint32_t page) +{ + if (page >= _pages) + throw FlashPageError(); + + waitFSR(); + writeFCMD(CALW_FCMD_CPB, 0); + + _wordCopy.setDstAddr(_addr + (page * _size)); + _wordCopy.setSrcAddr(_onBufferA ? _pageBufferA : _pageBufferB); + _wordCopy.setWords(_size / sizeof(uint32_t)); + _onBufferA = !_onBufferA; + waitFSR(); + _wordCopy.runv(); + writeFCMD(CALW_FCMD_WP, page); +} + +void +CalwFlash::readPage(uint32_t page, uint8_t* data) +{ + if (page >= _pages) + throw FlashPageError(); + + waitFSR(); + _samba.read(_addr + page * _size, data, _size); +} + +void +CalwFlash::resetCPU(void) +{ + printf("Reset CPU\n"); + + _samba.writeWord(NVIC_SCB_AIRCR, SCB_AIRCR_RESET_CPU_VAL); +} + +void +CalwFlash::waitFSR(int seconds) +{ + int tries = seconds * 1000; + uint32_t fsr0; + + while (tries-- > 0) + { + fsr0 = _samba.readWord(CALW_FSR); + if (fsr0 & 0x8) + throw FlashCmdError(); + if (fsr0 & 0x4) + throw FlashLockError(); + if (fsr0 & 0x1) + break; + usleep(1000); + } + if (tries == 0) + throw FlashTimeoutError(); +} + +void +CalwFlash::writeFCR(uint32_t arg) +{ + _samba.writeWord(CALW_FCR, arg); +} + +void +CalwFlash::writeFCMD(uint8_t cmd, uint32_t arg) +{ + _samba.writeWord(CALW_FCMD, (CALW_KEY << 24) | (arg << 8) | cmd); +} + +uint32_t +CalwFlash::readFSR() +{ + return _samba.readWord(CALW_FSR); +} diff --git a/src/CalwFlash.h b/src/CalwFlash.h new file mode 100644 index 00000000..de17a3f2 --- /dev/null +++ b/src/CalwFlash.h @@ -0,0 +1,84 @@ +/////////////////////////////////////////////////////////////////////////////// +// BOSSA +// +// Copyright (c) 2011-2020, 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 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 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 _CALWFLASH_H +#define _CALWFLASH_H + +#include +#include + +#include "Flash.h" + +class CalwFlash : public Flash +{ +public: + CalwFlash(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); + virtual ~CalwFlash(); + + void eraseAll(uint32_t offset); + void eraseAuto(bool enable) { } + + std::vector getLockRegions(); + + bool getSecurity() { return false; } + + bool getBod() { return false; } + bool canBod() { return true; } + + bool getBor() { return false; } + bool canBor() { return false; } + + bool getBootFlash() { return false; } + bool canBootFlash() { return true; } + + void writeOptions() { } + + void writePage(uint32_t page); + void readPage(uint32_t page, uint8_t* data); + + void resetCPU(void); + +private: + uint32_t _regs; + + void writeFCR(uint32_t arg); + void writeFCMD(uint8_t cmd, uint32_t arg); + void waitFSR(int seconds = 1); + uint32_t readFSR(); +}; + +#endif // _CALWFLASH_H diff --git a/src/Device.cpp b/src/Device.cpp index 0c94ae44..687f206d 100644 --- a/src/Device.cpp +++ b/src/Device.cpp @@ -31,6 +31,7 @@ #include "EefcFlash.h" #include "D2xNvmFlash.h" #include "D5xNvmFlash.h" +#include "CalwFlash.h" void Device::readChipId(uint32_t& chipId, uint32_t& extChipId) @@ -53,6 +54,7 @@ Device::create() uint32_t cpuId = 0; uint32_t extChipId = 0; uint32_t deviceId = 0; + uint32_t rstVct = 0; // Device identification must be performed carefully to avoid reading from // addresses that devices do not support which will lock up the CPU @@ -78,7 +80,8 @@ Device::create() else if (cpuId == 0xC240) { // SAM4 processors have a reset vector to the SAM-BA ROM - if ((_samba.readWord(0x4) & 0xfff00000) == 0x800000) + rstVct = _samba.readWord(0x4); + if ((rstVct & 0xfff00000) == 0x800000 || rstVct == 0x24d5) { readChipId(chipId, extChipId); } @@ -419,6 +422,21 @@ Device::create() flashPtr = new EefcFlash(_samba, "ATSAMV71x21", 0x400000, 4096, 512, 1, 128, 0x20401000, 0x20404000, 0x400e0c00, false); break; // + // SAM4L + // + case 0x2b0b0ae0: + _family = FAMILY_SAM4L; + flashPtr = new CalwFlash(_samba, "ATSAM4Lx8", 0x0, 1024, 512, 1, 16, 0x20001000, 0x20010000, 0x400a0000); + break; + case 0x2b0a09e0: + _family = FAMILY_SAM4L; + flashPtr = new CalwFlash(_samba, "ATSAM4Lx4", 0x0, 512, 512, 1, 16, 0x20001000, 0x20008000, 0x400a0000); + break; + case 0x2b0a07e0: + _family = FAMILY_SAM4L; + flashPtr = new CalwFlash(_samba, "ATSAM4Lx2", 0x0, 256, 512, 1, 16, 0x20001000, 0x20008000, 0x400a0000); + break; + // // No CHIPID devices // case 0: @@ -680,6 +698,12 @@ Device::reset() _samba.writeWord(0xFFFFFD00, 0xA500000D); break; + case FAMILY_SAM4L: + { + CalwFlash *cf = dynamic_cast(_flash.get()); + cf->resetCPU(); + break; + } default: break; } diff --git a/src/Device.h b/src/Device.h index 5475c557..a082050d 100644 --- a/src/Device.h +++ b/src/Device.h @@ -62,6 +62,8 @@ class Device FAMILY_SAM4S, FAMILY_SAM4E, + FAMILY_SAM4L, + FAMILY_SAM9XE, FAMILY_SAMD21, diff --git a/src/Flash.h b/src/Flash.h index 5d3a37b3..b396a16c 100644 --- a/src/Flash.h +++ b/src/Flash.h @@ -88,6 +88,14 @@ class FlashEraseError : public std::exception }; +class FlashOverrideSambaError : public std::exception +{ +public: + FlashOverrideSambaError() : exception() {}; + const char* what() const throw() { return "SAM-BA bootloader shouldn't be erased. Check flash start address."; } + +}; + template class FlashOption {