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

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)