at91samd: fix protect, add EEPROM and boot commands
[openocd.git] / src / flash / nor / at91samd.c
1 /***************************************************************************
2 * Copyright (C) 2013 by Andrey Yurovsky *
3 * Andrey Yurovsky <yurovsky@gmail.com> *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
19 ***************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "imp.h"
26 #include "helper/binarybuffer.h"
27
28 #define SAMD_NUM_SECTORS 16
29 #define SAMD_PAGE_SIZE_MAX 1024
30
31 #define SAMD_FLASH ((uint32_t)0x00000000) /* physical Flash memory */
32 #define SAMD_USER_ROW ((uint32_t)0x00804000) /* User Row of Flash */
33 #define SAMD_PAC1 0x41000000 /* Peripheral Access Control 1 */
34 #define SAMD_DSU 0x41002000 /* Device Service Unit */
35 #define SAMD_NVMCTRL 0x41004000 /* Non-volatile memory controller */
36
37 #define SAMD_DSU_DID 0x18 /* Device ID register */
38
39 #define SAMD_NVMCTRL_CTRLA 0x00 /* NVM control A register */
40 #define SAMD_NVMCTRL_CTRLB 0x04 /* NVM control B register */
41 #define SAMD_NVMCTRL_PARAM 0x08 /* NVM parameters register */
42 #define SAMD_NVMCTRL_INTFLAG 0x18 /* NVM Interupt Flag Status & Clear */
43 #define SAMD_NVMCTRL_STATUS 0x18 /* NVM status register */
44 #define SAMD_NVMCTRL_ADDR 0x1C /* NVM address register */
45 #define SAMD_NVMCTRL_LOCK 0x20 /* NVM Lock section register */
46
47 #define SAMD_CMDEX_KEY 0xA5UL
48 #define SAMD_NVM_CMD(n) ((SAMD_CMDEX_KEY << 8) | (n & 0x7F))
49
50 /* NVMCTRL commands. See Table 20-4 in 42129F–SAM–10/2013 */
51 #define SAMD_NVM_CMD_ER 0x02 /* Erase Row */
52 #define SAMD_NVM_CMD_WP 0x04 /* Write Page */
53 #define SAMD_NVM_CMD_EAR 0x05 /* Erase Auxilary Row */
54 #define SAMD_NVM_CMD_WAP 0x06 /* Write Auxilary Page */
55 #define SAMD_NVM_CMD_LR 0x40 /* Lock Region */
56 #define SAMD_NVM_CMD_UR 0x41 /* Unlock Region */
57 #define SAMD_NVM_CMD_SPRM 0x42 /* Set Power Reduction Mode */
58 #define SAMD_NVM_CMD_CPRM 0x43 /* Clear Power Reduction Mode */
59 #define SAMD_NVM_CMD_PBC 0x44 /* Page Buffer Clear */
60 #define SAMD_NVM_CMD_SSB 0x45 /* Set Security Bit */
61 #define SAMD_NVM_CMD_INVALL 0x46 /* Invalidate all caches */
62
63 /* Known identifiers */
64 #define SAMD_PROCESSOR_M0 0x01
65 #define SAMD_FAMILY_D 0x00
66 #define SAMD_SERIES_20 0x00
67 #define SAMD_SERIES_21 0x01
68 #define SAMD_SERIES_10 0x02
69 #define SAMD_SERIES_11 0x03
70
71 struct samd_part {
72 uint8_t id;
73 const char *name;
74 uint32_t flash_kb;
75 uint32_t ram_kb;
76 };
77
78 /* Known SAMD10 parts */
79 static const struct samd_part samd10_parts[] = {
80 { 0x0, "SAMD10D14AMU", 16, 4 },
81 { 0x1, "SAMD10D13AMU", 8, 4 },
82 { 0x2, "SAMD10D12AMU", 4, 4 },
83 { 0x3, "SAMD10D14ASU", 16, 4 },
84 { 0x4, "SAMD10D13ASU", 8, 4 },
85 { 0x5, "SAMD10D12ASU", 4, 4 },
86 { 0x6, "SAMD10C14A", 16, 4 },
87 { 0x7, "SAMD10C13A", 8, 4 },
88 { 0x8, "SAMD10C12A", 4, 4 },
89 };
90
91 /* Known SAMD11 parts */
92 static const struct samd_part samd11_parts[] = {
93 { 0x0, "SAMD11D14AMU", 16, 4 },
94 { 0x1, "SAMD11D13AMU", 8, 4 },
95 { 0x2, "SAMD11D12AMU", 4, 4 },
96 { 0x3, "SAMD11D14ASU", 16, 4 },
97 { 0x4, "SAMD11D13ASU", 8, 4 },
98 { 0x5, "SAMD11D12ASU", 4, 4 },
99 { 0x6, "SAMD11C14A", 16, 4 },
100 { 0x7, "SAMD11C13A", 8, 4 },
101 { 0x8, "SAMD11C12A", 4, 4 },
102 };
103
104 /* Known SAMD20 parts. See Table 12-8 in 42129F–SAM–10/2013 */
105 static const struct samd_part samd20_parts[] = {
106 { 0x0, "SAMD20J18A", 256, 32 },
107 { 0x1, "SAMD20J17A", 128, 16 },
108 { 0x2, "SAMD20J16A", 64, 8 },
109 { 0x3, "SAMD20J15A", 32, 4 },
110 { 0x4, "SAMD20J14A", 16, 2 },
111 { 0x5, "SAMD20G18A", 256, 32 },
112 { 0x6, "SAMD20G17A", 128, 16 },
113 { 0x7, "SAMD20G16A", 64, 8 },
114 { 0x8, "SAMD20G15A", 32, 4 },
115 { 0x9, "SAMD20G14A", 16, 2 },
116 { 0xA, "SAMD20E18A", 256, 32 },
117 { 0xB, "SAMD20E17A", 128, 16 },
118 { 0xC, "SAMD20E16A", 64, 8 },
119 { 0xD, "SAMD20E15A", 32, 4 },
120 { 0xE, "SAMD20E14A", 16, 2 },
121 };
122
123 /* Known SAMD21 parts. */
124 static const struct samd_part samd21_parts[] = {
125 { 0x0, "SAMD21J18A", 256, 32 },
126 { 0x1, "SAMD21J17A", 128, 16 },
127 { 0x2, "SAMD21J16A", 64, 8 },
128 { 0x3, "SAMD21J15A", 32, 4 },
129 { 0x4, "SAMD21J14A", 16, 2 },
130 { 0x5, "SAMD21G18A", 256, 32 },
131 { 0x6, "SAMD21G17A", 128, 16 },
132 { 0x7, "SAMD21G16A", 64, 8 },
133 { 0x8, "SAMD21G15A", 32, 4 },
134 { 0x9, "SAMD21G14A", 16, 2 },
135 { 0xA, "SAMD21E18A", 256, 32 },
136 { 0xB, "SAMD21E17A", 128, 16 },
137 { 0xC, "SAMD21E16A", 64, 8 },
138 { 0xD, "SAMD21E15A", 32, 4 },
139 { 0xE, "SAMD21E14A", 16, 2 },
140 };
141
142 /* Known SAMR21 parts. */
143 static const struct samd_part samr21_parts[] = {
144 { 0x19, "SAMR21G18A", 256, 32 },
145 { 0x1A, "SAMR21G17A", 128, 32 },
146 { 0x1B, "SAMR21G16A", 64, 32 },
147 { 0x1C, "SAMR21E18A", 256, 32 },
148 { 0x1D, "SAMR21E17A", 128, 32 },
149 { 0x1E, "SAMR21E16A", 64, 32 },
150 };
151
152
153 /* Each family of parts contains a parts table in the DEVSEL field of DID. The
154 * processor ID, family ID, and series ID are used to determine which exact
155 * family this is and then we can use the corresponding table. */
156 struct samd_family {
157 uint8_t processor;
158 uint8_t family;
159 uint8_t series;
160 const struct samd_part *parts;
161 size_t num_parts;
162 };
163
164 /* Known SAMD families */
165 static const struct samd_family samd_families[] = {
166 { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_20,
167 samd20_parts, ARRAY_SIZE(samd20_parts) },
168 { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_21,
169 samd21_parts, ARRAY_SIZE(samd21_parts) },
170 { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_21,
171 samr21_parts, ARRAY_SIZE(samr21_parts) },
172 { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_10,
173 samd10_parts, ARRAY_SIZE(samd10_parts) },
174 { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_11,
175 samd11_parts, ARRAY_SIZE(samd11_parts) },
176 };
177
178 struct samd_info {
179 uint32_t page_size;
180 int num_pages;
181 int sector_size;
182
183 bool probed;
184 struct target *target;
185 struct samd_info *next;
186 };
187
188 static struct samd_info *samd_chips;
189
190 static const struct samd_part *samd_find_part(uint32_t id)
191 {
192 uint8_t processor = (id >> 28);
193 uint8_t family = (id >> 24) & 0x0F;
194 uint8_t series = (id >> 16) & 0xFF;
195 uint8_t devsel = id & 0xFF;
196
197 for (unsigned i = 0; i < ARRAY_SIZE(samd_families); i++) {
198 if (samd_families[i].processor == processor &&
199 samd_families[i].series == series &&
200 samd_families[i].family == family) {
201 for (unsigned j = 0; j < samd_families[i].num_parts; j++) {
202 if (samd_families[i].parts[j].id == devsel)
203 return &samd_families[i].parts[j];
204 }
205 }
206 }
207
208 return NULL;
209 }
210
211 static int samd_protect_check(struct flash_bank *bank)
212 {
213 int res;
214 uint16_t lock;
215
216 res = target_read_u16(bank->target,
217 SAMD_NVMCTRL + SAMD_NVMCTRL_LOCK, &lock);
218 if (res != ERROR_OK)
219 return res;
220
221 /* Lock bits are active-low */
222 for (int i = 0; i < bank->num_sectors; i++)
223 bank->sectors[i].is_protected = !(lock & (1<<i));
224
225 return ERROR_OK;
226 }
227
228 static int samd_get_flash_page_info(struct target *target,
229 uint32_t *sizep, int *nump)
230 {
231 int res;
232 uint32_t param;
233
234 res = target_read_u32(target, SAMD_NVMCTRL + SAMD_NVMCTRL_PARAM, &param);
235 if (res == ERROR_OK) {
236 /* The PSZ field (bits 18:16) indicate the page size bytes as 2^(3+n)
237 * so 0 is 8KB and 7 is 1024KB. */
238 if (sizep)
239 *sizep = (8 << ((param >> 16) & 0x7));
240 /* The NVMP field (bits 15:0) indicates the total number of pages */
241 if (nump)
242 *nump = param & 0xFFFF;
243 } else {
244 LOG_ERROR("Couldn't read NVM Parameters register");
245 }
246
247 return res;
248 }
249
250 static int samd_probe(struct flash_bank *bank)
251 {
252 uint32_t id;
253 int res;
254 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
255 const struct samd_part *part;
256
257 if (chip->probed)
258 return ERROR_OK;
259
260 res = target_read_u32(bank->target, SAMD_DSU + SAMD_DSU_DID, &id);
261 if (res != ERROR_OK) {
262 LOG_ERROR("Couldn't read Device ID register");
263 return res;
264 }
265
266 part = samd_find_part(id);
267 if (part == NULL) {
268 LOG_ERROR("Couldn't find part correspoding to DID %08" PRIx32, id);
269 return ERROR_FAIL;
270 }
271
272 bank->size = part->flash_kb * 1024;
273
274 chip->sector_size = bank->size / SAMD_NUM_SECTORS;
275
276 res = samd_get_flash_page_info(bank->target, &chip->page_size,
277 &chip->num_pages);
278 if (res != ERROR_OK) {
279 LOG_ERROR("Couldn't determine Flash page size");
280 return res;
281 }
282
283 /* Sanity check: the total flash size in the DSU should match the page size
284 * multiplied by the number of pages. */
285 if (bank->size != chip->num_pages * chip->page_size) {
286 LOG_WARNING("SAMD: bank size doesn't match NVM parameters. "
287 "Identified %" PRIu32 "KB Flash but NVMCTRL reports %u %" PRIu32 "B pages",
288 part->flash_kb, chip->num_pages, chip->page_size);
289 }
290
291 /* Allocate the sector table */
292 bank->num_sectors = SAMD_NUM_SECTORS;
293 bank->sectors = calloc(bank->num_sectors, sizeof((bank->sectors)[0]));
294 if (!bank->sectors)
295 return ERROR_FAIL;
296
297 /* Fill out the sector information: all SAMD sectors are the same size and
298 * there is always a fixed number of them. */
299 for (int i = 0; i < bank->num_sectors; i++) {
300 bank->sectors[i].size = chip->sector_size;
301 bank->sectors[i].offset = i * chip->sector_size;
302 /* mark as unknown */
303 bank->sectors[i].is_erased = -1;
304 bank->sectors[i].is_protected = -1;
305 }
306
307 samd_protect_check(bank);
308
309 /* Done */
310 chip->probed = true;
311
312 LOG_INFO("SAMD MCU: %s (%" PRIu32 "KB Flash, %" PRIu32 "KB RAM)", part->name,
313 part->flash_kb, part->ram_kb);
314
315 return ERROR_OK;
316 }
317
318 static bool samd_check_error(struct target *target)
319 {
320 int ret;
321 bool error;
322 uint16_t status;
323
324 ret = target_read_u16(target,
325 SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, &status);
326 if (ret != ERROR_OK) {
327 LOG_ERROR("Can't read NVM status");
328 return true;
329 }
330
331 if (status & 0x001C) {
332 if (status & (1 << 4)) /* NVME */
333 LOG_ERROR("SAMD: NVM Error");
334 if (status & (1 << 3)) /* LOCKE */
335 LOG_ERROR("SAMD: NVM lock error");
336 if (status & (1 << 2)) /* PROGE */
337 LOG_ERROR("SAMD: NVM programming error");
338
339 error = true;
340 } else {
341 error = false;
342 }
343
344 /* Clear the error conditions by writing a one to them */
345 ret = target_write_u16(target,
346 SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, status);
347 if (ret != ERROR_OK)
348 LOG_ERROR("Can't clear NVM error conditions");
349
350 return error;
351 }
352
353 static int samd_issue_nvmctrl_command(struct target *target, uint16_t cmd)
354 {
355 if (target->state != TARGET_HALTED) {
356 LOG_ERROR("Target not halted");
357 return ERROR_TARGET_NOT_HALTED;
358 }
359
360 /* Read current configuration. */
361 uint16_t tmp = 0;
362 int res = target_read_u16(target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLB,
363 &tmp);
364 if (res != ERROR_OK)
365 return res;
366
367 /* Set cache disable. */
368 res = target_write_u16(target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLB,
369 tmp | (1<<18));
370 if (res != ERROR_OK)
371 return res;
372
373 /* Issue the NVM command */
374 int res_cmd = target_write_u16(target,
375 SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLA, SAMD_NVM_CMD(cmd));
376
377 /* Try to restore configuration, regardless of NVM command write
378 * status. */
379 res = target_write_u16(target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLB, tmp);
380
381 if (res_cmd != ERROR_OK)
382 return res_cmd;
383
384 if (res != ERROR_OK)
385 return res;
386
387 /* Check to see if the NVM command resulted in an error condition. */
388 if (samd_check_error(target))
389 return ERROR_FAIL;
390
391 return ERROR_OK;
392 }
393
394 static int samd_erase_row(struct target *target, uint32_t address)
395 {
396 int res;
397
398 /* Set an address contained in the row to be erased */
399 res = target_write_u32(target,
400 SAMD_NVMCTRL + SAMD_NVMCTRL_ADDR, address >> 1);
401
402 /* Issue the Erase Row command to erase that row. */
403 if (res == ERROR_OK)
404 res = samd_issue_nvmctrl_command(target,
405 address == SAMD_USER_ROW ? SAMD_NVM_CMD_EAR : SAMD_NVM_CMD_ER);
406
407 if (res != ERROR_OK) {
408 LOG_ERROR("Failed to erase row containing %08" PRIx32, address);
409 return ERROR_FAIL;
410 }
411
412 return ERROR_OK;
413 }
414
415 static bool is_user_row_reserved_bit(uint8_t bit)
416 {
417 /* See Table 9-3 in the SAMD20 datasheet for more information. */
418 switch (bit) {
419 /* Reserved bits */
420 case 3:
421 case 7:
422 /* Voltage regulator internal configuration with default value of 0x70,
423 * may not be changed. */
424 case 17 ... 24:
425 /* 41 is voltage regulator internal configuration and must not be
426 * changed. 42 through 47 are reserved. */
427 case 41 ... 47:
428 return true;
429 default:
430 break;
431 }
432
433 return false;
434 }
435
436 /* Modify the contents of the User Row in Flash. These are described in Table
437 * 9-3 of the SAMD20 datasheet. The User Row itself has a size of one page
438 * and contains a combination of "fuses" and calibration data in bits 24:17.
439 * We therefore try not to erase the row's contents unless we absolutely have
440 * to and we don't permit modifying reserved bits. */
441 static int samd_modify_user_row(struct target *target, uint32_t value,
442 uint8_t startb, uint8_t endb)
443 {
444 int res;
445
446 if (is_user_row_reserved_bit(startb) || is_user_row_reserved_bit(endb)) {
447 LOG_ERROR("Can't modify bits in the requested range");
448 return ERROR_FAIL;
449 }
450
451 /* Retrieve the MCU's page size, in bytes. This is also the size of the
452 * entire User Row. */
453 uint32_t page_size;
454 res = samd_get_flash_page_info(target, &page_size, NULL);
455 if (res != ERROR_OK) {
456 LOG_ERROR("Couldn't determine Flash page size");
457 return res;
458 }
459
460 /* Make sure the size is sane before we allocate. */
461 assert(page_size > 0 && page_size <= SAMD_PAGE_SIZE_MAX);
462
463 /* Make sure we're within the single page that comprises the User Row. */
464 if (startb >= (page_size * 8) || endb >= (page_size * 8)) {
465 LOG_ERROR("Can't modify bits outside the User Row page range");
466 return ERROR_FAIL;
467 }
468
469 uint8_t *buf = malloc(page_size);
470 if (!buf)
471 return ERROR_FAIL;
472
473 /* Read the user row (comprising one page) by half-words. */
474 res = target_read_memory(target, SAMD_USER_ROW, 2, page_size / 2, buf);
475 if (res != ERROR_OK)
476 goto out_user_row;
477
478 /* We will need to erase before writing if the new value needs a '1' in any
479 * position for which the current value had a '0'. Otherwise we can avoid
480 * erasing. */
481 uint32_t cur = buf_get_u32(buf, startb, endb - startb + 1);
482 if ((~cur) & value) {
483 res = samd_erase_row(target, SAMD_USER_ROW);
484 if (res != ERROR_OK) {
485 LOG_ERROR("Couldn't erase user row");
486 goto out_user_row;
487 }
488 }
489
490 /* Modify */
491 buf_set_u32(buf, startb, endb - startb + 1, value);
492
493 /* Write the page buffer back out to the target. A Flash write will be
494 * triggered automatically. */
495 res = target_write_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf);
496 if (res != ERROR_OK)
497 goto out_user_row;
498
499 if (samd_check_error(target)) {
500 res = ERROR_FAIL;
501 goto out_user_row;
502 }
503
504 /* Success */
505 res = ERROR_OK;
506
507 out_user_row:
508 free(buf);
509
510 return res;
511 }
512
513 static int samd_protect(struct flash_bank *bank, int set, int first, int last)
514 {
515 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
516
517 /* We can issue lock/unlock region commands with the target running but
518 * the settings won't persist unless we're able to modify the LOCK regions
519 * and that requires the target to be halted. */
520 if (bank->target->state != TARGET_HALTED) {
521 LOG_ERROR("Target not halted");
522 return ERROR_TARGET_NOT_HALTED;
523 }
524
525 int res = ERROR_OK;
526
527 for (int s = first; s <= last; s++) {
528 if (set != bank->sectors[s].is_protected) {
529 /* Load an address that is within this sector (we use offset 0) */
530 res = target_write_u32(bank->target,
531 SAMD_NVMCTRL + SAMD_NVMCTRL_ADDR,
532 ((s * chip->sector_size) >> 1));
533 if (res != ERROR_OK)
534 goto exit;
535
536 /* Tell the controller to lock that sector */
537 res = samd_issue_nvmctrl_command(bank->target,
538 set ? SAMD_NVM_CMD_LR : SAMD_NVM_CMD_UR);
539 if (res != ERROR_OK)
540 goto exit;
541 }
542 }
543
544 /* We've now applied our changes, however they will be undone by the next
545 * reset unless we also apply them to the LOCK bits in the User Page. The
546 * LOCK bits start at bit 48, correspoding to Sector 0 and end with bit 63,
547 * corresponding to Sector 15. A '1' means unlocked and a '0' means
548 * locked. See Table 9-3 in the SAMD20 datasheet for more details. */
549
550 res = samd_modify_user_row(bank->target, set ? 0x0000 : 0xFFFF,
551 48 + first, 48 + last);
552 if (res != ERROR_OK)
553 LOG_WARNING("SAMD: protect settings were not made persistent!");
554
555 res = ERROR_OK;
556
557 exit:
558 samd_protect_check(bank);
559
560 return res;
561 }
562
563 static int samd_erase(struct flash_bank *bank, int first, int last)
564 {
565 int res;
566 int rows_in_sector;
567 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
568
569 if (bank->target->state != TARGET_HALTED) {
570 LOG_ERROR("Target not halted");
571
572 return ERROR_TARGET_NOT_HALTED;
573 }
574
575 if (!chip->probed) {
576 if (samd_probe(bank) != ERROR_OK)
577 return ERROR_FLASH_BANK_NOT_PROBED;
578 }
579
580 /* The SAMD NVM has row erase granularity. There are four pages in a row
581 * and the number of rows in a sector depends on the sector size, which in
582 * turn depends on the Flash capacity as there is a fixed number of
583 * sectors. */
584 rows_in_sector = chip->sector_size / (chip->page_size * 4);
585
586 /* For each sector to be erased */
587 for (int s = first; s <= last; s++) {
588 if (bank->sectors[s].is_protected) {
589 LOG_ERROR("SAMD: failed to erase sector %d. That sector is write-protected", s);
590 return ERROR_FLASH_OPERATION_FAILED;
591 }
592
593 if (!bank->sectors[s].is_erased) {
594 /* For each row in that sector */
595 for (int r = s * rows_in_sector; r < (s + 1) * rows_in_sector; r++) {
596 res = samd_erase_row(bank->target, r * chip->page_size * 4);
597 if (res != ERROR_OK) {
598 LOG_ERROR("SAMD: failed to erase sector %d", s);
599 return res;
600 }
601 }
602
603 bank->sectors[s].is_erased = 1;
604 }
605 }
606
607 return ERROR_OK;
608 }
609
610 static struct flash_sector *samd_find_sector_by_address(struct flash_bank *bank, uint32_t address)
611 {
612 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
613
614 for (int i = 0; i < bank->num_sectors; i++) {
615 if (bank->sectors[i].offset <= address &&
616 address < bank->sectors[i].offset + chip->sector_size)
617 return &bank->sectors[i];
618 }
619 return NULL;
620 }
621
622 /* Write an entire row (four pages) from host buffer 'buf' to row-aligned
623 * 'address' in the Flash. */
624 static int samd_write_row(struct flash_bank *bank, uint32_t address,
625 const uint8_t *buf)
626 {
627 int res;
628 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
629
630 struct flash_sector *sector = samd_find_sector_by_address(bank, address);
631
632 if (!sector) {
633 LOG_ERROR("Can't find sector corresponding to address 0x%08" PRIx32, address);
634 return ERROR_FLASH_OPERATION_FAILED;
635 }
636
637 if (sector->is_protected) {
638 LOG_ERROR("Trying to write to a protected sector at 0x%08" PRIx32, address);
639 return ERROR_FLASH_OPERATION_FAILED;
640 }
641
642 /* Erase the row that we'll be writing to */
643 res = samd_erase_row(bank->target, address);
644 if (res != ERROR_OK)
645 return res;
646
647 /* Now write the pages in this row. */
648 for (unsigned int i = 0; i < 4; i++) {
649 bool error;
650
651 /* Write the page contents to the target's page buffer. A page write
652 * is issued automatically once the last location is written in the
653 * page buffer (ie: a complete page has been written out). */
654 res = target_write_memory(bank->target, address, 4,
655 chip->page_size / 4, buf);
656 if (res != ERROR_OK) {
657 LOG_ERROR("%s: %d", __func__, __LINE__);
658 return res;
659 }
660
661 error = samd_check_error(bank->target);
662 if (error)
663 return ERROR_FAIL;
664
665 /* Next page */
666 address += chip->page_size;
667 buf += chip->page_size;
668 }
669
670 sector->is_erased = 0;
671
672 return res;
673 }
674
675 /* Write partial contents into row-aligned 'address' on the Flash from host
676 * buffer 'buf' by writing 'nb' of 'buf' at 'row_offset' into the Flash row. */
677 static int samd_write_row_partial(struct flash_bank *bank, uint32_t address,
678 const uint8_t *buf, uint32_t row_offset, uint32_t nb)
679 {
680 int res;
681 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
682 uint32_t row_size = chip->page_size * 4;
683 uint8_t *rb = malloc(row_size);
684 if (!rb)
685 return ERROR_FAIL;
686
687 assert(row_offset + nb < row_size);
688 assert((address % row_size) == 0);
689
690 /* Retrieve the full row contents from Flash */
691 res = target_read_memory(bank->target, address, 4, row_size / 4, rb);
692 if (res != ERROR_OK) {
693 free(rb);
694 return res;
695 }
696
697 /* Insert our partial row over the data from Flash */
698 memcpy(rb + (row_offset % row_size), buf, nb);
699
700 /* Write the row back out */
701 res = samd_write_row(bank, address, rb);
702 free(rb);
703
704 return res;
705 }
706
707 static int samd_write(struct flash_bank *bank, const uint8_t *buffer,
708 uint32_t offset, uint32_t count)
709 {
710 int res;
711 uint32_t address;
712 uint32_t nb = 0;
713 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
714 uint32_t row_size = chip->page_size * 4;
715
716 if (bank->target->state != TARGET_HALTED) {
717 LOG_ERROR("Target not halted");
718
719 return ERROR_TARGET_NOT_HALTED;
720 }
721
722 if (!chip->probed) {
723 if (samd_probe(bank) != ERROR_OK)
724 return ERROR_FLASH_BANK_NOT_PROBED;
725 }
726
727 if (offset % row_size) {
728 /* We're starting at an unaligned offset so we'll write a partial row
729 * comprising that offset and up to the end of that row. */
730 nb = row_size - (offset % row_size);
731 if (nb > count)
732 nb = count;
733 } else if (count < row_size) {
734 /* We're writing an aligned but partial row. */
735 nb = count;
736 }
737
738 address = (offset / row_size) * row_size + bank->base;
739
740 if (nb > 0) {
741 res = samd_write_row_partial(bank, address, buffer,
742 offset % row_size, nb);
743 if (res != ERROR_OK)
744 return res;
745
746 /* We're done with the row contents */
747 count -= nb;
748 offset += nb;
749 buffer += row_size;
750 }
751
752 /* There's at least one aligned row to write out. */
753 if (count >= row_size) {
754 int nr = count / row_size + ((count % row_size) ? 1 : 0);
755 unsigned int r = 0;
756
757 for (unsigned int i = address / row_size;
758 (i < (address / row_size) + nr) && count > 0; i++) {
759 address = (i * row_size) + bank->base;
760
761 if (count >= row_size) {
762 res = samd_write_row(bank, address, buffer + (r * row_size));
763 /* Advance one row */
764 offset += row_size;
765 count -= row_size;
766 } else {
767 res = samd_write_row_partial(bank, address,
768 buffer + (r * row_size), 0, count);
769 /* We're done after this. */
770 offset += count;
771 count = 0;
772 }
773
774 r++;
775
776 if (res != ERROR_OK)
777 return res;
778 }
779 }
780
781 return ERROR_OK;
782 }
783
784 FLASH_BANK_COMMAND_HANDLER(samd_flash_bank_command)
785 {
786 struct samd_info *chip = samd_chips;
787
788 while (chip) {
789 if (chip->target == bank->target)
790 break;
791 chip = chip->next;
792 }
793
794 if (!chip) {
795 /* Create a new chip */
796 chip = calloc(1, sizeof(*chip));
797 if (!chip)
798 return ERROR_FAIL;
799
800 chip->target = bank->target;
801 chip->probed = false;
802
803 bank->driver_priv = chip;
804
805 /* Insert it into the chips list (at head) */
806 chip->next = samd_chips;
807 samd_chips = chip;
808 }
809
810 if (bank->base != SAMD_FLASH) {
811 LOG_ERROR("Address 0x%08" PRIx32 " invalid bank address (try 0x%08" PRIx32
812 "[at91samd series] )",
813 bank->base, SAMD_FLASH);
814 return ERROR_FAIL;
815 }
816
817 return ERROR_OK;
818 }
819
820 COMMAND_HANDLER(samd_handle_info_command)
821 {
822 return ERROR_OK;
823 }
824
825 COMMAND_HANDLER(samd_handle_chip_erase_command)
826 {
827 struct target *target = get_current_target(CMD_CTX);
828
829 if (target) {
830 /* Enable access to the DSU by disabling the write protect bit */
831 target_write_u32(target, SAMD_PAC1, (1<<1));
832 /* Tell the DSU to perform a full chip erase. It takes about 240ms to
833 * perform the erase. */
834 target_write_u8(target, SAMD_DSU, (1<<4));
835
836 command_print(CMD_CTX, "chip erased");
837 }
838
839 return ERROR_OK;
840 }
841
842 COMMAND_HANDLER(samd_handle_set_security_command)
843 {
844 int res = ERROR_OK;
845 struct target *target = get_current_target(CMD_CTX);
846
847 if (CMD_ARGC < 1 || (CMD_ARGC >= 1 && (strcmp(CMD_ARGV[0], "enable")))) {
848 command_print(CMD_CTX, "supply the \"enable\" argument to proceed.");
849 return ERROR_COMMAND_SYNTAX_ERROR;
850 }
851
852 if (target) {
853 if (target->state != TARGET_HALTED) {
854 LOG_ERROR("Target not halted");
855 return ERROR_TARGET_NOT_HALTED;
856 }
857
858 res = samd_issue_nvmctrl_command(target, SAMD_NVM_CMD_SSB);
859
860 /* Check (and clear) error conditions */
861 if (res == ERROR_OK)
862 command_print(CMD_CTX, "chip secured on next power-cycle");
863 else
864 command_print(CMD_CTX, "failed to secure chip");
865 }
866
867 return res;
868 }
869
870 COMMAND_HANDLER(samd_handle_eeprom_command)
871 {
872 int res = ERROR_OK;
873 struct target *target = get_current_target(CMD_CTX);
874
875 if (target) {
876 if (target->state != TARGET_HALTED) {
877 LOG_ERROR("Target not halted");
878 return ERROR_TARGET_NOT_HALTED;
879 }
880
881 if (CMD_ARGC >= 1) {
882 int val = atoi(CMD_ARGV[0]);
883 uint32_t code;
884
885 if (val == 0)
886 code = 7;
887 else {
888 /* Try to match size in bytes with corresponding size code */
889 for (code = 0; code <= 6; code++) {
890 if (val == (2 << (13 - code)))
891 break;
892 }
893
894 if (code > 6) {
895 command_print(CMD_CTX, "Invalid EEPROM size. Please see "
896 "datasheet for a list valid sizes.");
897 return ERROR_COMMAND_SYNTAX_ERROR;
898 }
899 }
900
901 res = samd_modify_user_row(target, code, 4, 6);
902 } else {
903 uint16_t val;
904 res = target_read_u16(target, SAMD_USER_ROW, &val);
905 if (res == ERROR_OK) {
906 uint32_t size = ((val >> 4) & 0x7); /* grab size code */
907
908 if (size == 0x7)
909 command_print(CMD_CTX, "EEPROM is disabled");
910 else {
911 /* Otherwise, 6 is 256B, 0 is 16KB */
912 command_print(CMD_CTX, "EEPROM size is %u bytes",
913 (2 << (13 - size)));
914 }
915 }
916 }
917 }
918
919 return res;
920 }
921
922 COMMAND_HANDLER(samd_handle_bootloader_command)
923 {
924 int res = ERROR_OK;
925 struct target *target = get_current_target(CMD_CTX);
926
927 if (target) {
928 if (target->state != TARGET_HALTED) {
929 LOG_ERROR("Target not halted");
930 return ERROR_TARGET_NOT_HALTED;
931 }
932
933 /* Retrieve the MCU's page size, in bytes. */
934 uint32_t page_size;
935 res = samd_get_flash_page_info(target, &page_size, NULL);
936 if (res != ERROR_OK) {
937 LOG_ERROR("Couldn't determine Flash page size");
938 return res;
939 }
940
941 if (CMD_ARGC >= 1) {
942 int val = atoi(CMD_ARGV[0]);
943 uint32_t code;
944
945 if (val == 0)
946 code = 7;
947 else {
948 /* Try to match size in bytes with corresponding size code */
949 for (code = 0; code <= 6; code++) {
950 if ((unsigned int)val == (2UL << (8UL - code)) * page_size)
951 break;
952 }
953
954 if (code > 6) {
955 command_print(CMD_CTX, "Invalid bootloader size. Please "
956 "see datasheet for a list valid sizes.");
957 return ERROR_COMMAND_SYNTAX_ERROR;
958 }
959
960 }
961
962 res = samd_modify_user_row(target, code, 0, 2);
963 } else {
964 uint16_t val;
965 res = target_read_u16(target, SAMD_USER_ROW, &val);
966 if (res == ERROR_OK) {
967 uint32_t size = (val & 0x7); /* grab size code */
968 uint32_t nb;
969
970 if (size == 0x7)
971 nb = 0;
972 else
973 nb = (2 << (8 - size)) * page_size;
974
975 /* There are 4 pages per row */
976 command_print(CMD_CTX, "Bootloader size is %u bytes (%u rows)",
977 nb, nb / (page_size * 4));
978 }
979 }
980 }
981
982 return res;
983 }
984
985 static const struct command_registration at91samd_exec_command_handlers[] = {
986 {
987 .name = "info",
988 .handler = samd_handle_info_command,
989 .mode = COMMAND_EXEC,
990 .help = "Print information about the current at91samd chip"
991 "and its flash configuration.",
992 },
993 {
994 .name = "chip-erase",
995 .handler = samd_handle_chip_erase_command,
996 .mode = COMMAND_EXEC,
997 .help = "Erase the entire Flash by using the Chip"
998 "Erase feature in the Device Service Unit (DSU).",
999 },
1000 {
1001 .name = "set-security",
1002 .handler = samd_handle_set_security_command,
1003 .mode = COMMAND_EXEC,
1004 .help = "Secure the chip's Flash by setting the Security Bit."
1005 "This makes it impossible to read the Flash contents."
1006 "The only way to undo this is to issue the chip-erase"
1007 "command.",
1008 },
1009 {
1010 .name = "eeprom",
1011 .usage = "[size_in_bytes]",
1012 .handler = samd_handle_eeprom_command,
1013 .mode = COMMAND_EXEC,
1014 .help = "Show or set the EEPROM size setting, stored in the User Row."
1015 "Please see Table 20-3 of the SAMD20 datasheet for allowed values."
1016 "Changes are stored immediately but take affect after the MCU is"
1017 "reset.",
1018 },
1019 {
1020 .name = "bootloader",
1021 .usage = "[size_in_bytes]",
1022 .handler = samd_handle_bootloader_command,
1023 .mode = COMMAND_EXEC,
1024 .help = "Show or set the bootloader size, stored in the User Row."
1025 "Please see Table 20-2 of the SAMD20 datasheet for allowed values."
1026 "Changes are stored immediately but take affect after the MCU is"
1027 "reset.",
1028 },
1029 COMMAND_REGISTRATION_DONE
1030 };
1031
1032 static const struct command_registration at91samd_command_handlers[] = {
1033 {
1034 .name = "at91samd",
1035 .mode = COMMAND_ANY,
1036 .help = "at91samd flash command group",
1037 .usage = "",
1038 .chain = at91samd_exec_command_handlers,
1039 },
1040 COMMAND_REGISTRATION_DONE
1041 };
1042
1043 struct flash_driver at91samd_flash = {
1044 .name = "at91samd",
1045 .commands = at91samd_command_handlers,
1046 .flash_bank_command = samd_flash_bank_command,
1047 .erase = samd_erase,
1048 .protect = samd_protect,
1049 .write = samd_write,
1050 .read = default_flash_read,
1051 .probe = samd_probe,
1052 .auto_probe = samd_probe,
1053 .erase_check = default_flash_blank_check,
1054 .protect_check = samd_protect_check,
1055 };

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)