1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2017 by Tomas Vanek *
7 * Based on at91samd.c *
8 * Copyright (C) 2013 by Andrey Yurovsky *
9 * Andrey Yurovsky <yurovsky@gmail.com> *
10 ***************************************************************************/
17 #include "helper/binarybuffer.h"
19 #include <helper/time_support.h>
20 #include <jtag/jtag.h>
21 #include <target/cortex_m.h>
23 /* A note to prefixing.
24 * Definitions and functions inherited from at91samd.c without
25 * any change retained the original prefix samd_ so they eventually
26 * may go to samd_common.h and .c
27 * As currently there are only 3 short functions identical with
28 * the original source, no common file was created. */
30 #define SAME5_PAGES_PER_BLOCK 16
31 #define SAME5_NUM_PROT_BLOCKS 32
32 #define SAMD_PAGE_SIZE_MAX 1024
34 #define SAMD_FLASH 0x00000000 /* physical Flash memory */
35 #define SAMD_USER_ROW 0x00804000 /* User Row of Flash */
37 #define SAME5_PAC 0x40000000 /* Peripheral Access Control */
39 #define SAMD_DSU 0x41002000 /* Device Service Unit */
40 #define SAMD_NVMCTRL 0x41004000 /* Non-volatile memory controller */
42 #define SAMD_DSU_STATUSA 1 /* DSU status register */
43 #define SAMD_DSU_DID 0x18 /* Device ID register */
44 #define SAMD_DSU_CTRL_EXT 0x100 /* CTRL register, external access */
46 #define SAME5_NVMCTRL_CTRLA 0x00 /* NVM control A register */
47 #define SAME5_NVMCTRL_CTRLB 0x04 /* NVM control B register */
48 #define SAMD_NVMCTRL_PARAM 0x08 /* NVM parameters register */
49 #define SAME5_NVMCTRL_INTFLAG 0x10 /* NVM interrupt flag register */
50 #define SAME5_NVMCTRL_STATUS 0x12 /* NVM status register */
51 #define SAME5_NVMCTRL_ADDR 0x14 /* NVM address register */
52 #define SAME5_NVMCTRL_LOCK 0x18 /* NVM Lock section register */
54 #define SAMD_CMDEX_KEY 0xA5UL
55 #define SAMD_NVM_CMD(n) ((SAMD_CMDEX_KEY << 8) | (n & 0x7F))
57 /* NVMCTRL commands. */
58 #define SAME5_NVM_CMD_EP 0x00 /* Erase Page (User Page only) */
59 #define SAME5_NVM_CMD_EB 0x01 /* Erase Block */
60 #define SAME5_NVM_CMD_WP 0x03 /* Write Page */
61 #define SAME5_NVM_CMD_WQW 0x04 /* Write Quad Word */
62 #define SAME5_NVM_CMD_LR 0x11 /* Lock Region */
63 #define SAME5_NVM_CMD_UR 0x12 /* Unlock Region */
64 #define SAME5_NVM_CMD_PBC 0x15 /* Page Buffer Clear */
65 #define SAME5_NVM_CMD_SSB 0x16 /* Set Security Bit */
68 #define SAME5_NVMCTRL_CTRLA_WMODE_MASK 0x30
70 #define SAME5_NVMCTRL_INTFLAG_DONE (1 << 0)
71 #define SAME5_NVMCTRL_INTFLAG_ADDRE (1 << 1)
72 #define SAME5_NVMCTRL_INTFLAG_PROGE (1 << 2)
73 #define SAME5_NVMCTRL_INTFLAG_LOCKE (1 << 3)
74 #define SAME5_NVMCTRL_INTFLAG_ECCSE (1 << 4)
75 #define SAME5_NVMCTRL_INTFLAG_ECCDE (1 << 5)
76 #define SAME5_NVMCTRL_INTFLAG_NVME (1 << 6)
79 /* Known identifiers */
80 #define SAMD_PROCESSOR_M0 0x01
81 #define SAMD_PROCESSOR_M4 0x06
82 #define SAMD_FAMILY_D 0x00
83 #define SAMD_FAMILY_E 0x03
84 #define SAMD_SERIES_51 0x06
85 #define SAME_SERIES_51 0x01
86 #define SAME_SERIES_53 0x03
87 #define SAME_SERIES_54 0x04
89 /* Device ID macros */
90 #define SAMD_GET_PROCESSOR(id) (id >> 28)
91 #define SAMD_GET_FAMILY(id) (((id >> 23) & 0x1F))
92 #define SAMD_GET_SERIES(id) (((id >> 16) & 0x3F))
93 #define SAMD_GET_DEVSEL(id) (id & 0xFF)
95 /* Bits to mask user row */
96 #define NVMUSERROW_SAM_E5_D5_MASK 0x7FFF00FF3C007FFFULL
105 /* See SAM D5x/E5x Family Silicon Errata and Data Sheet Clarification
107 /* Known SAMD51 parts. */
108 static const struct samd_part samd51_parts
[] = {
109 { 0x00, "SAMD51P20A", 1024, 256 },
110 { 0x01, "SAMD51P19A", 512, 192 },
111 { 0x02, "SAMD51N20A", 1024, 256 },
112 { 0x03, "SAMD51N19A", 512, 192 },
113 { 0x04, "SAMD51J20A", 1024, 256 },
114 { 0x05, "SAMD51J19A", 512, 192 },
115 { 0x06, "SAMD51J18A", 256, 128 },
116 { 0x07, "SAMD51G19A", 512, 192 },
117 { 0x08, "SAMD51G18A", 256, 128 },
120 /* Known SAME51 parts. */
121 static const struct samd_part same51_parts
[] = {
122 { 0x00, "SAME51N20A", 1024, 256 },
123 { 0x01, "SAME51N19A", 512, 192 },
124 { 0x02, "SAME51J19A", 512, 192 },
125 { 0x03, "SAME51J18A", 256, 128 },
126 { 0x04, "SAME51J20A", 1024, 256 },
127 { 0x05, "SAME51G19A", 512, 192 }, /* New in rev D */
128 { 0x06, "SAME51G18A", 256, 128 }, /* New in rev D */
131 /* Known SAME53 parts. */
132 static const struct samd_part same53_parts
[] = {
133 { 0x02, "SAME53N20A", 1024, 256 },
134 { 0x03, "SAME53N19A", 512, 192 },
135 { 0x04, "SAME53J20A", 1024, 256 },
136 { 0x05, "SAME53J19A", 512, 192 },
137 { 0x06, "SAME53J18A", 256, 128 },
138 { 0x55, "LAN9255/ZMX020", 1024, 256 },
139 { 0x56, "LAN9255/ZMX019", 512, 192 },
140 { 0x57, "LAN9255/ZMX018", 256, 128 },
143 /* Known SAME54 parts. */
144 static const struct samd_part same54_parts
[] = {
145 { 0x00, "SAME54P20A", 1024, 256 },
146 { 0x01, "SAME54P19A", 512, 192 },
147 { 0x02, "SAME54N20A", 1024, 256 },
148 { 0x03, "SAME54N19A", 512, 192 },
151 /* Each family of parts contains a parts table in the DEVSEL field of DID. The
152 * processor ID, family ID, and series ID are used to determine which exact
153 * family this is and then we can use the corresponding table. */
158 const struct samd_part
*parts
;
162 /* Known SAMD families */
163 static const struct samd_family samd_families
[] = {
164 { SAMD_PROCESSOR_M4
, SAMD_FAMILY_D
, SAMD_SERIES_51
,
165 samd51_parts
, ARRAY_SIZE(samd51_parts
) },
166 { SAMD_PROCESSOR_M4
, SAMD_FAMILY_E
, SAME_SERIES_51
,
167 same51_parts
, ARRAY_SIZE(same51_parts
) },
168 { SAMD_PROCESSOR_M4
, SAMD_FAMILY_E
, SAME_SERIES_53
,
169 same53_parts
, ARRAY_SIZE(same53_parts
) },
170 { SAMD_PROCESSOR_M4
, SAMD_FAMILY_E
, SAME_SERIES_54
,
171 same54_parts
, ARRAY_SIZE(same54_parts
) },
175 const struct samd_params
*par
;
182 struct target
*target
;
187 * Gives the family structure to specific device id.
188 * @param id The id of the device.
189 * @return On failure NULL, otherwise a pointer to the structure.
191 static const struct samd_family
*samd_find_family(uint32_t id
)
193 uint8_t processor
= SAMD_GET_PROCESSOR(id
);
194 uint8_t family
= SAMD_GET_FAMILY(id
);
195 uint8_t series
= SAMD_GET_SERIES(id
);
197 for (unsigned i
= 0; i
< ARRAY_SIZE(samd_families
); i
++) {
198 if (samd_families
[i
].processor
== processor
&&
199 samd_families
[i
].series
== series
&&
200 samd_families
[i
].family
== family
)
201 return &samd_families
[i
];
208 * Gives the part structure to specific device id.
209 * @param id The id of the device.
210 * @return On failure NULL, otherwise a pointer to the structure.
212 static const struct samd_part
*samd_find_part(uint32_t id
)
214 uint8_t devsel
= SAMD_GET_DEVSEL(id
);
215 const struct samd_family
*family
= samd_find_family(id
);
219 for (unsigned i
= 0; i
< family
->num_parts
; i
++) {
220 if (family
->parts
[i
].id
== devsel
)
221 return &family
->parts
[i
];
227 static int same5_protect_check(struct flash_bank
*bank
)
232 res
= target_read_u32(bank
->target
,
233 SAMD_NVMCTRL
+ SAME5_NVMCTRL_LOCK
, &lock
);
237 /* Lock bits are active-low */
238 for (unsigned int prot_block
= 0; prot_block
< bank
->num_prot_blocks
; prot_block
++)
239 bank
->prot_blocks
[prot_block
].is_protected
= !(lock
& (1u<<prot_block
));
244 static int samd_get_flash_page_info(struct target
*target
,
245 uint32_t *sizep
, int *nump
)
250 res
= target_read_u32(target
, SAMD_NVMCTRL
+ SAMD_NVMCTRL_PARAM
, ¶m
);
251 if (res
== ERROR_OK
) {
252 /* The PSZ field (bits 18:16) indicate the page size bytes as 2^(3+n)
253 * so 0 is 8KB and 7 is 1024KB. */
255 *sizep
= (8 << ((param
>> 16) & 0x7));
256 /* The NVMP field (bits 15:0) indicates the total number of pages */
258 *nump
= param
& 0xFFFF;
260 LOG_ERROR("Couldn't read NVM Parameters register");
266 static int same5_probe(struct flash_bank
*bank
)
270 struct samd_info
*chip
= (struct samd_info
*)bank
->driver_priv
;
271 const struct samd_part
*part
;
276 res
= target_read_u32(bank
->target
, SAMD_DSU
+ SAMD_DSU_DID
, &id
);
277 if (res
!= ERROR_OK
) {
278 LOG_ERROR("Couldn't read Device ID register");
282 part
= samd_find_part(id
);
284 LOG_ERROR("Couldn't find part corresponding to DID %08" PRIx32
, id
);
288 bank
->size
= part
->flash_kb
* 1024;
290 res
= samd_get_flash_page_info(bank
->target
, &chip
->page_size
,
292 if (res
!= ERROR_OK
) {
293 LOG_ERROR("Couldn't determine Flash page size");
297 /* Sanity check: the total flash size in the DSU should match the page size
298 * multiplied by the number of pages. */
299 if (bank
->size
!= chip
->num_pages
* chip
->page_size
) {
300 LOG_WARNING("SAM: bank size doesn't match NVM parameters. "
301 "Identified %" PRIu32
"KB Flash but NVMCTRL reports %u %" PRIu32
"B pages",
302 part
->flash_kb
, chip
->num_pages
, chip
->page_size
);
305 /* Erase granularity = 1 block = 16 pages */
306 chip
->sector_size
= chip
->page_size
* SAME5_PAGES_PER_BLOCK
;
308 /* Allocate the sector table */
309 bank
->num_sectors
= chip
->num_pages
/ SAME5_PAGES_PER_BLOCK
;
310 bank
->sectors
= alloc_block_array(0, chip
->sector_size
, bank
->num_sectors
);
314 /* 16 protection blocks per device */
315 chip
->prot_block_size
= bank
->size
/ SAME5_NUM_PROT_BLOCKS
;
317 /* Allocate the table of protection blocks */
318 bank
->num_prot_blocks
= SAME5_NUM_PROT_BLOCKS
;
319 bank
->prot_blocks
= alloc_block_array(0, chip
->prot_block_size
, bank
->num_prot_blocks
);
320 if (!bank
->prot_blocks
)
323 same5_protect_check(bank
);
328 LOG_INFO("SAM MCU: %s (%" PRIu32
"KB Flash, %" PRIu32
"KB RAM)", part
->name
,
329 part
->flash_kb
, part
->ram_kb
);
334 static int same5_wait_and_check_error(struct target
*target
)
337 /* Table 54-40 lists the maximum erase block time as 200 ms.
338 * Include some margin.
340 int timeout_ms
= 200 * 5;
341 int64_t ts_start
= timeval_ms();
345 ret
= target_read_u16(target
,
346 SAMD_NVMCTRL
+ SAME5_NVMCTRL_INTFLAG
, &intflag
);
347 if (ret
!= ERROR_OK
) {
348 LOG_ERROR("SAM: error reading the NVMCTRL_INTFLAG register");
351 if (intflag
& SAME5_NVMCTRL_INTFLAG_DONE
)
354 } while (timeval_ms() - ts_start
< timeout_ms
);
356 if (!(intflag
& SAME5_NVMCTRL_INTFLAG_DONE
)) {
357 LOG_ERROR("SAM: NVM programming timed out");
358 ret
= ERROR_FLASH_OPERATION_FAILED
;
361 if (intflag
& SAME5_NVMCTRL_INTFLAG_ECCSE
)
362 LOG_ERROR("SAM: ECC Single Error");
364 if (intflag
& SAME5_NVMCTRL_INTFLAG_ECCDE
) {
365 LOG_ERROR("SAM: ECC Double Error");
366 ret
= ERROR_FLASH_OPERATION_FAILED
;
369 if (intflag
& SAME5_NVMCTRL_INTFLAG_ADDRE
) {
370 LOG_ERROR("SAM: Addr Error");
371 ret
= ERROR_FLASH_OPERATION_FAILED
;
374 if (intflag
& SAME5_NVMCTRL_INTFLAG_NVME
) {
375 LOG_ERROR("SAM: NVM Error");
376 ret
= ERROR_FLASH_OPERATION_FAILED
;
379 if (intflag
& SAME5_NVMCTRL_INTFLAG_LOCKE
) {
380 LOG_ERROR("SAM: NVM lock error");
381 ret
= ERROR_FLASH_PROTECTED
;
384 if (intflag
& SAME5_NVMCTRL_INTFLAG_PROGE
) {
385 LOG_ERROR("SAM: NVM programming error");
386 ret
= ERROR_FLASH_OPER_UNSUPPORTED
;
389 /* Clear the error conditions by writing a one to them */
390 ret2
= target_write_u16(target
,
391 SAMD_NVMCTRL
+ SAME5_NVMCTRL_INTFLAG
, intflag
);
392 if (ret2
!= ERROR_OK
)
393 LOG_ERROR("Can't clear NVM error conditions");
398 static int same5_issue_nvmctrl_command(struct target
*target
, uint16_t cmd
)
402 if (target
->state
!= TARGET_HALTED
) {
403 LOG_ERROR("Target not halted");
404 return ERROR_TARGET_NOT_HALTED
;
407 /* Issue the NVM command */
408 /* 32-bit write is used to ensure atomic operation on ST-Link */
409 res
= target_write_u32(target
,
410 SAMD_NVMCTRL
+ SAME5_NVMCTRL_CTRLB
, SAMD_NVM_CMD(cmd
));
414 /* Check to see if the NVM command resulted in an error condition. */
415 return same5_wait_and_check_error(target
);
419 * Erases a flash block or page at the given address.
420 * @param target Pointer to the target structure.
421 * @param address The address of the row.
422 * @return On success ERROR_OK, on failure an errorcode.
424 static int same5_erase_block(struct target
*target
, uint32_t address
)
428 /* Set an address contained in the block to be erased */
429 res
= target_write_u32(target
,
430 SAMD_NVMCTRL
+ SAME5_NVMCTRL_ADDR
, address
);
432 /* Issue the Erase Block command. */
434 res
= same5_issue_nvmctrl_command(target
,
435 address
== SAMD_USER_ROW
? SAME5_NVM_CMD_EP
: SAME5_NVM_CMD_EB
);
437 if (res
!= ERROR_OK
) {
438 LOG_ERROR("Failed to erase block containing %08" PRIx32
, address
);
446 static int same5_pre_write_check(struct target
*target
)
451 if (target
->state
!= TARGET_HALTED
) {
452 LOG_ERROR("Target not halted");
453 return ERROR_TARGET_NOT_HALTED
;
456 /* Check if manual write mode is set */
457 res
= target_read_u32(target
, SAMD_NVMCTRL
+ SAME5_NVMCTRL_CTRLA
, &nvm_ctrla
);
461 if (nvm_ctrla
& SAME5_NVMCTRL_CTRLA_WMODE_MASK
) {
462 LOG_ERROR("The flash controller must be in manual write mode. Issue 'reset init' and retry.");
471 * Modify the contents of the User Row in Flash. The User Row itself
472 * has a size of one page and contains a combination of "fuses" and
473 * calibration data. Bits which have a value of zero in the mask will
475 * @param target Pointer to the target structure.
476 * @param data Pointer to the value to write.
477 * @param mask Pointer to bitmask, 0 -> value stays untouched.
478 * @param offset Offset in user row where new data will be applied.
479 * @param count Size of buffer and mask in bytes.
480 * @return On success ERROR_OK, on failure an errorcode.
482 static int same5_modify_user_row_masked(struct target
*target
,
483 const uint8_t *data
, const uint8_t *mask
,
484 uint32_t offset
, uint32_t count
)
488 /* Retrieve the MCU's flash page size, in bytes. */
490 res
= samd_get_flash_page_info(target
, &page_size
, NULL
);
491 if (res
!= ERROR_OK
) {
492 LOG_ERROR("Couldn't determine Flash page size");
496 /* Make sure the size is sane. */
497 assert(page_size
<= SAMD_PAGE_SIZE_MAX
&&
498 page_size
>= offset
+ count
);
500 uint8_t buf
[SAMD_PAGE_SIZE_MAX
];
501 /* Read the user row (comprising one page) by words. */
502 res
= target_read_memory(target
, SAMD_USER_ROW
, 4, page_size
/ 4, buf
);
506 /* Modify buffer and check if really changed */
507 bool changed
= false;
509 for (i
= 0; i
< count
; i
++) {
510 uint8_t old_b
= buf
[offset
+i
];
511 uint8_t new_b
= (old_b
& ~mask
[i
]) | (data
[i
] & mask
[i
]);
512 buf
[offset
+i
] = new_b
;
520 res
= same5_pre_write_check(target
);
524 res
= same5_erase_block(target
, SAMD_USER_ROW
);
525 if (res
!= ERROR_OK
) {
526 LOG_ERROR("Couldn't erase user row");
530 /* Write the page buffer back out to the target using Write Quad Word */
531 for (i
= 0; i
< page_size
; i
+= 4 * 4) {
532 res
= target_write_memory(target
, SAMD_USER_ROW
+ i
, 4, 4, buf
+ i
);
536 /* Trigger flash write */
537 res
= same5_issue_nvmctrl_command(target
, SAME5_NVM_CMD_WQW
);
546 * Modifies the user row register to the given value.
547 * @param target Pointer to the target structure.
548 * @param value The value to write.
549 * @param startb The bit-offset by which the given value is shifted.
550 * @param endb The bit-offset of the last bit in value to write.
551 * @return On success ERROR_OK, on failure an errorcode.
553 static int same5_modify_user_row(struct target
*target
, uint32_t value
,
554 uint8_t startb
, uint8_t endb
)
556 uint8_t buf_val
[8] = { 0 };
557 uint8_t buf_mask
[8] = { 0 };
559 assert(startb
<= endb
&& endb
< 64);
560 buf_set_u32(buf_val
, startb
, endb
+ 1 - startb
, value
);
561 buf_set_u32(buf_mask
, startb
, endb
+ 1 - startb
, 0xffffffff);
563 return same5_modify_user_row_masked(target
,
564 buf_val
, buf_mask
, 0, 8);
567 static int same5_protect(struct flash_bank
*bank
, int set
, unsigned int first
,
572 /* We can issue lock/unlock region commands with the target running but
573 * the settings won't persist unless we're able to modify the LOCK regions
574 * and that requires the target to be halted. */
575 if (bank
->target
->state
!= TARGET_HALTED
) {
576 LOG_ERROR("Target not halted");
577 return ERROR_TARGET_NOT_HALTED
;
580 for (unsigned int prot_block
= first
; prot_block
<= last
; prot_block
++) {
581 if (set
!= bank
->prot_blocks
[prot_block
].is_protected
) {
582 /* Load an address that is within this protection block (we use offset 0) */
583 res
= target_write_u32(bank
->target
,
584 SAMD_NVMCTRL
+ SAME5_NVMCTRL_ADDR
,
585 bank
->prot_blocks
[prot_block
].offset
);
589 /* Tell the controller to lock that block */
590 res
= same5_issue_nvmctrl_command(bank
->target
,
591 set
? SAME5_NVM_CMD_LR
: SAME5_NVM_CMD_UR
);
597 /* We've now applied our changes, however they will be undone by the next
598 * reset unless we also apply them to the LOCK bits in the User Page.
599 * A '1' means unlocked and a '0' means locked. */
600 const uint8_t lock
[4] = { 0, 0, 0, 0 };
601 const uint8_t unlock
[4] = { 0xff, 0xff, 0xff, 0xff };
602 uint8_t mask
[4] = { 0, 0, 0, 0 };
604 buf_set_u32(mask
, first
, last
+ 1 - first
, 0xffffffff);
606 res
= same5_modify_user_row_masked(bank
->target
,
607 set
? lock
: unlock
, mask
, 8, 4);
609 LOG_WARNING("SAM: protect settings were not made persistent!");
614 same5_protect_check(bank
);
619 static int same5_erase(struct flash_bank
*bank
, unsigned int first
,
623 struct samd_info
*chip
= (struct samd_info
*)bank
->driver_priv
;
625 if (bank
->target
->state
!= TARGET_HALTED
) {
626 LOG_ERROR("Target not halted");
628 return ERROR_TARGET_NOT_HALTED
;
632 return ERROR_FLASH_BANK_NOT_PROBED
;
634 /* For each sector to be erased */
635 for (unsigned int s
= first
; s
<= last
; s
++) {
636 res
= same5_erase_block(bank
->target
, bank
->sectors
[s
].offset
);
637 if (res
!= ERROR_OK
) {
638 LOG_ERROR("SAM: failed to erase sector %d at 0x%08" PRIx32
, s
, bank
->sectors
[s
].offset
);
647 static int same5_write(struct flash_bank
*bank
, const uint8_t *buffer
,
648 uint32_t offset
, uint32_t count
)
655 struct samd_info
*chip
= (struct samd_info
*)bank
->driver_priv
;
658 res
= same5_pre_write_check(bank
->target
);
663 return ERROR_FLASH_BANK_NOT_PROBED
;
665 res
= same5_issue_nvmctrl_command(bank
->target
, SAME5_NVM_CMD_PBC
);
666 if (res
!= ERROR_OK
) {
667 LOG_ERROR("%s: %d", __func__
, __LINE__
);
672 nb
= chip
->page_size
- offset
% chip
->page_size
;
676 address
= bank
->base
+ offset
;
677 pg_offset
= offset
% chip
->page_size
;
679 if (offset
% 4 || (offset
+ nb
) % 4) {
680 /* Either start or end of write is not word aligned */
682 pb
= malloc(chip
->page_size
);
687 /* Set temporary page buffer to 0xff and overwrite the relevant part */
688 memset(pb
, 0xff, chip
->page_size
);
689 memcpy(pb
+ pg_offset
, buffer
, nb
);
691 /* Align start address to a word boundary */
692 address
-= offset
% 4;
693 pg_offset
-= offset
% 4;
694 assert(pg_offset
% 4 == 0);
696 /* Extend length to whole words */
697 nw
= (nb
+ offset
% 4 + 3) / 4;
698 assert(pg_offset
+ 4 * nw
<= chip
->page_size
);
700 /* Now we have original data extended by 0xff bytes
701 * to the nearest word boundary on both start and end */
702 res
= target_write_memory(bank
->target
, address
, 4, nw
, pb
+ pg_offset
);
706 assert(pg_offset
+ 4 * nw
<= chip
->page_size
);
708 /* Word aligned data, use direct write from buffer */
709 res
= target_write_memory(bank
->target
, address
, 4, nw
, buffer
);
711 if (res
!= ERROR_OK
) {
712 LOG_ERROR("%s: %d", __func__
, __LINE__
);
716 res
= same5_issue_nvmctrl_command(bank
->target
, SAME5_NVM_CMD_WP
);
717 if (res
!= ERROR_OK
) {
718 LOG_ERROR("%s: write failed at address 0x%08" PRIx32
, __func__
, address
);
722 /* We're done with the page contents */
734 FLASH_BANK_COMMAND_HANDLER(same5_flash_bank_command
)
736 if (bank
->base
!= SAMD_FLASH
) {
737 LOG_ERROR("Address " TARGET_ADDR_FMT
" invalid bank address (try "
738 "0x%08x[same5] )", bank
->base
, SAMD_FLASH
);
742 struct samd_info
*chip
;
743 chip
= calloc(1, sizeof(*chip
));
745 LOG_ERROR("No memory for flash bank chip info");
749 chip
->target
= bank
->target
;
750 chip
->probed
= false;
752 bank
->driver_priv
= chip
;
758 COMMAND_HANDLER(same5_handle_chip_erase_command
)
760 struct target
*target
= get_current_target(CMD_CTX
);
764 /* Enable access to the DSU by disabling the write protect bit */
765 target_write_u32(target
, SAME5_PAC
, (1<<16) | (1<<5) | (1<<1));
766 /* intentionally without error checking - not accessible on secured chip */
768 /* Tell the DSU to perform a full chip erase. It takes about 240ms to
769 * perform the erase. */
770 int res
= target_write_u8(target
, SAMD_DSU
+ SAMD_DSU_CTRL_EXT
, (1<<4));
772 command_print(CMD
, "chip erase started");
774 command_print(CMD
, "write to DSU CTRL failed");
780 COMMAND_HANDLER(same5_handle_userpage_command
)
783 struct target
*target
= get_current_target(CMD_CTX
);
788 command_print(CMD
, "Too much Arguments given.");
789 return ERROR_COMMAND_SYNTAX_ERROR
;
793 uint64_t value
, mask
= NVMUSERROW_SAM_E5_D5_MASK
;
794 COMMAND_PARSE_NUMBER(u64
, CMD_ARGV
[0], value
);
798 COMMAND_PARSE_NUMBER(u64
, CMD_ARGV
[1], mask_temp
);
802 uint8_t val_buf
[8], mask_buf
[8];
803 target_buffer_set_u64(target
, val_buf
, value
);
804 target_buffer_set_u64(target
, mask_buf
, mask
);
806 res
= same5_modify_user_row_masked(target
,
807 val_buf
, mask_buf
, 0, sizeof(val_buf
));
811 int res2
= target_read_memory(target
, SAMD_USER_ROW
, 4, 2, buffer
);
812 if (res2
== ERROR_OK
) {
813 uint64_t value
= target_buffer_get_u64(target
, buffer
);
814 command_print(CMD
, "USER PAGE: 0x%016"PRIX64
, value
);
816 LOG_ERROR("USER PAGE could not be read.");
826 COMMAND_HANDLER(same5_handle_bootloader_command
)
829 struct target
*target
= get_current_target(CMD_CTX
);
836 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[0], size
);
837 uint32_t code
= (size
+ 8191) / 8192;
839 command_print(CMD
, "Invalid bootloader size. Please "
840 "see datasheet for a list valid sizes.");
841 return ERROR_COMMAND_SYNTAX_ERROR
;
844 res
= same5_modify_user_row(target
, 15 - code
, 26, 29);
848 int res2
= target_read_u32(target
, SAMD_USER_ROW
, &val
);
849 if (res2
== ERROR_OK
) {
850 uint32_t code
= (val
>> 26) & 0xf; /* grab size code */
851 uint32_t size
= (15 - code
) * 8192;
852 command_print(CMD
, "Bootloader protected in the first %"
853 PRIu32
" bytes", size
);
863 COMMAND_HANDLER(samd_handle_reset_deassert
)
865 struct target
*target
= get_current_target(CMD_CTX
);
867 enum reset_types jtag_reset_config
= jtag_get_reset_config();
871 /* If the target has been unresponsive before, try to re-establish
872 * communication now - CPU is held in reset by DSU, DAP is working */
873 if (!target_was_examined(target
))
874 target_examine_one(target
);
877 /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset()
878 * so we just release reset held by DSU
880 * n_RESET (srst) clears the DP, so reenable debug and set vector catch here
882 * After vectreset DSU release is not needed however makes no harm
884 if (target
->reset_halt
&& (jtag_reset_config
& RESET_HAS_SRST
)) {
885 res
= target_write_u32(target
, DCB_DHCSR
, DBGKEY
| C_HALT
| C_DEBUGEN
);
887 res
= target_write_u32(target
, DCB_DEMCR
,
888 TRCENA
| VC_HARDERR
| VC_BUSERR
| VC_CORERESET
);
889 /* do not return on error here, releasing DSU reset is more important */
892 /* clear CPU Reset Phase Extension bit */
893 int res2
= target_write_u8(target
, SAMD_DSU
+ SAMD_DSU_STATUSA
, (1<<1));
894 if (res2
!= ERROR_OK
)
900 static const struct command_registration same5_exec_command_handlers
[] = {
902 .name
= "dsu_reset_deassert",
904 .handler
= samd_handle_reset_deassert
,
905 .mode
= COMMAND_EXEC
,
906 .help
= "Deassert internal reset held by DSU."
909 .name
= "chip-erase",
911 .handler
= same5_handle_chip_erase_command
,
912 .mode
= COMMAND_EXEC
,
913 .help
= "Erase the entire Flash by using the Chip-"
914 "Erase feature in the Device Service Unit (DSU).",
917 .name
= "bootloader",
918 .usage
= "[size_in_bytes]",
919 .handler
= same5_handle_bootloader_command
,
920 .mode
= COMMAND_EXEC
,
921 .help
= "Show or set the bootloader protection size, stored in the User Row. "
922 "Changes are stored immediately but take affect after the MCU is "
927 .usage
= "[value] [mask]",
928 .handler
= same5_handle_userpage_command
,
929 .mode
= COMMAND_EXEC
,
930 .help
= "Show or set the first 64-bit part of user page "
931 "located at address 0x804000. Use the optional mask argument "
932 "to prevent changes at positions where the bitvalue is zero. "
933 "For security reasons the reserved-bits are masked out "
934 "in background and therefore cannot be changed.",
936 COMMAND_REGISTRATION_DONE
939 static const struct command_registration same5_command_handlers
[] = {
943 .help
= "atsame5 flash command group",
945 .chain
= same5_exec_command_handlers
,
947 COMMAND_REGISTRATION_DONE
950 const struct flash_driver atsame5_flash
= {
952 .commands
= same5_command_handlers
,
953 .flash_bank_command
= same5_flash_bank_command
,
954 .erase
= same5_erase
,
955 .protect
= same5_protect
,
956 .write
= same5_write
,
957 .read
= default_flash_read
,
958 .probe
= same5_probe
,
959 .auto_probe
= same5_probe
,
960 .erase_check
= default_flash_blank_check
,
961 .protect_check
= same5_protect_check
,
962 .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)