#include "imp.h"
#include "helper/binarybuffer.h"
+#include <jtag/jtag.h>
#include <target/cortex_m.h>
#define SAMD_NUM_PROT_BLOCKS 16
#define SAMD_NVMCTRL_CTRLA 0x00 /* NVM control A register */
#define SAMD_NVMCTRL_CTRLB 0x04 /* NVM control B register */
#define SAMD_NVMCTRL_PARAM 0x08 /* NVM parameters register */
-#define SAMD_NVMCTRL_INTFLAG 0x18 /* NVM Interupt Flag Status & Clear */
+#define SAMD_NVMCTRL_INTFLAG 0x18 /* NVM Interrupt Flag Status & Clear */
#define SAMD_NVMCTRL_STATUS 0x18 /* NVM status register */
#define SAMD_NVMCTRL_ADDR 0x1C /* NVM address register */
#define SAMD_NVMCTRL_LOCK 0x20 /* NVM Lock section register */
/* NVMCTRL commands. See Table 20-4 in 42129F–SAM–10/2013 */
#define SAMD_NVM_CMD_ER 0x02 /* Erase Row */
#define SAMD_NVM_CMD_WP 0x04 /* Write Page */
-#define SAMD_NVM_CMD_EAR 0x05 /* Erase Auxilary Row */
-#define SAMD_NVM_CMD_WAP 0x06 /* Write Auxilary Page */
+#define SAMD_NVM_CMD_EAR 0x05 /* Erase Auxiliary Row */
+#define SAMD_NVM_CMD_WAP 0x06 /* Write Auxiliary Page */
#define SAMD_NVM_CMD_LR 0x40 /* Lock Region */
#define SAMD_NVM_CMD_UR 0x41 /* Unlock Region */
#define SAMD_NVM_CMD_SPRM 0x42 /* Set Power Reduction Mode */
{ 0x26, "SAMD21E16B", 64, 8 },
{ 0x27, "SAMD21E15B", 32, 4 },
+ /* SAMD21 D and L Variants (from Errata)
+ http://ww1.microchip.com/downloads/en/DeviceDoc/
+ SAM-D21-Family-Silicon-Errata-and-DataSheet-Clarification-DS80000760D.pdf */
+ { 0x55, "SAMD21E16BU", 64, 8 },
+ { 0x56, "SAMD21E15BU", 32, 4 },
+ { 0x57, "SAMD21G16L", 64, 8 },
+ { 0x3E, "SAMD21E16L", 64, 8 },
+ { 0x3F, "SAMD21E15L", 32, 4 },
+ { 0x62, "SAMD21E16CU", 64, 8 },
+ { 0x63, "SAMD21E15CU", 32, 4 },
+ { 0x92, "SAMD21J17D", 128, 16 },
+ { 0x93, "SAMD21G17D", 128, 16 },
+ { 0x94, "SAMD21E17D", 128, 16 },
+ { 0x95, "SAMD21E17DU", 128, 16 },
+ { 0x96, "SAMD21G17L", 128, 16 },
+ { 0x97, "SAMD21E17L", 128, 16 },
+
/* Known SAMDA1 parts.
SAMD-A1 series uses the same series identifier like the SAMD21
taken from http://ww1.microchip.com/downloads/en/DeviceDoc/40001895A.pdf (pages 14-17) */
/* SAMR34/R35 parts have integrated SAML21 with a lora radio */
{ 0x28, "SAMR34J18", 256, 32 },
+ { 0x2B, "SAMR35J18", 256, 32 },
};
/* Known SAML22 parts. */
{
uint8_t devsel = SAMD_GET_DEVSEL(id);
const struct samd_family *family = samd_find_family(id);
- if (family == NULL)
+ if (!family)
return NULL;
for (unsigned i = 0; i < family->num_parts; i++) {
static int samd_protect_check(struct flash_bank *bank)
{
- int res, prot_block;
+ int res;
uint16_t lock;
res = target_read_u16(bank->target,
return res;
/* Lock bits are active-low */
- for (prot_block = 0; prot_block < bank->num_prot_blocks; prot_block++)
+ for (unsigned int prot_block = 0; prot_block < bank->num_prot_blocks; prot_block++)
bank->prot_blocks[prot_block].is_protected = !(lock & (1u<<prot_block));
return ERROR_OK;
}
part = samd_find_part(id);
- if (part == NULL) {
+ if (!part) {
LOG_ERROR("Couldn't find part corresponding to DID %08" PRIx32, id);
return ERROR_FAIL;
}
}
const struct samd_family *family;
family = samd_find_family(id);
- if (family == NULL) {
+ if (!family) {
LOG_ERROR("Couldn't determine device family");
return ERROR_FAIL;
}
return samd_modify_user_row_masked(target, value << startb, mask);
}
-static int samd_protect(struct flash_bank *bank, int set, int first_prot_bl, int last_prot_bl)
+static int samd_protect(struct flash_bank *bank, int set,
+ unsigned int first, unsigned int last)
{
int res = ERROR_OK;
- int prot_block;
/* We can issue lock/unlock region commands with the target running but
* the settings won't persist unless we're able to modify the LOCK regions
return ERROR_TARGET_NOT_HALTED;
}
- for (prot_block = first_prot_bl; prot_block <= last_prot_bl; prot_block++) {
+ for (unsigned int prot_block = first; prot_block <= last; prot_block++) {
if (set != bank->prot_blocks[prot_block].is_protected) {
/* Load an address that is within this protection block (we use offset 0) */
res = target_write_u32(bank->target,
res = samd_modify_user_row(bank->target,
set ? (uint64_t)0 : (uint64_t)UINT64_MAX,
- 48 + first_prot_bl, 48 + last_prot_bl);
+ 48 + first, 48 + last);
if (res != ERROR_OK)
LOG_WARNING("SAMD: protect settings were not made persistent!");
return res;
}
-static int samd_erase(struct flash_bank *bank, int first_sect, int last_sect)
+static int samd_erase(struct flash_bank *bank, unsigned int first,
+ unsigned int last)
{
- int res, s;
+ int res;
struct samd_info *chip = (struct samd_info *)bank->driver_priv;
if (bank->target->state != TARGET_HALTED) {
}
/* For each sector to be erased */
- for (s = first_sect; s <= last_sect; s++) {
+ for (unsigned int s = first; s <= last; s++) {
res = samd_erase_row(bank->target, bank->sectors[s].offset);
if (res != ERROR_OK) {
LOG_ERROR("SAMD: failed to erase sector %d at 0x%08" PRIx32, s, bank->sectors[s].offset);
}
free_pb:
- if (pb)
- free(pb);
-
+ free(pb);
return res;
}
return res;
}
-static COMMAND_HELPER(get_u64_from_hexarg, unsigned int num, uint64_t *value)
-{
- if (num >= CMD_ARGC) {
- command_print(CMD, "Too few Arguments.");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (strlen(CMD_ARGV[num]) >= 3 &&
- CMD_ARGV[num][0] == '0' &&
- CMD_ARGV[num][1] == 'x') {
- char *check = NULL;
- *value = strtoull(&(CMD_ARGV[num][2]), &check, 16);
- if ((value == 0 && errno == ERANGE) ||
- check == NULL || *check != 0) {
- command_print(CMD, "Invalid 64-bit hex value in argument %d.",
- num + 1);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- } else {
- command_print(CMD, "Argument %d needs to be a hex value.", num + 1);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- return ERROR_OK;
-}
-
COMMAND_HANDLER(samd_handle_nvmuserrow_command)
{
int res = ERROR_OK;
mask &= NVMUSERROW_LOCKBIT_MASK;
uint64_t value;
- res = CALL_COMMAND_HANDLER(get_u64_from_hexarg, 0, &value);
- if (res != ERROR_OK)
- return res;
+ COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], value);
+
if (CMD_ARGC == 2) {
uint64_t mask_temp;
- res = CALL_COMMAND_HANDLER(get_u64_from_hexarg, 1, &mask_temp);
- if (res != ERROR_OK)
- return res;
+ COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], mask_temp);
+
mask &= mask_temp;
}
res = samd_modify_user_row_masked(target, value, mask);