psoc4: update for 4x00BLE, L, M, S and PRoC BLE devices
[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 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 break;
379 }
380
381 struct samv_flash_bank *samv_info = bank->driver_priv;
382 samv_info->size_bytes = bank->size;
383 samv_info->probed = 1;
384
385 bank->base = SAMV_FLASH_BASE;
386 bank->num_sectors = bank->size / SAMV_SECTOR_SIZE;
387 bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
388 for (int s = 0; s < (int)bank->num_sectors; s++) {
389 bank->sectors[s].size = SAMV_SECTOR_SIZE;
390 bank->sectors[s].offset = s * SAMV_SECTOR_SIZE;
391 bank->sectors[s].is_erased = -1;
392 bank->sectors[s].is_protected = -1;
393 }
394
395 r = samv_protect_check(bank);
396 if (r != ERROR_OK)
397 return r;
398
399 return ERROR_OK;
400 }
401
402 static int samv_auto_probe(struct flash_bank *bank)
403 {
404 struct samv_flash_bank *samv_info = bank->driver_priv;
405 if (samv_info->probed)
406 return ERROR_OK;
407 return samv_probe(bank);
408 }
409
410 static int samv_erase(struct flash_bank *bank, int first, int last)
411 {
412 const int page_count = 32; /* 32 pages equals 16 KB lock region */
413
414 if (bank->target->state != TARGET_HALTED) {
415 LOG_ERROR("Target not halted");
416 return ERROR_TARGET_NOT_HALTED;
417 }
418
419 int r = samv_auto_probe(bank);
420 if (r != ERROR_OK)
421 return r;
422
423 /* easy case: we've been requested to erase the entire flash */
424 if ((first == 0) && ((last + 1) == (int)(bank->num_sectors)))
425 return samv_efc_perform_command(bank->target, SAMV_EFC_FCMD_EA, 0, NULL);
426
427 LOG_INFO("erasing lock regions %d-%d...", first, last);
428
429 for (int i = first; i <= last; i++) {
430 uint32_t status;
431 r = samv_erase_pages(bank->target, (i * page_count), page_count, &status);
432 LOG_INFO("erasing lock region %d", i);
433 if (r != ERROR_OK)
434 LOG_ERROR("error performing erase page @ lock region number %d",
435 (unsigned int)(i));
436 if (status & (1 << 2)) {
437 LOG_ERROR("lock region %d is locked", (unsigned int)(i));
438 return ERROR_FAIL;
439 }
440 if (status & (1 << 1)) {
441 LOG_ERROR("flash command error @lock region %d", (unsigned int)(i));
442 return ERROR_FAIL;
443 }
444 }
445 return ERROR_OK;
446 }
447
448 static int samv_protect(struct flash_bank *bank, int set, int first, int last)
449 {
450 if (bank->target->state != TARGET_HALTED) {
451 LOG_ERROR("Target not halted");
452 return ERROR_TARGET_NOT_HALTED;
453 }
454
455 int r;
456 if (set)
457 r = samv_flash_lock(bank->target, (unsigned)(first), (unsigned)(last));
458 else
459 r = samv_flash_unlock(bank->target, (unsigned)(first), (unsigned)(last));
460
461 return r;
462 }
463
464 static int samv_page_read(struct target *target,
465 unsigned page_num, uint8_t *buf)
466 {
467 uint32_t addr = SAMV_FLASH_BASE + page_num * SAMV_PAGE_SIZE;
468 int r = target_read_memory(target, addr, 4, SAMV_PAGE_SIZE / 4, buf);
469 if (r != ERROR_OK)
470 LOG_ERROR("flash program failed to read page @ 0x%08x",
471 (unsigned int)(addr));
472 return r;
473 }
474
475 static int samv_page_write(struct target *target,
476 unsigned pagenum, const uint8_t *buf)
477 {
478 uint32_t status;
479 const uint32_t addr = SAMV_FLASH_BASE + pagenum * SAMV_PAGE_SIZE;
480 int r;
481
482 LOG_DEBUG("write page %u at address 0x%08x", pagenum, (unsigned int)addr);
483 r = target_write_memory(target, addr, 4, SAMV_PAGE_SIZE / 4, buf);
484 if (r != ERROR_OK) {
485 LOG_ERROR("failed to buffer page at 0x%08x", (unsigned int)addr);
486 return r;
487 }
488
489 r = samv_efc_perform_command(target, SAMV_EFC_FCMD_WP, pagenum, &status);
490 if (r != ERROR_OK)
491 LOG_ERROR("error performing write page at 0x%08x", (unsigned int)addr);
492 if (status & (1 << 2)) {
493 LOG_ERROR("page at 0x%08x is locked", (unsigned int)addr);
494 return ERROR_FAIL;
495 }
496 if (status & (1 << 1)) {
497 LOG_ERROR("flash command error at 0x%08x", (unsigned int)addr);
498 return ERROR_FAIL;
499 }
500 return ERROR_OK;
501 }
502
503 static int samv_write(struct flash_bank *bank, const uint8_t *buffer,
504 uint32_t offset, uint32_t count)
505 {
506 if (bank->target->state != TARGET_HALTED) {
507 LOG_ERROR("target not halted");
508 return ERROR_TARGET_NOT_HALTED;
509 }
510
511 if (count == 0)
512 return ERROR_OK;
513
514 if ((offset + count) > bank->size) {
515 LOG_ERROR("flash write error - past end of bank");
516 LOG_ERROR(" offset: 0x%08x, count 0x%08x, bank end: 0x%08x",
517 (unsigned int)(offset),
518 (unsigned int)(count),
519 (unsigned int)(bank->size));
520 return ERROR_FAIL;
521 }
522
523 uint8_t pagebuffer[SAMV_PAGE_SIZE] = {0};
524 uint32_t page_cur = offset / SAMV_PAGE_SIZE;
525 uint32_t page_end = (offset + count - 1) / SAMV_PAGE_SIZE;
526
527 LOG_DEBUG("offset: 0x%08x, count: 0x%08x",
528 (unsigned int)(offset), (unsigned int)(count));
529 LOG_DEBUG("page start: %d, page end: %d", (int)(page_cur), (int)(page_end));
530
531 /* Special case: all one page */
532 /* Otherwise: */
533 /* (1) non-aligned start */
534 /* (2) body pages */
535 /* (3) non-aligned end. */
536
537 int r;
538 uint32_t page_offset;
539
540 /* handle special case - all one page. */
541 if (page_cur == page_end) {
542 LOG_DEBUG("special case, all in one page");
543 r = samv_page_read(bank->target, page_cur, pagebuffer);
544 if (r != ERROR_OK)
545 return r;
546
547 page_offset = offset & (SAMV_PAGE_SIZE-1);
548 memcpy(pagebuffer + page_offset, buffer, count);
549
550 r = samv_page_write(bank->target, page_cur, pagebuffer);
551 if (r != ERROR_OK)
552 return r;
553 return ERROR_OK;
554 }
555
556 /* step 1) handle the non-aligned starting address */
557 page_offset = offset & (SAMV_PAGE_SIZE - 1);
558 if (page_offset) {
559 LOG_DEBUG("non-aligned start");
560 /* read the partial page */
561 r = samv_page_read(bank->target, page_cur, pagebuffer);
562 if (r != ERROR_OK)
563 return r;
564
565 /* over-write with new data */
566 uint32_t n = SAMV_PAGE_SIZE - page_offset;
567 memcpy(pagebuffer + page_offset, buffer, n);
568
569 r = samv_page_write(bank->target, page_cur, pagebuffer);
570 if (r != ERROR_OK)
571 return r;
572
573 count -= n;
574 offset += n;
575 buffer += n;
576 page_cur++;
577 }
578
579 /* By checking that offset is correct here, we also fix a clang warning */
580 assert(offset % SAMV_PAGE_SIZE == 0);
581
582 /* step 2) handle the full pages */
583 LOG_DEBUG("full page loop: cur=%d, end=%d, count = 0x%08x",
584 (int)page_cur, (int)page_end, (unsigned int)(count));
585
586 while ((page_cur < page_end) && (count >= SAMV_PAGE_SIZE)) {
587 r = samv_page_write(bank->target, page_cur, buffer);
588 if (r != ERROR_OK)
589 return r;
590 count -= SAMV_PAGE_SIZE;
591 buffer += SAMV_PAGE_SIZE;
592 page_cur += 1;
593 }
594
595 /* step 3) write final page, if it's partial (otherwise it's already done) */
596 if (count) {
597 LOG_DEBUG("final partial page, count = 0x%08x", (unsigned int)(count));
598 /* we have a partial page */
599 r = samv_page_read(bank->target, page_cur, pagebuffer);
600 if (r != ERROR_OK)
601 return r;
602 memcpy(pagebuffer, buffer, count); /* data goes at start of page */
603 r = samv_page_write(bank->target, page_cur, pagebuffer);
604 if (r != ERROR_OK)
605 return r;
606 }
607 return ERROR_OK;
608 }
609
610 static int samv_get_info(struct flash_bank *bank, char *buf, int buf_size)
611 {
612 struct samv_flash_bank *samv_info = bank->driver_priv;
613 if (!samv_info->probed) {
614 int r = samv_probe(bank);
615 if (ERROR_OK != r)
616 return r;
617 }
618 snprintf(buf, buf_size, "Cortex-M7 detected with %d kB flash",
619 bank->size / 1024);
620 return ERROR_OK;
621 }
622
623 COMMAND_HANDLER(samv_handle_gpnvm_command)
624 {
625 struct flash_bank *bank = get_flash_bank_by_num_noprobe(0);
626 if (!bank)
627 return ERROR_FAIL;
628 struct samv_flash_bank *samv_info = bank->driver_priv;
629 struct target *target = bank->target;
630
631 if (target->state != TARGET_HALTED) {
632 LOG_ERROR("target not halted");
633 return ERROR_TARGET_NOT_HALTED;
634 }
635
636 int r;
637 if (!samv_info->probed) {
638 r = samv_auto_probe(bank);
639 if (r != ERROR_OK)
640 return r;
641 }
642
643 int who = 0;
644
645 switch (CMD_ARGC) {
646 case 0:
647 goto showall;
648 break;
649 case 1:
650 who = -1;
651 break;
652 case 2:
653 if (!strcmp(CMD_ARGV[0], "show") && !strcmp(CMD_ARGV[1], "all"))
654 who = -1;
655 else {
656 uint32_t v32;
657 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], v32);
658 who = v32;
659 }
660 break;
661 default:
662 return ERROR_COMMAND_SYNTAX_ERROR;
663 break;
664 }
665
666 uint32_t v;
667 if (!strcmp("show", CMD_ARGV[0])) {
668 if (who == -1) {
669 showall:
670 r = ERROR_OK;
671 for (int x = 0; x < SAMV_NUM_GPNVM_BITS; x++) {
672 r = samv_get_gpnvm(target, x, &v);
673 if (r != ERROR_OK)
674 break;
675 command_print(CMD_CTX, "samv-gpnvm%u: %u", x, v);
676 }
677 return r;
678 }
679 if ((who >= 0) && (((unsigned)who) < SAMV_NUM_GPNVM_BITS)) {
680 r = samv_get_gpnvm(target, who, &v);
681 command_print(CMD_CTX, "samv-gpnvm%u: %u", who, v);
682 return r;
683 } else {
684 command_print(CMD_CTX, "invalid gpnvm: %u", who);
685 return ERROR_COMMAND_SYNTAX_ERROR;
686 }
687 }
688
689 if (who == -1) {
690 command_print(CMD_CTX, "missing gpnvm number");
691 return ERROR_COMMAND_SYNTAX_ERROR;
692 }
693
694 if (!strcmp("set", CMD_ARGV[0]))
695 r = samv_set_gpnvm(target, who);
696 else if (!strcmp("clr", CMD_ARGV[0]) || !strcmp("clear", CMD_ARGV[0]))
697 r = samv_clear_gpnvm(target, who);
698 else {
699 command_print(CMD_CTX, "unknown command: %s", CMD_ARGV[0]);
700 r = ERROR_COMMAND_SYNTAX_ERROR;
701 }
702 return r;
703 }
704
705 static const struct command_registration atsamv_exec_command_handlers[] = {
706 {
707 .name = "gpnvm",
708 .handler = samv_handle_gpnvm_command,
709 .mode = COMMAND_EXEC,
710 .usage = "[('clr'|'set'|'show') bitnum]",
711 .help = "Without arguments, shows all bits in the gpnvm "
712 "register. Otherwise, clears, sets, or shows one "
713 "General Purpose Non-Volatile Memory (gpnvm) bit.",
714 },
715 COMMAND_REGISTRATION_DONE
716 };
717
718 static const struct command_registration atsamv_command_handlers[] = {
719 {
720 .name = "atsamv",
721 .mode = COMMAND_ANY,
722 .help = "atsamv flash command group",
723 .usage = "",
724 .chain = atsamv_exec_command_handlers,
725 },
726 COMMAND_REGISTRATION_DONE
727 };
728
729 struct flash_driver atsamv_flash = {
730 .name = "atsamv",
731 .commands = atsamv_command_handlers,
732 .flash_bank_command = samv_flash_bank_command,
733 .erase = samv_erase,
734 .protect = samv_protect,
735 .write = samv_write,
736 .read = default_flash_read,
737 .probe = samv_probe,
738 .auto_probe = samv_auto_probe,
739 .erase_check = default_flash_blank_check,
740 .protect_check = samv_protect_check,
741 .info = samv_get_info,
742 };

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)