* Copyright (C) 2011 by Olivier Schonken (at91sam3x* support) * *
* and Jim Norris *
* This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General public License as published by *
+ * it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS for A PARTICULAR PURPOSE. See the *
- * GNU General public License for more details. *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
* *
- * You should have received a copy of the GNU General public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
****************************************************************************/
/* Some of the the lower level code was based on code supplied by
#define offset_EFC_FSR 8
#define offset_EFC_FRR 12
-extern struct flash_driver at91sam3_flash;
+extern const struct flash_driver at91sam3_flash;
static float _tomhz(uint32_t freq_hz)
{
static struct sam3_chip *all_sam3_chips;
-static struct sam3_chip *get_current_sam3(struct command_context *cmd_ctx)
+static struct sam3_chip *get_current_sam3(struct command_invocation *cmd)
{
struct target *t;
static struct sam3_chip *p;
- t = get_current_target(cmd_ctx);
+ t = get_current_target(cmd->ctx);
if (!t) {
- command_print(cmd_ctx, "No current target?");
+ command_print(cmd, "No current target?");
return NULL;
}
if (!p) {
/* this should not happen */
/* the command is not registered until the chip is created? */
- command_print(cmd_ctx, "No SAM3 chips exist?");
+ command_print(cmd, "No SAM3 chips exist?");
return NULL;
}
return p;
p = p->next;
}
- command_print(cmd_ctx, "Cannot find SAM3 chip?");
+ command_print(cmd, "Cannot find SAM3 chip?");
return NULL;
}
},
},
+ {
+ .chipid_cidr = 0x29480360,
+ .name = "at91sam3n0b",
+ .total_flash_size = 32 * 1024,
+ .total_sram_size = 8 * 1024,
+ .n_gpnvms = 3,
+ .n_banks = 1,
+
+/* .bank[0] = { */
+ {
+ {
+ .probed = 0,
+ .pChip = NULL,
+ .pBank = NULL,
+ .bank_number = 0,
+ .base_address = FLASH_BANK_BASE_N,
+ .controller_address = 0x400e0A00,
+ .flash_wait_states = 6, /* workaround silicon bug */
+ .present = 1,
+ .size_bytes = 32 * 1024,
+ .nsectors = 2,
+ .sector_size = 16384,
+ .page_size = 256,
+ },
+
+/* .bank[1] = { */
+ {
+ .present = 0,
+ .probed = 0,
+ .bank_number = 1,
+ },
+ },
+ },
+
+ {
+ .chipid_cidr = 0x29380360,
+ .name = "at91sam3n0a",
+ .total_flash_size = 32 * 1024,
+ .total_sram_size = 8 * 1024,
+ .n_gpnvms = 3,
+ .n_banks = 1,
+
+/* .bank[0] = { */
+ {
+ {
+ .probed = 0,
+ .pChip = NULL,
+ .pBank = NULL,
+ .bank_number = 0,
+ .base_address = FLASH_BANK_BASE_N,
+ .controller_address = 0x400e0A00,
+ .flash_wait_states = 6, /* workaround silicon bug */
+ .present = 1,
+ .size_bytes = 32 * 1024,
+ .nsectors = 2,
+ .sector_size = 16384,
+ .page_size = 256,
+ },
+
+/* .bank[1] = { */
+ {
+ .present = 0,
+ .probed = 0,
+ .bank_number = 1,
+ },
+ },
+ },
+
+ {
+ .chipid_cidr = 0x29450260,
+ .name = "at91sam3n00b",
+ .total_flash_size = 16 * 1024,
+ .total_sram_size = 4 * 1024,
+ .n_gpnvms = 3,
+ .n_banks = 1,
+
+/* .bank[0] = { */
+ {
+ {
+ .probed = 0,
+ .pChip = NULL,
+ .pBank = NULL,
+ .bank_number = 0,
+ .base_address = FLASH_BANK_BASE_N,
+ .controller_address = 0x400e0A00,
+ .flash_wait_states = 6, /* workaround silicon bug */
+ .present = 1,
+ .size_bytes = 16 * 1024,
+ .nsectors = 1,
+ .sector_size = 16384,
+ .page_size = 256,
+ },
+
+/* .bank[1] = { */
+ {
+ .present = 0,
+ .probed = 0,
+ .bank_number = 1,
+ },
+ },
+ },
+
+ {
+ .chipid_cidr = 0x29350260,
+ .name = "at91sam3n00a",
+ .total_flash_size = 16 * 1024,
+ .total_sram_size = 4 * 1024,
+ .n_gpnvms = 3,
+ .n_banks = 1,
+
+/* .bank[0] = { */
+ {
+ {
+ .probed = 0,
+ .pChip = NULL,
+ .pBank = NULL,
+ .bank_number = 0,
+ .base_address = FLASH_BANK_BASE_N,
+ .controller_address = 0x400e0A00,
+ .flash_wait_states = 6, /* workaround silicon bug */
+ .present = 1,
+ .size_bytes = 16 * 1024,
+ .nsectors = 1,
+ .sector_size = 16384,
+ .page_size = 256,
+ },
+
+/* .bank[1] = { */
+ {
+ .present = 0,
+ .probed = 0,
+ .bank_number = 1,
+ },
+ },
+ },
+
+
/* Start at91sam3a series*/
/* System boots at address 0x0 */
/* gpnvm[1] = selects boot code */
int r;
uint32_t v;
- long long ms_now, ms_end;
+ int64_t ms_now, ms_end;
/* default */
if (status)
_unknown, /* 0 */
"arm946es", /* 1 */
"arm7tdmi", /* 2 */
- "cortex-m3", /* 3 */
+ "Cortex-M3", /* 3 */
"arm920t", /* 4 */
"arm926ejs", /* 5 */
_unknown, /* 6 */
return ERROR_OK;
}
-static int sam3_erase_check(struct flash_bank *bank)
-{
- int x;
-
- LOG_DEBUG("Here");
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
- if (0 == bank->num_sectors) {
- LOG_ERROR("Target: not supported/not probed");
- return ERROR_FAIL;
- }
-
- LOG_INFO("sam3 - supports auto-erase, erase_check ignored");
- for (x = 0; x < bank->num_sectors; x++)
- bank->sectors[x].is_erased = 1;
-
- LOG_DEBUG("Done");
- return ERROR_OK;
-}
-
static int sam3_protect_check(struct flash_bank *bank)
{
int r;
return ERROR_OK;
}
+/**
+ * Remove all chips from the internal list without distingushing which one
+ * is owned by this bank. This simplification works only for one shot
+ * deallocation like current flash_free_all_banks()
+ */
+void sam3_free_driver_priv(struct flash_bank *bank)
+{
+ struct sam3_chip *chip = all_sam3_chips;
+ while (chip) {
+ struct sam3_chip *next = chip->next;
+ free(chip);
+ chip = next;
+ }
+ all_sam3_chips = NULL;
+}
+
static int sam3_GetDetails(struct sam3_bank_private *pPrivate)
{
const struct sam3_chip_details *pDetails;
pDetails = all_sam3_details;
while (pDetails->name) {
/* Compare cidr without version bits */
- if (pDetails->chipid_cidr == (pPrivate->pChip->cfg.CHIPID_CIDR & 0xFFFFFFE0))
+ if (((pDetails->chipid_cidr ^ pPrivate->pChip->cfg.CHIPID_CIDR) & 0xFFFFFFE0) == 0)
break;
else
pDetails++;
return r;
}
-/* The code below is basically this: */
-/* compiled with */
-/* arm-none-eabi-gcc -mthumb -mcpu = cortex-m3 -O9 -S ./foobar.c -o foobar.s */
-/* */
-/* Only the *CPU* can write to the flash buffer. */
-/* the DAP cannot... so - we download this 28byte thing */
-/* Run the algorithm - (below) */
-/* to program the device */
-/* */
-/* ======================================== */
-/* #include <stdint.h> */
-/* */
-/* struct foo { */
-/* uint32_t *dst; */
-/* const uint32_t *src; */
-/* int n; */
-/* volatile uint32_t *base; */
-/* uint32_t cmd; */
-/* }; */
-/* */
-/* */
-/* uint32_t sam3_function(struct foo *p) */
-/* { */
-/* volatile uint32_t *v; */
-/* uint32_t *d; */
-/* const uint32_t *s; */
-/* int n; */
-/* uint32_t r; */
-/* */
-/* d = p->dst; */
-/* s = p->src; */
-/* n = p->n; */
-/* */
-/* do { */
-/* *d++ = *s++; */
-/* } while (--n) */
-/* ; */
-/* */
-/* v = p->base; */
-/* */
-/* v[ 1 ] = p->cmd; */
-/* do { */
-/* r = v[8/4]; */
-/* } while (!(r&1)) */
-/* ; */
-/* return r; */
-/* } */
-/* ======================================== */
-
-static const uint8_t
- sam3_page_write_opcodes[] = {
- /* 24 0000 0446 mov r4, r0 */
- 0x04, 0x46,
- /* 25 0002 6168 ldr r1, [r4, #4] */
- 0x61, 0x68,
- /* 26 0004 0068 ldr r0, [r0, #0] */
- 0x00, 0x68,
- /* 27 0006 A268 ldr r2, [r4, #8] */
- 0xa2, 0x68,
- /* 28 @ lr needed for prologue */
- /* 29 .L2: */
- /* 30 0008 51F8043B ldr r3, [r1], #4 */
- 0x51, 0xf8, 0x04, 0x3b,
- /* 31 000c 12F1FF32 adds r2, r2, #-1 */
- 0x12, 0xf1, 0xff, 0x32,
- /* 32 0010 40F8043B str r3, [r0], #4 */
- 0x40, 0xf8, 0x04, 0x3b,
- /* 33 0014 F8D1 bne .L2 */
- 0xf8, 0xd1,
- /* 34 0016 E268 ldr r2, [r4, #12] */
- 0xe2, 0x68,
- /* 35 0018 2369 ldr r3, [r4, #16] */
- 0x23, 0x69,
- /* 36 001a 5360 str r3, [r2, #4] */
- 0x53, 0x60,
- /* 37 001c 0832 adds r2, r2, #8 */
- 0x08, 0x32,
- /* 38 .L4: */
- /* 39 001e 1068 ldr r0, [r2, #0] */
- 0x10, 0x68,
- /* 40 0020 10F0010F tst r0, #1 */
- 0x10, 0xf0, 0x01, 0x0f,
- /* 41 0024 FBD0 beq .L4 */
- 0xfb, 0xd0,
- 0x00, 0xBE /* bkpt #0 */
-};
-
static int sam3_page_write(struct sam3_bank_private *pPrivate, unsigned pagenum, const uint8_t *buf)
{
uint32_t adr;
COMMAND_HANDLER(sam3_handle_info_command)
{
struct sam3_chip *pChip;
- pChip = get_current_sam3(CMD_CTX);
+ pChip = get_current_sam3(CMD);
if (!pChip)
return ERROR_OK;
if (pChip->details.bank[0].pBank == NULL) {
x = 0;
need_define:
- command_print(CMD_CTX,
+ command_print(CMD,
"Please define bank %d via command: flash bank %s ... ",
x,
at91sam3_flash.name);
int r, who;
struct sam3_chip *pChip;
- pChip = get_current_sam3(CMD_CTX);
+ pChip = get_current_sam3(CMD);
if (!pChip)
return ERROR_OK;
}
if (pChip->details.bank[0].pBank == NULL) {
- command_print(CMD_CTX, "Bank0 must be defined first via: flash bank %s ...",
+ command_print(CMD, "Bank0 must be defined first via: flash bank %s ...",
at91sam3_flash.name);
return ERROR_FAIL;
}
r = FLASHD_GetGPNVM(&(pChip->details.bank[0]), x, &v);
if (r != ERROR_OK)
break;
- command_print(CMD_CTX, "sam3-gpnvm%u: %u", x, v);
+ command_print(CMD, "sam3-gpnvm%u: %u", x, v);
}
return r;
}
if ((who >= 0) && (((unsigned)(who)) < pChip->details.n_gpnvms)) {
r = FLASHD_GetGPNVM(&(pChip->details.bank[0]), who, &v);
- command_print(CMD_CTX, "sam3-gpnvm%u: %u", who, v);
+ command_print(CMD, "sam3-gpnvm%u: %u", who, v);
return r;
} else {
- command_print(CMD_CTX, "sam3-gpnvm invalid GPNVM: %u", who);
+ command_print(CMD, "sam3-gpnvm invalid GPNVM: %u", who);
return ERROR_COMMAND_SYNTAX_ERROR;
}
}
if (who == -1) {
- command_print(CMD_CTX, "Missing GPNVM number");
+ command_print(CMD, "Missing GPNVM number");
return ERROR_COMMAND_SYNTAX_ERROR;
}
(0 == strcmp("clear", CMD_ARGV[0]))) /* quietly accept both */
r = FLASHD_ClrGPNVM(&(pChip->details.bank[0]), who);
else {
- command_print(CMD_CTX, "Unknown command: %s", CMD_ARGV[0]);
+ command_print(CMD, "Unknown command: %s", CMD_ARGV[0]);
r = ERROR_COMMAND_SYNTAX_ERROR;
}
return r;
{
struct sam3_chip *pChip;
- pChip = get_current_sam3(CMD_CTX);
+ pChip = get_current_sam3(CMD);
if (!pChip)
return ERROR_OK;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], v);
if (v > 200000) {
/* absurd slow clock of 200Khz? */
- command_print(CMD_CTX, "Absurd/illegal slow clock freq: %d\n", (int)(v));
+ command_print(CMD, "Absurd/illegal slow clock freq: %d\n", (int)(v));
return ERROR_COMMAND_SYNTAX_ERROR;
}
pChip->cfg.slow_freq = v;
}
default:
/* error */
- command_print(CMD_CTX, "Too many parameters");
+ command_print(CMD, "Too many parameters");
return ERROR_COMMAND_SYNTAX_ERROR;
break;
}
- command_print(CMD_CTX, "Slowclk freq: %d.%03dkhz",
+ command_print(CMD, "Slowclk freq: %d.%03dkhz",
(int)(pChip->cfg.slow_freq / 1000),
(int)(pChip->cfg.slow_freq % 1000));
return ERROR_OK;
.mode = COMMAND_EXEC,
.help = "Print information about the current at91sam3 chip"
"and its flash configuration.",
+ .usage = "",
},
{
.name = "slowclk",
COMMAND_REGISTRATION_DONE
};
-struct flash_driver at91sam3_flash = {
+const struct flash_driver at91sam3_flash = {
.name = "at91sam3",
.commands = at91sam3_command_handlers,
.flash_bank_command = sam3_flash_bank_command,
.read = default_flash_read,
.probe = sam3_probe,
.auto_probe = sam3_auto_probe,
- .erase_check = sam3_erase_check,
+ .erase_check = default_flash_blank_check,
.protect_check = sam3_protect_check,
+ .free_driver_priv = sam3_free_driver_priv,
};