Fix usage of timeval_ms()
[openocd.git] / src / flash / nor / atsamv.c
1 /***************************************************************************
2 * Copyright (C) 2009 by Duane Ellis *
3 * openocd@duaneellis.com *
4 * *
5 * Copyright (C) 2010 by Olaf Lüke (at91sam3s* support) *
6 * olaf@uni-paderborn.de *
7 * *
8 * Copyright (C) 2011 by Olivier Schonken, Jim Norris *
9 * (at91sam3x* & at91sam4 support)* *
10 * *
11 * Copyright (C) 2015 Morgan Quigley *
12 * (atsamv, atsams, and atsame support) *
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 * This program is distributed in the hope that it will be useful, *
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22 * GNU General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU General Public License *
25 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
26 ***************************************************************************/
27
28 /* Some of the the lower level code was based on code supplied by
29 * ATMEL under this copyright. */
30
31 /* BEGIN ATMEL COPYRIGHT */
32 /* ----------------------------------------------------------------------------
33 * ATMEL Microcontroller Software Support
34 * ----------------------------------------------------------------------------
35 * Copyright (c) 2009, Atmel Corporation
36 *
37 * All rights reserved.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions are met:
41 *
42 * - Redistributions of source code must retain the above copyright notice,
43 * this list of conditions and the disclaimer below.
44 *
45 * Atmel's name may not be used to endorse or promote products derived from
46 * this software without specific prior written permission.
47 *
48 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
49 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
50 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
51 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
52 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
53 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
54 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
55 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
56 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
57 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58 * ----------------------------------------------------------------------------
59 */
60 /* END ATMEL COPYRIGHT */
61
62 #ifdef HAVE_CONFIG_H
63 #include "config.h"
64 #endif
65
66 #include "imp.h"
67 #include <helper/time_support.h>
68
69 #define REG_NAME_WIDTH (12)
70
71 #define SAMV_EFC_FCMD_GETD (0x0) /* (EFC) Get Flash Descriptor */
72 #define SAMV_EFC_FCMD_WP (0x1) /* (EFC) Write Page */
73 #define SAMV_EFC_FCMD_WPL (0x2) /* (EFC) Write Page and Lock */
74 #define SAMV_EFC_FCMD_EWP (0x3) /* (EFC) Erase Page and Write Page */
75 #define SAMV_EFC_FCMD_EWPL (0x4) /* (EFC) Erase Page, Write Page then Lock*/
76 #define SAMV_EFC_FCMD_EA (0x5) /* (EFC) Erase All */
77 #define SAMV_EFC_FCMD_EPA (0x7) /* (EFC) Erase pages */
78 #define SAMV_EFC_FCMD_SLB (0x8) /* (EFC) Set Lock Bit */
79 #define SAMV_EFC_FCMD_CLB (0x9) /* (EFC) Clear Lock Bit */
80 #define SAMV_EFC_FCMD_GLB (0xA) /* (EFC) Get Lock Bit */
81 #define SAMV_EFC_FCMD_SFB (0xB) /* (EFC) Set Fuse Bit */
82 #define SAMV_EFC_FCMD_CFB (0xC) /* (EFC) Clear Fuse Bit */
83 #define SAMV_EFC_FCMD_GFB (0xD) /* (EFC) Get Fuse Bit */
84
85 #define OFFSET_EFC_FMR 0
86 #define OFFSET_EFC_FCR 4
87 #define OFFSET_EFC_FSR 8
88 #define OFFSET_EFC_FRR 12
89
90 #define SAMV_CHIPID_CIDR (0x400E0940)
91 #define SAMV_NUM_GPNVM_BITS 9
92 #define SAMV_CONTROLLER_ADDR (0x400e0c00)
93 #define SAMV_SECTOR_SIZE 16384
94 #define SAMV_PAGE_SIZE 512
95 #define SAMV_FLASH_BASE 0x00400000
96
97 extern struct flash_driver atsamv_flash;
98
99 struct samv_flash_bank {
100 int probed;
101 unsigned size_bytes;
102 unsigned gpnvm[SAMV_NUM_GPNVM_BITS];
103 };
104
105 /* The actual sector size of the SAMV7 flash memory is 128K bytes.
106 * 16 sectors for a 2048KB device. The lock regions are 16KB per lock
107 * region, with a 2048KB device having 128 lock regions.
108 * For the best results, num_sectors is thus set to the number of lock
109 * regions, and the sector_size set to the lock region size. Page
110 * erases are used to erase 16KB sections when programming */
111
112 static int samv_efc_get_status(struct target *target, uint32_t *v)
113 {
114 int r = target_read_u32(target, SAMV_CONTROLLER_ADDR + OFFSET_EFC_FSR, v);
115 return r;
116 }
117
118 static int samv_efc_get_result(struct target *target, uint32_t *v)
119 {
120 uint32_t rv;
121 int r = target_read_u32(target, SAMV_CONTROLLER_ADDR + OFFSET_EFC_FRR, &rv);
122 if (v)
123 *v = rv;
124 return r;
125 }
126
127 static int samv_efc_start_command(struct target *target,
128 unsigned command, unsigned argument)
129 {
130 uint32_t v;
131 samv_efc_get_status(target, &v);
132 if (!(v & 1)) {
133 LOG_ERROR("flash controller is not ready");
134 return ERROR_FAIL;
135 }
136
137 v = (0x5A << 24) | (argument << 8) | command;
138 LOG_DEBUG("starting flash command: 0x%08x", (unsigned int)(v));
139 int r = target_write_u32(target, SAMV_CONTROLLER_ADDR + OFFSET_EFC_FCR, v);
140 if (r != ERROR_OK)
141 LOG_DEBUG("write failed");
142 return r;
143 }
144
145 static int samv_efc_perform_command(struct target *target,
146 unsigned command, unsigned argument, uint32_t *status)
147 {
148 int r;
149 uint32_t v;
150 int64_t ms_now, ms_end;
151
152 if (status)
153 *status = 0;
154
155 r = samv_efc_start_command(target, command, argument);
156 if (r != ERROR_OK)
157 return r;
158
159 ms_end = 10000 + timeval_ms();
160
161 do {
162 r = samv_efc_get_status(target, &v);
163 if (r != ERROR_OK)
164 return r;
165 ms_now = timeval_ms();
166 if (ms_now > ms_end) {
167 /* error */
168 LOG_ERROR("Command timeout");
169 return ERROR_FAIL;
170 }
171 } while ((v & 1) == 0);
172
173 /* if requested, copy the flash controller error bits back to the caller */
174 if (status)
175 *status = (v & 0x6);
176 return ERROR_OK;
177 }
178
179 static int samv_erase_pages(struct target *target,
180 int first_page, int num_pages, uint32_t *status)
181 {
182 uint8_t erase_pages;
183 switch (num_pages) {
184 case 4:
185 erase_pages = 0x00;
186 break;
187 case 8:
188 erase_pages = 0x01;
189 break;
190 case 16:
191 erase_pages = 0x02;
192 break;
193 case 32:
194 erase_pages = 0x03;
195 break;
196 default:
197 erase_pages = 0x00;
198 break;
199 }
200
201 /* SAMV_EFC_FCMD_EPA
202 * According to the datasheet FARG[15:2] defines the page from which
203 * the erase will start.This page must be modulo 4, 8, 16 or 32
204 * according to the number of pages to erase. FARG[1:0] defines the
205 * number of pages to be erased. Previously (firstpage << 2) was used
206 * to conform to this, seems it should not be shifted...
207 */
208 return samv_efc_perform_command(target, SAMV_EFC_FCMD_EPA,
209 first_page | erase_pages, status);
210 }
211
212 static int samv_get_gpnvm(struct target *target, unsigned gpnvm, unsigned *out)
213 {
214 uint32_t v;
215 int r;
216
217 if (gpnvm >= SAMV_NUM_GPNVM_BITS) {
218 LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm, SAMV_NUM_GPNVM_BITS);
219 return ERROR_FAIL;
220 }
221
222 r = samv_efc_perform_command(target, SAMV_EFC_FCMD_GFB, 0, NULL);
223 if (r != ERROR_OK) {
224 LOG_ERROR("samv_get_gpnvm failed");
225 return r;
226 }
227
228 r = samv_efc_get_result(target, &v);
229
230 if (out)
231 *out = (v >> gpnvm) & 1;
232
233 return r;
234 }
235
236 static int samv_clear_gpnvm(struct target *target, unsigned gpnvm)
237 {
238 int r;
239 unsigned v;
240
241 if (gpnvm >= SAMV_NUM_GPNVM_BITS) {
242 LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm, SAMV_NUM_GPNVM_BITS);
243 return ERROR_FAIL;
244 }
245 r = samv_get_gpnvm(target, gpnvm, &v);
246 if (r != ERROR_OK) {
247 LOG_DEBUG("get gpnvm failed: %d", r);
248 return r;
249 }
250 r = samv_efc_perform_command(target, SAMV_EFC_FCMD_CFB, gpnvm, NULL);
251 LOG_DEBUG("clear gpnvm result: %d", r);
252 return r;
253 }
254
255 static int samv_set_gpnvm(struct target *target, unsigned gpnvm)
256 {
257 int r;
258 unsigned v;
259 if (gpnvm >= SAMV_NUM_GPNVM_BITS) {
260 LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm, SAMV_NUM_GPNVM_BITS);
261 return ERROR_FAIL;
262 }
263
264 r = samv_get_gpnvm(target, gpnvm, &v);
265 if (r != ERROR_OK)
266 return r;
267 if (v) {
268 r = ERROR_OK; /* the gpnvm bit is already set */
269 } else {
270 /* we need to set it */
271 r = samv_efc_perform_command(target, SAMV_EFC_FCMD_SFB, gpnvm, NULL);
272 }
273 return r;
274 }
275
276 static int samv_flash_unlock(struct target *target,
277 unsigned start_sector, unsigned end_sector)
278 {
279 int r;
280 uint32_t status;
281 uint32_t pg;
282 uint32_t pages_per_sector;
283
284 /* todo: look into this... i think this should be done on lock regions */
285 pages_per_sector = SAMV_SECTOR_SIZE / SAMV_PAGE_SIZE;
286 while (start_sector <= end_sector) {
287 pg = start_sector * pages_per_sector;
288 r = samv_efc_perform_command(target, SAMV_EFC_FCMD_CLB, pg, &status);
289 if (r != ERROR_OK)
290 return r;
291 start_sector++;
292 }
293 return ERROR_OK;
294 }
295
296 static int samv_flash_lock(struct target *target,
297 unsigned start_sector, unsigned end_sector)
298 {
299 uint32_t status;
300 uint32_t pg;
301 uint32_t pages_per_sector;
302 int r;
303
304 /* todo: look into this... i think this should be done on lock regions */
305 pages_per_sector = SAMV_SECTOR_SIZE / SAMV_PAGE_SIZE;
306 while (start_sector <= end_sector) {
307 pg = start_sector * pages_per_sector;
308 r = samv_efc_perform_command(target, SAMV_EFC_FCMD_SLB, pg, &status);
309 if (r != ERROR_OK)
310 return r;
311 start_sector++;
312 }
313 return ERROR_OK;
314 }
315
316 static int samv_protect_check(struct flash_bank *bank)
317 {
318 int r;
319 uint32_t v[4] = {0};
320
321 r = samv_efc_perform_command(bank->target, SAMV_EFC_FCMD_GLB, 0, NULL);
322 if (r == ERROR_OK) {
323 samv_efc_get_result(bank->target, &v[0]);
324 samv_efc_get_result(bank->target, &v[1]);
325 samv_efc_get_result(bank->target, &v[2]);
326 r = samv_efc_get_result(bank->target, &v[3]);
327 }
328 if (r != ERROR_OK)
329 return r;
330
331 for (int x = 0; x < bank->num_sectors; x++)
332 bank->sectors[x].is_protected = (!!(v[x >> 5] & (1 << (x % 32))));
333 return ERROR_OK;
334 }
335
336 FLASH_BANK_COMMAND_HANDLER(samv_flash_bank_command)
337 {
338 LOG_INFO("flash bank command");
339 struct samv_flash_bank *samv_info;
340 samv_info = calloc(1, sizeof(struct samv_flash_bank));
341 bank->driver_priv = samv_info;
342 return ERROR_OK;
343 }
344
345 static int samv_get_device_id(struct flash_bank *bank, uint32_t *device_id)
346 {
347 return target_read_u32(bank->target, SAMV_CHIPID_CIDR, device_id);
348 }
349
350 static int samv_probe(struct flash_bank *bank)
351 {
352 uint32_t device_id;
353 int r = samv_get_device_id(bank, &device_id);
354 if (r != ERROR_OK)
355 return r;
356 LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
357
358 uint8_t eproc = (device_id >> 5) & 0x7;
359 if (eproc != 0) {
360 LOG_ERROR("unexpected eproc code: %d was expecting 0 (Cortex-M7)", eproc);
361 return ERROR_FAIL;
362 }
363
364 uint8_t nvm_size_code = (device_id >> 8) & 0xf;
365 switch (nvm_size_code) {
366 case 12:
367 bank->size = 1024 * 1024;
368 break;
369 case 14:
370 bank->size = 2048 * 1024;
371 break;
372 default:
373 LOG_ERROR("unrecognized flash size code: %d", nvm_size_code);
374 return ERROR_FAIL;
375 break;
376 }
377
378 struct samv_flash_bank *samv_info = bank->driver_priv;
379 samv_info->size_bytes = bank->size;
380 samv_info->probed = 1;
381
382 bank->base = SAMV_FLASH_BASE;
383 bank->num_sectors = bank->size / SAMV_SECTOR_SIZE;
384 bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
385 for (int s = 0; s < (int)bank->num_sectors; s++) {
386 bank->sectors[s].size = SAMV_SECTOR_SIZE;
387 bank->sectors[s].offset = s * SAMV_SECTOR_SIZE;
388 bank->sectors[s].is_erased = -1;
389 bank->sectors[s].is_protected = -1;
390 }
391
392 r = samv_protect_check(bank);
393 if (r != ERROR_OK)
394 return r;
395
396 return ERROR_OK;
397 }
398
399 static int samv_auto_probe(struct flash_bank *bank)
400 {
401 struct samv_flash_bank *samv_info = bank->driver_priv;
402 if (samv_info->probed)
403 return ERROR_OK;
404 return samv_probe(bank);
405 }
406
407 static int samv_erase(struct flash_bank *bank, int first, int last)
408 {
409 const int page_count = 32; /* 32 pages equals 16 KB lock region */
410
411 if (bank->target->state != TARGET_HALTED) {
412 LOG_ERROR("Target not halted");
413 return ERROR_TARGET_NOT_HALTED;
414 }
415
416 int r = samv_auto_probe(bank);
417 if (r != ERROR_OK)
418 return r;
419
420 /* easy case: we've been requested to erase the entire flash */
421 if ((first == 0) && ((last + 1) == (int)(bank->num_sectors)))
422 return samv_efc_perform_command(bank->target, SAMV_EFC_FCMD_EA, 0, NULL);
423
424 LOG_INFO("erasing lock regions %d-%d...", first, last);
425
426 for (int i = first; i <= last; i++) {
427 uint32_t status;
428 r = samv_erase_pages(bank->target, (i * page_count), page_count, &status);
429 LOG_INFO("erasing lock region %d", i);
430 if (r != ERROR_OK)
431 LOG_ERROR("error performing erase page @ lock region number %d",
432 (unsigned int)(i));
433 if (status & (1 << 2)) {
434 LOG_ERROR("lock region %d is locked", (unsigned int)(i));
435 return ERROR_FAIL;
436 }
437 if (status & (1 << 1)) {
438 LOG_ERROR("flash command error @lock region %d", (unsigned int)(i));
439 return ERROR_FAIL;
440 }
441 }
442 return ERROR_OK;
443 }
444
445 static int samv_protect(struct flash_bank *bank, int set, int first, int last)
446 {
447 if (bank->target->state != TARGET_HALTED) {
448 LOG_ERROR("Target not halted");
449 return ERROR_TARGET_NOT_HALTED;
450 }
451
452 int r;
453 if (set)
454 r = samv_flash_lock(bank->target, (unsigned)(first), (unsigned)(last));
455 else
456 r = samv_flash_unlock(bank->target, (unsigned)(first), (unsigned)(last));
457
458 return r;
459 }
460
461 static int samv_page_read(struct target *target,
462 unsigned page_num, uint8_t *buf)
463 {
464 uint32_t addr = SAMV_FLASH_BASE + page_num * SAMV_PAGE_SIZE;
465 int r = target_read_memory(target, addr, 4, SAMV_PAGE_SIZE / 4, buf);
466 if (r != ERROR_OK)
467 LOG_ERROR("flash program failed to read page @ 0x%08x",
468 (unsigned int)(addr));
469 return r;
470 }
471
472 static int samv_page_write(struct target *target,
473 unsigned pagenum, const uint8_t *buf)
474 {
475 uint32_t status;
476 const uint32_t addr = SAMV_FLASH_BASE + pagenum * SAMV_PAGE_SIZE;
477 int r;
478
479 LOG_DEBUG("write page %u at address 0x%08x", pagenum, (unsigned int)addr);
480 r = target_write_memory(target, addr, 4, SAMV_PAGE_SIZE / 4, buf);
481 if (r != ERROR_OK) {
482 LOG_ERROR("failed to buffer page at 0x%08x", (unsigned int)addr);
483 return r;
484 }
485
486 r = samv_efc_perform_command(target, SAMV_EFC_FCMD_WP, pagenum, &status);
487 if (r != ERROR_OK)
488 LOG_ERROR("error performing write page at 0x%08x", (unsigned int)addr);
489 if (status & (1 << 2)) {
490 LOG_ERROR("page at 0x%08x is locked", (unsigned int)addr);
491 return ERROR_FAIL;
492 }
493 if (status & (1 << 1)) {
494 LOG_ERROR("flash command error at 0x%08x", (unsigned int)addr);
495 return ERROR_FAIL;
496 }
497 return ERROR_OK;
498 }
499
500 static int samv_write(struct flash_bank *bank, const uint8_t *buffer,
501 uint32_t offset, uint32_t count)
502 {
503 if (bank->target->state != TARGET_HALTED) {
504 LOG_ERROR("target not halted");
505 return ERROR_TARGET_NOT_HALTED;
506 }
507
508 if (count == 0)
509 return ERROR_OK;
510
511 if ((offset + count) > bank->size) {
512 LOG_ERROR("flash write error - past end of bank");
513 LOG_ERROR(" offset: 0x%08x, count 0x%08x, bank end: 0x%08x",
514 (unsigned int)(offset),
515 (unsigned int)(count),
516 (unsigned int)(bank->size));
517 return ERROR_FAIL;
518 }
519
520 uint8_t pagebuffer[SAMV_PAGE_SIZE] = {0};
521 uint32_t page_cur = offset / SAMV_PAGE_SIZE;
522 uint32_t page_end = (offset + count - 1) / SAMV_PAGE_SIZE;
523
524 LOG_DEBUG("offset: 0x%08x, count: 0x%08x",
525 (unsigned int)(offset), (unsigned int)(count));
526 LOG_DEBUG("page start: %d, page end: %d", (int)(page_cur), (int)(page_end));
527
528 /* Special case: all one page */
529 /* Otherwise: */
530 /* (1) non-aligned start */
531 /* (2) body pages */
532 /* (3) non-aligned end. */
533
534 int r;
535 uint32_t page_offset;
536
537 /* handle special case - all one page. */
538 if (page_cur == page_end) {
539 LOG_DEBUG("special case, all in one page");
540 r = samv_page_read(bank->target, page_cur, pagebuffer);
541 if (r != ERROR_OK)
542 return r;
543
544 page_offset = offset & (SAMV_PAGE_SIZE-1);
545 memcpy(pagebuffer + page_offset, buffer, count);
546
547 r = samv_page_write(bank->target, page_cur, pagebuffer);
548 if (r != ERROR_OK)
549 return r;
550 return ERROR_OK;
551 }
552
553 /* step 1) handle the non-aligned starting address */
554 page_offset = offset & (SAMV_PAGE_SIZE - 1);
555 if (page_offset) {
556 LOG_DEBUG("non-aligned start");
557 /* read the partial page */
558 r = samv_page_read(bank->target, page_cur, pagebuffer);
559 if (r != ERROR_OK)
560 return r;
561
562 /* over-write with new data */
563 uint32_t n = SAMV_PAGE_SIZE - page_offset;
564 memcpy(pagebuffer + page_offset, buffer, n);
565
566 r = samv_page_write(bank->target, page_cur, pagebuffer);
567 if (r != ERROR_OK)
568 return r;
569
570 count -= n;
571 offset += n;
572 buffer += n;
573 page_cur++;
574 }
575
576 /* By checking that offset is correct here, we also fix a clang warning */
577 assert(offset % SAMV_PAGE_SIZE == 0);
578
579 /* step 2) handle the full pages */
580 LOG_DEBUG("full page loop: cur=%d, end=%d, count = 0x%08x",
581 (int)page_cur, (int)page_end, (unsigned int)(count));
582
583 while ((page_cur < page_end) && (count >= SAMV_PAGE_SIZE)) {
584 r = samv_page_write(bank->target, page_cur, buffer);
585 if (r != ERROR_OK)
586 return r;
587 count -= SAMV_PAGE_SIZE;
588 buffer += SAMV_PAGE_SIZE;
589 page_cur += 1;
590 }
591
592 /* step 3) write final page, if it's partial (otherwise it's already done) */
593 if (count) {
594 LOG_DEBUG("final partial page, count = 0x%08x", (unsigned int)(count));
595 /* we have a partial page */
596 r = samv_page_read(bank->target, page_cur, pagebuffer);
597 if (r != ERROR_OK)
598 return r;
599 memcpy(pagebuffer, buffer, count); /* data goes at start of page */
600 r = samv_page_write(bank->target, page_cur, pagebuffer);
601 if (r != ERROR_OK)
602 return r;
603 }
604 return ERROR_OK;
605 }
606
607 static int samv_get_info(struct flash_bank *bank, char *buf, int buf_size)
608 {
609 struct samv_flash_bank *samv_info = bank->driver_priv;
610 if (!samv_info->probed) {
611 int r = samv_probe(bank);
612 if (ERROR_OK != r)
613 return r;
614 }
615 snprintf(buf, buf_size, "Cortex-M7 detected with %d kB flash",
616 bank->size / 1024);
617 return ERROR_OK;
618 }
619
620 COMMAND_HANDLER(samv_handle_gpnvm_command)
621 {
622 struct flash_bank *bank = get_flash_bank_by_num_noprobe(0);
623 if (!bank)
624 return ERROR_FAIL;
625 struct samv_flash_bank *samv_info = bank->driver_priv;
626 struct target *target = bank->target;
627
628 if (target->state != TARGET_HALTED) {
629 LOG_ERROR("target not halted");
630 return ERROR_TARGET_NOT_HALTED;
631 }
632
633 int r;
634 if (!samv_info->probed) {
635 r = samv_auto_probe(bank);
636 if (r != ERROR_OK)
637 return r;
638 }
639
640 int who = 0;
641
642 switch (CMD_ARGC) {
643 case 0:
644 goto showall;
645 break;
646 case 1:
647 who = -1;
648 break;
649 case 2:
650 if (!strcmp(CMD_ARGV[0], "show") && !strcmp(CMD_ARGV[1], "all"))
651 who = -1;
652 else {
653 uint32_t v32;
654 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], v32);
655 who = v32;
656 }
657 break;
658 default:
659 return ERROR_COMMAND_SYNTAX_ERROR;
660 break;
661 }
662
663 uint32_t v;
664 if (!strcmp("show", CMD_ARGV[0])) {
665 if (who == -1) {
666 showall:
667 r = ERROR_OK;
668 for (int x = 0; x < SAMV_NUM_GPNVM_BITS; x++) {
669 r = samv_get_gpnvm(target, x, &v);
670 if (r != ERROR_OK)
671 break;
672 command_print(CMD_CTX, "samv-gpnvm%u: %u", x, v);
673 }
674 return r;
675 }
676 if ((who >= 0) && (((unsigned)who) < SAMV_NUM_GPNVM_BITS)) {
677 r = samv_get_gpnvm(target, who, &v);
678 command_print(CMD_CTX, "samv-gpnvm%u: %u", who, v);
679 return r;
680 } else {
681 command_print(CMD_CTX, "invalid gpnvm: %u", who);
682 return ERROR_COMMAND_SYNTAX_ERROR;
683 }
684 }
685
686 if (who == -1) {
687 command_print(CMD_CTX, "missing gpnvm number");
688 return ERROR_COMMAND_SYNTAX_ERROR;
689 }
690
691 if (!strcmp("set", CMD_ARGV[0]))
692 r = samv_set_gpnvm(target, who);
693 else if (!strcmp("clr", CMD_ARGV[0]) || !strcmp("clear", CMD_ARGV[0]))
694 r = samv_clear_gpnvm(target, who);
695 else {
696 command_print(CMD_CTX, "unknown command: %s", CMD_ARGV[0]);
697 r = ERROR_COMMAND_SYNTAX_ERROR;
698 }
699 return r;
700 }
701
702 static const struct command_registration atsamv_exec_command_handlers[] = {
703 {
704 .name = "gpnvm",
705 .handler = samv_handle_gpnvm_command,
706 .mode = COMMAND_EXEC,
707 .usage = "[('clr'|'set'|'show') bitnum]",
708 .help = "Without arguments, shows all bits in the gpnvm "
709 "register. Otherwise, clears, sets, or shows one "
710 "General Purpose Non-Volatile Memory (gpnvm) bit.",
711 },
712 COMMAND_REGISTRATION_DONE
713 };
714
715 static const struct command_registration atsamv_command_handlers[] = {
716 {
717 .name = "atsamv",
718 .mode = COMMAND_ANY,
719 .help = "atsamv flash command group",
720 .usage = "",
721 .chain = atsamv_exec_command_handlers,
722 },
723 COMMAND_REGISTRATION_DONE
724 };
725
726 struct flash_driver atsamv_flash = {
727 .name = "atsamv",
728 .commands = atsamv_command_handlers,
729 .flash_bank_command = samv_flash_bank_command,
730 .erase = samv_erase,
731 .protect = samv_protect,
732 .write = samv_write,
733 .read = default_flash_read,
734 .probe = samv_probe,
735 .auto_probe = samv_auto_probe,
736 .erase_check = default_flash_blank_check,
737 .protect_check = samv_protect_check,
738 .info = samv_get_info,
739 };

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)