jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / flash / nor / atsame5.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2017 by Tomas Vanek *
5 * vanekt@fbl.cz *
6 * *
7 * Based on at91samd.c *
8 * Copyright (C) 2013 by Andrey Yurovsky *
9 * Andrey Yurovsky <yurovsky@gmail.com> *
10 ***************************************************************************/
11
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15
16 #include "imp.h"
17 #include "helper/binarybuffer.h"
18
19 #include <helper/time_support.h>
20 #include <jtag/jtag.h>
21 #include <target/cortex_m.h>
22
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. */
29
30 #define SAME5_PAGES_PER_BLOCK 16
31 #define SAME5_NUM_PROT_BLOCKS 32
32 #define SAMD_PAGE_SIZE_MAX 1024
33
34 #define SAMD_FLASH 0x00000000 /* physical Flash memory */
35 #define SAMD_USER_ROW 0x00804000 /* User Row of Flash */
36
37 #define SAME5_PAC 0x40000000 /* Peripheral Access Control */
38
39 #define SAMD_DSU 0x41002000 /* Device Service Unit */
40 #define SAMD_NVMCTRL 0x41004000 /* Non-volatile memory controller */
41
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 */
45
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 */
53
54 #define SAMD_CMDEX_KEY 0xA5UL
55 #define SAMD_NVM_CMD(n) ((SAMD_CMDEX_KEY << 8) | (n & 0x7F))
56
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 */
66
67 /* NVMCTRL bits */
68 #define SAME5_NVMCTRL_CTRLA_WMODE_MASK 0x30
69
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)
77
78
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
88
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)
94
95 /* Bits to mask user row */
96 #define NVMUSERROW_SAM_E5_D5_MASK 0x7FFF00FF3C007FFFULL
97
98 struct samd_part {
99 uint8_t id;
100 const char *name;
101 uint32_t flash_kb;
102 uint32_t ram_kb;
103 };
104
105 /* See SAM D5x/E5x Family Silicon Errata and Data Sheet Clarification
106 * DS80000748K */
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 },
118 };
119
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 */
129 };
130
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 },
141 };
142
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 },
149 };
150
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. */
154 struct samd_family {
155 uint8_t processor;
156 uint8_t family;
157 uint8_t series;
158 const struct samd_part *parts;
159 size_t num_parts;
160 };
161
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) },
172 };
173
174 struct samd_info {
175 const struct samd_params *par;
176 uint32_t page_size;
177 int num_pages;
178 int sector_size;
179 int prot_block_size;
180
181 bool probed;
182 struct target *target;
183 };
184
185
186 /**
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.
190 */
191 static const struct samd_family *samd_find_family(uint32_t id)
192 {
193 uint8_t processor = SAMD_GET_PROCESSOR(id);
194 uint8_t family = SAMD_GET_FAMILY(id);
195 uint8_t series = SAMD_GET_SERIES(id);
196
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];
202 }
203
204 return NULL;
205 }
206
207 /**
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.
211 */
212 static const struct samd_part *samd_find_part(uint32_t id)
213 {
214 uint8_t devsel = SAMD_GET_DEVSEL(id);
215 const struct samd_family *family = samd_find_family(id);
216 if (!family)
217 return NULL;
218
219 for (unsigned i = 0; i < family->num_parts; i++) {
220 if (family->parts[i].id == devsel)
221 return &family->parts[i];
222 }
223
224 return NULL;
225 }
226
227 static int same5_protect_check(struct flash_bank *bank)
228 {
229 int res;
230 uint32_t lock;
231
232 res = target_read_u32(bank->target,
233 SAMD_NVMCTRL + SAME5_NVMCTRL_LOCK, &lock);
234 if (res != ERROR_OK)
235 return res;
236
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));
240
241 return ERROR_OK;
242 }
243
244 static int samd_get_flash_page_info(struct target *target,
245 uint32_t *sizep, int *nump)
246 {
247 int res;
248 uint32_t param;
249
250 res = target_read_u32(target, SAMD_NVMCTRL + SAMD_NVMCTRL_PARAM, &param);
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. */
254 if (sizep)
255 *sizep = (8 << ((param >> 16) & 0x7));
256 /* The NVMP field (bits 15:0) indicates the total number of pages */
257 if (nump)
258 *nump = param & 0xFFFF;
259 } else {
260 LOG_ERROR("Couldn't read NVM Parameters register");
261 }
262
263 return res;
264 }
265
266 static int same5_probe(struct flash_bank *bank)
267 {
268 uint32_t id;
269 int res;
270 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
271 const struct samd_part *part;
272
273 if (chip->probed)
274 return ERROR_OK;
275
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");
279 return res;
280 }
281
282 part = samd_find_part(id);
283 if (!part) {
284 LOG_ERROR("Couldn't find part corresponding to DID %08" PRIx32, id);
285 return ERROR_FAIL;
286 }
287
288 bank->size = part->flash_kb * 1024;
289
290 res = samd_get_flash_page_info(bank->target, &chip->page_size,
291 &chip->num_pages);
292 if (res != ERROR_OK) {
293 LOG_ERROR("Couldn't determine Flash page size");
294 return res;
295 }
296
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);
303 }
304
305 /* Erase granularity = 1 block = 16 pages */
306 chip->sector_size = chip->page_size * SAME5_PAGES_PER_BLOCK;
307
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);
311 if (!bank->sectors)
312 return ERROR_FAIL;
313
314 /* 16 protection blocks per device */
315 chip->prot_block_size = bank->size / SAME5_NUM_PROT_BLOCKS;
316
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)
321 return ERROR_FAIL;
322
323 same5_protect_check(bank);
324
325 /* Done */
326 chip->probed = true;
327
328 LOG_INFO("SAM MCU: %s (%" PRIu32 "KB Flash, %" PRIu32 "KB RAM)", part->name,
329 part->flash_kb, part->ram_kb);
330
331 return ERROR_OK;
332 }
333
334 static int same5_wait_and_check_error(struct target *target)
335 {
336 int ret, ret2;
337 /* Table 54-40 lists the maximum erase block time as 200 ms.
338 * Include some margin.
339 */
340 int timeout_ms = 200 * 5;
341 int64_t ts_start = timeval_ms();
342 uint16_t intflag;
343
344 do {
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");
349 return ret;
350 }
351 if (intflag & SAME5_NVMCTRL_INTFLAG_DONE)
352 break;
353 keep_alive();
354 } while (timeval_ms() - ts_start < timeout_ms);
355
356 if (!(intflag & SAME5_NVMCTRL_INTFLAG_DONE)) {
357 LOG_ERROR("SAM: NVM programming timed out");
358 ret = ERROR_FLASH_OPERATION_FAILED;
359 }
360 #if 0
361 if (intflag & SAME5_NVMCTRL_INTFLAG_ECCSE)
362 LOG_ERROR("SAM: ECC Single Error");
363
364 if (intflag & SAME5_NVMCTRL_INTFLAG_ECCDE) {
365 LOG_ERROR("SAM: ECC Double Error");
366 ret = ERROR_FLASH_OPERATION_FAILED;
367 }
368 #endif
369 if (intflag & SAME5_NVMCTRL_INTFLAG_ADDRE) {
370 LOG_ERROR("SAM: Addr Error");
371 ret = ERROR_FLASH_OPERATION_FAILED;
372 }
373
374 if (intflag & SAME5_NVMCTRL_INTFLAG_NVME) {
375 LOG_ERROR("SAM: NVM Error");
376 ret = ERROR_FLASH_OPERATION_FAILED;
377 }
378
379 if (intflag & SAME5_NVMCTRL_INTFLAG_LOCKE) {
380 LOG_ERROR("SAM: NVM lock error");
381 ret = ERROR_FLASH_PROTECTED;
382 }
383
384 if (intflag & SAME5_NVMCTRL_INTFLAG_PROGE) {
385 LOG_ERROR("SAM: NVM programming error");
386 ret = ERROR_FLASH_OPER_UNSUPPORTED;
387 }
388
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");
394
395 return ret;
396 }
397
398 static int same5_issue_nvmctrl_command(struct target *target, uint16_t cmd)
399 {
400 int res;
401
402 if (target->state != TARGET_HALTED) {
403 LOG_ERROR("Target not halted");
404 return ERROR_TARGET_NOT_HALTED;
405 }
406
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));
411 if (res != ERROR_OK)
412 return res;
413
414 /* Check to see if the NVM command resulted in an error condition. */
415 return same5_wait_and_check_error(target);
416 }
417
418 /**
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.
423 */
424 static int same5_erase_block(struct target *target, uint32_t address)
425 {
426 int res;
427
428 /* Set an address contained in the block to be erased */
429 res = target_write_u32(target,
430 SAMD_NVMCTRL + SAME5_NVMCTRL_ADDR, address);
431
432 /* Issue the Erase Block command. */
433 if (res == ERROR_OK)
434 res = same5_issue_nvmctrl_command(target,
435 address == SAMD_USER_ROW ? SAME5_NVM_CMD_EP : SAME5_NVM_CMD_EB);
436
437 if (res != ERROR_OK) {
438 LOG_ERROR("Failed to erase block containing %08" PRIx32, address);
439 return ERROR_FAIL;
440 }
441
442 return ERROR_OK;
443 }
444
445
446 static int same5_pre_write_check(struct target *target)
447 {
448 int res;
449 uint32_t nvm_ctrla;
450
451 if (target->state != TARGET_HALTED) {
452 LOG_ERROR("Target not halted");
453 return ERROR_TARGET_NOT_HALTED;
454 }
455
456 /* Check if manual write mode is set */
457 res = target_read_u32(target, SAMD_NVMCTRL + SAME5_NVMCTRL_CTRLA, &nvm_ctrla);
458 if (res != ERROR_OK)
459 return res;
460
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.");
463 return ERROR_FAIL;
464 }
465
466 return res;
467 }
468
469
470 /**
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
474 * not be changed.
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.
481 */
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)
485 {
486 int res;
487
488 /* Retrieve the MCU's flash page size, in bytes. */
489 uint32_t page_size;
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");
493 return res;
494 }
495
496 /* Make sure the size is sane. */
497 assert(page_size <= SAMD_PAGE_SIZE_MAX &&
498 page_size >= offset + count);
499
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);
503 if (res != ERROR_OK)
504 return res;
505
506 /* Modify buffer and check if really changed */
507 bool changed = false;
508 uint32_t i;
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;
513 if (old_b != new_b)
514 changed = true;
515 }
516
517 if (!changed)
518 return ERROR_OK;
519
520 res = same5_pre_write_check(target);
521 if (res != ERROR_OK)
522 return res;
523
524 res = same5_erase_block(target, SAMD_USER_ROW);
525 if (res != ERROR_OK) {
526 LOG_ERROR("Couldn't erase user row");
527 return res;
528 }
529
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);
533 if (res != ERROR_OK)
534 return res;
535
536 /* Trigger flash write */
537 res = same5_issue_nvmctrl_command(target, SAME5_NVM_CMD_WQW);
538 if (res != ERROR_OK)
539 return res;
540 }
541
542 return res;
543 }
544
545 /**
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.
552 */
553 static int same5_modify_user_row(struct target *target, uint32_t value,
554 uint8_t startb, uint8_t endb)
555 {
556 uint8_t buf_val[8] = { 0 };
557 uint8_t buf_mask[8] = { 0 };
558
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);
562
563 return same5_modify_user_row_masked(target,
564 buf_val, buf_mask, 0, 8);
565 }
566
567 static int same5_protect(struct flash_bank *bank, int set, unsigned int first,
568 unsigned int last)
569 {
570 int res = ERROR_OK;
571
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;
578 }
579
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);
586 if (res != ERROR_OK)
587 goto exit;
588
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);
592 if (res != ERROR_OK)
593 goto exit;
594 }
595 }
596
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 };
603
604 buf_set_u32(mask, first, last + 1 - first, 0xffffffff);
605
606 res = same5_modify_user_row_masked(bank->target,
607 set ? lock : unlock, mask, 8, 4);
608 if (res != ERROR_OK)
609 LOG_WARNING("SAM: protect settings were not made persistent!");
610
611 res = ERROR_OK;
612
613 exit:
614 same5_protect_check(bank);
615
616 return res;
617 }
618
619 static int same5_erase(struct flash_bank *bank, unsigned int first,
620 unsigned int last)
621 {
622 int res;
623 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
624
625 if (bank->target->state != TARGET_HALTED) {
626 LOG_ERROR("Target not halted");
627
628 return ERROR_TARGET_NOT_HALTED;
629 }
630
631 if (!chip->probed)
632 return ERROR_FLASH_BANK_NOT_PROBED;
633
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);
639 return res;
640 }
641 }
642
643 return ERROR_OK;
644 }
645
646
647 static int same5_write(struct flash_bank *bank, const uint8_t *buffer,
648 uint32_t offset, uint32_t count)
649 {
650 int res;
651 uint32_t address;
652 uint32_t pg_offset;
653 uint32_t nb;
654 uint32_t nw;
655 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
656 uint8_t *pb = NULL;
657
658 res = same5_pre_write_check(bank->target);
659 if (res != ERROR_OK)
660 return res;
661
662 if (!chip->probed)
663 return ERROR_FLASH_BANK_NOT_PROBED;
664
665 res = same5_issue_nvmctrl_command(bank->target, SAME5_NVM_CMD_PBC);
666 if (res != ERROR_OK) {
667 LOG_ERROR("%s: %d", __func__, __LINE__);
668 return res;
669 }
670
671 while (count) {
672 nb = chip->page_size - offset % chip->page_size;
673 if (count < nb)
674 nb = count;
675
676 address = bank->base + offset;
677 pg_offset = offset % chip->page_size;
678
679 if (offset % 4 || (offset + nb) % 4) {
680 /* Either start or end of write is not word aligned */
681 if (!pb) {
682 pb = malloc(chip->page_size);
683 if (!pb)
684 return ERROR_FAIL;
685 }
686
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);
690
691 /* Align start address to a word boundary */
692 address -= offset % 4;
693 pg_offset -= offset % 4;
694 assert(pg_offset % 4 == 0);
695
696 /* Extend length to whole words */
697 nw = (nb + offset % 4 + 3) / 4;
698 assert(pg_offset + 4 * nw <= chip->page_size);
699
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);
703 } else {
704 assert(nb % 4 == 0);
705 nw = nb / 4;
706 assert(pg_offset + 4 * nw <= chip->page_size);
707
708 /* Word aligned data, use direct write from buffer */
709 res = target_write_memory(bank->target, address, 4, nw, buffer);
710 }
711 if (res != ERROR_OK) {
712 LOG_ERROR("%s: %d", __func__, __LINE__);
713 goto free_pb;
714 }
715
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);
719 goto free_pb;
720 }
721
722 /* We're done with the page contents */
723 count -= nb;
724 offset += nb;
725 buffer += nb;
726 }
727
728 free_pb:
729 free(pb);
730 return res;
731 }
732
733
734 FLASH_BANK_COMMAND_HANDLER(same5_flash_bank_command)
735 {
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);
739 return ERROR_FAIL;
740 }
741
742 struct samd_info *chip;
743 chip = calloc(1, sizeof(*chip));
744 if (!chip) {
745 LOG_ERROR("No memory for flash bank chip info");
746 return ERROR_FAIL;
747 }
748
749 chip->target = bank->target;
750 chip->probed = false;
751
752 bank->driver_priv = chip;
753
754 return ERROR_OK;
755 }
756
757
758 COMMAND_HANDLER(same5_handle_chip_erase_command)
759 {
760 struct target *target = get_current_target(CMD_CTX);
761 if (!target)
762 return ERROR_FAIL;
763
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 */
767
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));
771 if (res == ERROR_OK)
772 command_print(CMD, "chip erase started");
773 else
774 command_print(CMD, "write to DSU CTRL failed");
775
776 return res;
777 }
778
779
780 COMMAND_HANDLER(same5_handle_userpage_command)
781 {
782 int res = ERROR_OK;
783 struct target *target = get_current_target(CMD_CTX);
784 if (!target)
785 return ERROR_FAIL;
786
787 if (CMD_ARGC > 2) {
788 command_print(CMD, "Too much Arguments given.");
789 return ERROR_COMMAND_SYNTAX_ERROR;
790 }
791
792 if (CMD_ARGC >= 1) {
793 uint64_t value, mask = NVMUSERROW_SAM_E5_D5_MASK;
794 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], value);
795
796 if (CMD_ARGC == 2) {
797 uint64_t mask_temp;
798 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], mask_temp);
799 mask &= mask_temp;
800 }
801
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);
805
806 res = same5_modify_user_row_masked(target,
807 val_buf, mask_buf, 0, sizeof(val_buf));
808 }
809
810 uint8_t buffer[8];
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);
815 } else {
816 LOG_ERROR("USER PAGE could not be read.");
817 }
818
819 if (CMD_ARGC >= 1)
820 return res;
821 else
822 return res2;
823 }
824
825
826 COMMAND_HANDLER(same5_handle_bootloader_command)
827 {
828 int res = ERROR_OK;
829 struct target *target = get_current_target(CMD_CTX);
830 if (!target)
831 return ERROR_FAIL;
832
833 if (CMD_ARGC >= 1) {
834 unsigned long size;
835
836 COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[0], size);
837 uint32_t code = (size + 8191) / 8192;
838 if (code > 15) {
839 command_print(CMD, "Invalid bootloader size. Please "
840 "see datasheet for a list valid sizes.");
841 return ERROR_COMMAND_SYNTAX_ERROR;
842 }
843
844 res = same5_modify_user_row(target, 15 - code, 26, 29);
845 }
846
847 uint32_t val;
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);
854 }
855
856 if (CMD_ARGC >= 1)
857 return res;
858 else
859 return res2;
860 }
861
862
863 COMMAND_HANDLER(samd_handle_reset_deassert)
864 {
865 struct target *target = get_current_target(CMD_CTX);
866 int res = ERROR_OK;
867 enum reset_types jtag_reset_config = jtag_get_reset_config();
868 if (!target)
869 return ERROR_FAIL;
870
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);
875 target_poll(target);
876
877 /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset()
878 * so we just release reset held by DSU
879 *
880 * n_RESET (srst) clears the DP, so reenable debug and set vector catch here
881 *
882 * After vectreset DSU release is not needed however makes no harm
883 */
884 if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) {
885 res = target_write_u32(target, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
886 if (res == ERROR_OK)
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 */
890 }
891
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)
895 return res2;
896
897 return res;
898 }
899
900 static const struct command_registration same5_exec_command_handlers[] = {
901 {
902 .name = "dsu_reset_deassert",
903 .usage = "",
904 .handler = samd_handle_reset_deassert,
905 .mode = COMMAND_EXEC,
906 .help = "Deassert internal reset held by DSU."
907 },
908 {
909 .name = "chip-erase",
910 .usage = "",
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).",
915 },
916 {
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 "
923 "reset.",
924 },
925 {
926 .name = "userpage",
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.",
935 },
936 COMMAND_REGISTRATION_DONE
937 };
938
939 static const struct command_registration same5_command_handlers[] = {
940 {
941 .name = "atsame5",
942 .mode = COMMAND_ANY,
943 .help = "atsame5 flash command group",
944 .usage = "",
945 .chain = same5_exec_command_handlers,
946 },
947 COMMAND_REGISTRATION_DONE
948 };
949
950 const struct flash_driver atsame5_flash = {
951 .name = "atsame5",
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,
963 };

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)