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

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)