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

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)