coding style: remove useless break after a goto or return
[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 const 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 10:
367 bank->size = 512 * 1024;
368 break;
369 case 12:
370 bank->size = 1024 * 1024;
371 break;
372 case 14:
373 bank->size = 2048 * 1024;
374 break;
375 default:
376 LOG_ERROR("unrecognized flash size code: %d", nvm_size_code);
377 return ERROR_FAIL;
378 }
379
380 struct samv_flash_bank *samv_info = bank->driver_priv;
381 samv_info->size_bytes = bank->size;
382 samv_info->probed = 1;
383
384 bank->base = SAMV_FLASH_BASE;
385 bank->num_sectors = bank->size / SAMV_SECTOR_SIZE;
386 bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
387 for (int s = 0; s < (int)bank->num_sectors; s++) {
388 bank->sectors[s].size = SAMV_SECTOR_SIZE;
389 bank->sectors[s].offset = s * SAMV_SECTOR_SIZE;
390 bank->sectors[s].is_erased = -1;
391 bank->sectors[s].is_protected = -1;
392 }
393
394 r = samv_protect_check(bank);
395 if (r != ERROR_OK)
396 return r;
397
398 return ERROR_OK;
399 }
400
401 static int samv_auto_probe(struct flash_bank *bank)
402 {
403 struct samv_flash_bank *samv_info = bank->driver_priv;
404 if (samv_info->probed)
405 return ERROR_OK;
406 return samv_probe(bank);
407 }
408
409 static int samv_erase(struct flash_bank *bank, int first, int last)
410 {
411 const int page_count = 32; /* 32 pages equals 16 KB lock region */
412
413 if (bank->target->state != TARGET_HALTED) {
414 LOG_ERROR("Target not halted");
415 return ERROR_TARGET_NOT_HALTED;
416 }
417
418 int r = samv_auto_probe(bank);
419 if (r != ERROR_OK)
420 return r;
421
422 /* easy case: we've been requested to erase the entire flash */
423 if ((first == 0) && ((last + 1) == (int)(bank->num_sectors)))
424 return samv_efc_perform_command(bank->target, SAMV_EFC_FCMD_EA, 0, NULL);
425
426 LOG_INFO("erasing lock regions %d-%d...", first, last);
427
428 for (int i = first; i <= last; i++) {
429 uint32_t status;
430 r = samv_erase_pages(bank->target, (i * page_count), page_count, &status);
431 LOG_INFO("erasing lock region %d", i);
432 if (r != ERROR_OK)
433 LOG_ERROR("error performing erase page @ lock region number %d",
434 (unsigned int)(i));
435 if (status & (1 << 2)) {
436 LOG_ERROR("lock region %d is locked", (unsigned int)(i));
437 return ERROR_FAIL;
438 }
439 if (status & (1 << 1)) {
440 LOG_ERROR("flash command error @lock region %d", (unsigned int)(i));
441 return ERROR_FAIL;
442 }
443 }
444 return ERROR_OK;
445 }
446
447 static int samv_protect(struct flash_bank *bank, int set, int first, int last)
448 {
449 if (bank->target->state != TARGET_HALTED) {
450 LOG_ERROR("Target not halted");
451 return ERROR_TARGET_NOT_HALTED;
452 }
453
454 int r;
455 if (set)
456 r = samv_flash_lock(bank->target, (unsigned)(first), (unsigned)(last));
457 else
458 r = samv_flash_unlock(bank->target, (unsigned)(first), (unsigned)(last));
459
460 return r;
461 }
462
463 static int samv_page_read(struct target *target,
464 unsigned page_num, uint8_t *buf)
465 {
466 uint32_t addr = SAMV_FLASH_BASE + page_num * SAMV_PAGE_SIZE;
467 int r = target_read_memory(target, addr, 4, SAMV_PAGE_SIZE / 4, buf);
468 if (r != ERROR_OK)
469 LOG_ERROR("flash program failed to read page @ 0x%08x",
470 (unsigned int)(addr));
471 return r;
472 }
473
474 static int samv_page_write(struct target *target,
475 unsigned pagenum, const uint8_t *buf)
476 {
477 uint32_t status;
478 const uint32_t addr = SAMV_FLASH_BASE + pagenum * SAMV_PAGE_SIZE;
479 int r;
480
481 LOG_DEBUG("write page %u at address 0x%08x", pagenum, (unsigned int)addr);
482 r = target_write_memory(target, addr, 4, SAMV_PAGE_SIZE / 4, buf);
483 if (r != ERROR_OK) {
484 LOG_ERROR("failed to buffer page at 0x%08x", (unsigned int)addr);
485 return r;
486 }
487
488 r = samv_efc_perform_command(target, SAMV_EFC_FCMD_WP, pagenum, &status);
489 if (r != ERROR_OK)
490 LOG_ERROR("error performing write page at 0x%08x", (unsigned int)addr);
491 if (status & (1 << 2)) {
492 LOG_ERROR("page at 0x%08x is locked", (unsigned int)addr);
493 return ERROR_FAIL;
494 }
495 if (status & (1 << 1)) {
496 LOG_ERROR("flash command error at 0x%08x", (unsigned int)addr);
497 return ERROR_FAIL;
498 }
499 return ERROR_OK;
500 }
501
502 static int samv_write(struct flash_bank *bank, const uint8_t *buffer,
503 uint32_t offset, uint32_t count)
504 {
505 if (bank->target->state != TARGET_HALTED) {
506 LOG_ERROR("target not halted");
507 return ERROR_TARGET_NOT_HALTED;
508 }
509
510 if (count == 0)
511 return ERROR_OK;
512
513 if ((offset + count) > bank->size) {
514 LOG_ERROR("flash write error - past end of bank");
515 LOG_ERROR(" offset: 0x%08x, count 0x%08x, bank end: 0x%08x",
516 (unsigned int)(offset),
517 (unsigned int)(count),
518 (unsigned int)(bank->size));
519 return ERROR_FAIL;
520 }
521
522 uint8_t pagebuffer[SAMV_PAGE_SIZE] = {0};
523 uint32_t page_cur = offset / SAMV_PAGE_SIZE;
524 uint32_t page_end = (offset + count - 1) / SAMV_PAGE_SIZE;
525
526 LOG_DEBUG("offset: 0x%08x, count: 0x%08x",
527 (unsigned int)(offset), (unsigned int)(count));
528 LOG_DEBUG("page start: %d, page end: %d", (int)(page_cur), (int)(page_end));
529
530 /* Special case: all one page */
531 /* Otherwise: */
532 /* (1) non-aligned start */
533 /* (2) body pages */
534 /* (3) non-aligned end. */
535
536 int r;
537 uint32_t page_offset;
538
539 /* handle special case - all one page. */
540 if (page_cur == page_end) {
541 LOG_DEBUG("special case, all in one page");
542 r = samv_page_read(bank->target, page_cur, pagebuffer);
543 if (r != ERROR_OK)
544 return r;
545
546 page_offset = offset & (SAMV_PAGE_SIZE-1);
547 memcpy(pagebuffer + page_offset, buffer, count);
548
549 r = samv_page_write(bank->target, page_cur, pagebuffer);
550 if (r != ERROR_OK)
551 return r;
552 return ERROR_OK;
553 }
554
555 /* step 1) handle the non-aligned starting address */
556 page_offset = offset & (SAMV_PAGE_SIZE - 1);
557 if (page_offset) {
558 LOG_DEBUG("non-aligned start");
559 /* read the partial page */
560 r = samv_page_read(bank->target, page_cur, pagebuffer);
561 if (r != ERROR_OK)
562 return r;
563
564 /* over-write with new data */
565 uint32_t n = SAMV_PAGE_SIZE - page_offset;
566 memcpy(pagebuffer + page_offset, buffer, n);
567
568 r = samv_page_write(bank->target, page_cur, pagebuffer);
569 if (r != ERROR_OK)
570 return r;
571
572 count -= n;
573 offset += n;
574 buffer += n;
575 page_cur++;
576 }
577
578 /* By checking that offset is correct here, we also fix a clang warning */
579 assert(offset % SAMV_PAGE_SIZE == 0);
580
581 /* step 2) handle the full pages */
582 LOG_DEBUG("full page loop: cur=%d, end=%d, count = 0x%08x",
583 (int)page_cur, (int)page_end, (unsigned int)(count));
584
585 while ((page_cur < page_end) && (count >= SAMV_PAGE_SIZE)) {
586 r = samv_page_write(bank->target, page_cur, buffer);
587 if (r != ERROR_OK)
588 return r;
589 count -= SAMV_PAGE_SIZE;
590 buffer += SAMV_PAGE_SIZE;
591 page_cur += 1;
592 }
593
594 /* step 3) write final page, if it's partial (otherwise it's already done) */
595 if (count) {
596 LOG_DEBUG("final partial page, count = 0x%08x", (unsigned int)(count));
597 /* we have a partial page */
598 r = samv_page_read(bank->target, page_cur, pagebuffer);
599 if (r != ERROR_OK)
600 return r;
601 memcpy(pagebuffer, buffer, count); /* data goes at start of page */
602 r = samv_page_write(bank->target, page_cur, pagebuffer);
603 if (r != ERROR_OK)
604 return r;
605 }
606 return ERROR_OK;
607 }
608
609 static int samv_get_info(struct flash_bank *bank, char *buf, int buf_size)
610 {
611 struct samv_flash_bank *samv_info = bank->driver_priv;
612 if (!samv_info->probed) {
613 int r = samv_probe(bank);
614 if (ERROR_OK != r)
615 return r;
616 }
617 snprintf(buf, buf_size, "Cortex-M7 detected with %d kB flash",
618 bank->size / 1024);
619 return ERROR_OK;
620 }
621
622 COMMAND_HANDLER(samv_handle_gpnvm_command)
623 {
624 struct flash_bank *bank = get_flash_bank_by_num_noprobe(0);
625 if (!bank)
626 return ERROR_FAIL;
627 struct samv_flash_bank *samv_info = bank->driver_priv;
628 struct target *target = bank->target;
629
630 if (target->state != TARGET_HALTED) {
631 LOG_ERROR("target not halted");
632 return ERROR_TARGET_NOT_HALTED;
633 }
634
635 int r;
636 if (!samv_info->probed) {
637 r = samv_auto_probe(bank);
638 if (r != ERROR_OK)
639 return r;
640 }
641
642 int who = 0;
643
644 switch (CMD_ARGC) {
645 case 0:
646 goto showall;
647 case 1:
648 who = -1;
649 break;
650 case 2:
651 if (!strcmp(CMD_ARGV[0], "show") && !strcmp(CMD_ARGV[1], "all"))
652 who = -1;
653 else {
654 uint32_t v32;
655 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], v32);
656 who = v32;
657 }
658 break;
659 default:
660 return ERROR_COMMAND_SYNTAX_ERROR;
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, "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, "samv-gpnvm%u: %u", who, v);
679 return r;
680 } else {
681 command_print(CMD, "invalid gpnvm: %u", who);
682 return ERROR_COMMAND_SYNTAX_ERROR;
683 }
684 }
685
686 if (who == -1) {
687 command_print(CMD, "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, "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 const 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 .free_driver_priv = default_flash_free_driver_priv,
740 };

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)