aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGareth McMullin2015-03-18 19:07:03 -0700
committerGareth McMullin2015-03-18 19:07:03 -0700
commit7372fca2f600f4e60eafec99fc0dfad220fd3e3d (patch)
tree3da3e869a5f210165a4cc8819d34cd2838afe955
parent018d9cce806ba96768fccec65bb6570943207c76 (diff)
parent1de685198c2dc7792bb5808989afb268203d1ded (diff)
Merge pull request #83 from gsmcmullin/samd_no_ap
samd: Remove low level ADIv5 calls an favour of target_mem_write.
-rw-r--r--src/samd.c247
1 files changed, 114 insertions, 133 deletions
diff --git a/src/samd.c b/src/samd.c
index 68f5bc4..e12bcc9 100644
--- a/src/samd.c
+++ b/src/samd.c
@@ -59,7 +59,7 @@ const struct command_s samd_cmd_list[] = {
{"user_row", (cmd_handler)samd_cmd_read_userrow, "Prints user row from flash"},
{"serial", (cmd_handler)samd_cmd_serial, "Prints serial number"},
{"mbist", (cmd_handler)samd_cmd_mbist, "Runs the built-in memory test"},
- {"set_security_bit", (cmd_handler)samd_cmd_ssb, "Sets the Security Bit"},
+ {"set_security_bit", (cmd_handler)samd_cmd_ssb, "Sets the Security Bit"},
{NULL, NULL, NULL}
};
@@ -222,14 +222,14 @@ samd_reset(struct target_s *target)
* or SYSRESETREQ: 0x05FA0004 (system reset)
*/
target_mem_write32(target, CORTEXM_AIRCR,
- CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ);
+ CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ);
/* Exit extended reset */
if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) &
SAMD_STATUSA_CRSTEXT) {
/* Write bit to clear from extended reset */
target_mem_write32(target, SAMD_DSU_CTRLSTAT,
- SAMD_STATUSA_CRSTEXT);
+ SAMD_STATUSA_CRSTEXT);
}
/* Poll for release from reset */
@@ -301,10 +301,10 @@ samd_protected_attach(struct target_s *target)
* regain access to the chip.
*/
- /* Patch back in the normal cortexm attach for next time */
- target->attach = cortexm_attach;
+ /* Patch back in the normal cortexm attach for next time */
+ target->attach = cortexm_attach;
- /* Allow attach this time */
+ /* Allow attach this time */
return true;
}
@@ -374,82 +374,80 @@ bool samd_probe(struct target_s *target)
uint32_t pid = samd_read_pid(target);
/* Check the ARM Coresight Component and Perhiperal IDs */
- if (cid == SAMD_CID_VALUE &&
- (pid & SAMD_PID_MASK) == SAMD_PID_CONST_VALUE) {
-
- /* Read the Device ID */
- uint32_t did = target_mem_read32(target, SAMD_DSU_DID);
-
- /* If the Device ID matches */
- if ((did & SAMD_DID_MASK) == SAMD_DID_CONST_VALUE) {
-
- uint32_t ctrlstat = target_mem_read32(target,
- SAMD_DSU_CTRLSTAT);
- struct samd_descr samd = samd_parse_device_id(did);
-
- /* Protected? */
- int protected = (ctrlstat & SAMD_STATUSB_PROT);
-
- /* Part String */
- if (protected) {
- sprintf(variant_string,
- "Atmel SAMD%d%c%dA%s (rev %c) (PROT=1)",
- samd.series, samd.pin, samd.mem,
- samd.package, samd.revision);
- } else {
- sprintf(variant_string,
- "Atmel SAMD%d%c%dA%s (rev %c)",
- samd.series, samd.pin, samd.mem,
- samd.package, samd.revision);
- }
-
- /* Setup Target */
- target->driver = variant_string;
- target->reset = samd_reset;
-
- if (samd.series == 20 && samd.revision == 'B') {
- /**
- * These functions check for and
- * extended reset. Appears to be
- * related to Errata 35.4.1 ref 12015
- */
- target->detach = samd20_revB_detach;
- target->halt_resume = samd20_revB_halt_resume;
- }
- if (protected) {
- /**
- * Overload the default cortexm attach
- * for when the samd is protected.
- * This function allows users to
- * attach on a temporary basis so they
- * can rescue the device.
- */
- target->attach = samd_protected_attach;
- }
-
- target->xml_mem_map = samd_xml_memory_map;
- target->flash_erase = samd_flash_erase;
- target->flash_write = samd_flash_write;
- target_add_commands(target, samd_cmd_list, "SAMD");
-
- /* If we're not in reset here */
- if (!connect_assert_srst) {
- /* We'll have to release the target from
- * extended reset to make attach possible */
- if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) &
- SAMD_STATUSA_CRSTEXT) {
-
- /* Write bit to clear from extended reset */
- target_mem_write32(target, SAMD_DSU_CTRLSTAT,
- SAMD_STATUSA_CRSTEXT);
- }
- }
-
- return true;
+ if ((cid != SAMD_CID_VALUE) ||
+ ((pid & SAMD_PID_MASK) != SAMD_PID_CONST_VALUE))
+ return false;
+
+ /* Read the Device ID */
+ uint32_t did = target_mem_read32(target, SAMD_DSU_DID);
+
+ /* If the Device ID matches */
+ if ((did & SAMD_DID_MASK) != SAMD_DID_CONST_VALUE)
+ return false;
+
+ uint32_t ctrlstat = target_mem_read32(target,
+ SAMD_DSU_CTRLSTAT);
+ struct samd_descr samd = samd_parse_device_id(did);
+
+ /* Protected? */
+ bool protected = (ctrlstat & SAMD_STATUSB_PROT);
+
+ /* Part String */
+ if (protected) {
+ sprintf(variant_string,
+ "Atmel SAMD%d%c%dA%s (rev %c) (PROT=1)",
+ samd.series, samd.pin, samd.mem,
+ samd.package, samd.revision);
+ } else {
+ sprintf(variant_string,
+ "Atmel SAMD%d%c%dA%s (rev %c)",
+ samd.series, samd.pin, samd.mem,
+ samd.package, samd.revision);
+ }
+
+ /* Setup Target */
+ target->driver = variant_string;
+ target->reset = samd_reset;
+
+ if (samd.series == 20 && samd.revision == 'B') {
+ /**
+ * These functions check for and
+ * extended reset. Appears to be
+ * related to Errata 35.4.1 ref 12015
+ */
+ target->detach = samd20_revB_detach;
+ target->halt_resume = samd20_revB_halt_resume;
+ }
+ if (protected) {
+ /**
+ * Overload the default cortexm attach
+ * for when the samd is protected.
+ * This function allows users to
+ * attach on a temporary basis so they
+ * can rescue the device.
+ */
+ target->attach = samd_protected_attach;
+ }
+
+ target->xml_mem_map = samd_xml_memory_map;
+ target->flash_erase = samd_flash_erase;
+ target->flash_write = samd_flash_write;
+ target_add_commands(target, samd_cmd_list, "SAMD");
+
+ /* If we're not in reset here */
+ if (!connect_assert_srst) {
+ /* We'll have to release the target from
+ * extended reset to make attach possible */
+ if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) &
+ SAMD_STATUSA_CRSTEXT) {
+
+ /* Write bit to clear from extended reset */
+ target_mem_write32(target, SAMD_DSU_CTRLSTAT,
+ SAMD_STATUSA_CRSTEXT);
}
}
- return false;
+ return true;
}
/**
@@ -489,7 +487,7 @@ static int samd_flash_erase(struct target_s *target, uint32_t addr, size_t len)
SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEROW);
/* Poll for NVM Ready */
while ((target_mem_read32(target, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0)
- if(target_check_error(target))
+ if (target_check_error(target))
return -1;
/* Lock */
@@ -508,7 +506,6 @@ static int samd_flash_erase(struct target_s *target, uint32_t addr, size_t len)
static int samd_flash_write(struct target_s *target, uint32_t dest,
const uint8_t *src, size_t len)
{
- ADIv5_AP_t *ap = adiv5_target_ap(target);
/* Find the size of our 32-bit data buffer */
uint32_t offset = dest % 4;
uint32_t words = (offset + len + 3) / 4;
@@ -527,54 +524,30 @@ static int samd_flash_write(struct target_s *target, uint32_t dest,
uint32_t first_page = dest & ~(SAMD_PAGE_SIZE - 1);
/* The start address of the last page involved in the write */
uint32_t last_page = (dest + len - 1) & ~(SAMD_PAGE_SIZE - 1);
- uint32_t end_of_this_page;
-
+ uint32_t next_page;
+ uint32_t length;
for (uint32_t page = first_page; page <= last_page; page += SAMD_PAGE_SIZE) {
- end_of_this_page = page + (SAMD_PAGE_SIZE - 4);
-
- if (addr > page || (page == last_page && end < end_of_this_page)) {
- /* Setup write */
- adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
- ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE);
- adiv5_ap_write(ap, ADIV5_AP_TAR, addr);
- adiv5_dp_write(ap->dp, ADIV5_DP_SELECT,
- ((uint32_t)ap->apsel << 24)|(ADIV5_AP_DRW & 0xF0));
-
- /* Partial, manual page write */
- for (; addr <= MINIMUM(end, end_of_this_page); addr += 4, i++) {
- adiv5_dp_write(ap->dp, ADIV5_AP_DRW, data[i]);
- }
-
- /* Unlock */
- samd_unlock_current_address(target);
-
- /* Issue the write page command */
- target_mem_write32(target, SAMD_NVMC_CTRLA,
- SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE);
- } else {
- /* Write first word to set address */
- target_mem_write32(target, addr, data[i]); addr += 4; i++;
-
- /* Unlock */
- samd_unlock_current_address(target);
-
- /* Set up write */
- adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
- ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE);
- adiv5_ap_write(ap, ADIV5_AP_TAR, addr);
- adiv5_dp_write(ap->dp, ADIV5_DP_SELECT,
- ((uint32_t)ap->apsel << 24)|(ADIV5_AP_DRW & 0xF0));
-
- /* Full, automatic page write */
- for (; addr < page + SAMD_PAGE_SIZE; addr += 4, i++) {
- adiv5_dp_write(ap->dp, ADIV5_AP_DRW, data[i]);
- }
- }
+ next_page = page + SAMD_PAGE_SIZE;
+ length = MINIMUM(end + 4, next_page) - addr;
+
+ /* Write within a single page. This may be part or all of the page */
+ target_mem_write(target, addr, &data[i], length);
+ addr += length; i += (length >> 2);
+
+ /* If MANW=0 (default) we may have triggered an automatic
+ * write. Ignore this */
+
+ /* Unlock */
+ samd_unlock_current_address(target);
+
+ /* Issue the write page command */
+ target_mem_write32(target, SAMD_NVMC_CTRLA,
+ SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE);
/* Poll for NVM Ready */
while ((target_mem_read32(target, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0)
- if(target_check_error(target))
+ if (target_check_error(target))
return -1;
/* Lock */
@@ -591,7 +564,8 @@ static bool samd_cmd_erase_all(target *t)
{
/* Clear the DSU status bits */
target_mem_write32(t, SAMD_DSU_CTRLSTAT,
- (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL));
+ SAMD_STATUSA_DONE | SAMD_STATUSA_PERR |
+ SAMD_STATUSA_FAIL);
/* Erase all */
target_mem_write32(t, SAMD_DSU_CTRLSTAT, SAMD_CTRL_CHIP_ERASE);
@@ -600,7 +574,7 @@ static bool samd_cmd_erase_all(target *t)
uint32_t status;
while (((status = target_mem_read32(t, SAMD_DSU_CTRLSTAT)) &
(SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)) == 0)
- if(target_check_error(t))
+ if (target_check_error(t))
return false;
/* Test the protection error bit in Status A */
@@ -642,7 +616,7 @@ static bool samd_set_flashlock(target *t, uint16_t value)
/* Poll for NVM Ready */
while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0)
- if(target_check_error(t))
+ if (target_check_error(t))
return -1;
/* Modify the high byte of the user row */
@@ -656,16 +630,19 @@ static bool samd_set_flashlock(target *t, uint16_t value)
target_mem_write32(t, SAMD_NVMC_CTRLA,
SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEAUXPAGE);
- return true;
+ return true;
}
+
static bool samd_cmd_lock_flash(target *t)
{
return samd_set_flashlock(t, 0x0000);
}
+
static bool samd_cmd_unlock_flash(target *t)
{
return samd_set_flashlock(t, 0xFFFF);
}
+
static bool samd_cmd_read_userrow(target *t)
{
gdb_outf("User Row: 0x%08x%08x\n",
@@ -674,6 +651,7 @@ static bool samd_cmd_read_userrow(target *t)
return true;
}
+
/**
* Reads the 128-bit serial number from the NVM
*/
@@ -689,6 +667,7 @@ static bool samd_cmd_serial(target *t)
return true;
}
+
/**
* Returns the size (in bytes) of the current SAM D20's flash memory.
*/
@@ -703,6 +682,7 @@ static uint32_t samd_flash_size(target *t)
/* Shift the maximum flash size (256KB) down as appropriate */
return (0x40000 >> (devsel % 5));
}
+
/**
* Runs the Memory Built In Self Test (MBIST)
*/
@@ -722,7 +702,7 @@ static bool samd_cmd_mbist(target *t)
uint32_t status;
while (((status = target_mem_read32(t, SAMD_DSU_CTRLSTAT)) &
(SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)) == 0)
- if(target_check_error(t))
+ if (target_check_error(t))
return false;
/* Test the protection error bit in Status A */
@@ -734,7 +714,7 @@ static bool samd_cmd_mbist(target *t)
/* Test the fail bit in Status A */
if (status & SAMD_STATUSA_FAIL) {
gdb_outf("MBIST Fail @ 0x%08x\n",
- target_mem_read32(t, SAMD_DSU_ADDRESS));
+ target_mem_read32(t, SAMD_DSU_ADDRESS));
} else {
gdb_outf("MBIST Passed!\n");
}
@@ -750,9 +730,9 @@ static bool samd_cmd_ssb(target *t)
target_mem_write32(t, SAMD_NVMC_CTRLA,
SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_SSB);
- /* Poll for NVM Ready */
- while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0)
- if(target_check_error(t))
+ /* Poll for NVM Ready */
+ while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0)
+ if (target_check_error(t))
return -1;
gdb_outf("Set the security bit! "
@@ -760,3 +740,4 @@ static bool samd_cmd_ssb(target *t)
return true;
}
+