aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Eoin Meadows2014-07-06 17:31:49 +0100
committerGareth McMullin2014-09-03 21:17:48 +1200
commite75798f201a0e4e566f09066c96b0637addc23cb (patch)
treedb7cb8084baaa4f1bd1a90ad9a3a6a082b9526ab
parent02812b6bf1b9caf7123c436749c020f30bd9edc2 (diff)
Optimised flash write, programming speed is now approx. 2x faster
-rw-r--r--src/samd20.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/samd20.c b/src/samd20.c
index 93e8be9..f8fc119 100644
--- a/src/samd20.c
+++ b/src/samd20.c
@@ -353,9 +353,6 @@ static int samd20_flash_erase(struct target_s *target, uint32_t addr, int len)
addr &= ~(SAMD20_ROW_SIZE - 1);
len &= ~(SAMD20_ROW_SIZE - 1);
-
-
-
while (len) {
/* Write address of first word in row to erase it */
/* Must be shifted right for 16-bit address, see Datasheet ยง20.8.8 Address */
@@ -414,10 +411,16 @@ static int samd20_flash_write(struct target_s *target, uint32_t dest,
end_of_this_page = page + (SAMD20_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_ap_mem_write(ap, addr, data[i]);
+ adiv5_dp_write_ap(ap->dp, ADIV5_AP_DRW, data[i]);
}
/* Unlock */
@@ -433,9 +436,16 @@ static int samd20_flash_write(struct target_s *target, uint32_t dest,
/* Unlock */
samd20_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 + SAMD20_PAGE_SIZE; addr += 4, i++) {
- adiv5_ap_mem_write(ap, addr, data[i]);
+ adiv5_dp_write_ap(ap->dp, ADIV5_AP_DRW, data[i]);
}
}