1 // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-Source-Code)
4 * Copyright (C) 2009 by Duane Ellis <openocd@duaneellis.com>
7 * Copyright (C) 2010 by Olaf Lüke <olaf@uni-paderborn.de>
9 * at91sam3x* & at91sam4 support
10 * Copyright (C) 2011 by Olivier Schonken and Jim Norris
12 * atsamv, atsams, and atsame support
13 * Copyright (C) 2015 Morgan Quigley
15 * Some of the lower level code was based on code supplied by
16 * ATMEL under BSD-Source-Code License and this copyright.
17 * ATMEL Microcontroller Software Support
18 * Copyright (c) 2009, Atmel Corporation. All rights reserved.
26 #include <helper/time_support.h>
28 #define REG_NAME_WIDTH (12)
30 #define SAMV_EFC_FCMD_GETD (0x0) /* (EFC) Get Flash Descriptor */
31 #define SAMV_EFC_FCMD_WP (0x1) /* (EFC) Write Page */
32 #define SAMV_EFC_FCMD_WPL (0x2) /* (EFC) Write Page and Lock */
33 #define SAMV_EFC_FCMD_EWP (0x3) /* (EFC) Erase Page and Write Page */
34 #define SAMV_EFC_FCMD_EWPL (0x4) /* (EFC) Erase Page, Write Page then Lock*/
35 #define SAMV_EFC_FCMD_EA (0x5) /* (EFC) Erase All */
36 #define SAMV_EFC_FCMD_EPA (0x7) /* (EFC) Erase pages */
37 #define SAMV_EFC_FCMD_SLB (0x8) /* (EFC) Set Lock Bit */
38 #define SAMV_EFC_FCMD_CLB (0x9) /* (EFC) Clear Lock Bit */
39 #define SAMV_EFC_FCMD_GLB (0xA) /* (EFC) Get Lock Bit */
40 #define SAMV_EFC_FCMD_SFB (0xB) /* (EFC) Set Fuse Bit */
41 #define SAMV_EFC_FCMD_CFB (0xC) /* (EFC) Clear Fuse Bit */
42 #define SAMV_EFC_FCMD_GFB (0xD) /* (EFC) Get Fuse Bit */
44 #define OFFSET_EFC_FMR 0
45 #define OFFSET_EFC_FCR 4
46 #define OFFSET_EFC_FSR 8
47 #define OFFSET_EFC_FRR 12
49 #define SAMV_CHIPID_CIDR (0x400E0940)
50 #define SAMV_NUM_GPNVM_BITS 9
51 #define SAMV_CONTROLLER_ADDR (0x400e0c00)
52 #define SAMV_SECTOR_SIZE 16384
53 #define SAMV_PAGE_SIZE 512
54 #define SAMV_FLASH_BASE 0x00400000
56 extern const struct flash_driver atsamv_flash
;
58 struct samv_flash_bank
{
61 unsigned gpnvm
[SAMV_NUM_GPNVM_BITS
];
64 /* The actual sector size of the SAMV7 flash memory is 128K bytes.
65 * 16 sectors for a 2048KB device. The lock regions are 16KB per lock
66 * region, with a 2048KB device having 128 lock regions.
67 * For the best results, num_sectors is thus set to the number of lock
68 * regions, and the sector_size set to the lock region size. Page
69 * erases are used to erase 16KB sections when programming */
71 static int samv_efc_get_status(struct target
*target
, uint32_t *v
)
73 int r
= target_read_u32(target
, SAMV_CONTROLLER_ADDR
+ OFFSET_EFC_FSR
, v
);
77 static int samv_efc_get_result(struct target
*target
, uint32_t *v
)
80 int r
= target_read_u32(target
, SAMV_CONTROLLER_ADDR
+ OFFSET_EFC_FRR
, &rv
);
86 static int samv_efc_start_command(struct target
*target
,
87 unsigned command
, unsigned argument
)
90 samv_efc_get_status(target
, &v
);
92 LOG_ERROR("flash controller is not ready");
96 v
= (0x5A << 24) | (argument
<< 8) | command
;
97 LOG_DEBUG("starting flash command: 0x%08x", (unsigned int)(v
));
98 int r
= target_write_u32(target
, SAMV_CONTROLLER_ADDR
+ OFFSET_EFC_FCR
, v
);
100 LOG_DEBUG("write failed");
104 static int samv_efc_perform_command(struct target
*target
,
105 unsigned command
, unsigned argument
, uint32_t *status
)
109 int64_t ms_now
, ms_end
;
114 r
= samv_efc_start_command(target
, command
, argument
);
118 ms_end
= 10000 + timeval_ms();
121 r
= samv_efc_get_status(target
, &v
);
124 ms_now
= timeval_ms();
125 if (ms_now
> ms_end
) {
127 LOG_ERROR("Command timeout");
130 } while ((v
& 1) == 0);
132 /* if requested, copy the flash controller error bits back to the caller */
138 static int samv_erase_pages(struct target
*target
,
139 int first_page
, int num_pages
, uint32_t *status
)
161 * According to the datasheet FARG[15:2] defines the page from which
162 * the erase will start.This page must be modulo 4, 8, 16 or 32
163 * according to the number of pages to erase. FARG[1:0] defines the
164 * number of pages to be erased. Previously (firstpage << 2) was used
165 * to conform to this, seems it should not be shifted...
167 return samv_efc_perform_command(target
, SAMV_EFC_FCMD_EPA
,
168 first_page
| erase_pages
, status
);
171 static int samv_get_gpnvm(struct target
*target
, unsigned gpnvm
, unsigned *out
)
176 if (gpnvm
>= SAMV_NUM_GPNVM_BITS
) {
177 LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm
, SAMV_NUM_GPNVM_BITS
);
181 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_GFB
, 0, NULL
);
183 LOG_ERROR("samv_get_gpnvm failed");
187 r
= samv_efc_get_result(target
, &v
);
190 *out
= (v
>> gpnvm
) & 1;
195 static int samv_clear_gpnvm(struct target
*target
, unsigned gpnvm
)
200 if (gpnvm
>= SAMV_NUM_GPNVM_BITS
) {
201 LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm
, SAMV_NUM_GPNVM_BITS
);
204 r
= samv_get_gpnvm(target
, gpnvm
, &v
);
206 LOG_DEBUG("get gpnvm failed: %d", r
);
209 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_CFB
, gpnvm
, NULL
);
210 LOG_DEBUG("clear gpnvm result: %d", r
);
214 static int samv_set_gpnvm(struct target
*target
, unsigned gpnvm
)
218 if (gpnvm
>= SAMV_NUM_GPNVM_BITS
) {
219 LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm
, SAMV_NUM_GPNVM_BITS
);
223 r
= samv_get_gpnvm(target
, gpnvm
, &v
);
227 r
= ERROR_OK
; /* the gpnvm bit is already set */
229 /* we need to set it */
230 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_SFB
, gpnvm
, NULL
);
235 static int samv_flash_unlock(struct target
*target
,
236 unsigned start_sector
, unsigned end_sector
)
241 uint32_t pages_per_sector
;
243 /* todo: look into this... i think this should be done on lock regions */
244 pages_per_sector
= SAMV_SECTOR_SIZE
/ SAMV_PAGE_SIZE
;
245 while (start_sector
<= end_sector
) {
246 pg
= start_sector
* pages_per_sector
;
247 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_CLB
, pg
, &status
);
255 static int samv_flash_lock(struct target
*target
,
256 unsigned start_sector
, unsigned end_sector
)
260 uint32_t pages_per_sector
;
263 /* todo: look into this... i think this should be done on lock regions */
264 pages_per_sector
= SAMV_SECTOR_SIZE
/ SAMV_PAGE_SIZE
;
265 while (start_sector
<= end_sector
) {
266 pg
= start_sector
* pages_per_sector
;
267 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_SLB
, pg
, &status
);
275 static int samv_protect_check(struct flash_bank
*bank
)
280 r
= samv_efc_perform_command(bank
->target
, SAMV_EFC_FCMD_GLB
, 0, NULL
);
282 samv_efc_get_result(bank
->target
, &v
[0]);
283 samv_efc_get_result(bank
->target
, &v
[1]);
284 samv_efc_get_result(bank
->target
, &v
[2]);
285 r
= samv_efc_get_result(bank
->target
, &v
[3]);
290 for (unsigned int x
= 0; x
< bank
->num_sectors
; x
++)
291 bank
->sectors
[x
].is_protected
= (!!(v
[x
>> 5] & (1 << (x
% 32))));
295 FLASH_BANK_COMMAND_HANDLER(samv_flash_bank_command
)
297 LOG_INFO("flash bank command");
298 struct samv_flash_bank
*samv_info
;
299 samv_info
= calloc(1, sizeof(struct samv_flash_bank
));
300 bank
->driver_priv
= samv_info
;
304 static int samv_get_device_id(struct flash_bank
*bank
, uint32_t *device_id
)
306 return target_read_u32(bank
->target
, SAMV_CHIPID_CIDR
, device_id
);
309 static int samv_probe(struct flash_bank
*bank
)
312 int r
= samv_get_device_id(bank
, &device_id
);
315 LOG_INFO("device id = 0x%08" PRIx32
"", device_id
);
317 uint8_t eproc
= (device_id
>> 5) & 0x7;
319 LOG_ERROR("unexpected eproc code: %d was expecting 0 (Cortex-M7)", eproc
);
323 uint8_t nvm_size_code
= (device_id
>> 8) & 0xf;
324 switch (nvm_size_code
) {
326 bank
->size
= 512 * 1024;
329 bank
->size
= 1024 * 1024;
332 bank
->size
= 2048 * 1024;
335 LOG_ERROR("unrecognized flash size code: %d", nvm_size_code
);
339 struct samv_flash_bank
*samv_info
= bank
->driver_priv
;
340 samv_info
->size_bytes
= bank
->size
;
341 samv_info
->probed
= true;
343 bank
->base
= SAMV_FLASH_BASE
;
344 bank
->num_sectors
= bank
->size
/ SAMV_SECTOR_SIZE
;
345 bank
->sectors
= calloc(bank
->num_sectors
, sizeof(struct flash_sector
));
346 for (unsigned int s
= 0; s
< bank
->num_sectors
; s
++) {
347 bank
->sectors
[s
].size
= SAMV_SECTOR_SIZE
;
348 bank
->sectors
[s
].offset
= s
* SAMV_SECTOR_SIZE
;
349 bank
->sectors
[s
].is_erased
= -1;
350 bank
->sectors
[s
].is_protected
= -1;
353 r
= samv_protect_check(bank
);
360 static int samv_auto_probe(struct flash_bank
*bank
)
362 struct samv_flash_bank
*samv_info
= bank
->driver_priv
;
363 if (samv_info
->probed
)
365 return samv_probe(bank
);
368 static int samv_erase(struct flash_bank
*bank
, unsigned int first
,
371 const int page_count
= 32; /* 32 pages equals 16 KB lock region */
373 if (bank
->target
->state
!= TARGET_HALTED
) {
374 LOG_ERROR("Target not halted");
375 return ERROR_TARGET_NOT_HALTED
;
378 int r
= samv_auto_probe(bank
);
382 /* easy case: we've been requested to erase the entire flash */
383 if ((first
== 0) && ((last
+ 1) == bank
->num_sectors
))
384 return samv_efc_perform_command(bank
->target
, SAMV_EFC_FCMD_EA
, 0, NULL
);
386 LOG_INFO("erasing lock regions %u-%u...", first
, last
);
388 for (unsigned int i
= first
; i
<= last
; i
++) {
390 r
= samv_erase_pages(bank
->target
, (i
* page_count
), page_count
, &status
);
391 LOG_INFO("erasing lock region %u", i
);
393 LOG_ERROR("error performing erase page @ lock region number %u", i
);
394 if (status
& (1 << 2)) {
395 LOG_ERROR("lock region %u is locked", i
);
398 if (status
& (1 << 1)) {
399 LOG_ERROR("flash command error @lock region %u", i
);
406 static int samv_protect(struct flash_bank
*bank
, int set
, unsigned int first
,
409 if (bank
->target
->state
!= TARGET_HALTED
) {
410 LOG_ERROR("Target not halted");
411 return ERROR_TARGET_NOT_HALTED
;
416 r
= samv_flash_lock(bank
->target
, first
, last
);
418 r
= samv_flash_unlock(bank
->target
, first
, last
);
423 static int samv_page_read(struct target
*target
,
424 unsigned page_num
, uint8_t *buf
)
426 uint32_t addr
= SAMV_FLASH_BASE
+ page_num
* SAMV_PAGE_SIZE
;
427 int r
= target_read_memory(target
, addr
, 4, SAMV_PAGE_SIZE
/ 4, buf
);
429 LOG_ERROR("flash program failed to read page @ 0x%08x",
430 (unsigned int)(addr
));
434 static int samv_page_write(struct target
*target
,
435 unsigned pagenum
, const uint8_t *buf
)
438 const uint32_t addr
= SAMV_FLASH_BASE
+ pagenum
* SAMV_PAGE_SIZE
;
441 LOG_DEBUG("write page %u at address 0x%08x", pagenum
, (unsigned int)addr
);
442 r
= target_write_memory(target
, addr
, 4, SAMV_PAGE_SIZE
/ 4, buf
);
444 LOG_ERROR("failed to buffer page at 0x%08x", (unsigned int)addr
);
448 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_WP
, pagenum
, &status
);
450 LOG_ERROR("error performing write page at 0x%08x", (unsigned int)addr
);
451 if (status
& (1 << 2)) {
452 LOG_ERROR("page at 0x%08x is locked", (unsigned int)addr
);
455 if (status
& (1 << 1)) {
456 LOG_ERROR("flash command error at 0x%08x", (unsigned int)addr
);
462 static int samv_write(struct flash_bank
*bank
, const uint8_t *buffer
,
463 uint32_t offset
, uint32_t count
)
465 if (bank
->target
->state
!= TARGET_HALTED
) {
466 LOG_ERROR("target not halted");
467 return ERROR_TARGET_NOT_HALTED
;
473 if ((offset
+ count
) > bank
->size
) {
474 LOG_ERROR("flash write error - past end of bank");
475 LOG_ERROR(" offset: 0x%08x, count 0x%08x, bank end: 0x%08x",
476 (unsigned int)(offset
),
477 (unsigned int)(count
),
478 (unsigned int)(bank
->size
));
482 uint8_t pagebuffer
[SAMV_PAGE_SIZE
] = {0};
483 uint32_t page_cur
= offset
/ SAMV_PAGE_SIZE
;
484 uint32_t page_end
= (offset
+ count
- 1) / SAMV_PAGE_SIZE
;
486 LOG_DEBUG("offset: 0x%08x, count: 0x%08x",
487 (unsigned int)(offset
), (unsigned int)(count
));
488 LOG_DEBUG("page start: %d, page end: %d", (int)(page_cur
), (int)(page_end
));
490 /* Special case: all one page */
492 /* (1) non-aligned start */
494 /* (3) non-aligned end. */
497 uint32_t page_offset
;
499 /* handle special case - all one page. */
500 if (page_cur
== page_end
) {
501 LOG_DEBUG("special case, all in one page");
502 r
= samv_page_read(bank
->target
, page_cur
, pagebuffer
);
506 page_offset
= offset
& (SAMV_PAGE_SIZE
-1);
507 memcpy(pagebuffer
+ page_offset
, buffer
, count
);
509 r
= samv_page_write(bank
->target
, page_cur
, pagebuffer
);
515 /* step 1) handle the non-aligned starting address */
516 page_offset
= offset
& (SAMV_PAGE_SIZE
- 1);
518 LOG_DEBUG("non-aligned start");
519 /* read the partial page */
520 r
= samv_page_read(bank
->target
, page_cur
, pagebuffer
);
524 /* over-write with new data */
525 uint32_t n
= SAMV_PAGE_SIZE
- page_offset
;
526 memcpy(pagebuffer
+ page_offset
, buffer
, n
);
528 r
= samv_page_write(bank
->target
, page_cur
, pagebuffer
);
538 /* By checking that offset is correct here, we also fix a clang warning */
539 assert(offset
% SAMV_PAGE_SIZE
== 0);
541 /* step 2) handle the full pages */
542 LOG_DEBUG("full page loop: cur=%d, end=%d, count = 0x%08x",
543 (int)page_cur
, (int)page_end
, (unsigned int)(count
));
545 while ((page_cur
< page_end
) && (count
>= SAMV_PAGE_SIZE
)) {
546 r
= samv_page_write(bank
->target
, page_cur
, buffer
);
549 count
-= SAMV_PAGE_SIZE
;
550 buffer
+= SAMV_PAGE_SIZE
;
554 /* step 3) write final page, if it's partial (otherwise it's already done) */
556 LOG_DEBUG("final partial page, count = 0x%08x", (unsigned int)(count
));
557 /* we have a partial page */
558 r
= samv_page_read(bank
->target
, page_cur
, pagebuffer
);
561 memcpy(pagebuffer
, buffer
, count
); /* data goes at start of page */
562 r
= samv_page_write(bank
->target
, page_cur
, pagebuffer
);
569 static int samv_get_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
571 struct samv_flash_bank
*samv_info
= bank
->driver_priv
;
572 if (!samv_info
->probed
) {
573 int r
= samv_probe(bank
);
577 command_print_sameline(cmd
, "Cortex-M7 detected with %" PRIu32
" kB flash\n",
582 COMMAND_HANDLER(samv_handle_gpnvm_command
)
584 struct flash_bank
*bank
= get_flash_bank_by_num_noprobe(0);
587 struct samv_flash_bank
*samv_info
= bank
->driver_priv
;
588 struct target
*target
= bank
->target
;
590 if (target
->state
!= TARGET_HALTED
) {
591 LOG_ERROR("target not halted");
592 return ERROR_TARGET_NOT_HALTED
;
596 if (!samv_info
->probed
) {
597 r
= samv_auto_probe(bank
);
611 if (!strcmp(CMD_ARGV
[0], "show") && !strcmp(CMD_ARGV
[1], "all"))
615 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], v32
);
620 return ERROR_COMMAND_SYNTAX_ERROR
;
624 if (!strcmp("show", CMD_ARGV
[0])) {
628 for (int x
= 0; x
< SAMV_NUM_GPNVM_BITS
; x
++) {
629 r
= samv_get_gpnvm(target
, x
, &v
);
632 command_print(CMD
, "samv-gpnvm%u: %u", x
, v
);
636 if ((who
>= 0) && (((unsigned)who
) < SAMV_NUM_GPNVM_BITS
)) {
637 r
= samv_get_gpnvm(target
, who
, &v
);
641 command_print(CMD
, "samv-gpnvm%u: %u", who
, v
);
644 command_print(CMD
, "invalid gpnvm: %u", who
);
645 return ERROR_COMMAND_SYNTAX_ERROR
;
650 command_print(CMD
, "missing gpnvm number");
651 return ERROR_COMMAND_SYNTAX_ERROR
;
654 if (!strcmp("set", CMD_ARGV
[0]))
655 r
= samv_set_gpnvm(target
, who
);
656 else if (!strcmp("clr", CMD_ARGV
[0]) || !strcmp("clear", CMD_ARGV
[0]))
657 r
= samv_clear_gpnvm(target
, who
);
659 command_print(CMD
, "unknown command: %s", CMD_ARGV
[0]);
660 r
= ERROR_COMMAND_SYNTAX_ERROR
;
665 static const struct command_registration atsamv_exec_command_handlers
[] = {
668 .handler
= samv_handle_gpnvm_command
,
669 .mode
= COMMAND_EXEC
,
670 .usage
= "[('clr'|'set'|'show') bitnum]",
671 .help
= "Without arguments, shows all bits in the gpnvm "
672 "register. Otherwise, clears, sets, or shows one "
673 "General Purpose Non-Volatile Memory (gpnvm) bit.",
675 COMMAND_REGISTRATION_DONE
678 static const struct command_registration atsamv_command_handlers
[] = {
682 .help
= "atsamv flash command group",
684 .chain
= atsamv_exec_command_handlers
,
686 COMMAND_REGISTRATION_DONE
689 const struct flash_driver atsamv_flash
= {
691 .commands
= atsamv_command_handlers
,
692 .flash_bank_command
= samv_flash_bank_command
,
694 .protect
= samv_protect
,
696 .read
= default_flash_read
,
698 .auto_probe
= samv_auto_probe
,
699 .erase_check
= default_flash_blank_check
,
700 .protect_check
= samv_protect_check
,
701 .info
= samv_get_info
,
702 .free_driver_priv
= default_flash_free_driver_priv
,
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)