target/sam: flash read write return bool
This commit is contained in:
parent
44f7984c58
commit
67c9f3f6e2
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue