#include "imp.h"
#include "helper/binarybuffer.h"
+#include <helper/time_support.h>
#include <target/cortex_m.h>
/* A note to prefixing.
- * Definitions and functions ingerited from at91samd.c without
- * any change retained the original prefix samd_ so they eventualy
+ * Definitions and functions inherited from at91samd.c without
+ * any change retained the original prefix samd_ so they eventually
* may go to samd_common.h and .c
- * As currently there are olny 3 short functions identical with
+ * As currently there are only 3 short functions identical with
* the original source, no common file was created. */
#define SAME5_PAGES_PER_BLOCK 16
};
/* See SAM D5x/E5x Family Silicon Errata and Data Sheet Clarification
- * DS80000748B */
+ * DS80000748K */
/* Known SAMD51 parts. */
static const struct samd_part samd51_parts[] = {
{ 0x00, "SAMD51P20A", 1024, 256 },
{ 0x02, "SAME51J19A", 512, 192 },
{ 0x03, "SAME51J18A", 256, 128 },
{ 0x04, "SAME51J20A", 1024, 256 },
+ { 0x05, "SAME51G19A", 512, 192 }, /* New in rev D */
+ { 0x06, "SAME51G18A", 256, 128 }, /* New in rev D */
};
/* Known SAME53 parts. */
static int same5_protect_check(struct flash_bank *bank)
{
- int res, prot_block;
+ int res;
uint32_t lock;
res = target_read_u32(bank->target,
return res;
/* Lock bits are active-low */
- for (prot_block = 0; prot_block < bank->num_prot_blocks; prot_block++)
+ for (unsigned int prot_block = 0; prot_block < bank->num_prot_blocks; prot_block++)
bank->prot_blocks[prot_block].is_protected = !(lock & (1u<<prot_block));
return ERROR_OK;
static int same5_wait_and_check_error(struct target *target)
{
int ret, ret2;
- int rep_cnt = 100;
+ /* Table 54-40 lists the maximum erase block time as 200 ms.
+ * Include some margin.
+ */
+ int timeout_ms = 200 * 5;
+ int64_t ts_start = timeval_ms();
uint16_t intflag;
do {
ret = target_read_u16(target,
SAMD_NVMCTRL + SAME5_NVMCTRL_INTFLAG, &intflag);
- if (ret == ERROR_OK && intflag & SAME5_NVMCTRL_INTFLAG_DONE)
+ if (ret != ERROR_OK) {
+ LOG_ERROR("SAM: error reading the NVMCTRL_INTFLAG register");
+ return ret;
+ }
+ if (intflag & SAME5_NVMCTRL_INTFLAG_DONE)
break;
- } while (--rep_cnt);
+ keep_alive();
+ } while (timeval_ms() - ts_start < timeout_ms);
- if (ret != ERROR_OK) {
- LOG_ERROR("Can't read NVM INTFLAG");
- return ret;
+ if (!(intflag & SAME5_NVMCTRL_INTFLAG_DONE)) {
+ LOG_ERROR("SAM: NVM programming timed out");
+ ret = ERROR_FLASH_OPERATION_FAILED;
}
#if 0
if (intflag & SAME5_NVMCTRL_INTFLAG_ECCSE)
buf_val, buf_mask, 0, 8);
}
-static int same5_protect(struct flash_bank *bank, int set, int first_prot_bl, int last_prot_bl)
+static int same5_protect(struct flash_bank *bank, int set, unsigned int first,
+ unsigned int last)
{
int res = ERROR_OK;
- int prot_block;
/* We can issue lock/unlock region commands with the target running but
* the settings won't persist unless we're able to modify the LOCK regions
return ERROR_TARGET_NOT_HALTED;
}
- for (prot_block = first_prot_bl; prot_block <= last_prot_bl; prot_block++) {
+ for (unsigned int prot_block = first; prot_block <= last; prot_block++) {
if (set != bank->prot_blocks[prot_block].is_protected) {
/* Load an address that is within this protection block (we use offset 0) */
res = target_write_u32(bank->target,
const uint8_t unlock[4] = { 0xff, 0xff, 0xff, 0xff };
uint8_t mask[4] = { 0, 0, 0, 0 };
- buf_set_u32(mask, first_prot_bl, last_prot_bl + 1 - first_prot_bl, 0xffffffff);
+ buf_set_u32(mask, first, last + 1 - first, 0xffffffff);
res = same5_modify_user_row_masked(bank->target,
set ? lock : unlock, mask, 8, 4);
return res;
}
-static int same5_erase(struct flash_bank *bank, int first_sect, int last_sect)
+static int same5_erase(struct flash_bank *bank, unsigned int first,
+ unsigned int last)
{
- int res, s;
+ int res;
struct samd_info *chip = (struct samd_info *)bank->driver_priv;
if (bank->target->state != TARGET_HALTED) {
return ERROR_FLASH_BANK_NOT_PROBED;
/* For each sector to be erased */
- for (s = first_sect; s <= last_sect; s++) {
+ for (unsigned int s = first; s <= last; s++) {
res = same5_erase_block(bank->target, bank->sectors[s].offset);
if (res != ERROR_OK) {
LOG_ERROR("SAM: failed to erase sector %d at 0x%08" PRIx32, s, bank->sectors[s].offset);
}
free_pb:
- if (pb)
- free(pb);
-
+ free(pb);
return res;
}
{
if (bank->base != SAMD_FLASH) {
LOG_ERROR("Address " TARGET_ADDR_FMT " invalid bank address (try "
- "0x%08" PRIx32 "[same5] )", bank->base, SAMD_FLASH);
+ "0x%08x[same5] )", bank->base, SAMD_FLASH);
return ERROR_FAIL;
}
* perform the erase. */
int res = target_write_u8(target, SAMD_DSU + SAMD_DSU_CTRL_EXT, (1<<4));
if (res == ERROR_OK)
- command_print(CMD_CTX, "chip erase started");
+ command_print(CMD, "chip erase started");
else
- command_print(CMD_CTX, "write to DSU CTRL failed");
+ command_print(CMD, "write to DSU CTRL failed");
return res;
}
return ERROR_FAIL;
if (CMD_ARGC > 2) {
- command_print(CMD_CTX, "Too much Arguments given.");
+ command_print(CMD, "Too much Arguments given.");
return ERROR_COMMAND_SYNTAX_ERROR;
}
int res2 = target_read_memory(target, SAMD_USER_ROW, 4, 2, buffer);
if (res2 == ERROR_OK) {
uint64_t value = target_buffer_get_u64(target, buffer);
- command_print(CMD_CTX, "USER PAGE: 0x%016"PRIX64, value);
+ command_print(CMD, "USER PAGE: 0x%016"PRIX64, value);
} else {
LOG_ERROR("USER PAGE could not be read.");
}
unsigned long size = strtoul(CMD_ARGV[0], NULL, 0);
uint32_t code = (size + 8191) / 8192;
if (code > 15) {
- command_print(CMD_CTX, "Invalid bootloader size. Please "
+ command_print(CMD, "Invalid bootloader size. Please "
"see datasheet for a list valid sizes.");
return ERROR_COMMAND_SYNTAX_ERROR;
}
if (res2 == ERROR_OK) {
uint32_t code = (val >> 26) & 0xf; /* grab size code */
uint32_t size = (15 - code) * 8192;
- command_print(CMD_CTX, "Bootloader protected in the first %"
+ command_print(CMD, "Bootloader protected in the first %"
PRIu32 " bytes", size);
}
static const struct command_registration same5_exec_command_handlers[] = {
{
.name = "dsu_reset_deassert",
+ .usage = "",
.handler = samd_handle_reset_deassert,
.mode = COMMAND_EXEC,
- .help = "Deasert internal reset held by DSU."
+ .help = "Deassert internal reset held by DSU."
},
{
.name = "chip-erase",
+ .usage = "",
.handler = same5_handle_chip_erase_command,
.mode = COMMAND_EXEC,
.help = "Erase the entire Flash by using the Chip-"
COMMAND_REGISTRATION_DONE
};
-struct flash_driver atsame5_flash = {
+const struct flash_driver atsame5_flash = {
.name = "atsame5",
.commands = same5_command_handlers,
.flash_bank_command = same5_flash_bank_command,