target/sam: flash read write return bool

This commit is contained in:
Rafael Silva 2022-08-24 12:38:51 +01:00 committed by Rachel Mant
parent 44f7984c58
commit 67c9f3f6e2
4 changed files with 85 additions and 99 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}
/*

View File

@ -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;
}
/**