flash/nor/at91samd: add samr34j18.
[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, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include "imp.h"
24 #include "helper/binarybuffer.h"
25
26 #include <target/cortex_m.h>
27
28 #define SAMD_NUM_PROT_BLOCKS 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_STATUSA 1 /* DSU status register */
38 #define SAMD_DSU_DID 0x18 /* Device ID register */
39 #define SAMD_DSU_CTRL_EXT 0x100 /* CTRL register, external access */
40
41 #define SAMD_NVMCTRL_CTRLA 0x00 /* NVM control A register */
42 #define SAMD_NVMCTRL_CTRLB 0x04 /* NVM control B register */
43 #define SAMD_NVMCTRL_PARAM 0x08 /* NVM parameters register */
44 #define SAMD_NVMCTRL_INTFLAG 0x18 /* NVM Interupt Flag Status & Clear */
45 #define SAMD_NVMCTRL_STATUS 0x18 /* NVM status register */
46 #define SAMD_NVMCTRL_ADDR 0x1C /* NVM address register */
47 #define SAMD_NVMCTRL_LOCK 0x20 /* NVM Lock section register */
48
49 #define SAMD_CMDEX_KEY 0xA5UL
50 #define SAMD_NVM_CMD(n) ((SAMD_CMDEX_KEY << 8) | (n & 0x7F))
51
52 /* NVMCTRL commands. See Table 20-4 in 42129F–SAM–10/2013 */
53 #define SAMD_NVM_CMD_ER 0x02 /* Erase Row */
54 #define SAMD_NVM_CMD_WP 0x04 /* Write Page */
55 #define SAMD_NVM_CMD_EAR 0x05 /* Erase Auxilary Row */
56 #define SAMD_NVM_CMD_WAP 0x06 /* Write Auxilary Page */
57 #define SAMD_NVM_CMD_LR 0x40 /* Lock Region */
58 #define SAMD_NVM_CMD_UR 0x41 /* Unlock Region */
59 #define SAMD_NVM_CMD_SPRM 0x42 /* Set Power Reduction Mode */
60 #define SAMD_NVM_CMD_CPRM 0x43 /* Clear Power Reduction Mode */
61 #define SAMD_NVM_CMD_PBC 0x44 /* Page Buffer Clear */
62 #define SAMD_NVM_CMD_SSB 0x45 /* Set Security Bit */
63 #define SAMD_NVM_CMD_INVALL 0x46 /* Invalidate all caches */
64
65 /* NVMCTRL bits */
66 #define SAMD_NVM_CTRLB_MANW 0x80
67
68 /* Known identifiers */
69 #define SAMD_PROCESSOR_M0 0x01
70 #define SAMD_FAMILY_D 0x00
71 #define SAMD_FAMILY_L 0x01
72 #define SAMD_FAMILY_C 0x02
73 #define SAMD_SERIES_20 0x00
74 #define SAMD_SERIES_21 0x01
75 #define SAMD_SERIES_22 0x02
76 #define SAMD_SERIES_10 0x02
77 #define SAMD_SERIES_11 0x03
78 #define SAMD_SERIES_09 0x04
79
80 /* Device ID macros */
81 #define SAMD_GET_PROCESSOR(id) (id >> 28)
82 #define SAMD_GET_FAMILY(id) (((id >> 23) & 0x1F))
83 #define SAMD_GET_SERIES(id) (((id >> 16) & 0x3F))
84 #define SAMD_GET_DEVSEL(id) (id & 0xFF)
85
86 /* Bits to mask out lockbits in user row */
87 #define NVMUSERROW_LOCKBIT_MASK ((uint64_t)0x0000FFFFFFFFFFFF)
88
89 struct samd_part {
90 uint8_t id;
91 const char *name;
92 uint32_t flash_kb;
93 uint32_t ram_kb;
94 };
95
96 /* Known SAMD09 parts. DID reset values missing in RM, see
97 * https://github.com/avrxml/asf/blob/master/sam0/utils/cmsis/samd09/include/ */
98 static const struct samd_part samd09_parts[] = {
99 { 0x0, "SAMD09D14A", 16, 4 },
100 { 0x7, "SAMD09C13A", 8, 4 },
101 };
102
103 /* Known SAMD10 parts */
104 static const struct samd_part samd10_parts[] = {
105 { 0x0, "SAMD10D14AMU", 16, 4 },
106 { 0x1, "SAMD10D13AMU", 8, 4 },
107 { 0x2, "SAMD10D12AMU", 4, 4 },
108 { 0x3, "SAMD10D14ASU", 16, 4 },
109 { 0x4, "SAMD10D13ASU", 8, 4 },
110 { 0x5, "SAMD10D12ASU", 4, 4 },
111 { 0x6, "SAMD10C14A", 16, 4 },
112 { 0x7, "SAMD10C13A", 8, 4 },
113 { 0x8, "SAMD10C12A", 4, 4 },
114 };
115
116 /* Known SAMD11 parts */
117 static const struct samd_part samd11_parts[] = {
118 { 0x0, "SAMD11D14AM", 16, 4 },
119 { 0x1, "SAMD11D13AMU", 8, 4 },
120 { 0x2, "SAMD11D12AMU", 4, 4 },
121 { 0x3, "SAMD11D14ASS", 16, 4 },
122 { 0x4, "SAMD11D13ASU", 8, 4 },
123 { 0x5, "SAMD11D12ASU", 4, 4 },
124 { 0x6, "SAMD11C14A", 16, 4 },
125 { 0x7, "SAMD11C13A", 8, 4 },
126 { 0x8, "SAMD11C12A", 4, 4 },
127 { 0x9, "SAMD11D14AU", 16, 4 },
128 };
129
130 /* Known SAMD20 parts. See Table 12-8 in 42129F–SAM–10/2013 */
131 static const struct samd_part samd20_parts[] = {
132 { 0x0, "SAMD20J18A", 256, 32 },
133 { 0x1, "SAMD20J17A", 128, 16 },
134 { 0x2, "SAMD20J16A", 64, 8 },
135 { 0x3, "SAMD20J15A", 32, 4 },
136 { 0x4, "SAMD20J14A", 16, 2 },
137 { 0x5, "SAMD20G18A", 256, 32 },
138 { 0x6, "SAMD20G17A", 128, 16 },
139 { 0x7, "SAMD20G16A", 64, 8 },
140 { 0x8, "SAMD20G15A", 32, 4 },
141 { 0x9, "SAMD20G14A", 16, 2 },
142 { 0xA, "SAMD20E18A", 256, 32 },
143 { 0xB, "SAMD20E17A", 128, 16 },
144 { 0xC, "SAMD20E16A", 64, 8 },
145 { 0xD, "SAMD20E15A", 32, 4 },
146 { 0xE, "SAMD20E14A", 16, 2 },
147 };
148
149 /* Known SAMD21 parts. */
150 static const struct samd_part samd21_parts[] = {
151 { 0x0, "SAMD21J18A", 256, 32 },
152 { 0x1, "SAMD21J17A", 128, 16 },
153 { 0x2, "SAMD21J16A", 64, 8 },
154 { 0x3, "SAMD21J15A", 32, 4 },
155 { 0x4, "SAMD21J14A", 16, 2 },
156 { 0x5, "SAMD21G18A", 256, 32 },
157 { 0x6, "SAMD21G17A", 128, 16 },
158 { 0x7, "SAMD21G16A", 64, 8 },
159 { 0x8, "SAMD21G15A", 32, 4 },
160 { 0x9, "SAMD21G14A", 16, 2 },
161 { 0xA, "SAMD21E18A", 256, 32 },
162 { 0xB, "SAMD21E17A", 128, 16 },
163 { 0xC, "SAMD21E16A", 64, 8 },
164 { 0xD, "SAMD21E15A", 32, 4 },
165 { 0xE, "SAMD21E14A", 16, 2 },
166
167 /* SAMR21 parts have integrated SAMD21 with a radio */
168 { 0x18, "SAMR21G19A", 256, 32 }, /* with 512k of serial flash */
169 { 0x19, "SAMR21G18A", 256, 32 },
170 { 0x1A, "SAMR21G17A", 128, 32 },
171 { 0x1B, "SAMR21G16A", 64, 16 },
172 { 0x1C, "SAMR21E18A", 256, 32 },
173 { 0x1D, "SAMR21E17A", 128, 32 },
174 { 0x1E, "SAMR21E16A", 64, 16 },
175
176 /* SAMD21 B Variants (Table 3-7 from rev I of datasheet) */
177 { 0x20, "SAMD21J16B", 64, 8 },
178 { 0x21, "SAMD21J15B", 32, 4 },
179 { 0x23, "SAMD21G16B", 64, 8 },
180 { 0x24, "SAMD21G15B", 32, 4 },
181 { 0x26, "SAMD21E16B", 64, 8 },
182 { 0x27, "SAMD21E15B", 32, 4 },
183
184 /* Known SAMDA1 parts.
185 SAMD-A1 series uses the same series identifier like the SAMD21
186 taken from http://ww1.microchip.com/downloads/en/DeviceDoc/40001895A.pdf (pages 14-17) */
187 { 0x29, "SAMDA1J16A", 64, 8 },
188 { 0x2A, "SAMDA1J15A", 32, 4 },
189 { 0x2B, "SAMDA1J14A", 16, 4 },
190 { 0x2C, "SAMDA1G16A", 64, 8 },
191 { 0x2D, "SAMDA1G15A", 32, 4 },
192 { 0x2E, "SAMDA1G14A", 16, 4 },
193 { 0x2F, "SAMDA1E16A", 64, 8 },
194 { 0x30, "SAMDA1E15A", 32, 4 },
195 { 0x31, "SAMDA1E14A", 16, 4 },
196 { 0x64, "SAMDA1J16B", 64, 8 },
197 { 0x65, "SAMDA1J15B", 32, 4 },
198 { 0x66, "SAMDA1J14B", 16, 4 },
199 { 0x67, "SAMDA1G16B", 64, 8 },
200 { 0x68, "SAMDA1G15B", 32, 4 },
201 { 0x69, "SAMDA1G14B", 16, 4 },
202 { 0x6A, "SAMDA1E16B", 64, 8 },
203 { 0x6B, "SAMDA1E15B", 32, 4 },
204 { 0x6C, "SAMDA1E14B", 16, 4 },
205 };
206
207 /* Known SAML21 parts. */
208 static const struct samd_part saml21_parts[] = {
209 { 0x00, "SAML21J18A", 256, 32 },
210 { 0x01, "SAML21J17A", 128, 16 },
211 { 0x02, "SAML21J16A", 64, 8 },
212 { 0x05, "SAML21G18A", 256, 32 },
213 { 0x06, "SAML21G17A", 128, 16 },
214 { 0x07, "SAML21G16A", 64, 8 },
215 { 0x0A, "SAML21E18A", 256, 32 },
216 { 0x0B, "SAML21E17A", 128, 16 },
217 { 0x0C, "SAML21E16A", 64, 8 },
218 { 0x0D, "SAML21E15A", 32, 4 },
219 { 0x0F, "SAML21J18B", 256, 32 },
220 { 0x10, "SAML21J17B", 128, 16 },
221 { 0x11, "SAML21J16B", 64, 8 },
222 { 0x14, "SAML21G18B", 256, 32 },
223 { 0x15, "SAML21G17B", 128, 16 },
224 { 0x16, "SAML21G16B", 64, 8 },
225 { 0x19, "SAML21E18B", 256, 32 },
226 { 0x1A, "SAML21E17B", 128, 16 },
227 { 0x1B, "SAML21E16B", 64, 8 },
228 { 0x1C, "SAML21E15B", 32, 4 },
229
230 /* SAMR30 parts have integrated SAML21 with a radio */
231 { 0x1E, "SAMR30G18A", 256, 32 },
232 { 0x1F, "SAMR30E18A", 256, 32 },
233
234 /* SAMR34/R35 parts have integrated SAML21 with a lora radio */
235 { 0x28, "SAMR34J18", 256, 32 },
236 };
237
238 /* Known SAML22 parts. */
239 static const struct samd_part saml22_parts[] = {
240 { 0x00, "SAML22N18A", 256, 32 },
241 { 0x01, "SAML22N17A", 128, 16 },
242 { 0x02, "SAML22N16A", 64, 8 },
243 { 0x05, "SAML22J18A", 256, 32 },
244 { 0x06, "SAML22J17A", 128, 16 },
245 { 0x07, "SAML22J16A", 64, 8 },
246 { 0x0A, "SAML22G18A", 256, 32 },
247 { 0x0B, "SAML22G17A", 128, 16 },
248 { 0x0C, "SAML22G16A", 64, 8 },
249 };
250
251 /* Known SAMC20 parts. */
252 static const struct samd_part samc20_parts[] = {
253 { 0x00, "SAMC20J18A", 256, 32 },
254 { 0x01, "SAMC20J17A", 128, 16 },
255 { 0x02, "SAMC20J16A", 64, 8 },
256 { 0x03, "SAMC20J15A", 32, 4 },
257 { 0x05, "SAMC20G18A", 256, 32 },
258 { 0x06, "SAMC20G17A", 128, 16 },
259 { 0x07, "SAMC20G16A", 64, 8 },
260 { 0x08, "SAMC20G15A", 32, 4 },
261 { 0x0A, "SAMC20E18A", 256, 32 },
262 { 0x0B, "SAMC20E17A", 128, 16 },
263 { 0x0C, "SAMC20E16A", 64, 8 },
264 { 0x0D, "SAMC20E15A", 32, 4 },
265 };
266
267 /* Known SAMC21 parts. */
268 static const struct samd_part samc21_parts[] = {
269 { 0x00, "SAMC21J18A", 256, 32 },
270 { 0x01, "SAMC21J17A", 128, 16 },
271 { 0x02, "SAMC21J16A", 64, 8 },
272 { 0x03, "SAMC21J15A", 32, 4 },
273 { 0x05, "SAMC21G18A", 256, 32 },
274 { 0x06, "SAMC21G17A", 128, 16 },
275 { 0x07, "SAMC21G16A", 64, 8 },
276 { 0x08, "SAMC21G15A", 32, 4 },
277 { 0x0A, "SAMC21E18A", 256, 32 },
278 { 0x0B, "SAMC21E17A", 128, 16 },
279 { 0x0C, "SAMC21E16A", 64, 8 },
280 { 0x0D, "SAMC21E15A", 32, 4 },
281 };
282
283 /* Each family of parts contains a parts table in the DEVSEL field of DID. The
284 * processor ID, family ID, and series ID are used to determine which exact
285 * family this is and then we can use the corresponding table. */
286 struct samd_family {
287 uint8_t processor;
288 uint8_t family;
289 uint8_t series;
290 const struct samd_part *parts;
291 size_t num_parts;
292 uint64_t nvm_userrow_res_mask; /* protect bits which are reserved, 0 -> protect */
293 };
294
295 /* Known SAMD families */
296 static const struct samd_family samd_families[] = {
297 { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_20,
298 samd20_parts, ARRAY_SIZE(samd20_parts),
299 (uint64_t)0xFFFF01FFFE01FF77 },
300 { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_21,
301 samd21_parts, ARRAY_SIZE(samd21_parts),
302 (uint64_t)0xFFFF01FFFE01FF77 },
303 { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_09,
304 samd09_parts, ARRAY_SIZE(samd09_parts),
305 (uint64_t)0xFFFF01FFFE01FF77 },
306 { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_10,
307 samd10_parts, ARRAY_SIZE(samd10_parts),
308 (uint64_t)0xFFFF01FFFE01FF77 },
309 { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_11,
310 samd11_parts, ARRAY_SIZE(samd11_parts),
311 (uint64_t)0xFFFF01FFFE01FF77 },
312 { SAMD_PROCESSOR_M0, SAMD_FAMILY_L, SAMD_SERIES_21,
313 saml21_parts, ARRAY_SIZE(saml21_parts),
314 (uint64_t)0xFFFF03FFFC01FF77 },
315 { SAMD_PROCESSOR_M0, SAMD_FAMILY_L, SAMD_SERIES_22,
316 saml22_parts, ARRAY_SIZE(saml22_parts),
317 (uint64_t)0xFFFF03FFFC01FF77 },
318 { SAMD_PROCESSOR_M0, SAMD_FAMILY_C, SAMD_SERIES_20,
319 samc20_parts, ARRAY_SIZE(samc20_parts),
320 (uint64_t)0xFFFF03FFFC01FF77 },
321 { SAMD_PROCESSOR_M0, SAMD_FAMILY_C, SAMD_SERIES_21,
322 samc21_parts, ARRAY_SIZE(samc21_parts),
323 (uint64_t)0xFFFF03FFFC01FF77 },
324 };
325
326 struct samd_info {
327 uint32_t page_size;
328 int num_pages;
329 int sector_size;
330 int prot_block_size;
331
332 bool probed;
333 struct target *target;
334 };
335
336
337 /**
338 * Gives the family structure to specific device id.
339 * @param id The id of the device.
340 * @return On failure NULL, otherwise a pointer to the structure.
341 */
342 static const struct samd_family *samd_find_family(uint32_t id)
343 {
344 uint8_t processor = SAMD_GET_PROCESSOR(id);
345 uint8_t family = SAMD_GET_FAMILY(id);
346 uint8_t series = SAMD_GET_SERIES(id);
347
348 for (unsigned i = 0; i < ARRAY_SIZE(samd_families); i++) {
349 if (samd_families[i].processor == processor &&
350 samd_families[i].series == series &&
351 samd_families[i].family == family)
352 return &samd_families[i];
353 }
354
355 return NULL;
356 }
357
358 /**
359 * Gives the part structure to specific device id.
360 * @param id The id of the device.
361 * @return On failure NULL, otherwise a pointer to the structure.
362 */
363 static const struct samd_part *samd_find_part(uint32_t id)
364 {
365 uint8_t devsel = SAMD_GET_DEVSEL(id);
366 const struct samd_family *family = samd_find_family(id);
367 if (family == NULL)
368 return NULL;
369
370 for (unsigned i = 0; i < family->num_parts; i++) {
371 if (family->parts[i].id == devsel)
372 return &family->parts[i];
373 }
374
375 return NULL;
376 }
377
378 static int samd_protect_check(struct flash_bank *bank)
379 {
380 int res, prot_block;
381 uint16_t lock;
382
383 res = target_read_u16(bank->target,
384 SAMD_NVMCTRL + SAMD_NVMCTRL_LOCK, &lock);
385 if (res != ERROR_OK)
386 return res;
387
388 /* Lock bits are active-low */
389 for (prot_block = 0; prot_block < bank->num_prot_blocks; prot_block++)
390 bank->prot_blocks[prot_block].is_protected = !(lock & (1u<<prot_block));
391
392 return ERROR_OK;
393 }
394
395 static int samd_get_flash_page_info(struct target *target,
396 uint32_t *sizep, int *nump)
397 {
398 int res;
399 uint32_t param;
400
401 res = target_read_u32(target, SAMD_NVMCTRL + SAMD_NVMCTRL_PARAM, &param);
402 if (res == ERROR_OK) {
403 /* The PSZ field (bits 18:16) indicate the page size bytes as 2^(3+n)
404 * so 0 is 8KB and 7 is 1024KB. */
405 if (sizep)
406 *sizep = (8 << ((param >> 16) & 0x7));
407 /* The NVMP field (bits 15:0) indicates the total number of pages */
408 if (nump)
409 *nump = param & 0xFFFF;
410 } else {
411 LOG_ERROR("Couldn't read NVM Parameters register");
412 }
413
414 return res;
415 }
416
417 static int samd_probe(struct flash_bank *bank)
418 {
419 uint32_t id;
420 int res;
421 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
422 const struct samd_part *part;
423
424 if (chip->probed)
425 return ERROR_OK;
426
427 res = target_read_u32(bank->target, SAMD_DSU + SAMD_DSU_DID, &id);
428 if (res != ERROR_OK) {
429 LOG_ERROR("Couldn't read Device ID register");
430 return res;
431 }
432
433 part = samd_find_part(id);
434 if (part == NULL) {
435 LOG_ERROR("Couldn't find part corresponding to DID %08" PRIx32, id);
436 return ERROR_FAIL;
437 }
438
439 bank->size = part->flash_kb * 1024;
440
441 res = samd_get_flash_page_info(bank->target, &chip->page_size,
442 &chip->num_pages);
443 if (res != ERROR_OK) {
444 LOG_ERROR("Couldn't determine Flash page size");
445 return res;
446 }
447
448 /* Sanity check: the total flash size in the DSU should match the page size
449 * multiplied by the number of pages. */
450 if (bank->size != chip->num_pages * chip->page_size) {
451 LOG_WARNING("SAMD: bank size doesn't match NVM parameters. "
452 "Identified %" PRIu32 "KB Flash but NVMCTRL reports %u %" PRIu32 "B pages",
453 part->flash_kb, chip->num_pages, chip->page_size);
454 }
455
456 /* Erase granularity = 1 row = 4 pages */
457 chip->sector_size = chip->page_size * 4;
458
459 /* Allocate the sector table */
460 bank->num_sectors = chip->num_pages / 4;
461 bank->sectors = alloc_block_array(0, chip->sector_size, bank->num_sectors);
462 if (!bank->sectors)
463 return ERROR_FAIL;
464
465 /* 16 protection blocks per device */
466 chip->prot_block_size = bank->size / SAMD_NUM_PROT_BLOCKS;
467
468 /* Allocate the table of protection blocks */
469 bank->num_prot_blocks = SAMD_NUM_PROT_BLOCKS;
470 bank->prot_blocks = alloc_block_array(0, chip->prot_block_size, bank->num_prot_blocks);
471 if (!bank->prot_blocks)
472 return ERROR_FAIL;
473
474 samd_protect_check(bank);
475
476 /* Done */
477 chip->probed = true;
478
479 LOG_INFO("SAMD MCU: %s (%" PRIu32 "KB Flash, %" PRIu32 "KB RAM)", part->name,
480 part->flash_kb, part->ram_kb);
481
482 return ERROR_OK;
483 }
484
485 static int samd_check_error(struct target *target)
486 {
487 int ret, ret2;
488 uint16_t status;
489
490 ret = target_read_u16(target,
491 SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, &status);
492 if (ret != ERROR_OK) {
493 LOG_ERROR("Can't read NVM status");
494 return ret;
495 }
496
497 if ((status & 0x001C) == 0)
498 return ERROR_OK;
499
500 if (status & (1 << 4)) { /* NVME */
501 LOG_ERROR("SAMD: NVM Error");
502 ret = ERROR_FLASH_OPERATION_FAILED;
503 }
504
505 if (status & (1 << 3)) { /* LOCKE */
506 LOG_ERROR("SAMD: NVM lock error");
507 ret = ERROR_FLASH_PROTECTED;
508 }
509
510 if (status & (1 << 2)) { /* PROGE */
511 LOG_ERROR("SAMD: NVM programming error");
512 ret = ERROR_FLASH_OPER_UNSUPPORTED;
513 }
514
515 /* Clear the error conditions by writing a one to them */
516 ret2 = target_write_u16(target,
517 SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, status);
518 if (ret2 != ERROR_OK)
519 LOG_ERROR("Can't clear NVM error conditions");
520
521 return ret;
522 }
523
524 static int samd_issue_nvmctrl_command(struct target *target, uint16_t cmd)
525 {
526 int res;
527
528 if (target->state != TARGET_HALTED) {
529 LOG_ERROR("Target not halted");
530 return ERROR_TARGET_NOT_HALTED;
531 }
532
533 /* Issue the NVM command */
534 res = target_write_u16(target,
535 SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLA, SAMD_NVM_CMD(cmd));
536 if (res != ERROR_OK)
537 return res;
538
539 /* Check to see if the NVM command resulted in an error condition. */
540 return samd_check_error(target);
541 }
542
543 /**
544 * Erases a flash-row at the given address.
545 * @param target Pointer to the target structure.
546 * @param address The address of the row.
547 * @return On success ERROR_OK, on failure an errorcode.
548 */
549 static int samd_erase_row(struct target *target, uint32_t address)
550 {
551 int res;
552
553 /* Set an address contained in the row to be erased */
554 res = target_write_u32(target,
555 SAMD_NVMCTRL + SAMD_NVMCTRL_ADDR, address >> 1);
556
557 /* Issue the Erase Row command to erase that row. */
558 if (res == ERROR_OK)
559 res = samd_issue_nvmctrl_command(target,
560 address == SAMD_USER_ROW ? SAMD_NVM_CMD_EAR : SAMD_NVM_CMD_ER);
561
562 if (res != ERROR_OK) {
563 LOG_ERROR("Failed to erase row containing %08" PRIx32, address);
564 return ERROR_FAIL;
565 }
566
567 return ERROR_OK;
568 }
569
570 /**
571 * Returns the bitmask of reserved bits in register.
572 * @param target Pointer to the target structure.
573 * @param mask Bitmask, 0 -> value stays untouched.
574 * @return On success ERROR_OK, on failure an errorcode.
575 */
576 static int samd_get_reservedmask(struct target *target, uint64_t *mask)
577 {
578 int res;
579 /* Get the devicetype */
580 uint32_t id;
581 res = target_read_u32(target, SAMD_DSU + SAMD_DSU_DID, &id);
582 if (res != ERROR_OK) {
583 LOG_ERROR("Couldn't read Device ID register");
584 return res;
585 }
586 const struct samd_family *family;
587 family = samd_find_family(id);
588 if (family == NULL) {
589 LOG_ERROR("Couldn't determine device family");
590 return ERROR_FAIL;
591 }
592 *mask = family->nvm_userrow_res_mask;
593 return ERROR_OK;
594 }
595
596 static int read_userrow(struct target *target, uint64_t *userrow)
597 {
598 int res;
599 uint8_t buffer[8];
600
601 res = target_read_memory(target, SAMD_USER_ROW, 4, 2, buffer);
602 if (res != ERROR_OK)
603 return res;
604
605 *userrow = target_buffer_get_u64(target, buffer);
606 return ERROR_OK;
607 }
608
609 /**
610 * Modify the contents of the User Row in Flash. The User Row itself
611 * has a size of one page and contains a combination of "fuses" and
612 * calibration data. Bits which have a value of zero in the mask will
613 * not be changed. Up to now devices only use the first 64 bits.
614 * @param target Pointer to the target structure.
615 * @param value_input The value to write.
616 * @param value_mask Bitmask, 0 -> value stays untouched.
617 * @return On success ERROR_OK, on failure an errorcode.
618 */
619 static int samd_modify_user_row_masked(struct target *target,
620 uint64_t value_input, uint64_t value_mask)
621 {
622 int res;
623 uint32_t nvm_ctrlb;
624 bool manual_wp = true;
625
626 /* Retrieve the MCU's page size, in bytes. This is also the size of the
627 * entire User Row. */
628 uint32_t page_size;
629 res = samd_get_flash_page_info(target, &page_size, NULL);
630 if (res != ERROR_OK) {
631 LOG_ERROR("Couldn't determine Flash page size");
632 return res;
633 }
634
635 /* Make sure the size is sane. */
636 assert(page_size <= SAMD_PAGE_SIZE_MAX &&
637 page_size >= sizeof(value_input));
638
639 uint8_t buf[SAMD_PAGE_SIZE_MAX];
640 /* Read the user row (comprising one page) by words. */
641 res = target_read_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf);
642 if (res != ERROR_OK)
643 return res;
644
645 uint64_t value_device;
646 res = read_userrow(target, &value_device);
647 if (res != ERROR_OK)
648 return res;
649 uint64_t value_new = (value_input & value_mask) | (value_device & ~value_mask);
650
651 /* We will need to erase before writing if the new value needs a '1' in any
652 * position for which the current value had a '0'. Otherwise we can avoid
653 * erasing. */
654 if ((~value_device) & value_new) {
655 res = samd_erase_row(target, SAMD_USER_ROW);
656 if (res != ERROR_OK) {
657 LOG_ERROR("Couldn't erase user row");
658 return res;
659 }
660 }
661
662 /* Modify */
663 target_buffer_set_u64(target, buf, value_new);
664
665 /* Write the page buffer back out to the target. */
666 res = target_write_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf);
667 if (res != ERROR_OK)
668 return res;
669
670 /* Check if we need to do manual page write commands */
671 res = target_read_u32(target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLB, &nvm_ctrlb);
672 if (res == ERROR_OK)
673 manual_wp = (nvm_ctrlb & SAMD_NVM_CTRLB_MANW) != 0;
674 else {
675 LOG_ERROR("Read of NVM register CTRKB failed.");
676 return ERROR_FAIL;
677 }
678 if (manual_wp) {
679 /* Trigger flash write */
680 res = samd_issue_nvmctrl_command(target, SAMD_NVM_CMD_WAP);
681 } else {
682 res = samd_check_error(target);
683 }
684
685 return res;
686 }
687
688 /**
689 * Modifies the user row register to the given value.
690 * @param target Pointer to the target structure.
691 * @param value The value to write.
692 * @param startb The bit-offset by which the given value is shifted.
693 * @param endb The bit-offset of the last bit in value to write.
694 * @return On success ERROR_OK, on failure an errorcode.
695 */
696 static int samd_modify_user_row(struct target *target, uint64_t value,
697 uint8_t startb, uint8_t endb)
698 {
699 uint64_t mask = 0;
700 int i;
701 for (i = startb ; i <= endb ; i++)
702 mask |= ((uint64_t)1) << i;
703
704 return samd_modify_user_row_masked(target, value << startb, mask);
705 }
706
707 static int samd_protect(struct flash_bank *bank, int set, int first_prot_bl, int last_prot_bl)
708 {
709 int res = ERROR_OK;
710 int prot_block;
711
712 /* We can issue lock/unlock region commands with the target running but
713 * the settings won't persist unless we're able to modify the LOCK regions
714 * and that requires the target to be halted. */
715 if (bank->target->state != TARGET_HALTED) {
716 LOG_ERROR("Target not halted");
717 return ERROR_TARGET_NOT_HALTED;
718 }
719
720 for (prot_block = first_prot_bl; prot_block <= last_prot_bl; prot_block++) {
721 if (set != bank->prot_blocks[prot_block].is_protected) {
722 /* Load an address that is within this protection block (we use offset 0) */
723 res = target_write_u32(bank->target,
724 SAMD_NVMCTRL + SAMD_NVMCTRL_ADDR,
725 bank->prot_blocks[prot_block].offset >> 1);
726 if (res != ERROR_OK)
727 goto exit;
728
729 /* Tell the controller to lock that block */
730 res = samd_issue_nvmctrl_command(bank->target,
731 set ? SAMD_NVM_CMD_LR : SAMD_NVM_CMD_UR);
732 if (res != ERROR_OK)
733 goto exit;
734 }
735 }
736
737 /* We've now applied our changes, however they will be undone by the next
738 * reset unless we also apply them to the LOCK bits in the User Page. The
739 * LOCK bits start at bit 48, corresponding to Sector 0 and end with bit 63,
740 * corresponding to Sector 15. A '1' means unlocked and a '0' means
741 * locked. See Table 9-3 in the SAMD20 datasheet for more details. */
742
743 res = samd_modify_user_row(bank->target,
744 set ? (uint64_t)0 : (uint64_t)UINT64_MAX,
745 48 + first_prot_bl, 48 + last_prot_bl);
746 if (res != ERROR_OK)
747 LOG_WARNING("SAMD: protect settings were not made persistent!");
748
749 res = ERROR_OK;
750
751 exit:
752 samd_protect_check(bank);
753
754 return res;
755 }
756
757 static int samd_erase(struct flash_bank *bank, int first_sect, int last_sect)
758 {
759 int res, s;
760 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
761
762 if (bank->target->state != TARGET_HALTED) {
763 LOG_ERROR("Target not halted");
764
765 return ERROR_TARGET_NOT_HALTED;
766 }
767
768 if (!chip->probed) {
769 if (samd_probe(bank) != ERROR_OK)
770 return ERROR_FLASH_BANK_NOT_PROBED;
771 }
772
773 /* For each sector to be erased */
774 for (s = first_sect; s <= last_sect; s++) {
775 res = samd_erase_row(bank->target, bank->sectors[s].offset);
776 if (res != ERROR_OK) {
777 LOG_ERROR("SAMD: failed to erase sector %d at 0x%08" PRIx32, s, bank->sectors[s].offset);
778 return res;
779 }
780 }
781
782 return ERROR_OK;
783 }
784
785
786 static int samd_write(struct flash_bank *bank, const uint8_t *buffer,
787 uint32_t offset, uint32_t count)
788 {
789 int res;
790 uint32_t nvm_ctrlb;
791 uint32_t address;
792 uint32_t pg_offset;
793 uint32_t nb;
794 uint32_t nw;
795 struct samd_info *chip = (struct samd_info *)bank->driver_priv;
796 uint8_t *pb = NULL;
797 bool manual_wp;
798
799 if (bank->target->state != TARGET_HALTED) {
800 LOG_ERROR("Target not halted");
801 return ERROR_TARGET_NOT_HALTED;
802 }
803
804 if (!chip->probed) {
805 if (samd_probe(bank) != ERROR_OK)
806 return ERROR_FLASH_BANK_NOT_PROBED;
807 }
808
809 /* Check if we need to do manual page write commands */
810 res = target_read_u32(bank->target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLB, &nvm_ctrlb);
811
812 if (res != ERROR_OK)
813 return res;
814
815 if (nvm_ctrlb & SAMD_NVM_CTRLB_MANW)
816 manual_wp = true;
817 else
818 manual_wp = false;
819
820 res = samd_issue_nvmctrl_command(bank->target, SAMD_NVM_CMD_PBC);
821 if (res != ERROR_OK) {
822 LOG_ERROR("%s: %d", __func__, __LINE__);
823 return res;
824 }
825
826 while (count) {
827 nb = chip->page_size - offset % chip->page_size;
828 if (count < nb)
829 nb = count;
830
831 address = bank->base + offset;
832 pg_offset = offset % chip->page_size;
833
834 if (offset % 4 || (offset + nb) % 4) {
835 /* Either start or end of write is not word aligned */
836 if (!pb) {
837 pb = malloc(chip->page_size);
838 if (!pb)
839 return ERROR_FAIL;
840 }
841
842 /* Set temporary page buffer to 0xff and overwrite the relevant part */
843 memset(pb, 0xff, chip->page_size);
844 memcpy(pb + pg_offset, buffer, nb);
845
846 /* Align start address to a word boundary */
847 address -= offset % 4;
848 pg_offset -= offset % 4;
849 assert(pg_offset % 4 == 0);
850
851 /* Extend length to whole words */
852 nw = (nb + offset % 4 + 3) / 4;
853 assert(pg_offset + 4 * nw <= chip->page_size);
854
855 /* Now we have original data extended by 0xff bytes
856 * to the nearest word boundary on both start and end */
857 res = target_write_memory(bank->target, address, 4, nw, pb + pg_offset);
858 } else {
859 assert(nb % 4 == 0);
860 nw = nb / 4;
861 assert(pg_offset + 4 * nw <= chip->page_size);
862
863 /* Word aligned data, use direct write from buffer */
864 res = target_write_memory(bank->target, address, 4, nw, buffer);
865 }
866 if (res != ERROR_OK) {
867 LOG_ERROR("%s: %d", __func__, __LINE__);
868 goto free_pb;
869 }
870
871 /* Devices with errata 13134 have automatic page write enabled by default
872 * For other devices issue a write page CMD to the NVM
873 * If the page has not been written up to the last word
874 * then issue CMD_WP always */
875 if (manual_wp || pg_offset + 4 * nw < chip->page_size) {
876 res = samd_issue_nvmctrl_command(bank->target, SAMD_NVM_CMD_WP);
877 } else {
878 /* Access through AHB is stalled while flash is being programmed */
879 usleep(200);
880
881 res = samd_check_error(bank->target);
882 }
883
884 if (res != ERROR_OK) {
885 LOG_ERROR("%s: write failed at address 0x%08" PRIx32, __func__, address);
886 goto free_pb;
887 }
888
889 /* We're done with the page contents */
890 count -= nb;
891 offset += nb;
892 buffer += nb;
893 }
894
895 free_pb:
896 if (pb)
897 free(pb);
898
899 return res;
900 }
901
902 FLASH_BANK_COMMAND_HANDLER(samd_flash_bank_command)
903 {
904 if (bank->base != SAMD_FLASH) {
905 LOG_ERROR("Address 0x%08" PRIx32 " invalid bank address (try 0x%08" PRIx32
906 "[at91samd series] )",
907 bank->base, SAMD_FLASH);
908 return ERROR_FAIL;
909 }
910
911 struct samd_info *chip;
912 chip = calloc(1, sizeof(*chip));
913 if (!chip) {
914 LOG_ERROR("No memory for flash bank chip info");
915 return ERROR_FAIL;
916 }
917
918 chip->target = bank->target;
919 chip->probed = false;
920
921 bank->driver_priv = chip;
922
923 return ERROR_OK;
924 }
925
926 COMMAND_HANDLER(samd_handle_info_command)
927 {
928 return ERROR_OK;
929 }
930
931 COMMAND_HANDLER(samd_handle_chip_erase_command)
932 {
933 struct target *target = get_current_target(CMD_CTX);
934 int res = ERROR_FAIL;
935
936 if (target) {
937 /* Enable access to the DSU by disabling the write protect bit */
938 target_write_u32(target, SAMD_PAC1, (1<<1));
939 /* intentionally without error checking - not accessible on secured chip */
940
941 /* Tell the DSU to perform a full chip erase. It takes about 240ms to
942 * perform the erase. */
943 res = target_write_u8(target, SAMD_DSU + SAMD_DSU_CTRL_EXT, (1<<4));
944 if (res == ERROR_OK)
945 command_print(CMD_CTX, "chip erase started");
946 else
947 command_print(CMD_CTX, "write to DSU CTRL failed");
948 }
949
950 return res;
951 }
952
953 COMMAND_HANDLER(samd_handle_set_security_command)
954 {
955 int res = ERROR_OK;
956 struct target *target = get_current_target(CMD_CTX);
957
958 if (CMD_ARGC < 1 || (CMD_ARGC >= 1 && (strcmp(CMD_ARGV[0], "enable")))) {
959 command_print(CMD_CTX, "supply the \"enable\" argument to proceed.");
960 return ERROR_COMMAND_SYNTAX_ERROR;
961 }
962
963 if (target) {
964 if (target->state != TARGET_HALTED) {
965 LOG_ERROR("Target not halted");
966 return ERROR_TARGET_NOT_HALTED;
967 }
968
969 res = samd_issue_nvmctrl_command(target, SAMD_NVM_CMD_SSB);
970
971 /* Check (and clear) error conditions */
972 if (res == ERROR_OK)
973 command_print(CMD_CTX, "chip secured on next power-cycle");
974 else
975 command_print(CMD_CTX, "failed to secure chip");
976 }
977
978 return res;
979 }
980
981 COMMAND_HANDLER(samd_handle_eeprom_command)
982 {
983 int res = ERROR_OK;
984 struct target *target = get_current_target(CMD_CTX);
985
986 if (target) {
987 if (target->state != TARGET_HALTED) {
988 LOG_ERROR("Target not halted");
989 return ERROR_TARGET_NOT_HALTED;
990 }
991
992 if (CMD_ARGC >= 1) {
993 int val = atoi(CMD_ARGV[0]);
994 uint32_t code;
995
996 if (val == 0)
997 code = 7;
998 else {
999 /* Try to match size in bytes with corresponding size code */
1000 for (code = 0; code <= 6; code++) {
1001 if (val == (2 << (13 - code)))
1002 break;
1003 }
1004
1005 if (code > 6) {
1006 command_print(CMD_CTX, "Invalid EEPROM size. Please see "
1007 "datasheet for a list valid sizes.");
1008 return ERROR_COMMAND_SYNTAX_ERROR;
1009 }
1010 }
1011
1012 res = samd_modify_user_row(target, code, 4, 6);
1013 } else {
1014 uint16_t val;
1015 res = target_read_u16(target, SAMD_USER_ROW, &val);
1016 if (res == ERROR_OK) {
1017 uint32_t size = ((val >> 4) & 0x7); /* grab size code */
1018
1019 if (size == 0x7)
1020 command_print(CMD_CTX, "EEPROM is disabled");
1021 else {
1022 /* Otherwise, 6 is 256B, 0 is 16KB */
1023 command_print(CMD_CTX, "EEPROM size is %u bytes",
1024 (2 << (13 - size)));
1025 }
1026 }
1027 }
1028 }
1029
1030 return res;
1031 }
1032
1033 static COMMAND_HELPER(get_u64_from_hexarg, unsigned int num, uint64_t *value)
1034 {
1035 if (num >= CMD_ARGC) {
1036 command_print(CMD_CTX, "Too few Arguments.");
1037 return ERROR_COMMAND_SYNTAX_ERROR;
1038 }
1039
1040 if (strlen(CMD_ARGV[num]) >= 3 &&
1041 CMD_ARGV[num][0] == '0' &&
1042 CMD_ARGV[num][1] == 'x') {
1043 char *check = NULL;
1044 *value = strtoull(&(CMD_ARGV[num][2]), &check, 16);
1045 if ((value == 0 && errno == ERANGE) ||
1046 check == NULL || *check != 0) {
1047 command_print(CMD_CTX, "Invalid 64-bit hex value in argument %d.",
1048 num + 1);
1049 return ERROR_COMMAND_SYNTAX_ERROR;
1050 }
1051 } else {
1052 command_print(CMD_CTX, "Argument %d needs to be a hex value.", num + 1);
1053 return ERROR_COMMAND_SYNTAX_ERROR;
1054 }
1055 return ERROR_OK;
1056 }
1057
1058 COMMAND_HANDLER(samd_handle_nvmuserrow_command)
1059 {
1060 int res = ERROR_OK;
1061 struct target *target = get_current_target(CMD_CTX);
1062
1063 if (target) {
1064 if (CMD_ARGC > 2) {
1065 command_print(CMD_CTX, "Too much Arguments given.");
1066 return ERROR_COMMAND_SYNTAX_ERROR;
1067 }
1068
1069 if (CMD_ARGC > 0) {
1070 if (target->state != TARGET_HALTED) {
1071 LOG_ERROR("Target not halted.");
1072 return ERROR_TARGET_NOT_HALTED;
1073 }
1074
1075 uint64_t mask;
1076 res = samd_get_reservedmask(target, &mask);
1077 if (res != ERROR_OK) {
1078 LOG_ERROR("Couldn't determine the mask for reserved bits.");
1079 return ERROR_FAIL;
1080 }
1081 mask &= NVMUSERROW_LOCKBIT_MASK;
1082
1083 uint64_t value;
1084 res = CALL_COMMAND_HANDLER(get_u64_from_hexarg, 0, &value);
1085 if (res != ERROR_OK)
1086 return res;
1087 if (CMD_ARGC == 2) {
1088 uint64_t mask_temp;
1089 res = CALL_COMMAND_HANDLER(get_u64_from_hexarg, 1, &mask_temp);
1090 if (res != ERROR_OK)
1091 return res;
1092 mask &= mask_temp;
1093 }
1094 res = samd_modify_user_row_masked(target, value, mask);
1095 if (res != ERROR_OK)
1096 return res;
1097 }
1098
1099 /* read register */
1100 uint64_t value;
1101 res = read_userrow(target, &value);
1102 if (res == ERROR_OK)
1103 command_print(CMD_CTX, "NVMUSERROW: 0x%016"PRIX64, value);
1104 else
1105 LOG_ERROR("NVMUSERROW could not be read.");
1106 }
1107 return res;
1108 }
1109
1110 COMMAND_HANDLER(samd_handle_bootloader_command)
1111 {
1112 int res = ERROR_OK;
1113 struct target *target = get_current_target(CMD_CTX);
1114
1115 if (target) {
1116 if (target->state != TARGET_HALTED) {
1117 LOG_ERROR("Target not halted");
1118 return ERROR_TARGET_NOT_HALTED;
1119 }
1120
1121 /* Retrieve the MCU's page size, in bytes. */
1122 uint32_t page_size;
1123 res = samd_get_flash_page_info(target, &page_size, NULL);
1124 if (res != ERROR_OK) {
1125 LOG_ERROR("Couldn't determine Flash page size");
1126 return res;
1127 }
1128
1129 if (CMD_ARGC >= 1) {
1130 int val = atoi(CMD_ARGV[0]);
1131 uint32_t code;
1132
1133 if (val == 0)
1134 code = 7;
1135 else {
1136 /* Try to match size in bytes with corresponding size code */
1137 for (code = 0; code <= 6; code++) {
1138 if ((unsigned int)val == (2UL << (8UL - code)) * page_size)
1139 break;
1140 }
1141
1142 if (code > 6) {
1143 command_print(CMD_CTX, "Invalid bootloader size. Please "
1144 "see datasheet for a list valid sizes.");
1145 return ERROR_COMMAND_SYNTAX_ERROR;
1146 }
1147
1148 }
1149
1150 res = samd_modify_user_row(target, code, 0, 2);
1151 } else {
1152 uint16_t val;
1153 res = target_read_u16(target, SAMD_USER_ROW, &val);
1154 if (res == ERROR_OK) {
1155 uint32_t size = (val & 0x7); /* grab size code */
1156 uint32_t nb;
1157
1158 if (size == 0x7)
1159 nb = 0;
1160 else
1161 nb = (2 << (8 - size)) * page_size;
1162
1163 /* There are 4 pages per row */
1164 command_print(CMD_CTX, "Bootloader size is %" PRIu32 " bytes (%" PRIu32 " rows)",
1165 nb, (uint32_t)(nb / (page_size * 4)));
1166 }
1167 }
1168 }
1169
1170 return res;
1171 }
1172
1173
1174
1175 COMMAND_HANDLER(samd_handle_reset_deassert)
1176 {
1177 struct target *target = get_current_target(CMD_CTX);
1178 int retval = ERROR_OK;
1179 enum reset_types jtag_reset_config = jtag_get_reset_config();
1180
1181 /* If the target has been unresponsive before, try to re-establish
1182 * communication now - CPU is held in reset by DSU, DAP is working */
1183 if (!target_was_examined(target))
1184 target_examine_one(target);
1185 target_poll(target);
1186
1187 /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset()
1188 * so we just release reset held by DSU
1189 *
1190 * n_RESET (srst) clears the DP, so reenable debug and set vector catch here
1191 *
1192 * After vectreset DSU release is not needed however makes no harm
1193 */
1194 if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) {
1195 retval = target_write_u32(target, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
1196 if (retval == ERROR_OK)
1197 retval = target_write_u32(target, DCB_DEMCR,
1198 TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
1199 /* do not return on error here, releasing DSU reset is more important */
1200 }
1201
1202 /* clear CPU Reset Phase Extension bit */
1203 int retval2 = target_write_u8(target, SAMD_DSU + SAMD_DSU_STATUSA, (1<<1));
1204 if (retval2 != ERROR_OK)
1205 return retval2;
1206
1207 return retval;
1208 }
1209
1210 static const struct command_registration at91samd_exec_command_handlers[] = {
1211 {
1212 .name = "dsu_reset_deassert",
1213 .handler = samd_handle_reset_deassert,
1214 .mode = COMMAND_EXEC,
1215 .help = "Deasert internal reset held by DSU."
1216 },
1217 {
1218 .name = "info",
1219 .handler = samd_handle_info_command,
1220 .mode = COMMAND_EXEC,
1221 .help = "Print information about the current at91samd chip "
1222 "and its flash configuration.",
1223 },
1224 {
1225 .name = "chip-erase",
1226 .handler = samd_handle_chip_erase_command,
1227 .mode = COMMAND_EXEC,
1228 .help = "Erase the entire Flash by using the Chip-"
1229 "Erase feature in the Device Service Unit (DSU).",
1230 },
1231 {
1232 .name = "set-security",
1233 .handler = samd_handle_set_security_command,
1234 .mode = COMMAND_EXEC,
1235 .help = "Secure the chip's Flash by setting the Security Bit. "
1236 "This makes it impossible to read the Flash contents. "
1237 "The only way to undo this is to issue the chip-erase "
1238 "command.",
1239 },
1240 {
1241 .name = "eeprom",
1242 .usage = "[size_in_bytes]",
1243 .handler = samd_handle_eeprom_command,
1244 .mode = COMMAND_EXEC,
1245 .help = "Show or set the EEPROM size setting, stored in the User Row. "
1246 "Please see Table 20-3 of the SAMD20 datasheet for allowed values. "
1247 "Changes are stored immediately but take affect after the MCU is "
1248 "reset.",
1249 },
1250 {
1251 .name = "bootloader",
1252 .usage = "[size_in_bytes]",
1253 .handler = samd_handle_bootloader_command,
1254 .mode = COMMAND_EXEC,
1255 .help = "Show or set the bootloader size, stored in the User Row. "
1256 "Please see Table 20-2 of the SAMD20 datasheet for allowed values. "
1257 "Changes are stored immediately but take affect after the MCU is "
1258 "reset.",
1259 },
1260 {
1261 .name = "nvmuserrow",
1262 .usage = "[value] [mask]",
1263 .handler = samd_handle_nvmuserrow_command,
1264 .mode = COMMAND_EXEC,
1265 .help = "Show or set the nvmuserrow register. It is 64 bit wide "
1266 "and located at address 0x804000. Use the optional mask argument "
1267 "to prevent changes at positions where the bitvalue is zero. "
1268 "For security reasons the lock- and reserved-bits are masked out "
1269 "in background and therefore cannot be changed.",
1270 },
1271 COMMAND_REGISTRATION_DONE
1272 };
1273
1274 static const struct command_registration at91samd_command_handlers[] = {
1275 {
1276 .name = "at91samd",
1277 .mode = COMMAND_ANY,
1278 .help = "at91samd flash command group",
1279 .usage = "",
1280 .chain = at91samd_exec_command_handlers,
1281 },
1282 COMMAND_REGISTRATION_DONE
1283 };
1284
1285 struct flash_driver at91samd_flash = {
1286 .name = "at91samd",
1287 .commands = at91samd_command_handlers,
1288 .flash_bank_command = samd_flash_bank_command,
1289 .erase = samd_erase,
1290 .protect = samd_protect,
1291 .write = samd_write,
1292 .read = default_flash_read,
1293 .probe = samd_probe,
1294 .auto_probe = samd_probe,
1295 .erase_check = default_flash_blank_check,
1296 .protect_check = samd_protect_check,
1297 .free_driver_priv = default_flash_free_driver_priv,
1298 };

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)