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 struct samv_flash_bank
{
59 unsigned gpnvm
[SAMV_NUM_GPNVM_BITS
];
62 /* The actual sector size of the SAMV7 flash memory is 128K bytes.
63 * 16 sectors for a 2048KB device. The lock regions are 16KB per lock
64 * region, with a 2048KB device having 128 lock regions.
65 * For the best results, num_sectors is thus set to the number of lock
66 * regions, and the sector_size set to the lock region size. Page
67 * erases are used to erase 16KB sections when programming */
69 static int samv_efc_get_status(struct target
*target
, uint32_t *v
)
71 int r
= target_read_u32(target
, SAMV_CONTROLLER_ADDR
+ OFFSET_EFC_FSR
, v
);
75 static int samv_efc_get_result(struct target
*target
, uint32_t *v
)
78 int r
= target_read_u32(target
, SAMV_CONTROLLER_ADDR
+ OFFSET_EFC_FRR
, &rv
);
84 static int samv_efc_start_command(struct target
*target
,
85 unsigned command
, unsigned argument
)
88 samv_efc_get_status(target
, &v
);
90 LOG_ERROR("flash controller is not ready");
94 v
= (0x5A << 24) | (argument
<< 8) | command
;
95 LOG_DEBUG("starting flash command: 0x%08x", (unsigned int)(v
));
96 int r
= target_write_u32(target
, SAMV_CONTROLLER_ADDR
+ OFFSET_EFC_FCR
, v
);
98 LOG_DEBUG("write failed");
102 static int samv_efc_perform_command(struct target
*target
,
103 unsigned command
, unsigned argument
, uint32_t *status
)
107 int64_t ms_now
, ms_end
;
112 r
= samv_efc_start_command(target
, command
, argument
);
116 ms_end
= 10000 + timeval_ms();
119 r
= samv_efc_get_status(target
, &v
);
122 ms_now
= timeval_ms();
123 if (ms_now
> ms_end
) {
125 LOG_ERROR("Command timeout");
128 } while ((v
& 1) == 0);
130 /* if requested, copy the flash controller error bits back to the caller */
136 static int samv_erase_pages(struct target
*target
,
137 int first_page
, int num_pages
, uint32_t *status
)
159 * According to the datasheet FARG[15:2] defines the page from which
160 * the erase will start.This page must be modulo 4, 8, 16 or 32
161 * according to the number of pages to erase. FARG[1:0] defines the
162 * number of pages to be erased. Previously (firstpage << 2) was used
163 * to conform to this, seems it should not be shifted...
165 return samv_efc_perform_command(target
, SAMV_EFC_FCMD_EPA
,
166 first_page
| erase_pages
, status
);
169 static int samv_get_gpnvm(struct target
*target
, unsigned gpnvm
, unsigned *out
)
174 if (gpnvm
>= SAMV_NUM_GPNVM_BITS
) {
175 LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm
, SAMV_NUM_GPNVM_BITS
);
179 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_GFB
, 0, NULL
);
181 LOG_ERROR("samv_get_gpnvm failed");
185 r
= samv_efc_get_result(target
, &v
);
188 *out
= (v
>> gpnvm
) & 1;
193 static int samv_clear_gpnvm(struct target
*target
, unsigned gpnvm
)
198 if (gpnvm
>= SAMV_NUM_GPNVM_BITS
) {
199 LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm
, SAMV_NUM_GPNVM_BITS
);
202 r
= samv_get_gpnvm(target
, gpnvm
, &v
);
204 LOG_DEBUG("get gpnvm failed: %d", r
);
207 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_CFB
, gpnvm
, NULL
);
208 LOG_DEBUG("clear gpnvm result: %d", r
);
212 static int samv_set_gpnvm(struct target
*target
, unsigned gpnvm
)
216 if (gpnvm
>= SAMV_NUM_GPNVM_BITS
) {
217 LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm
, SAMV_NUM_GPNVM_BITS
);
221 r
= samv_get_gpnvm(target
, gpnvm
, &v
);
225 r
= ERROR_OK
; /* the gpnvm bit is already set */
227 /* we need to set it */
228 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_SFB
, gpnvm
, NULL
);
233 static int samv_flash_unlock(struct target
*target
,
234 unsigned start_sector
, unsigned end_sector
)
239 uint32_t pages_per_sector
;
241 /* todo: look into this... i think this should be done on lock regions */
242 pages_per_sector
= SAMV_SECTOR_SIZE
/ SAMV_PAGE_SIZE
;
243 while (start_sector
<= end_sector
) {
244 pg
= start_sector
* pages_per_sector
;
245 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_CLB
, pg
, &status
);
253 static int samv_flash_lock(struct target
*target
,
254 unsigned start_sector
, unsigned end_sector
)
258 uint32_t pages_per_sector
;
261 /* todo: look into this... i think this should be done on lock regions */
262 pages_per_sector
= SAMV_SECTOR_SIZE
/ SAMV_PAGE_SIZE
;
263 while (start_sector
<= end_sector
) {
264 pg
= start_sector
* pages_per_sector
;
265 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_SLB
, pg
, &status
);
273 static int samv_protect_check(struct flash_bank
*bank
)
278 r
= samv_efc_perform_command(bank
->target
, SAMV_EFC_FCMD_GLB
, 0, NULL
);
280 samv_efc_get_result(bank
->target
, &v
[0]);
281 samv_efc_get_result(bank
->target
, &v
[1]);
282 samv_efc_get_result(bank
->target
, &v
[2]);
283 r
= samv_efc_get_result(bank
->target
, &v
[3]);
288 for (unsigned int x
= 0; x
< bank
->num_sectors
; x
++)
289 bank
->sectors
[x
].is_protected
= (!!(v
[x
>> 5] & (1 << (x
% 32))));
293 FLASH_BANK_COMMAND_HANDLER(samv_flash_bank_command
)
295 LOG_INFO("flash bank command");
296 struct samv_flash_bank
*samv_info
;
297 samv_info
= calloc(1, sizeof(struct samv_flash_bank
));
298 bank
->driver_priv
= samv_info
;
302 static int samv_get_device_id(struct flash_bank
*bank
, uint32_t *device_id
)
304 return target_read_u32(bank
->target
, SAMV_CHIPID_CIDR
, device_id
);
307 static int samv_probe(struct flash_bank
*bank
)
310 int r
= samv_get_device_id(bank
, &device_id
);
313 LOG_INFO("device id = 0x%08" PRIx32
"", device_id
);
315 uint8_t eproc
= (device_id
>> 5) & 0x7;
317 LOG_ERROR("unexpected eproc code: %d was expecting 0 (Cortex-M7)", eproc
);
321 uint8_t nvm_size_code
= (device_id
>> 8) & 0xf;
322 switch (nvm_size_code
) {
324 bank
->size
= 512 * 1024;
327 bank
->size
= 1024 * 1024;
330 bank
->size
= 2048 * 1024;
333 LOG_ERROR("unrecognized flash size code: %d", nvm_size_code
);
337 struct samv_flash_bank
*samv_info
= bank
->driver_priv
;
338 samv_info
->size_bytes
= bank
->size
;
339 samv_info
->probed
= true;
341 bank
->base
= SAMV_FLASH_BASE
;
342 bank
->num_sectors
= bank
->size
/ SAMV_SECTOR_SIZE
;
343 bank
->sectors
= calloc(bank
->num_sectors
, sizeof(struct flash_sector
));
344 for (unsigned int s
= 0; s
< bank
->num_sectors
; s
++) {
345 bank
->sectors
[s
].size
= SAMV_SECTOR_SIZE
;
346 bank
->sectors
[s
].offset
= s
* SAMV_SECTOR_SIZE
;
347 bank
->sectors
[s
].is_erased
= -1;
348 bank
->sectors
[s
].is_protected
= -1;
351 r
= samv_protect_check(bank
);
358 static int samv_auto_probe(struct flash_bank
*bank
)
360 struct samv_flash_bank
*samv_info
= bank
->driver_priv
;
361 if (samv_info
->probed
)
363 return samv_probe(bank
);
366 static int samv_erase(struct flash_bank
*bank
, unsigned int first
,
369 const int page_count
= 32; /* 32 pages equals 16 KB lock region */
371 if (bank
->target
->state
!= TARGET_HALTED
) {
372 LOG_ERROR("Target not halted");
373 return ERROR_TARGET_NOT_HALTED
;
376 int r
= samv_auto_probe(bank
);
380 /* easy case: we've been requested to erase the entire flash */
381 if ((first
== 0) && ((last
+ 1) == bank
->num_sectors
))
382 return samv_efc_perform_command(bank
->target
, SAMV_EFC_FCMD_EA
, 0, NULL
);
384 LOG_INFO("erasing lock regions %u-%u...", first
, last
);
386 for (unsigned int i
= first
; i
<= last
; i
++) {
388 r
= samv_erase_pages(bank
->target
, (i
* page_count
), page_count
, &status
);
389 LOG_INFO("erasing lock region %u", i
);
391 LOG_ERROR("error performing erase page @ lock region number %u", i
);
392 if (status
& (1 << 2)) {
393 LOG_ERROR("lock region %u is locked", i
);
396 if (status
& (1 << 1)) {
397 LOG_ERROR("flash command error @lock region %u", i
);
404 static int samv_protect(struct flash_bank
*bank
, int set
, unsigned int first
,
407 if (bank
->target
->state
!= TARGET_HALTED
) {
408 LOG_ERROR("Target not halted");
409 return ERROR_TARGET_NOT_HALTED
;
414 r
= samv_flash_lock(bank
->target
, first
, last
);
416 r
= samv_flash_unlock(bank
->target
, first
, last
);
421 static int samv_page_read(struct target
*target
,
422 unsigned page_num
, uint8_t *buf
)
424 uint32_t addr
= SAMV_FLASH_BASE
+ page_num
* SAMV_PAGE_SIZE
;
425 int r
= target_read_memory(target
, addr
, 4, SAMV_PAGE_SIZE
/ 4, buf
);
427 LOG_ERROR("flash program failed to read page @ 0x%08x",
428 (unsigned int)(addr
));
432 static int samv_page_write(struct target
*target
,
433 unsigned pagenum
, const uint8_t *buf
)
436 const uint32_t addr
= SAMV_FLASH_BASE
+ pagenum
* SAMV_PAGE_SIZE
;
439 LOG_DEBUG("write page %u at address 0x%08x", pagenum
, (unsigned int)addr
);
440 r
= target_write_memory(target
, addr
, 4, SAMV_PAGE_SIZE
/ 4, buf
);
442 LOG_ERROR("failed to buffer page at 0x%08x", (unsigned int)addr
);
446 r
= samv_efc_perform_command(target
, SAMV_EFC_FCMD_WP
, pagenum
, &status
);
448 LOG_ERROR("error performing write page at 0x%08x", (unsigned int)addr
);
449 if (status
& (1 << 2)) {
450 LOG_ERROR("page at 0x%08x is locked", (unsigned int)addr
);
453 if (status
& (1 << 1)) {
454 LOG_ERROR("flash command error at 0x%08x", (unsigned int)addr
);
460 static int samv_write(struct flash_bank
*bank
, const uint8_t *buffer
,
461 uint32_t offset
, uint32_t count
)
463 if (bank
->target
->state
!= TARGET_HALTED
) {
464 LOG_ERROR("target not halted");
465 return ERROR_TARGET_NOT_HALTED
;
471 if ((offset
+ count
) > bank
->size
) {
472 LOG_ERROR("flash write error - past end of bank");
473 LOG_ERROR(" offset: 0x%08x, count 0x%08x, bank end: 0x%08x",
474 (unsigned int)(offset
),
475 (unsigned int)(count
),
476 (unsigned int)(bank
->size
));
480 uint8_t pagebuffer
[SAMV_PAGE_SIZE
] = {0};
481 uint32_t page_cur
= offset
/ SAMV_PAGE_SIZE
;
482 uint32_t page_end
= (offset
+ count
- 1) / SAMV_PAGE_SIZE
;
484 LOG_DEBUG("offset: 0x%08x, count: 0x%08x",
485 (unsigned int)(offset
), (unsigned int)(count
));
486 LOG_DEBUG("page start: %d, page end: %d", (int)(page_cur
), (int)(page_end
));
488 /* Special case: all one page */
490 /* (1) non-aligned start */
492 /* (3) non-aligned end. */
495 uint32_t page_offset
;
497 /* handle special case - all one page. */
498 if (page_cur
== page_end
) {
499 LOG_DEBUG("special case, all in one page");
500 r
= samv_page_read(bank
->target
, page_cur
, pagebuffer
);
504 page_offset
= offset
& (SAMV_PAGE_SIZE
-1);
505 memcpy(pagebuffer
+ page_offset
, buffer
, count
);
507 r
= samv_page_write(bank
->target
, page_cur
, pagebuffer
);
513 /* step 1) handle the non-aligned starting address */
514 page_offset
= offset
& (SAMV_PAGE_SIZE
- 1);
516 LOG_DEBUG("non-aligned start");
517 /* read the partial page */
518 r
= samv_page_read(bank
->target
, page_cur
, pagebuffer
);
522 /* over-write with new data */
523 uint32_t n
= SAMV_PAGE_SIZE
- page_offset
;
524 memcpy(pagebuffer
+ page_offset
, buffer
, n
);
526 r
= samv_page_write(bank
->target
, page_cur
, pagebuffer
);
536 /* By checking that offset is correct here, we also fix a clang warning */
537 assert(offset
% SAMV_PAGE_SIZE
== 0);
539 /* step 2) handle the full pages */
540 LOG_DEBUG("full page loop: cur=%d, end=%d, count = 0x%08x",
541 (int)page_cur
, (int)page_end
, (unsigned int)(count
));
543 while ((page_cur
< page_end
) && (count
>= SAMV_PAGE_SIZE
)) {
544 r
= samv_page_write(bank
->target
, page_cur
, buffer
);
547 count
-= SAMV_PAGE_SIZE
;
548 buffer
+= SAMV_PAGE_SIZE
;
552 /* step 3) write final page, if it's partial (otherwise it's already done) */
554 LOG_DEBUG("final partial page, count = 0x%08x", (unsigned int)(count
));
555 /* we have a partial page */
556 r
= samv_page_read(bank
->target
, page_cur
, pagebuffer
);
559 memcpy(pagebuffer
, buffer
, count
); /* data goes at start of page */
560 r
= samv_page_write(bank
->target
, page_cur
, pagebuffer
);
567 static int samv_get_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
569 struct samv_flash_bank
*samv_info
= bank
->driver_priv
;
570 if (!samv_info
->probed
) {
571 int r
= samv_probe(bank
);
575 command_print_sameline(cmd
, "Cortex-M7 detected with %" PRIu32
" kB flash\n",
580 COMMAND_HANDLER(samv_handle_gpnvm_command
)
582 struct flash_bank
*bank
= get_flash_bank_by_num_noprobe(0);
585 struct samv_flash_bank
*samv_info
= bank
->driver_priv
;
586 struct target
*target
= bank
->target
;
588 if (target
->state
!= TARGET_HALTED
) {
589 LOG_ERROR("target not halted");
590 return ERROR_TARGET_NOT_HALTED
;
594 if (!samv_info
->probed
) {
595 r
= samv_auto_probe(bank
);
609 if (!strcmp(CMD_ARGV
[0], "show") && !strcmp(CMD_ARGV
[1], "all"))
613 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], v32
);
618 return ERROR_COMMAND_SYNTAX_ERROR
;
622 if (!strcmp("show", CMD_ARGV
[0])) {
626 for (int x
= 0; x
< SAMV_NUM_GPNVM_BITS
; x
++) {
627 r
= samv_get_gpnvm(target
, x
, &v
);
630 command_print(CMD
, "samv-gpnvm%u: %u", x
, v
);
634 if ((who
>= 0) && (((unsigned)who
) < SAMV_NUM_GPNVM_BITS
)) {
635 r
= samv_get_gpnvm(target
, who
, &v
);
639 command_print(CMD
, "samv-gpnvm%u: %u", who
, v
);
642 command_print(CMD
, "invalid gpnvm: %u", who
);
643 return ERROR_COMMAND_SYNTAX_ERROR
;
648 command_print(CMD
, "missing gpnvm number");
649 return ERROR_COMMAND_SYNTAX_ERROR
;
652 if (!strcmp("set", CMD_ARGV
[0]))
653 r
= samv_set_gpnvm(target
, who
);
654 else if (!strcmp("clr", CMD_ARGV
[0]) || !strcmp("clear", CMD_ARGV
[0]))
655 r
= samv_clear_gpnvm(target
, who
);
657 command_print(CMD
, "unknown command: %s", CMD_ARGV
[0]);
658 r
= ERROR_COMMAND_SYNTAX_ERROR
;
663 static const struct command_registration atsamv_exec_command_handlers
[] = {
666 .handler
= samv_handle_gpnvm_command
,
667 .mode
= COMMAND_EXEC
,
668 .usage
= "[('clr'|'set'|'show') bitnum]",
669 .help
= "Without arguments, shows all bits in the gpnvm "
670 "register. Otherwise, clears, sets, or shows one "
671 "General Purpose Non-Volatile Memory (gpnvm) bit.",
673 COMMAND_REGISTRATION_DONE
676 static const struct command_registration atsamv_command_handlers
[] = {
680 .help
= "atsamv flash command group",
682 .chain
= atsamv_exec_command_handlers
,
684 COMMAND_REGISTRATION_DONE
687 const struct flash_driver atsamv_flash
= {
689 .commands
= atsamv_command_handlers
,
690 .flash_bank_command
= samv_flash_bank_command
,
692 .protect
= samv_protect
,
694 .read
= default_flash_read
,
696 .auto_probe
= samv_auto_probe
,
697 .erase_check
= default_flash_blank_check
,
698 .protect_check
= samv_protect_check
,
699 .info
= samv_get_info
,
700 .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)