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

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)