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

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)