#include "Device.h"
#include "EfcFlash.h"
#include "EefcFlash.h"
#include "D2xNvmFlash.h"
#include "D5xNvmFlash.h"
void
Device::readChipId(uint32_t& chipId, uint32_t& extChipId)
{
if ((chipId = _samba.readWord(0x400e0740)) != 0)
{
extChipId = _samba.readWord(0x400e0744);
}
else if ((chipId = _samba.readWord(0x400e0940)) != 0)
{
extChipId = _samba.readWord(0x400e0944);
}
}
void
Device::create()
{
Flash* flashPtr;
uint32_t chipId = 0;
uint32_t cpuId = 0;
uint32_t extChipId = 0;
uint32_t deviceId = 0;
if ((_samba.readWord(0x0) & 0xff000000) == 0xea000000)
{
chipId = _samba.readWord(0xfffff240);
}
else
{
cpuId = _samba.readWord(0xe000ed00) & 0x0000fff0;
if (cpuId == 0xC600)
{
deviceId = _samba.readWord(0x41002018);
}
else if (cpuId == 0xC240)
{
if ((_samba.readWord(0x4) & 0xfff00000) == 0x800000)
{
readChipId(chipId, extChipId);
}
else
{
deviceId = _samba.readWord(0x41002018);
}
}
else
{
readChipId(chipId, extChipId);
}
}
switch (chipId & 0x7fffffe0)
{
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;
case 0x270b0a40:
_family = FAMILY_SAM7S;
flashPtr = new EfcFlash(_samba, "AT91SAM7S512", 0x100000, 2048, 256, 2, 32, 0x202000, 0x210000, false);
break;
case 0x270d0940: case 0x270b0940: _family = FAMILY_SAM7S;
flashPtr = new EfcFlash(_samba, "AT91SAM7S256", 0x100000, 1024, 256, 1, 16, 0x202000, 0x210000, false);
break;
case 0x270c0740: case 0x270a0740: _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;
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;
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;
case 0x29870ee0: case 0x29970ee0: case 0x29A70ee0: _family = FAMILY_SAM4S;
flashPtr = new EefcFlash(_samba, "ATSAM4SD32", 0x400000, 4096, 512, 2, 256, 4, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x29870ce0: case 0x29970ce0: case 0x29a70ce0: _family = FAMILY_SAM4S;
flashPtr = new EefcFlash(_samba, "ATSAM4SD16", 0x400000, 2048, 512, 2, 256, 4, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x28870ce0: case 0x28970ce0: case 0x28A70ce0: _family = FAMILY_SAM4S;
flashPtr = new EefcFlash(_samba, "ATSAM4SA16", 0x400000, 2048, 512, 1, 256, 4, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x288c0ce0 : case 0x289c0ce0 : case 0x28ac0ce0 : _family = FAMILY_SAM4S;
flashPtr = new EefcFlash(_samba, "ATSAM4S16", 0x400000, 2048, 512, 1, 128, 4, 0x20001000, 0x20020000, 0x400e0a00, false);
break;
case 0x288c0ae0 : case 0x289c0ae0 : case 0x28ac0ae0 : _family = FAMILY_SAM4S;
flashPtr = new EefcFlash(_samba, "ATSAM4S8", 0x400000, 1024, 512, 1, 64, 4, 0x20001000, 0x20020000, 0x400e0a00, false);
break;
case 0x288b09e0 : case 0x289b09e0 : case 0x28ab09e0 : _family = FAMILY_SAM4S;
flashPtr = new EefcFlash(_samba, "ATSAM4S4", 0x400000, 512, 512, 1, 32, 4, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x288b07e0 : case 0x289b07e0 : case 0x28ab07e0 : _family = FAMILY_SAM4S;
flashPtr = new EefcFlash(_samba, "ATSAM4S2", 0x400000, 256, 512, 1, 16, 4, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x29340960 : case 0x29440960 : case 0x29540960 : _family = FAMILY_SAM3N;
flashPtr = new EefcFlash(_samba, "ATSAM3N4", 0x400000, 1024, 256, 1, 16, 4, 0x20001000, 0x20006000, 0x400e0a00, false);
break;
case 0x29390760 : case 0x29490760 : case 0x29590760 : _family = FAMILY_SAM3N;
flashPtr = new EefcFlash(_samba, "ATSAM3N2", 0x400000, 512, 256, 1, 8, 4, 0x20001000, 0x20004000, 0x400e0a00, false);
break;
case 0x29380560 : case 0x29480560 : case 0x29580560 : _family = FAMILY_SAM3N;
flashPtr = new EefcFlash(_samba, "ATSAM3N1", 0x400000, 256, 256, 1, 4, 4, 0x20000800, 0x20002000, 0x400e0a00, false);
break;
case 0x29380360 : case 0x29480360 : case 0x29580360 : _family = FAMILY_SAM3N;
flashPtr = new EefcFlash(_samba, "ATSAM3N0", 0x400000, 128, 256, 1, 1, 4, 0x20000800, 0x20002000, 0x400e0a00, false);
break;
case 0x299b0a60 : case 0x29ab0a60 : _family = FAMILY_SAM3S;
flashPtr = new EefcFlash(_samba, "ATSAM3SD8", 0x400000, 2048, 256, 1, 16, 4, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x289b0a60 : case 0x28ab0a60 : _family = FAMILY_SAM3S;
flashPtr = new EefcFlash(_samba, "ATSAM3S8", 0x400000, 2048, 256, 1, 16, 4, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x28800960 : case 0x28900960 : case 0x28a00960 : _family = FAMILY_SAM3S;
flashPtr = new EefcFlash(_samba, "ATSAM3S4", 0x400000, 1024, 256, 1, 16, 4, 0x20001000, 0x2000c000, 0x400e0a00, false);
break;
case 0x288a0760 : case 0x289a0760 : case 0x28aa0760 : _family = FAMILY_SAM3S;
flashPtr = new EefcFlash(_samba, "ATSAM3S2", 0x400000, 512, 256, 1, 8, 4, 0x20000800, 0x20008000, 0x400e0a00, false);
break;
case 0x28890560 : case 0x28990560 : case 0x28a90560 : _family = FAMILY_SAM3S;
flashPtr = new EefcFlash(_samba, "ATSAM3S1", 0x400000, 256, 256, 1, 4, 4, 0x20000800, 0x20004000, 0x400e0a00, false);
break;
case 0x28000960 : case 0x28100960 : _family = FAMILY_SAM3U;
flashPtr = new EefcFlash(_samba, "ATSAM3U4", 0xE0000, 1024, 256, 2, 32, 4, 0x20001000, 0x20008000, 0x400e0800, false);
break;
case 0x280a0760 : case 0x281a0760 : _family = FAMILY_SAM3U;
flashPtr = new EefcFlash(_samba, "ATSAM3U2", 0x80000, 512, 256, 1, 16, 4, 0x20001000, 0x20004000, 0x400e0800, false);
break;
case 0x28090560 : case 0x28190560 : _family = FAMILY_SAM3U;
flashPtr = new EefcFlash(_samba, "ATSAM3U1", 0x80000, 256, 256, 1, 8, 4, 0x20001000, 0x20002000, 0x400e0800, false);
break;
case 0x286e0a60 : case 0x285e0a60 : case 0x284e0a60 : _family = FAMILY_SAM3X;
flashPtr = new EefcFlash(_samba, "ATSAM3X8", 0x80000, 2048, 256, 2, 32, 4, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x285b0960 : case 0x284b0960 : _family = FAMILY_SAM3X;
flashPtr = new EefcFlash(_samba, "ATSAM3X4", 0x80000, 1024, 256, 2, 16, 4, 0x20001000, 0x20008000, 0x400e0a00, false);
break;
case 0x283e0A60 : _family = FAMILY_SAM3A;
flashPtr = new EefcFlash(_samba, "ATSAM3A8", 0x80000, 2048, 256, 2, 32, 4, 0x20001000, 0x20010000, 0x400e0a00, false);
break;
case 0x283b0960 : _family = FAMILY_SAM3A;
flashPtr = new EefcFlash(_samba, "ATSAM3A4", 0x80000, 1024, 256, 2, 16, 4, 0x20001000, 0x20008000, 0x400e0a00, false);
break;
case 0x27330740 :
_family = FAMILY_SAM7L;
flashPtr = new EefcFlash(_samba, "ATSAM7L128", 0x100000, 512, 256, 1, 16, 0, 0x2ffb40, 0x300700, 0xffffff60, false);
break;
case 0x27330540 :
_family = FAMILY_SAM7L;
flashPtr = new EefcFlash(_samba, "ATSAM7L64", 0x100000, 256, 256, 1, 8, 0, 0x2ffb40, 0x300700, 0xffffff60, false);
break;
case 0x329aa3a0 :
_family = FAMILY_SAM9XE;
flashPtr = new EefcFlash(_samba, "ATSAM9XE512", 0x200000, 1024, 512, 1, 32, 0, 0x300000, 0x307000, 0xfffffa00, true);
break;
case 0x329a93a0 :
_family = FAMILY_SAM9XE;
flashPtr = new EefcFlash(_samba, "ATSAM9XE256", 0x200000, 512, 512, 1, 16, 0, 0x300000, 0x307000, 0xfffffa00, true);
break;
case 0x329973a0 :
_family = FAMILY_SAM9XE;
flashPtr = new EefcFlash(_samba, "ATSAM9XE128", 0x200000, 256, 512, 1, 8, 0, 0x300000, 0x303000, 0xfffffa00, true);
break;
case 0x23cc0ce0:
switch (extChipId)
{
case 0x00120200: case 0x00120201: _family = FAMILY_SAM4E;
flashPtr = new EefcFlash(_samba, "ATSAM4E16", 0x400000, 2048, 512, 1, 128, 4, 0x20001000, 0x20020000, 0x400e0a00, false);
break;
case 0x00120208: case 0x00120209: _family = FAMILY_SAM4E;
flashPtr = new EefcFlash(_samba, "ATSAM4E8", 0x400000, 1024, 512, 1, 64, 4, 0x20001000, 0x20020000, 0x400e0a00, false);
break;
}
break;
case 0x210d0a00:
_family = FAMILY_SAME70;
flashPtr = new EefcFlash(_samba, "ATSAME70x19", 0x400000, 1024, 512, 1, 32, 4, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x21020c00:
_family = FAMILY_SAME70;
flashPtr = new EefcFlash(_samba, "ATSAME70x20", 0x400000, 2048, 512, 1, 64, 4, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x21020e00:
_family = FAMILY_SAME70;
flashPtr = new EefcFlash(_samba, "ATSAME70x21", 0x400000, 4096, 512, 1, 128, 4, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x211d0a00:
_family = FAMILY_SAMS70;
flashPtr = new EefcFlash(_samba, "ATSAMS70x19", 0x400000, 1024, 512, 1, 32, 4, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x21120c00:
_family = FAMILY_SAMS70;
flashPtr = new EefcFlash(_samba, "ATSAMS70x20", 0x400000, 2048, 512, 1, 64, 4, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x21120e00:
_family = FAMILY_SAMS70;
flashPtr = new EefcFlash(_samba, "ATSAMS70x21", 0x400000, 4096, 512, 1, 128, 4, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x213d0a00:
_family = FAMILY_SAMV70;
flashPtr = new EefcFlash(_samba, "ATSAMV70x19", 0x400000, 1024, 512, 1, 32, 4, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x21320c00:
_family = FAMILY_SAMV70;
flashPtr = new EefcFlash(_samba, "ATSAMV70x20", 0x400000, 2048, 512, 1, 64, 4, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x212d0a00:
_family = FAMILY_SAMV71;
flashPtr = new EefcFlash(_samba, "ATSAMV71x19", 0x400000, 1024, 512, 1, 32, 4, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x21220c00:
_family = FAMILY_SAMV71;
flashPtr = new EefcFlash(_samba, "ATSAMV71x20", 0x400000, 2048, 512, 1, 64, 4, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0x21220e00:
_family = FAMILY_SAMV71;
flashPtr = new EefcFlash(_samba, "ATSAMV71x21", 0x400000, 4096, 512, 1, 128, 4, 0x20401000, 0x20404000, 0x400e0c00, false);
break;
case 0:
switch (deviceId & 0xffff00ff)
{
case 0x1101000D: case 0x11010008: case 0x11010003: _family = FAMILY_SAMC21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMC21x15", 512, 64, 0x20000800, 0x20001000) ;
break;
case 0x1101000C: case 0x11010007: case 0x11010002: _family = FAMILY_SAMC21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMC21x16", 1024, 64, 0x20000800, 0x20002000) ;
break;
case 0x1101000B: case 0x11010006: case 0x11010001: case 0x11010021: _family = FAMILY_SAMC21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMC21x17", 2048, 64, 0x20002000, 0x20004000) ;
break;
case 0x1101000A: case 0x11010005: case 0x11010000: case 0x11010020: _family = FAMILY_SAMC21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMC21x18", 4096, 64, 0x20004000, 0x20008000) ;
break;
case 0x10010003: case 0x10010008: case 0x1001000d: case 0x10010021: case 0x10010024: case 0x10010027: case 0x10010056: case 0x10010063: _family = FAMILY_SAMD21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMD21x15", 512, 64, 0x20000800, 0x20001000) ;
break;
case 0x10010002: case 0x10010007: case 0x1001000c: case 0x10010020: case 0x10010023: case 0x10010026: case 0x10010055: case 0x10010062: _family = FAMILY_SAMD21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMD21x16", 1024, 64, 0x20001000, 0x20002000) ;
break;
case 0x10010001: case 0x10010006: case 0x1001000b: case 0x10010010: _family = FAMILY_SAMD21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMD21x17", 2048, 64, 0x20002000, 0x20004000) ;
break;
case 0x10010000: case 0x10010005: case 0x1001000a: case 0x1001000f: _family = FAMILY_SAMD21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMD21x18", 4096, 64, 0x20004000, 0x20008000) ;
break;
case 0x1001001e: case 0x1001001b: _family = FAMILY_SAMR21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMR21x16", 1024, 64, 0x20001000, 0x20002000) ;
break;
case 0x1001001d: case 0x1001001a: _family = FAMILY_SAMR21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMR21x17", 2048, 64, 0x20002000, 0x20004000) ;
break;
case 0x1001001c: case 0x10010019: _family = FAMILY_SAMR21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMR21x18", 4096, 64, 0x20004000, 0x20008000) ;
break;
case 0x10010018: _family = FAMILY_SAMR21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMR21x19", 4096, 64, 0x20004000, 0x20008000) ;
break;
case 0x1081000d: case 0x1081001c: _family = FAMILY_SAML21;
flashPtr = new D2xNvmFlash(_samba, "ATSAML21x15", 512, 64, 0x20000800, 0x20001000) ;
break;
case 0x10810002: case 0x10810007: case 0x1081000c: case 0x10810011: case 0x10810016: case 0x1081001b: _family = FAMILY_SAML21;
flashPtr = new D2xNvmFlash(_samba, "ATSAML21x16", 1024, 64, 0x20001000, 0x20002000) ;
break;
case 0x10810001: case 0x10810006: case 0x1081000b: case 0x10810010: case 0x10810015: case 0x1081001a: _family = FAMILY_SAML21;
flashPtr = new D2xNvmFlash(_samba, "ATSAML21x17", 2048, 64, 0x20002000, 0x20004000) ;
break;
case 0x10810000: case 0x10810005: case 0x1081000a: case 0x1081000f: case 0x10810014: case 0x10810019: _family = FAMILY_SAML21;
flashPtr = new D2xNvmFlash(_samba, "ATSAML21x18", 4096, 64, 0x20004000, 0x20008000) ;
break;
case 0x10810028: _family = FAMILY_SAML21;
flashPtr = new D2xNvmFlash(_samba, "ATSAMR34J18", 4096, 64, 0x20004000, 0x20008000) ;
break;
case 0x60060006: case 0x60060008: _family = FAMILY_SAMD51;
flashPtr = new D5xNvmFlash(_samba, "ATSAMD51x18", 512, 512, 0x20004000, 0x20008000) ;
break;
case 0x60060001: case 0x60060003: case 0x60060005: case 0x60060007: _family = FAMILY_SAMD51;
flashPtr = new D5xNvmFlash(_samba, "ATSAMD51x19", 1024, 512, 0x20004000, 0x20008000) ;
break;
case 0x60060000: case 0x60060002: case 0x60060004: _family = FAMILY_SAMD51;
flashPtr = new D5xNvmFlash(_samba, "ATSAMD51x20", 2048, 512, 0x20004000, 0x20008000) ;
break;
case 0x61810006: case 0x61810003: _family = FAMILY_SAME51;
flashPtr = new D5xNvmFlash(_samba, "ATSAME51x18", 512, 512, 0x20004000, 0x20008000) ;
break;
case 0x61810005: case 0x61810002: case 0x61810001: _family = FAMILY_SAME51;
flashPtr = new D5xNvmFlash(_samba, "ATSAME51x19", 1024, 512, 0x20004000, 0x20008000) ;
break;
case 0x61810004: case 0x61810000: _family = FAMILY_SAME51;
flashPtr = new D5xNvmFlash(_samba, "ATSAME51x20", 2048, 512, 0x20004000, 0x20008000) ;
break;
case 0x61830006: _family = FAMILY_SAME53;
flashPtr = new D5xNvmFlash(_samba, "ATSAME53x18", 512, 512, 0x20004000, 0x20008000) ;
break;
case 0x61830005: case 0x61830003: _family = FAMILY_SAME53;
flashPtr = new D5xNvmFlash(_samba, "ATSAME53x19", 1024, 512, 0x20004000, 0x20008000) ;
break;
case 0x61830004: case 0x61830002: _family = FAMILY_SAME53;
flashPtr = new D5xNvmFlash(_samba, "ATSAME53x20", 2048, 512, 0x20004000, 0x20008000) ;
break;
case 0x61840001: case 0x61840003: _family = FAMILY_SAME54;
flashPtr = new D5xNvmFlash(_samba, "ATSAME54x19", 1024, 512, 0x20004000, 0x20008000) ;
break;
case 0x61840000: case 0x61840002: _family = FAMILY_SAME54;
flashPtr = new D5xNvmFlash(_samba, "ATSAME54x20", 2048, 512, 0x20004000, 0x20008000) ;
break;
default:
throw DeviceUnsupportedError();
break;
}
break;
default:
throw DeviceUnsupportedError();
break;
}
_flash = std::unique_ptr<Flash>(flashPtr);
}
void
Device::reset()
{
try
{
switch (_family)
{
case FAMILY_SAMC21:
case FAMILY_SAMD21:
case FAMILY_SAMR21:
case FAMILY_SAML21:
case FAMILY_SAMD51:
case FAMILY_SAME51:
case FAMILY_SAME53:
case FAMILY_SAME54:
case FAMILY_SAME70:
case FAMILY_SAMS70:
case FAMILY_SAMV70:
case FAMILY_SAMV71:
_samba.writeWord(0xE000ED0C, 0x05FA0004);
break;
case FAMILY_SAM3X:
case FAMILY_SAM3S:
case FAMILY_SAM3A:
_samba.writeWord(0x400E1A00, 0xA500000D);
break;
case FAMILY_SAM3U:
_samba.writeWord(0x400E1200, 0xA500000D);
break;
case FAMILY_SAM3N:
case FAMILY_SAM4S:
_samba.writeWord(0x400E1400, 0xA500000D);
break;
case FAMILY_SAM4E:
_samba.writeWord(0x400E1800, 0xA500000D);
break;
case FAMILY_SAM7S:
case FAMILY_SAM7SE:
case FAMILY_SAM7X:
case FAMILY_SAM7XC:
case FAMILY_SAM7L:
case FAMILY_SAM9XE:
_samba.writeWord(0xFFFFFD00, 0xA500000D);
break;
default:
break;
}
}
catch (const std::exception&)
{ }
}
std::unique_ptr<Device> new_device(Samba& samba)
{
return std::unique_ptr<Device>(new Device(samba));
}