flash/nor/at91samd: add small delay before checking nvm status
[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 != 1) {
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 /* Access through AHB is stalled while flash is being programmed */
662 usleep(200);
663
664 error = samd_check_error(bank->target);
665 if (error)
666 return ERROR_FAIL;
667
668 /* Next page */
669 address += chip->page_size;
670 buf += chip->page_size;
671 }
672
673 sector->is_erased = 0;
674
675 return res;
676 }
677
678 /* Write partial contents into row-aligned 'address' on the Flash from host
679 * buffer 'buf' by writing 'nb' of 'buf' at 'row_offset' into the Flash row. */
680 static int samd_write_row_partial(struct flash_bank *bank, uint32_t address,
681 const uint8_t *buf, uint32_t row_offset, uint32_t nb)
682 {
683 int res;
684 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
685 uint32_t row_size = chip->page_size * 4;
686 uint8_t *rb = malloc(row_size);
687 if (!rb)
688 return ERROR_FAIL;
689
690 assert(row_offset + nb < row_size);
691 assert((address % row_size) == 0);
692
693 /* Retrieve the full row contents from Flash */
694 res = target_read_memory(bank->target, address, 4, row_size / 4, rb);
695 if (res != ERROR_OK) {
696 free(rb);
697 return res;
698 }
699
700 /* Insert our partial row over the data from Flash */
701 memcpy(rb + (row_offset % row_size), buf, nb);
702
703 /* Write the row back out */
704 res = samd_write_row(bank, address, rb);
705 free(rb);
706
707 return res;
708 }
709
710 static int samd_write(struct flash_bank *bank, const uint8_t *buffer,
711 uint32_t offset, uint32_t count)
712 {
713 int res;
714 uint32_t address;
715 uint32_t nb = 0;
716 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
717 uint32_t row_size = chip->page_size * 4;
718
719 if (bank->target->state != TARGET_HALTED) {
720 LOG_ERROR("Target not halted");
721
722 return ERROR_TARGET_NOT_HALTED;
723 }
724
725 if (!chip->probed) {
726 if (samd_probe(bank) != ERROR_OK)
727 return ERROR_FLASH_BANK_NOT_PROBED;
728 }
729
730 if (offset % row_size) {
731 /* We're starting at an unaligned offset so we'll write a partial row
732 * comprising that offset and up to the end of that row. */
733 nb = row_size - (offset % row_size);
734 if (nb > count)
735 nb = count;
736 } else if (count < row_size) {
737 /* We're writing an aligned but partial row. */
738 nb = count;
739 }
740
741 address = (offset / row_size) * row_size + bank->base;
742
743 if (nb > 0) {
744 res = samd_write_row_partial(bank, address, buffer,
745 offset % row_size, nb);
746 if (res != ERROR_OK)
747 return res;
748
749 /* We're done with the row contents */
750 count -= nb;
751 offset += nb;
752 buffer += row_size;
753 }
754
755 /* There's at least one aligned row to write out. */
756 if (count >= row_size) {
757 int nr = count / row_size + ((count % row_size) ? 1 : 0);
758 unsigned int r = 0;
759
760 for (unsigned int i = address / row_size;
761 (i < (address / row_size) + nr) && count > 0; i++) {
762 address = (i * row_size) + bank->base;
763
764 if (count >= row_size) {
765 res = samd_write_row(bank, address, buffer + (r * row_size));
766 /* Advance one row */
767 offset += row_size;
768 count -= row_size;
769 } else {
770 res = samd_write_row_partial(bank, address,
771 buffer + (r * row_size), 0, count);
772 /* We're done after this. */
773 offset += count;
774 count = 0;
775 }
776
777 r++;
778
779 if (res != ERROR_OK)
780 return res;
781 }
782 }
783
784 return ERROR_OK;
785 }
786
787 FLASH_BANK_COMMAND_HANDLER(samd_flash_bank_command)
788 {
789 struct samd_info *chip = samd_chips;
790
791 while (chip) {
792 if (chip->target == bank->target)
793 break;
794 chip = chip->next;
795 }
796
797 if (!chip) {
798 /* Create a new chip */
799 chip = calloc(1, sizeof(*chip));
800 if (!chip)
801 return ERROR_FAIL;
802
803 chip->target = bank->target;
804 chip->probed = false;
805
806 bank->driver_priv = chip;
807
808 /* Insert it into the chips list (at head) */
809 chip->next = samd_chips;
810 samd_chips = chip;
811 }
812
813 if (bank->base != SAMD_FLASH) {
814 LOG_ERROR("Address 0x%08" PRIx32 " invalid bank address (try 0x%08" PRIx32
815 "[at91samd series] )",
816 bank->base, SAMD_FLASH);
817 return ERROR_FAIL;
818 }
819
820 return ERROR_OK;
821 }
822
823 COMMAND_HANDLER(samd_handle_info_command)
824 {
825 return ERROR_OK;
826 }
827
828 COMMAND_HANDLER(samd_handle_chip_erase_command)
829 {
830 struct target *target = get_current_target(CMD_CTX);
831
832 if (target) {
833 /* Enable access to the DSU by disabling the write protect bit */
834 target_write_u32(target, SAMD_PAC1, (1<<1));
835 /* Tell the DSU to perform a full chip erase. It takes about 240ms to
836 * perform the erase. */
837 target_write_u8(target, SAMD_DSU, (1<<4));
838
839 command_print(CMD_CTX, "chip erased");
840 }
841
842 return ERROR_OK;
843 }
844
845 COMMAND_HANDLER(samd_handle_set_security_command)
846 {
847 int res = ERROR_OK;
848 struct target *target = get_current_target(CMD_CTX);
849
850 if (CMD_ARGC < 1 || (CMD_ARGC >= 1 && (strcmp(CMD_ARGV[0], "enable")))) {
851 command_print(CMD_CTX, "supply the \"enable\" argument to proceed.");
852 return ERROR_COMMAND_SYNTAX_ERROR;
853 }
854
855 if (target) {
856 if (target->state != TARGET_HALTED) {
857 LOG_ERROR("Target not halted");
858 return ERROR_TARGET_NOT_HALTED;
859 }
860
861 res = samd_issue_nvmctrl_command(target, SAMD_NVM_CMD_SSB);
862
863 /* Check (and clear) error conditions */
864 if (res == ERROR_OK)
865 command_print(CMD_CTX, "chip secured on next power-cycle");
866 else
867 command_print(CMD_CTX, "failed to secure chip");
868 }
869
870 return res;
871 }
872
873 COMMAND_HANDLER(samd_handle_eeprom_command)
874 {
875 int res = ERROR_OK;
876 struct target *target = get_current_target(CMD_CTX);
877
878 if (target) {
879 if (target->state != TARGET_HALTED) {
880 LOG_ERROR("Target not halted");
881 return ERROR_TARGET_NOT_HALTED;
882 }
883
884 if (CMD_ARGC >= 1) {
885 int val = atoi(CMD_ARGV[0]);
886 uint32_t code;
887
888 if (val == 0)
889 code = 7;
890 else {
891 /* Try to match size in bytes with corresponding size code */
892 for (code = 0; code <= 6; code++) {
893 if (val == (2 << (13 - code)))
894 break;
895 }
896
897 if (code > 6) {
898 command_print(CMD_CTX, "Invalid EEPROM size. Please see "
899 "datasheet for a list valid sizes.");
900 return ERROR_COMMAND_SYNTAX_ERROR;
901 }
902 }
903
904 res = samd_modify_user_row(target, code, 4, 6);
905 } else {
906 uint16_t val;
907 res = target_read_u16(target, SAMD_USER_ROW, &val);
908 if (res == ERROR_OK) {
909 uint32_t size = ((val >> 4) & 0x7); /* grab size code */
910
911 if (size == 0x7)
912 command_print(CMD_CTX, "EEPROM is disabled");
913 else {
914 /* Otherwise, 6 is 256B, 0 is 16KB */
915 command_print(CMD_CTX, "EEPROM size is %u bytes",
916 (2 << (13 - size)));
917 }
918 }
919 }
920 }
921
922 return res;
923 }
924
925 COMMAND_HANDLER(samd_handle_bootloader_command)
926 {
927 int res = ERROR_OK;
928 struct target *target = get_current_target(CMD_CTX);
929
930 if (target) {
931 if (target->state != TARGET_HALTED) {
932 LOG_ERROR("Target not halted");
933 return ERROR_TARGET_NOT_HALTED;
934 }
935
936 /* Retrieve the MCU's page size, in bytes. */
937 uint32_t page_size;
938 res = samd_get_flash_page_info(target, &page_size, NULL);
939 if (res != ERROR_OK) {
940 LOG_ERROR("Couldn't determine Flash page size");
941 return res;
942 }
943
944 if (CMD_ARGC >= 1) {
945 int val = atoi(CMD_ARGV[0]);
946 uint32_t code;
947
948 if (val == 0)
949 code = 7;
950 else {
951 /* Try to match size in bytes with corresponding size code */
952 for (code = 0; code <= 6; code++) {
953 if ((unsigned int)val == (2UL << (8UL - code)) * page_size)
954 break;
955 }
956
957 if (code > 6) {
958 command_print(CMD_CTX, "Invalid bootloader size. Please "
959 "see datasheet for a list valid sizes.");
960 return ERROR_COMMAND_SYNTAX_ERROR;
961 }
962
963 }
964
965 res = samd_modify_user_row(target, code, 0, 2);
966 } else {
967 uint16_t val;
968 res = target_read_u16(target, SAMD_USER_ROW, &val);
969 if (res == ERROR_OK) {
970 uint32_t size = (val & 0x7); /* grab size code */
971 uint32_t nb;
972
973 if (size == 0x7)
974 nb = 0;
975 else
976 nb = (2 << (8 - size)) * page_size;
977
978 /* There are 4 pages per row */
979 command_print(CMD_CTX, "Bootloader size is %u bytes (%u rows)",
980 nb, nb / (page_size * 4));
981 }
982 }
983 }
984
985 return res;
986 }
987
988 static const struct command_registration at91samd_exec_command_handlers[] = {
989 {
990 .name = "info",
991 .handler = samd_handle_info_command,
992 .mode = COMMAND_EXEC,
993 .help = "Print information about the current at91samd chip"
994 "and its flash configuration.",
995 },
996 {
997 .name = "chip-erase",
998 .handler = samd_handle_chip_erase_command,
999 .mode = COMMAND_EXEC,
1000 .help = "Erase the entire Flash by using the Chip"
1001 "Erase feature in the Device Service Unit (DSU).",
1002 },
1003 {
1004 .name = "set-security",
1005 .handler = samd_handle_set_security_command,
1006 .mode = COMMAND_EXEC,
1007 .help = "Secure the chip's Flash by setting the Security Bit."
1008 "This makes it impossible to read the Flash contents."
1009 "The only way to undo this is to issue the chip-erase"
1010 "command.",
1011 },
1012 {
1013 .name = "eeprom",
1014 .usage = "[size_in_bytes]",
1015 .handler = samd_handle_eeprom_command,
1016 .mode = COMMAND_EXEC,
1017 .help = "Show or set the EEPROM size setting, stored in the User Row."
1018 "Please see Table 20-3 of the SAMD20 datasheet for allowed values."
1019 "Changes are stored immediately but take affect after the MCU is"
1020 "reset.",
1021 },
1022 {
1023 .name = "bootloader",
1024 .usage = "[size_in_bytes]",
1025 .handler = samd_handle_bootloader_command,
1026 .mode = COMMAND_EXEC,
1027 .help = "Show or set the bootloader size, stored in the User Row."
1028 "Please see Table 20-2 of the SAMD20 datasheet for allowed values."
1029 "Changes are stored immediately but take affect after the MCU is"
1030 "reset.",
1031 },
1032 COMMAND_REGISTRATION_DONE
1033 };
1034
1035 static const struct command_registration at91samd_command_handlers[] = {
1036 {
1037 .name = "at91samd",
1038 .mode = COMMAND_ANY,
1039 .help = "at91samd flash command group",
1040 .usage = "",
1041 .chain = at91samd_exec_command_handlers,
1042 },
1043 COMMAND_REGISTRATION_DONE
1044 };
1045
1046 struct flash_driver at91samd_flash = {
1047 .name = "at91samd",
1048 .commands = at91samd_command_handlers,
1049 .flash_bank_command = samd_flash_bank_command,
1050 .erase = samd_erase,
1051 .protect = samd_protect,
1052 .write = samd_write,
1053 .read = default_flash_read,
1054 .probe = samd_probe,
1055 .auto_probe = samd_probe,
1056 .erase_check = default_flash_blank_check,
1057 .protect_check = samd_protect_check,
1058 };

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)