From 54eb3a719fc78c66d0fb60944440a830092f69eb Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 4 Apr 2015 15:01:35 -0700 Subject: samd: use new flash interface. --- src/samd.c | 111 ++++++++++++++++++++++--------------------------------------- 1 file changed, 39 insertions(+), 72 deletions(-) diff --git a/src/samd.c b/src/samd.c index c8517aa..ae38255 100644 --- a/src/samd.c +++ b/src/samd.c @@ -40,9 +40,9 @@ #include "gdb_packet.h" #include "cortexm.h" -static int samd_flash_erase(target *t, uint32_t addr, size_t len); -static int samd_flash_write(target *t, uint32_t dest, - const uint8_t *src, size_t len); +static int samd_flash_erase(struct target_flash *t, uint32_t addr, size_t len); +static int samd_flash_write(struct target_flash *f, + uint32_t dest, const void *src, size_t len); static bool samd_cmd_erase_all(target *t); static bool samd_cmd_lock_flash(target *t); @@ -63,21 +63,6 @@ const struct command_s samd_cmd_list[] = { {NULL, NULL, NULL} }; -/** - * 256KB Flash Max., 32KB RAM Max. The smallest unit of erase is the - * one row = 256 bytes. - */ -static const char samd_xml_memory_map[] = "" -/* ""*/ - "" - " " - " 0x100" - " " - " " - ""; - /* Non-Volatile Memory Controller (NVMC) Parameters */ #define SAMD_ROW_SIZE 256 #define SAMD_PAGE_SIZE 64 @@ -361,6 +346,19 @@ struct samd_descr samd_parse_device_id(uint32_t did) return samd; } +static void samd_add_flash(target *t, uint32_t addr, size_t length) +{ + struct target_flash *f = calloc(1, sizeof(*f)); + f->start = addr; + f->length = length; + f->blocksize = SAMD_ROW_SIZE; + f->erase = samd_flash_erase; + f->write = target_flash_write_buffered; + f->done = target_flash_done_buffered; + f->write_buf = samd_flash_write; + f->buf_size = SAMD_PAGE_SIZE; + target_add_flash(t, f); +} char variant_string[40]; bool samd_probe(target *t) @@ -423,9 +421,8 @@ bool samd_probe(target *t) t->attach = samd_protected_attach; } - t->xml_mem_map = samd_xml_memory_map; - t->flash_erase = samd_flash_erase; - t->flash_write = samd_flash_write; + target_add_ram(t, 0x20000000, 0x8000); + samd_add_flash(t, 0x00000000, 0x40000); target_add_commands(t, samd_cmd_list, "SAMD"); /* If we're not in reset here */ @@ -463,11 +460,9 @@ static void samd_unlock_current_address(target *t) /** * Erase flash row by row */ -static int samd_flash_erase(target *t, uint32_t addr, size_t len) +static int samd_flash_erase(struct target_flash *f, uint32_t addr, size_t len) { - addr &= ~(SAMD_ROW_SIZE - 1); - len &= ~(SAMD_ROW_SIZE - 1); - + target *t = f->t; 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 */ @@ -487,8 +482,8 @@ static int samd_flash_erase(target *t, uint32_t addr, size_t len) /* Lock */ samd_lock_current_address(t); - addr += SAMD_ROW_SIZE; - len -= SAMD_ROW_SIZE; + addr += f->blocksize; + len -= f->blocksize; } return 0; @@ -497,56 +492,28 @@ static int samd_flash_erase(target *t, uint32_t addr, size_t len) /** * Write flash page by page */ -static int samd_flash_write(target *t, uint32_t dest, - const uint8_t *src, size_t len) +static int samd_flash_write(struct target_flash *f, + uint32_t dest, const void *src, size_t len) { - /* Find the size of our 32-bit data buffer */ - uint32_t offset = dest % 4; - uint32_t words = (offset + len + 3) / 4; - uint32_t data[words], i = 0; - - /* Populate the data buffer */ - memset((uint8_t *)data, 0xFF, words * 4); - memcpy((uint8_t *)data + offset, src, len); - - /* The address of the first word involved in the write */ - uint32_t addr = dest & ~0x3; - /* The address of the last word involved in the write */ - uint32_t end = (dest + len - 1) & ~0x3; - - /* The start address of the first page involved in the write */ - 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 next_page; - uint32_t length; - - for (uint32_t page = first_page; page <= last_page; page += SAMD_PAGE_SIZE) { - next_page = page + SAMD_PAGE_SIZE; - length = MIN(end + 4, next_page) - addr; - - /* Write within a single page. This may be part or all of the page */ - target_mem_write(t, addr, &data[i], length); - addr += length; i += (length >> 2); - - /* If MANW=0 (default) we may have triggered an automatic - * write. Ignore this */ + target *t = f->t; - /* Unlock */ - samd_unlock_current_address(t); + /* Write within a single page. This may be part or all of the page */ + target_mem_write(t, dest, src, len); - /* Issue the write page command */ - target_mem_write32(t, SAMD_NVMC_CTRLA, - SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE); + /* Unlock */ + samd_unlock_current_address(t); - /* Poll for NVM Ready */ - while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) - if (target_check_error(t)) - return -1; + /* Issue the write page command */ + target_mem_write32(t, SAMD_NVMC_CTRLA, + SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE); - /* Lock */ - samd_lock_current_address(t); - } + /* Poll for NVM Ready */ + while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) + if (target_check_error(t)) + return -1; + + /* Lock */ + samd_lock_current_address(t); return 0; } -- cgit v1.2.3