From 67f9d26644e8cf121018135280cb6042aaee9054 Mon Sep 17 00:00:00 2001 From: dpslwk Date: Sun, 6 May 2018 15:10:16 +0100 Subject: [PATCH] samd: Add support for L21 & L22 (PR #345) --- src/target/samd.c | 139 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 126 insertions(+), 13 deletions(-) diff --git a/src/target/samd.c b/src/target/samd.c index f5d4282..df2b371 100644 --- a/src/target/samd.c +++ b/src/target/samd.c @@ -25,6 +25,7 @@ * * SAMD20E17A (rev C) * * SAMD20J18A (rev B) * * SAMD21J18A (rev B) + * * SAML21J17B (rev B) * * */ /* Refer to the SAM D20 Datasheet: @@ -129,14 +130,16 @@ const struct command_s samd_cmd_list[] = { #define SAMD_STATUSB_PROT (1 << 16) /* Device Identification Register (DID) */ -#define SAMD_DID_MASK 0xFFBC0000 +#define SAMD_DID_MASK 0xFF3C0000 #define SAMD_DID_CONST_VALUE 0x10000000 -#define SAMD_DID_DEVSEL_MASK 0x0F +#define SAMD_DID_DEVSEL_MASK 0xFF #define SAMD_DID_DEVSEL_POS 0 #define SAMD_DID_REVISION_MASK 0x0F #define SAMD_DID_REVISION_POS 8 -#define SAMD_DID_SERIES_MASK 0x03 +#define SAMD_DID_SERIES_MASK 0x1F #define SAMD_DID_SERIES_POS 16 +#define SAMD_DID_FAMILY_MASK 0x1F +#define SAMD_DID_FAMILY_POS 23 /* Peripheral ID */ #define SAMD_PID_MASK 0x00F7FFFF @@ -145,6 +148,79 @@ const struct command_s samd_cmd_list[] = { /* Component ID */ #define SAMD_CID_VALUE 0xB105100D +/* Family parts */ +struct samd_part { + uint8_t devsel; + char pin; + uint8_t mem; + uint8_t variant; +}; + +static const struct samd_part samd_d21_parts[] = { + {0x00, 'J', 18, 'A'}, /* SAMD21J18A */ + {0x01, 'J', 17, 'A'}, /* SAMD21J17A */ + {0x02, 'J', 16, 'A'}, /* SAMD21J16A */ + {0x03, 'J', 15, 'A'}, /* SAMD21J15A */ + {0x05, 'G', 18, 'A'}, /* SAMD21G18A */ + {0x06, 'G', 17, 'A'}, /* SAMD21G17A */ + {0x07, 'G', 16, 'A'}, /* SAMD21G16A */ + {0x08, 'G', 15, 'A'}, /* SAMD21G15A */ + {0x0A, 'E', 18, 'A'}, /* SAMD21E18A */ + {0x0B, 'E', 17, 'A'}, /* SAMD21E17A */ + {0x0C, 'E', 16, 'A'}, /* SAMD21E16A */ + {0x0D, 'E', 15, 'A'}, /* SAMD21E15A */ + {0x0F, 'G', 18, 'A'}, /* SAMD21G18A (WLCSP) */ + {0x10, 'G', 17, 'A'}, /* SAMD21G17A (WLCSP) */ + {0x20, 'J', 16, 'B'}, /* SAMD21J16B */ + {0x21, 'J', 15, 'B'}, /* SAMD21J15B */ + {0x23, 'G', 16, 'B'}, /* SAMD21G16B */ + {0x24, 'G', 15, 'B'}, /* SAMD21G15B */ + {0x26, 'E', 16, 'B'}, /* SAMD21E16B */ + {0x27, 'E', 15, 'B'}, /* SAMD21E15B */ + {0x55, 'E', 16, 'B'}, /* SAMD21E16B (WLCSP) */ + {0x56, 'E', 15, 'B'}, /* SAMD21E15B (WLCSP) */ + {0x62, 'E', 16, 'C'}, /* SAMD21E16C (WLCSP) */ + {0x63, 'E', 15, 'C'}, /* SAMD21E15C (WLCSP) */ + {0xFF, 0, 0, 0} +}; + +static const struct samd_part samd_l21_parts[] = { + {0x00, 'J', 18, 'A'}, /* SAML21J18A */ + {0x01, 'J', 17, 'A'}, /* SAML21J17A */ + {0x02, 'J', 16, 'A'}, /* SAML21J16A */ + {0x05, 'G', 18, 'A'}, /* SAML21G18A */ + {0x06, 'G', 17, 'A'}, /* SAML21G17A */ + {0x07, 'G', 16, 'A'}, /* SAML21G16A */ + {0x0A, 'E', 18, 'A'}, /* SAML21E18A */ + {0x0B, 'E', 17, 'A'}, /* SAML21E17A */ + {0x0C, 'E', 16, 'A'}, /* SAML21E16A */ + {0x0D, 'E', 15, 'A'}, /* SAML21E15A */ + {0x0F, 'J', 18, 'B'}, /* SAML21J18B */ + {0x10, 'J', 17, 'B'}, /* SAML21J17B */ + {0x11, 'J', 16, 'B'}, /* SAML21J16B */ + {0x14, 'G', 18, 'B'}, /* SAML21G18B */ + {0x15, 'G', 17, 'B'}, /* SAML21G17B */ + {0x16, 'G', 16, 'B'}, /* SAML21G16B */ + {0x19, 'E', 18, 'B'}, /* SAML21E18B */ + {0x1A, 'E', 17, 'B'}, /* SAML21E17B */ + {0x1B, 'E', 16, 'B'}, /* SAML21E16B */ + {0x1C, 'E', 15, 'B'}, /* SAML21E15B */ + {0xFF, 0, 0, 0} +}; + +static const struct samd_part samd_l22_parts[] = { + {0x00, 'N', 18, 'A'}, /* SAML22N18 */ + {0x01, 'N', 17, 'A'}, /* SAML22N17 */ + {0x02, 'N', 16, 'A'}, /* SAML22N16 */ + {0x05, 'J', 18, 'A'}, /* SAML22J18 */ + {0x06, 'J', 17, 'A'}, /* SAML22J17 */ + {0x07, 'J', 16, 'A'}, /* SAML22J16 */ + {0x0A, 'G', 18, 'A'}, /* SAML22G18 */ + {0x0B, 'G', 17, 'A'}, /* SAML22G17 */ + {0x0C, 'G', 16, 'A'}, /* SAML22G16 */ + {0xFF, 0, 0, 0} +}; + /** * Reads the SAM D20 Peripheral ID */ @@ -293,17 +369,23 @@ static bool samd_protected_attach(target *t) * describing the SAM D device. */ struct samd_descr { + char family; uint8_t series; char revision; char pin; uint8_t mem; + char variant; char package[3]; }; struct samd_descr samd_parse_device_id(uint32_t did) { struct samd_descr samd; + uint8_t i = 0; + const struct samd_part *parts = samd_d21_parts; memset(samd.package, 0, 3); + uint8_t family = (did >> SAMD_DID_FAMILY_POS) + & SAMD_DID_FAMILY_MASK; uint8_t series = (did >> SAMD_DID_SERIES_POS) & SAMD_DID_SERIES_MASK; uint8_t revision = (did >> SAMD_DID_REVISION_POS) @@ -311,11 +393,24 @@ struct samd_descr samd_parse_device_id(uint32_t did) uint8_t devsel = (did >> SAMD_DID_DEVSEL_POS) & SAMD_DID_DEVSEL_MASK; + /* Family */ + switch (family) { + case 0: samd.family = 'D'; break; + case 1: samd.family = 'L'; parts = samd_l21_parts; break; + case 2: samd.family = 'C'; break; + } /* Series */ switch (series) { case 0: samd.series = 20; break; case 1: samd.series = 21; break; - case 2: samd.series = 10; break; + case 2: + if (family == 1) { + samd.series = 22; + parts = samd_l22_parts; + } else { + samd.series = 10; + } + break; case 3: samd.series = 11; break; } /* Revision */ @@ -323,7 +418,6 @@ struct samd_descr samd_parse_device_id(uint32_t did) switch (samd.series) { case 20: /* SAM D20 */ - case 21: /* SAM D21 */ switch (devsel / 5) { case 0: samd.pin = 'J'; break; case 1: samd.pin = 'G'; break; @@ -331,6 +425,20 @@ struct samd_descr samd_parse_device_id(uint32_t did) default: samd.pin = 'u'; break; } samd.mem = 18 - (devsel % 5); + samd.variant = 'A'; + break; + case 21: /* SAM D21/L21 */ + case 22: /* SAM L22 */ + i = 0; + while (parts[i].devsel != 0xFF) { + if (parts[i].devsel == devsel) { + samd.pin = parts[i].pin; + samd.mem = parts[i].mem; + samd.variant = parts[i].variant; + break; + } + i++; + } break; case 10: /* SAM D10 */ case 11: /* SAM D11 */ @@ -340,6 +448,7 @@ struct samd_descr samd_parse_device_id(uint32_t did) } samd.pin = 'D'; samd.mem = 14 - (devsel % 3); + samd.variant = 'A'; break; } @@ -389,15 +498,19 @@ bool samd_probe(target *t) /* Part String */ if (protected) { - snprintf(variant_string, sizeof(variant_string), - "Atmel SAMD%d%c%dA%s (rev %c) (PROT=1)", - samd.series, samd.pin, samd.mem, - samd.package, samd.revision); + sprintf(variant_string, + "Atmel SAM%c%d%c%d%c%s (rev %c) (PROT=1)", + samd.family, + samd.series, samd.pin, samd.mem, + samd.variant, + samd.package, samd.revision); } else { - snprintf(variant_string, sizeof(variant_string), - "Atmel SAMD%d%c%dA%s (rev %c)", - samd.series, samd.pin, samd.mem, - samd.package, samd.revision); + sprintf(variant_string, + "Atmel SAM%c%d%c%d%c%s (rev %c)", + samd.family, + samd.series, samd.pin, samd.mem, + samd.variant, + samd.package, samd.revision); } /* Setup Target */