jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / flash / nor / atsame5.c
1 /***************************************************************************
2 * Copyright (C) 2017 by Tomas Vanek *
3 * vanekt@fbl.cz *
4 * *
5 * Based on at91samd.c *
6 * Copyright (C) 2013 by Andrey Yurovsky *
7 * Andrey Yurovsky <yurovsky@gmail.com> *
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 * This program is distributed in the hope that it will be useful, *
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17 * GNU General Public License for more details. *
18 * *
19 * You should have received a copy of the GNU General Public License *
20 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
21 ***************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "imp.h"
28 #include "helper/binarybuffer.h"
29
30 #include <helper/time_support.h>
31 #include <jtag/jtag.h>
32 #include <target/cortex_m.h>
33
34 /* A note to prefixing.
35 * Definitions and functions inherited from at91samd.c without
36 * any change retained the original prefix samd_ so they eventually
37 * may go to samd_common.h and .c
38 * As currently there are only 3 short functions identical with
39 * the original source, no common file was created. */
40
41 #define SAME5_PAGES_PER_BLOCK 16
42 #define SAME5_NUM_PROT_BLOCKS 32
43 #define SAMD_PAGE_SIZE_MAX 1024
44
45 #define SAMD_FLASH 0x00000000 /* physical Flash memory */
46 #define SAMD_USER_ROW 0x00804000 /* User Row of Flash */
47
48 #define SAME5_PAC 0x40000000 /* Peripheral Access Control */
49
50 #define SAMD_DSU 0x41002000 /* Device Service Unit */
51 #define SAMD_NVMCTRL 0x41004000 /* Non-volatile memory controller */
52
53 #define SAMD_DSU_STATUSA 1 /* DSU status register */
54 #define SAMD_DSU_DID 0x18 /* Device ID register */
55 #define SAMD_DSU_CTRL_EXT 0x100 /* CTRL register, external access */
56
57 #define SAME5_NVMCTRL_CTRLA 0x00 /* NVM control A register */
58 #define SAME5_NVMCTRL_CTRLB 0x04 /* NVM control B register */
59 #define SAMD_NVMCTRL_PARAM 0x08 /* NVM parameters register */
60 #define SAME5_NVMCTRL_INTFLAG 0x10 /* NVM interrupt flag register */
61 #define SAME5_NVMCTRL_STATUS 0x12 /* NVM status register */
62 #define SAME5_NVMCTRL_ADDR 0x14 /* NVM address register */
63 #define SAME5_NVMCTRL_LOCK 0x18 /* NVM Lock section register */
64
65 #define SAMD_CMDEX_KEY 0xA5UL
66 #define SAMD_NVM_CMD(n) ((SAMD_CMDEX_KEY << 8) | (n & 0x7F))
67
68 /* NVMCTRL commands. */
69 #define SAME5_NVM_CMD_EP 0x00 /* Erase Page (User Page only) */
70 #define SAME5_NVM_CMD_EB 0x01 /* Erase Block */
71 #define SAME5_NVM_CMD_WP 0x03 /* Write Page */
72 #define SAME5_NVM_CMD_WQW 0x04 /* Write Quad Word */
73 #define SAME5_NVM_CMD_LR 0x11 /* Lock Region */
74 #define SAME5_NVM_CMD_UR 0x12 /* Unlock Region */
75 #define SAME5_NVM_CMD_PBC 0x15 /* Page Buffer Clear */
76 #define SAME5_NVM_CMD_SSB 0x16 /* Set Security Bit */
77
78 /* NVMCTRL bits */
79 #define SAME5_NVMCTRL_CTRLA_WMODE_MASK 0x30
80
81 #define SAME5_NVMCTRL_INTFLAG_DONE (1 << 0)
82 #define SAME5_NVMCTRL_INTFLAG_ADDRE (1 << 1)
83 #define SAME5_NVMCTRL_INTFLAG_PROGE (1 << 2)
84 #define SAME5_NVMCTRL_INTFLAG_LOCKE (1 << 3)
85 #define SAME5_NVMCTRL_INTFLAG_ECCSE (1 << 4)
86 #define SAME5_NVMCTRL_INTFLAG_ECCDE (1 << 5)
87 #define SAME5_NVMCTRL_INTFLAG_NVME (1 << 6)
88
89
90 /* Known identifiers */
91 #define SAMD_PROCESSOR_M0 0x01
92 #define SAMD_PROCESSOR_M4 0x06
93 #define SAMD_FAMILY_D 0x00
94 #define SAMD_FAMILY_E 0x03
95 #define SAMD_SERIES_51 0x06
96 #define SAME_SERIES_51 0x01
97 #define SAME_SERIES_53 0x03
98 #define SAME_SERIES_54 0x04
99
100 /* Device ID macros */
101 #define SAMD_GET_PROCESSOR(id) (id >> 28)
102 #define SAMD_GET_FAMILY(id) (((id >> 23) & 0x1F))
103 #define SAMD_GET_SERIES(id) (((id >> 16) & 0x3F))
104 #define SAMD_GET_DEVSEL(id) (id & 0xFF)
105
106 /* Bits to mask user row */
107 #define NVMUSERROW_SAM_E5_D5_MASK ((uint64_t)0x7FFF00FF3C007FFF)
108
109 struct samd_part {
110 uint8_t id;
111 const char *name;
112 uint32_t flash_kb;
113 uint32_t ram_kb;
114 };
115
116 /* See SAM D5x/E5x Family Silicon Errata and Data Sheet Clarification
117 * DS80000748K */
118 /* Known SAMD51 parts. */
119 static const struct samd_part samd51_parts[] = {
120 { 0x00, "SAMD51P20A", 1024, 256 },
121 { 0x01, "SAMD51P19A", 512, 192 },
122 { 0x02, "SAMD51N20A", 1024, 256 },
123 { 0x03, "SAMD51N19A", 512, 192 },
124 { 0x04, "SAMD51J20A", 1024, 256 },
125 { 0x05, "SAMD51J19A", 512, 192 },
126 { 0x06, "SAMD51J18A", 256, 128 },
127 { 0x07, "SAMD51G19A", 512, 192 },
128 { 0x08, "SAMD51G18A", 256, 128 },
129 };
130
131 /* Known SAME51 parts. */
132 static const struct samd_part same51_parts[] = {
133 { 0x00, "SAME51N20A", 1024, 256 },
134 { 0x01, "SAME51N19A", 512, 192 },
135 { 0x02, "SAME51J19A", 512, 192 },
136 { 0x03, "SAME51J18A", 256, 128 },
137 { 0x04, "SAME51J20A", 1024, 256 },
138 { 0x05, "SAME51G19A", 512, 192 }, /* New in rev D */
139 { 0x06, "SAME51G18A", 256, 128 }, /* New in rev D */
140 };
141
142 /* Known SAME53 parts. */
143 static const struct samd_part same53_parts[] = {
144 { 0x02, "SAME53N20A", 1024, 256 },
145 { 0x03, "SAME53N19A", 512, 192 },
146 { 0x04, "SAME53J20A", 1024, 256 },
147 { 0x05, "SAME53J19A", 512, 192 },
148 { 0x06, "SAME53J18A", 256, 128 },
149 };
150
151 /* Known SAME54 parts. */
152 static const struct samd_part same54_parts[] = {
153 { 0x00, "SAME54P20A", 1024, 256 },
154 { 0x01, "SAME54P19A", 512, 192 },
155 { 0x02, "SAME54N20A", 1024, 256 },
156 { 0x03, "SAME54N19A", 512, 192 },
157 };
158
159 /* Each family of parts contains a parts table in the DEVSEL field of DID. The
160 * processor ID, family ID, and series ID are used to determine which exact
161 * family this is and then we can use the corresponding table. */
162 struct samd_family {
163 uint8_t processor;
164 uint8_t family;
165 uint8_t series;
166 const struct samd_part *parts;
167 size_t num_parts;
168 };
169
170 /* Known SAMD families */
171 static const struct samd_family samd_families[] = {
172 { SAMD_PROCESSOR_M4, SAMD_FAMILY_D, SAMD_SERIES_51,
173 samd51_parts, ARRAY_SIZE(samd51_parts) },
174 { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, SAME_SERIES_51,
175 same51_parts, ARRAY_SIZE(same51_parts) },
176 { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, SAME_SERIES_53,
177 same53_parts, ARRAY_SIZE(same53_parts) },
178 { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, SAME_SERIES_54,
179 same54_parts, ARRAY_SIZE(same54_parts) },
180 };
181
182 struct samd_info {
183 const struct samd_params *par;
184 uint32_t page_size;
185 int num_pages;
186 int sector_size;
187 int prot_block_size;
188
189 bool probed;
190 struct target *target;
191 };
192
193
194 /**
195 * Gives the family structure to specific device id.
196 * @param id The id of the device.
197 * @return On failure NULL, otherwise a pointer to the structure.
198 */
199 static const struct samd_family *samd_find_family(uint32_t id)
200 {
201 uint8_t processor = SAMD_GET_PROCESSOR(id);
202 uint8_t family = SAMD_GET_FAMILY(id);
203 uint8_t series = SAMD_GET_SERIES(id);
204
205 for (unsigned i = 0; i < ARRAY_SIZE(samd_families); i++) {
206 if (samd_families[i].processor == processor &&
207 samd_families[i].series == series &&
208 samd_families[i].family == family)
209 return &samd_families[i];
210 }
211
212 return NULL;
213 }
214
215 /**
216 * Gives the part structure to specific device id.
217 * @param id The id of the device.
218 * @return On failure NULL, otherwise a pointer to the structure.
219 */
220 static const struct samd_part *samd_find_part(uint32_t id)
221 {
222 uint8_t devsel = SAMD_GET_DEVSEL(id);
223 const struct samd_family *family = samd_find_family(id);
224 if (!family)
225 return NULL;
226
227 for (unsigned i = 0; i < family->num_parts; i++) {
228 if (family->parts[i].id == devsel)
229 return &family->parts[i];
230 }
231
232 return NULL;
233 }
234
235 static int same5_protect_check(struct flash_bank *bank)
236 {
237 int res;
238 uint32_t lock;
239
240 res = target_read_u32(bank->target,
241 SAMD_NVMCTRL + SAME5_NVMCTRL_LOCK, &lock);
242 if (res != ERROR_OK)
243 return res;
244
245 /* Lock bits are active-low */
246 for (unsigned int prot_block = 0; prot_block < bank->num_prot_blocks; prot_block++)
247 bank->prot_blocks[prot_block].is_protected = !(lock & (1u<<prot_block));
248
249 return ERROR_OK;
250 }
251
252 static int samd_get_flash_page_info(struct target *target,
253 uint32_t *sizep, int *nump)
254 {
255 int res;
256 uint32_t param;
257
258 res = target_read_u32(target, SAMD_NVMCTRL + SAMD_NVMCTRL_PARAM, &param);
259 if (res == ERROR_OK) {
260 /* The PSZ field (bits 18:16) indicate the page size bytes as 2^(3+n)
261 * so 0 is 8KB and 7 is 1024KB. */
262 if (sizep)
263 *sizep = (8 << ((param >> 16) & 0x7));
264 /* The NVMP field (bits 15:0) indicates the total number of pages */
265 if (nump)
266 *nump = param & 0xFFFF;
267 } else {
268 LOG_ERROR("Couldn't read NVM Parameters register");
269 }
270
271 return res;
272 }
273
274 static int same5_probe(struct flash_bank *bank)
275 {
276 uint32_t id;
277 int res;
278 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
279 const struct samd_part *part;
280
281 if (chip->probed)
282 return ERROR_OK;
283
284 res = target_read_u32(bank->target, SAMD_DSU + SAMD_DSU_DID, &id);
285 if (res != ERROR_OK) {
286 LOG_ERROR("Couldn't read Device ID register");
287 return res;
288 }
289
290 part = samd_find_part(id);
291 if (!part) {
292 LOG_ERROR("Couldn't find part corresponding to DID %08" PRIx32, id);
293 return ERROR_FAIL;
294 }
295
296 bank->size = part->flash_kb * 1024;
297
298 res = samd_get_flash_page_info(bank->target, &chip->page_size,
299 &chip->num_pages);
300 if (res != ERROR_OK) {
301 LOG_ERROR("Couldn't determine Flash page size");
302 return res;
303 }
304
305 /* Sanity check: the total flash size in the DSU should match the page size
306 * multiplied by the number of pages. */
307 if (bank->size != chip->num_pages * chip->page_size) {
308 LOG_WARNING("SAM: bank size doesn't match NVM parameters. "
309 "Identified %" PRIu32 "KB Flash but NVMCTRL reports %u %" PRIu32 "B pages",
310 part->flash_kb, chip->num_pages, chip->page_size);
311 }
312
313 /* Erase granularity = 1 block = 16 pages */
314 chip->sector_size = chip->page_size * SAME5_PAGES_PER_BLOCK;
315
316 /* Allocate the sector table */
317 bank->num_sectors = chip->num_pages / SAME5_PAGES_PER_BLOCK;
318 bank->sectors = alloc_block_array(0, chip->sector_size, bank->num_sectors);
319 if (!bank->sectors)
320 return ERROR_FAIL;
321
322 /* 16 protection blocks per device */
323 chip->prot_block_size = bank->size / SAME5_NUM_PROT_BLOCKS;
324
325 /* Allocate the table of protection blocks */
326 bank->num_prot_blocks = SAME5_NUM_PROT_BLOCKS;
327 bank->prot_blocks = alloc_block_array(0, chip->prot_block_size, bank->num_prot_blocks);
328 if (!bank->prot_blocks)
329 return ERROR_FAIL;
330
331 same5_protect_check(bank);
332
333 /* Done */
334 chip->probed = true;
335
336 LOG_INFO("SAM MCU: %s (%" PRIu32 "KB Flash, %" PRIu32 "KB RAM)", part->name,
337 part->flash_kb, part->ram_kb);
338
339 return ERROR_OK;
340 }
341
342 static int same5_wait_and_check_error(struct target *target)
343 {
344 int ret, ret2;
345 /* Table 54-40 lists the maximum erase block time as 200 ms.
346 * Include some margin.
347 */
348 int timeout_ms = 200 * 5;
349 int64_t ts_start = timeval_ms();
350 uint16_t intflag;
351
352 do {
353 ret = target_read_u16(target,
354 SAMD_NVMCTRL + SAME5_NVMCTRL_INTFLAG, &intflag);
355 if (ret != ERROR_OK) {
356 LOG_ERROR("SAM: error reading the NVMCTRL_INTFLAG register");
357 return ret;
358 }
359 if (intflag & SAME5_NVMCTRL_INTFLAG_DONE)
360 break;
361 keep_alive();
362 } while (timeval_ms() - ts_start < timeout_ms);
363
364 if (!(intflag & SAME5_NVMCTRL_INTFLAG_DONE)) {
365 LOG_ERROR("SAM: NVM programming timed out");
366 ret = ERROR_FLASH_OPERATION_FAILED;
367 }
368 #if 0
369 if (intflag & SAME5_NVMCTRL_INTFLAG_ECCSE)
370 LOG_ERROR("SAM: ECC Single Error");
371
372 if (intflag & SAME5_NVMCTRL_INTFLAG_ECCDE) {
373 LOG_ERROR("SAM: ECC Double Error");
374 ret = ERROR_FLASH_OPERATION_FAILED;
375 }
376 #endif
377 if (intflag & SAME5_NVMCTRL_INTFLAG_ADDRE) {
378 LOG_ERROR("SAM: Addr Error");
379 ret = ERROR_FLASH_OPERATION_FAILED;
380 }
381
382 if (intflag & SAME5_NVMCTRL_INTFLAG_NVME) {
383 LOG_ERROR("SAM: NVM Error");
384 ret = ERROR_FLASH_OPERATION_FAILED;
385 }
386
387 if (intflag & SAME5_NVMCTRL_INTFLAG_LOCKE) {
388 LOG_ERROR("SAM: NVM lock error");
389 ret = ERROR_FLASH_PROTECTED;
390 }
391
392 if (intflag & SAME5_NVMCTRL_INTFLAG_PROGE) {
393 LOG_ERROR("SAM: NVM programming error");
394 ret = ERROR_FLASH_OPER_UNSUPPORTED;
395 }
396
397 /* Clear the error conditions by writing a one to them */
398 ret2 = target_write_u16(target,
399 SAMD_NVMCTRL + SAME5_NVMCTRL_INTFLAG, intflag);
400 if (ret2 != ERROR_OK)
401 LOG_ERROR("Can't clear NVM error conditions");
402
403 return ret;
404 }
405
406 static int same5_issue_nvmctrl_command(struct target *target, uint16_t cmd)
407 {
408 int res;
409
410 if (target->state != TARGET_HALTED) {
411 LOG_ERROR("Target not halted");
412 return ERROR_TARGET_NOT_HALTED;
413 }
414
415 /* Issue the NVM command */
416 /* 32-bit write is used to ensure atomic operation on ST-Link */
417 res = target_write_u32(target,
418 SAMD_NVMCTRL + SAME5_NVMCTRL_CTRLB, SAMD_NVM_CMD(cmd));
419 if (res != ERROR_OK)
420 return res;
421
422 /* Check to see if the NVM command resulted in an error condition. */
423 return same5_wait_and_check_error(target);
424 }
425
426 /**
427 * Erases a flash block or page at the given address.
428 * @param target Pointer to the target structure.
429 * @param address The address of the row.
430 * @return On success ERROR_OK, on failure an errorcode.
431 */
432 static int same5_erase_block(struct target *target, uint32_t address)
433 {
434 int res;
435
436 /* Set an address contained in the block to be erased */
437 res = target_write_u32(target,
438 SAMD_NVMCTRL + SAME5_NVMCTRL_ADDR, address);
439
440 /* Issue the Erase Block command. */
441 if (res == ERROR_OK)
442 res = same5_issue_nvmctrl_command(target,
443 address == SAMD_USER_ROW ? SAME5_NVM_CMD_EP : SAME5_NVM_CMD_EB);
444
445 if (res != ERROR_OK) {
446 LOG_ERROR("Failed to erase block containing %08" PRIx32, address);
447 return ERROR_FAIL;
448 }
449
450 return ERROR_OK;
451 }
452
453
454 static int same5_pre_write_check(struct target *target)
455 {
456 int res;
457 uint32_t nvm_ctrla;
458
459 if (target->state != TARGET_HALTED) {
460 LOG_ERROR("Target not halted");
461 return ERROR_TARGET_NOT_HALTED;
462 }
463
464 /* Check if manual write mode is set */
465 res = target_read_u32(target, SAMD_NVMCTRL + SAME5_NVMCTRL_CTRLA, &nvm_ctrla);
466 if (res != ERROR_OK)
467 return res;
468
469 if (nvm_ctrla & SAME5_NVMCTRL_CTRLA_WMODE_MASK) {
470 LOG_ERROR("The flash controller must be in manual write mode. Issue 'reset init' and retry.");
471 return ERROR_FAIL;
472 }
473
474 return res;
475 }
476
477
478 /**
479 * Modify the contents of the User Row in Flash. The User Row itself
480 * has a size of one page and contains a combination of "fuses" and
481 * calibration data. Bits which have a value of zero in the mask will
482 * not be changed.
483 * @param target Pointer to the target structure.
484 * @param data Pointer to the value to write.
485 * @param mask Pointer to bitmask, 0 -> value stays untouched.
486 * @param offset Offset in user row where new data will be applied.
487 * @param count Size of buffer and mask in bytes.
488 * @return On success ERROR_OK, on failure an errorcode.
489 */
490 static int same5_modify_user_row_masked(struct target *target,
491 const uint8_t *data, const uint8_t *mask,
492 uint32_t offset, uint32_t count)
493 {
494 int res;
495
496 /* Retrieve the MCU's flash page size, in bytes. */
497 uint32_t page_size;
498 res = samd_get_flash_page_info(target, &page_size, NULL);
499 if (res != ERROR_OK) {
500 LOG_ERROR("Couldn't determine Flash page size");
501 return res;
502 }
503
504 /* Make sure the size is sane. */
505 assert(page_size <= SAMD_PAGE_SIZE_MAX &&
506 page_size >= offset + count);
507
508 uint8_t buf[SAMD_PAGE_SIZE_MAX];
509 /* Read the user row (comprising one page) by words. */
510 res = target_read_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf);
511 if (res != ERROR_OK)
512 return res;
513
514 /* Modify buffer and check if really changed */
515 bool changed = false;
516 uint32_t i;
517 for (i = 0; i < count; i++) {
518 uint8_t old_b = buf[offset+i];
519 uint8_t new_b = (old_b & ~mask[i]) | (data[i] & mask[i]);
520 buf[offset+i] = new_b;
521 if (old_b != new_b)
522 changed = true;
523 }
524
525 if (!changed)
526 return ERROR_OK;
527
528 res = same5_pre_write_check(target);
529 if (res != ERROR_OK)
530 return res;
531
532 res = same5_erase_block(target, SAMD_USER_ROW);
533 if (res != ERROR_OK) {
534 LOG_ERROR("Couldn't erase user row");
535 return res;
536 }
537
538 /* Write the page buffer back out to the target using Write Quad Word */
539 for (i = 0; i < page_size; i += 4 * 4) {
540 res = target_write_memory(target, SAMD_USER_ROW + i, 4, 4, buf + i);
541 if (res != ERROR_OK)
542 return res;
543
544 /* Trigger flash write */
545 res = same5_issue_nvmctrl_command(target, SAME5_NVM_CMD_WQW);
546 if (res != ERROR_OK)
547 return res;
548 }
549
550 return res;
551 }
552
553 /**
554 * Modifies the user row register to the given value.
555 * @param target Pointer to the target structure.
556 * @param value The value to write.
557 * @param startb The bit-offset by which the given value is shifted.
558 * @param endb The bit-offset of the last bit in value to write.
559 * @return On success ERROR_OK, on failure an errorcode.
560 */
561 static int same5_modify_user_row(struct target *target, uint32_t value,
562 uint8_t startb, uint8_t endb)
563 {
564 uint8_t buf_val[8] = { 0 };
565 uint8_t buf_mask[8] = { 0 };
566
567 assert(startb <= endb && endb < 64);
568 buf_set_u32(buf_val, startb, endb + 1 - startb, value);
569 buf_set_u32(buf_mask, startb, endb + 1 - startb, 0xffffffff);
570
571 return same5_modify_user_row_masked(target,
572 buf_val, buf_mask, 0, 8);
573 }
574
575 static int same5_protect(struct flash_bank *bank, int set, unsigned int first,
576 unsigned int last)
577 {
578 int res = ERROR_OK;
579
580 /* We can issue lock/unlock region commands with the target running but
581 * the settings won't persist unless we're able to modify the LOCK regions
582 * and that requires the target to be halted. */
583 if (bank->target->state != TARGET_HALTED) {
584 LOG_ERROR("Target not halted");
585 return ERROR_TARGET_NOT_HALTED;
586 }
587
588 for (unsigned int prot_block = first; prot_block <= last; prot_block++) {
589 if (set != bank->prot_blocks[prot_block].is_protected) {
590 /* Load an address that is within this protection block (we use offset 0) */
591 res = target_write_u32(bank->target,
592 SAMD_NVMCTRL + SAME5_NVMCTRL_ADDR,
593 bank->prot_blocks[prot_block].offset);
594 if (res != ERROR_OK)
595 goto exit;
596
597 /* Tell the controller to lock that block */
598 res = same5_issue_nvmctrl_command(bank->target,
599 set ? SAME5_NVM_CMD_LR : SAME5_NVM_CMD_UR);
600 if (res != ERROR_OK)
601 goto exit;
602 }
603 }
604
605 /* We've now applied our changes, however they will be undone by the next
606 * reset unless we also apply them to the LOCK bits in the User Page.
607 * A '1' means unlocked and a '0' means locked. */
608 const uint8_t lock[4] = { 0, 0, 0, 0 };
609 const uint8_t unlock[4] = { 0xff, 0xff, 0xff, 0xff };
610 uint8_t mask[4] = { 0, 0, 0, 0 };
611
612 buf_set_u32(mask, first, last + 1 - first, 0xffffffff);
613
614 res = same5_modify_user_row_masked(bank->target,
615 set ? lock : unlock, mask, 8, 4);
616 if (res != ERROR_OK)
617 LOG_WARNING("SAM: protect settings were not made persistent!");
618
619 res = ERROR_OK;
620
621 exit:
622 same5_protect_check(bank);
623
624 return res;
625 }
626
627 static int same5_erase(struct flash_bank *bank, unsigned int first,
628 unsigned int last)
629 {
630 int res;
631 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
632
633 if (bank->target->state != TARGET_HALTED) {
634 LOG_ERROR("Target not halted");
635
636 return ERROR_TARGET_NOT_HALTED;
637 }
638
639 if (!chip->probed)
640 return ERROR_FLASH_BANK_NOT_PROBED;
641
642 /* For each sector to be erased */
643 for (unsigned int s = first; s <= last; s++) {
644 res = same5_erase_block(bank->target, bank->sectors[s].offset);
645 if (res != ERROR_OK) {
646 LOG_ERROR("SAM: failed to erase sector %d at 0x%08" PRIx32, s, bank->sectors[s].offset);
647 return res;
648 }
649 }
650
651 return ERROR_OK;
652 }
653
654
655 static int same5_write(struct flash_bank *bank, const uint8_t *buffer,
656 uint32_t offset, uint32_t count)
657 {
658 int res;
659 uint32_t address;
660 uint32_t pg_offset;
661 uint32_t nb;
662 uint32_t nw;
663 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
664 uint8_t *pb = NULL;
665
666 res = same5_pre_write_check(bank->target);
667 if (res != ERROR_OK)
668 return res;
669
670 if (!chip->probed)
671 return ERROR_FLASH_BANK_NOT_PROBED;
672
673 res = same5_issue_nvmctrl_command(bank->target, SAME5_NVM_CMD_PBC);
674 if (res != ERROR_OK) {
675 LOG_ERROR("%s: %d", __func__, __LINE__);
676 return res;
677 }
678
679 while (count) {
680 nb = chip->page_size - offset % chip->page_size;
681 if (count < nb)
682 nb = count;
683
684 address = bank->base + offset;
685 pg_offset = offset % chip->page_size;
686
687 if (offset % 4 || (offset + nb) % 4) {
688 /* Either start or end of write is not word aligned */
689 if (!pb) {
690 pb = malloc(chip->page_size);
691 if (!pb)
692 return ERROR_FAIL;
693 }
694
695 /* Set temporary page buffer to 0xff and overwrite the relevant part */
696 memset(pb, 0xff, chip->page_size);
697 memcpy(pb + pg_offset, buffer, nb);
698
699 /* Align start address to a word boundary */
700 address -= offset % 4;
701 pg_offset -= offset % 4;
702 assert(pg_offset % 4 == 0);
703
704 /* Extend length to whole words */
705 nw = (nb + offset % 4 + 3) / 4;
706 assert(pg_offset + 4 * nw <= chip->page_size);
707
708 /* Now we have original data extended by 0xff bytes
709 * to the nearest word boundary on both start and end */
710 res = target_write_memory(bank->target, address, 4, nw, pb + pg_offset);
711 } else {
712 assert(nb % 4 == 0);
713 nw = nb / 4;
714 assert(pg_offset + 4 * nw <= chip->page_size);
715
716 /* Word aligned data, use direct write from buffer */
717 res = target_write_memory(bank->target, address, 4, nw, buffer);
718 }
719 if (res != ERROR_OK) {
720 LOG_ERROR("%s: %d", __func__, __LINE__);
721 goto free_pb;
722 }
723
724 res = same5_issue_nvmctrl_command(bank->target, SAME5_NVM_CMD_WP);
725 if (res != ERROR_OK) {
726 LOG_ERROR("%s: write failed at address 0x%08" PRIx32, __func__, address);
727 goto free_pb;
728 }
729
730 /* We're done with the page contents */
731 count -= nb;
732 offset += nb;
733 buffer += nb;
734 }
735
736 free_pb:
737 free(pb);
738 return res;
739 }
740
741
742 FLASH_BANK_COMMAND_HANDLER(same5_flash_bank_command)
743 {
744 if (bank->base != SAMD_FLASH) {
745 LOG_ERROR("Address " TARGET_ADDR_FMT " invalid bank address (try "
746 "0x%08x[same5] )", bank->base, SAMD_FLASH);
747 return ERROR_FAIL;
748 }
749
750 struct samd_info *chip;
751 chip = calloc(1, sizeof(*chip));
752 if (!chip) {
753 LOG_ERROR("No memory for flash bank chip info");
754 return ERROR_FAIL;
755 }
756
757 chip->target = bank->target;
758 chip->probed = false;
759
760 bank->driver_priv = chip;
761
762 return ERROR_OK;
763 }
764
765
766 COMMAND_HANDLER(same5_handle_chip_erase_command)
767 {
768 struct target *target = get_current_target(CMD_CTX);
769 if (!target)
770 return ERROR_FAIL;
771
772 /* Enable access to the DSU by disabling the write protect bit */
773 target_write_u32(target, SAME5_PAC, (1<<16) | (1<<5) | (1<<1));
774 /* intentionally without error checking - not accessible on secured chip */
775
776 /* Tell the DSU to perform a full chip erase. It takes about 240ms to
777 * perform the erase. */
778 int res = target_write_u8(target, SAMD_DSU + SAMD_DSU_CTRL_EXT, (1<<4));
779 if (res == ERROR_OK)
780 command_print(CMD, "chip erase started");
781 else
782 command_print(CMD, "write to DSU CTRL failed");
783
784 return res;
785 }
786
787
788 COMMAND_HANDLER(same5_handle_userpage_command)
789 {
790 int res = ERROR_OK;
791 struct target *target = get_current_target(CMD_CTX);
792 if (!target)
793 return ERROR_FAIL;
794
795 if (CMD_ARGC > 2) {
796 command_print(CMD, "Too much Arguments given.");
797 return ERROR_COMMAND_SYNTAX_ERROR;
798 }
799
800 if (CMD_ARGC >= 1) {
801 uint64_t value, mask = NVMUSERROW_SAM_E5_D5_MASK;
802 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], value);
803
804 if (CMD_ARGC == 2) {
805 uint64_t mask_temp;
806 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], mask_temp);
807 mask &= mask_temp;
808 }
809
810 uint8_t val_buf[8], mask_buf[8];
811 target_buffer_set_u64(target, val_buf, value);
812 target_buffer_set_u64(target, mask_buf, mask);
813
814 res = same5_modify_user_row_masked(target,
815 val_buf, mask_buf, 0, sizeof(val_buf));
816 }
817
818 uint8_t buffer[8];
819 int res2 = target_read_memory(target, SAMD_USER_ROW, 4, 2, buffer);
820 if (res2 == ERROR_OK) {
821 uint64_t value = target_buffer_get_u64(target, buffer);
822 command_print(CMD, "USER PAGE: 0x%016"PRIX64, value);
823 } else {
824 LOG_ERROR("USER PAGE could not be read.");
825 }
826
827 if (CMD_ARGC >= 1)
828 return res;
829 else
830 return res2;
831 }
832
833
834 COMMAND_HANDLER(same5_handle_bootloader_command)
835 {
836 int res = ERROR_OK;
837 struct target *target = get_current_target(CMD_CTX);
838 if (!target)
839 return ERROR_FAIL;
840
841 if (CMD_ARGC >= 1) {
842 unsigned long size;
843
844 COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[0], size);
845 uint32_t code = (size + 8191) / 8192;
846 if (code > 15) {
847 command_print(CMD, "Invalid bootloader size. Please "
848 "see datasheet for a list valid sizes.");
849 return ERROR_COMMAND_SYNTAX_ERROR;
850 }
851
852 res = same5_modify_user_row(target, 15 - code, 26, 29);
853 }
854
855 uint32_t val;
856 int res2 = target_read_u32(target, SAMD_USER_ROW, &val);
857 if (res2 == ERROR_OK) {
858 uint32_t code = (val >> 26) & 0xf; /* grab size code */
859 uint32_t size = (15 - code) * 8192;
860 command_print(CMD, "Bootloader protected in the first %"
861 PRIu32 " bytes", size);
862 }
863
864 if (CMD_ARGC >= 1)
865 return res;
866 else
867 return res2;
868 }
869
870
871 COMMAND_HANDLER(samd_handle_reset_deassert)
872 {
873 struct target *target = get_current_target(CMD_CTX);
874 int res = ERROR_OK;
875 enum reset_types jtag_reset_config = jtag_get_reset_config();
876 if (!target)
877 return ERROR_FAIL;
878
879 /* If the target has been unresponsive before, try to re-establish
880 * communication now - CPU is held in reset by DSU, DAP is working */
881 if (!target_was_examined(target))
882 target_examine_one(target);
883 target_poll(target);
884
885 /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset()
886 * so we just release reset held by DSU
887 *
888 * n_RESET (srst) clears the DP, so reenable debug and set vector catch here
889 *
890 * After vectreset DSU release is not needed however makes no harm
891 */
892 if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) {
893 res = target_write_u32(target, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
894 if (res == ERROR_OK)
895 res = target_write_u32(target, DCB_DEMCR,
896 TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
897 /* do not return on error here, releasing DSU reset is more important */
898 }
899
900 /* clear CPU Reset Phase Extension bit */
901 int res2 = target_write_u8(target, SAMD_DSU + SAMD_DSU_STATUSA, (1<<1));
902 if (res2 != ERROR_OK)
903 return res2;
904
905 return res;
906 }
907
908 static const struct command_registration same5_exec_command_handlers[] = {
909 {
910 .name = "dsu_reset_deassert",
911 .usage = "",
912 .handler = samd_handle_reset_deassert,
913 .mode = COMMAND_EXEC,
914 .help = "Deassert internal reset held by DSU."
915 },
916 {
917 .name = "chip-erase",
918 .usage = "",
919 .handler = same5_handle_chip_erase_command,
920 .mode = COMMAND_EXEC,
921 .help = "Erase the entire Flash by using the Chip-"
922 "Erase feature in the Device Service Unit (DSU).",
923 },
924 {
925 .name = "bootloader",
926 .usage = "[size_in_bytes]",
927 .handler = same5_handle_bootloader_command,
928 .mode = COMMAND_EXEC,
929 .help = "Show or set the bootloader protection size, stored in the User Row. "
930 "Changes are stored immediately but take affect after the MCU is "
931 "reset.",
932 },
933 {
934 .name = "userpage",
935 .usage = "[value] [mask]",
936 .handler = same5_handle_userpage_command,
937 .mode = COMMAND_EXEC,
938 .help = "Show or set the first 64-bit part of user page "
939 "located at address 0x804000. Use the optional mask argument "
940 "to prevent changes at positions where the bitvalue is zero. "
941 "For security reasons the reserved-bits are masked out "
942 "in background and therefore cannot be changed.",
943 },
944 COMMAND_REGISTRATION_DONE
945 };
946
947 static const struct command_registration same5_command_handlers[] = {
948 {
949 .name = "atsame5",
950 .mode = COMMAND_ANY,
951 .help = "atsame5 flash command group",
952 .usage = "",
953 .chain = same5_exec_command_handlers,
954 },
955 COMMAND_REGISTRATION_DONE
956 };
957
958 const struct flash_driver atsame5_flash = {
959 .name = "atsame5",
960 .commands = same5_command_handlers,
961 .flash_bank_command = same5_flash_bank_command,
962 .erase = same5_erase,
963 .protect = same5_protect,
964 .write = same5_write,
965 .read = default_flash_read,
966 .probe = same5_probe,
967 .auto_probe = same5_probe,
968 .erase_check = default_flash_blank_check,
969 .protect_check = same5_protect_check,
970 .free_driver_priv = default_flash_free_driver_priv,
971 };

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)