From 67c9f3f6e2d44b09b75fd41f659d99e826bfb2c9 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Wed, 24 Aug 2022 12:38:51 +0100 Subject: [PATCH] target/sam: flash read write return bool --- src/target/sam3x.c | 53 ++++++++++++-------------- src/target/sam4l.c | 92 ++++++++++++++++++++------------------------- src/target/samd.c | 17 ++++----- src/target/samx5x.c | 22 +++++------ 4 files changed, 85 insertions(+), 99 deletions(-) diff --git a/src/target/sam3x.c b/src/target/sam3x.c index 93b9c66..2b46ecf 100644 --- a/src/target/sam3x.c +++ b/src/target/sam3x.c @@ -28,9 +28,9 @@ #include "target.h" #include "target_internal.h" -static int sam_flash_erase(target_flash_s *f, target_addr_t addr, size_t len); -static int sam3_flash_erase(target_flash_s *f, target_addr_t addr, size_t len); -static int sam_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len); +static bool sam_flash_erase(target_flash_s *f, target_addr_t addr, size_t len); +static bool sam3_flash_erase(target_flash_s *f, target_addr_t addr, size_t len); +static bool sam_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len); static int sam_gpnvm_get(target *t, uint32_t base, uint32_t *gpnvm); @@ -498,24 +498,20 @@ bool sam3x_probe(target *t) return false; } -static int -sam_flash_cmd(target *t, uint32_t base, uint8_t cmd, uint16_t arg) +static bool sam_flash_cmd(target *t, uint32_t base, uint8_t cmd, uint16_t arg) { - DEBUG_INFO("%s: base = 0x%08"PRIx32" cmd = 0x%02X, arg = 0x%06X\n", - __func__, base, cmd, arg); + DEBUG_INFO("%s: base = 0x%08" PRIx32 " cmd = 0x%02X, arg = 0x%06X\n", __func__, base, cmd, arg); - if(base == 0) - return -1; + if (base == 0) + return false; - target_mem_write32(t, EEFC_FCR(base), - EEFC_FCR_FKEY | cmd | ((uint32_t)arg << 8)); + target_mem_write32(t, EEFC_FCR(base), EEFC_FCR_FKEY | cmd | ((uint32_t)arg << 8)); while (!(target_mem_read32(t, EEFC_FSR(base)) & EEFC_FSR_FRDY)) - if(target_check_error(t)) - return -1; + if (target_check_error(t)) + return false; - uint32_t sr = target_mem_read32(t, EEFC_FSR(base)); - return sr & EEFC_FSR_ERROR; + return !(target_mem_read32(t, EEFC_FSR(base)) & EEFC_FSR_ERROR); } static enum sam_driver sam_driver(target *t) @@ -535,7 +531,7 @@ static enum sam_driver sam_driver(target *t) return DRIVER_SAMX7X; } -static int sam_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) +static bool sam_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) { target *t = f->t; uint32_t base = ((struct sam_flash *)f)->eefc_base; @@ -549,8 +545,8 @@ static int sam_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) while (len) { int16_t arg = chunk | 0x1; - if(sam_flash_cmd(t, base, EEFC_FCR_FCMD_EPA, arg)) - return -1; + if(!sam_flash_cmd(t, base, EEFC_FCR_FCMD_EPA, arg)) + return false; if (len > f->blocksize) len -= f->blocksize; @@ -558,19 +554,22 @@ static int sam_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) len = 0; chunk += 8; } - return 0; + return true; } -static int sam3_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) +static bool sam3_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) { /* The SAM3X/SAM3N don't really have a page erase function. * We do nothing here and use Erase/Write page in flash_write. */ - (void)f; (void)addr; (void)len; - return 0; + (void)f; + (void)addr; + (void)len; + + return true; } -static int sam_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len) +static bool sam_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len) { target *t = f->t; struct sam_flash *sf = (struct sam_flash *)f; @@ -578,15 +577,13 @@ static int sam_flash_write(target_flash_s *f, target_addr_t dest, const void *sr unsigned chunk = (dest - f->start) / f->writesize; target_mem_write(t, dest, src, len); - if(sam_flash_cmd(t, base, sf->write_cmd, chunk)) - return -1; - return 0; + return sam_flash_cmd(t, base, sf->write_cmd, chunk); } static int sam_gpnvm_get(target *t, uint32_t base, uint32_t *gpnvm) { - if(!gpnvm || sam_flash_cmd(t, base, EEFC_FCR_FCMD_GGPB, 0)) + if(!gpnvm || !sam_flash_cmd(t, base, EEFC_FCR_FCMD_GGPB, 0)) return -1; *gpnvm = target_mem_read32(t, EEFC_FRR(base)); @@ -652,7 +649,7 @@ static bool sam_cmd_gpnvm(target *t, int argc, const char **argv) { if (work_mask & 1) { uint8_t cmd = (work_values & 1) ? EEFC_FCR_FCMD_SGPB : EEFC_FCR_FCMD_CGPB; - if(sam_flash_cmd(t, base, cmd, bit)) + if(!sam_flash_cmd(t, base, cmd, bit)) return false; } work_mask >>= 1; diff --git a/src/target/sam4l.c b/src/target/sam4l.c index 6ea8a5f..254243f 100644 --- a/src/target/sam4l.c +++ b/src/target/sam4l.c @@ -103,8 +103,8 @@ #define FLASHCALW_FGPFRLO (FLASHCALW_BASE + 0x18) static void sam4l_extended_reset(target *t); -static int sam4l_flash_erase(target_flash_s *f, target_addr_t addr, size_t len); -static int sam4l_flash_write_buf(target_flash_s *f, target_addr_t dest, const void *src, size_t len); +static bool sam4l_flash_erase(target_flash_s *f, target_addr_t addr, size_t len); +static bool sam4l_flash_write_buf(target_flash_s *f, target_addr_t dest, const void *src, size_t len); /* why Atmel couldn't make it sequential ... */ static const size_t __ram_size[16] = { @@ -159,7 +159,7 @@ static const size_t __nvp_size[16] = { /* Arbitrary time to wait for FLASH controller to be ready */ -#define FLASH_TIMEOUT 10000 +#define FLASH_TIMEOUT 1000 /* ms */ /* * Populate a target_flash struct with the necessary function pointers @@ -292,63 +292,55 @@ sam4l_extended_reset(target *t) * Need the target struct to call the mem_read32 and mem_write32 function * pointers. */ -static int -sam4l_flash_command(target *t, uint32_t page, uint32_t cmd) +static bool sam4l_flash_command(target *t, uint32_t page, uint32_t cmd) { - uint32_t cmd_reg; - uint32_t status; - int timeout; - DEBUG_INFO("\nSAM4L: sam4l_flash_command: FSR: 0x%08x, page = %d, " - "command = %d\n", (unsigned int)(FLASHCALW_FSR), - (int) page, (int) cmd); + DEBUG_INFO( + "\nSAM4L: sam4l_flash_command: FSR: 0x%08" PRIx32 ", page = %lu, command = %lu\n", FLASHCALW_FSR, page, cmd); + /* wait for Flash controller ready */ - for (timeout = 0; timeout < FLASH_TIMEOUT; timeout++) { - status = target_mem_read32(t, FLASHCALW_FSR); - if (status & FLASHCALW_FSR_FRDY) { - break; + platform_timeout timeout; + platform_timeout_set(&timeout, FLASH_TIMEOUT); + while (!(target_mem_read32(t, FLASHCALW_FSR) & FLASHCALW_FSR_FRDY)) { + if (platform_timeout_is_expired(&timeout)) { + DEBUG_WARN("\nSAM4L: sam4l_flash_command: Not ready!\n"); + return false; } } - if (timeout == FLASH_TIMEOUT) { - DEBUG_WARN("\nSAM4L: sam4l_flash_command: Not ready! " - "Status = 0x%08x\n", (unsigned int) status); - return -1; /* Failed */ - } + /* load up the new command */ - cmd_reg = (cmd & FLASHCALW_FCMD_CMD_MASK) | - ((page & FLASHCALW_FCMD_PAGEN_MASK) << FLASHCALW_FCMD_PAGEN_SHIFT) | - (0xA5 << FLASHCALW_FCMD_KEY_SHIFT); - DEBUG_INFO("\nSAM4L: sam4l_flash_command: Wrting command word 0x%08x\n", - (unsigned int) cmd_reg); + const uint32_t cmd_reg = (cmd & FLASHCALW_FCMD_CMD_MASK) | + ((page & FLASHCALW_FCMD_PAGEN_MASK) << FLASHCALW_FCMD_PAGEN_SHIFT) | + (0xA5U << FLASHCALW_FCMD_KEY_SHIFT); + + DEBUG_INFO("\nSAM4L: sam4l_flash_command: Wrting command word 0x%08" PRIx32 "\n", cmd_reg); + /* and kick it off */ target_mem_write32(t, FLASHCALW_FCMD, cmd_reg); + /* don't actually wait for it to finish, the next command will stall if it is not done */ - return 0; + return true; } /* * Write data from 'src' into flash using the algorithim provided by * Atmel in their data sheet. */ -static int sam4l_flash_write_buf(target_flash_s *f, target_addr_t addr, const void *src, size_t len) +static bool sam4l_flash_write_buf(target_flash_s *f, target_addr_t addr, const void *src, size_t len) { target *t = f->t; uint32_t *src_data = (uint32_t *)src; - uint32_t ndx; - uint16_t page; - DEBUG_INFO("\nSAM4L: sam4l_flash_write_buf: addr = 0x%08lx, len %d\n", - (long unsigned int) addr, (int) len); + DEBUG_INFO("\nSAM4L: sam4l_flash_write_buf: addr = 0x%08" PRIx32 ", len %d\n", addr, len); + /* This will fail with unaligned writes, the write_buf version */ - page = addr / SAM4L_PAGE_SIZE; + const uint16_t page = addr / SAM4L_PAGE_SIZE; - if (len != SAM4L_PAGE_SIZE) { - return -1; - } + if (len != SAM4L_PAGE_SIZE) + return false; /* clear the page buffer */ - if (sam4l_flash_command(t, 0, FLASH_CMD_CPB)) { - return -1; - } + if (!sam4l_flash_command(t, 0, FLASH_CMD_CPB)) + return false; /* Now fill page buffer with our 512 bytes of data */ @@ -356,7 +348,7 @@ static int sam4l_flash_write_buf(target_flash_s *f, target_addr_t addr, const vo * last 64 bits (8 bytes) to be incorrect on even pages (0, 2, 4, ...) * since it works this way I've not investigated further. */ - for (ndx = 0; ndx < SAM4L_PAGE_SIZE; ndx += 4) { + for (size_t ndx = 0; ndx < SAM4L_PAGE_SIZE; ndx += 4) { /* * the page buffer overlaps flash, its only 512 bytes long * and no matter where you write it from it goes to the page @@ -364,26 +356,23 @@ static int sam4l_flash_write_buf(target_flash_s *f, target_addr_t addr, const vo * instead we just write 0 - pagelen (512) and that fills our * buffer correctly. */ - target_mem_write32(t, addr+ndx, *src_data); + target_mem_write32(t, addr + ndx, *src_data); src_data++; } + /* write the page */ - if (sam4l_flash_command(t, page, FLASH_CMD_WP)) { - return -1; - } - return 0; + return sam4l_flash_command(t, page, FLASH_CMD_WP); } /* * Erase flash across the addresses specified by addr and len */ -static int sam4l_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) +static bool sam4l_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) { target *t = f->t; uint16_t page; - DEBUG_INFO("SAM4L: flash erase address 0x%08x for %d bytes\n", - (unsigned int) addr, (unsigned int) len); + DEBUG_INFO("SAM4L: flash erase address 0x%08" PRIx32 " for %d bytes\n", addr, len); /* * NB: if addr isn't aligned to a page boundary, or length * is not an even multiple of page sizes, we may end up @@ -392,14 +381,15 @@ static int sam4l_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) while (len) { page = addr / SAM4L_PAGE_SIZE; - if (sam4l_flash_command(t, page, FLASH_CMD_EP)) { - return -1; - } + if (!sam4l_flash_command(t, page, FLASH_CMD_EP)) + return false; + if (len > SAM4L_PAGE_SIZE) len -= SAM4L_PAGE_SIZE; else len = 0; + addr += SAM4L_PAGE_SIZE; } - return 0; + return true; } diff --git a/src/target/samd.c b/src/target/samd.c index d0c656e..d8c0394 100644 --- a/src/target/samd.c +++ b/src/target/samd.c @@ -39,8 +39,8 @@ #include "target_internal.h" #include "cortexm.h" -static int samd_flash_erase(target_flash_s *f, target_addr_t addr, size_t len); -static int samd_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len); +static bool samd_flash_erase(target_flash_s *f, target_addr_t addr, size_t len); +static bool samd_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len); bool samd_mass_erase(target *t); static bool samd_cmd_lock_flash(target *t, int argc, const char **argv); @@ -579,7 +579,7 @@ static void samd_unlock_current_address(target *t) /* * Erase flash row by row */ -static int samd_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) +static bool samd_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) { target *t = f->t; while (len) { @@ -596,7 +596,7 @@ static int samd_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) /* Poll for NVM Ready */ while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) if (target_check_error(t)) - return -1; + return false; /* Lock */ samd_lock_current_address(t); @@ -608,14 +608,13 @@ static int samd_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) len = 0; } - return 0; + return true; } /* * Write flash page by page */ -static int samd_flash_write(target_flash_s *f, - target_addr_t dest, const void *src, size_t len) +static bool samd_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len) { target *t = f->t; @@ -632,12 +631,12 @@ static int samd_flash_write(target_flash_s *f, /* Poll for NVM Ready */ while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) if (target_check_error(t)) - return -1; + return false; /* Lock */ samd_lock_current_address(t); - return 0; + return true; } /* diff --git a/src/target/samx5x.c b/src/target/samx5x.c index faeae8c..f41cbce 100644 --- a/src/target/samx5x.c +++ b/src/target/samx5x.c @@ -38,8 +38,8 @@ #include "target_internal.h" #include "cortexm.h" -static int samx5x_flash_erase(target_flash_s *f, target_addr_t addr, size_t len); -static int samx5x_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len); +static bool samx5x_flash_erase(target_flash_s *f, target_addr_t addr, size_t len); +static bool samx5x_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len); static bool samx5x_cmd_lock_flash(target *t, int argc, const char **argv); static bool samx5x_cmd_unlock_flash(target *t, int argc, const char **argv); static bool samx5x_cmd_unlock_bootprot(target *t, int argc, const char **argv); @@ -496,7 +496,7 @@ static int samx5x_check_nvm_error(target *t) /** * Erase flash block by block */ -static int samx5x_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) +static bool samx5x_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) { target *t = f->t; uint16_t errs = samx5x_read_nvm_error(t); @@ -517,12 +517,12 @@ static int samx5x_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) if (addr < (15 - bootprot) * 8192) { DEBUG_WARN("Bootprot\n"); - return -1; + return false; } if (~runlock & (1 << addr / lock_region_size)) { DEBUG_WARN("runlock\n"); - return -1; + return false; } while (len) { @@ -541,12 +541,12 @@ static int samx5x_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) SAMX5X_STATUS_READY) == 0) if (target_check_error(t) || samx5x_check_nvm_error(t)) { DEBUG_WARN("NVM Ready\n"); - return -1; + return false; } if (target_check_error(t) || samx5x_check_nvm_error(t)) { DEBUG_WARN("Error\n"); - return -1; + return false; } /* Lock */ @@ -556,13 +556,13 @@ static int samx5x_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) len -= f->blocksize; } - return 0; + return true; } /** * Write flash page by page */ -static int samx5x_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len) +static bool samx5x_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len) { target *t = f->t; bool error = false; @@ -595,13 +595,13 @@ static int samx5x_flash_write(target_flash_s *f, target_addr_t dest, const void if (error || target_check_error(t) || samx5x_check_nvm_error(t)) { DEBUG_WARN("Error writing flash page at 0x%08"PRIx32 " (len 0x%08zx)\n", dest, len); - return -1; + return false; } /* Lock */ samx5x_lock_current_address(t); - return 0; + return true; } /**