12ea15b2099c33e10db0c93d3a8ccb99f191f7bb
[openocd.git] / src / flash / nor / stellaris.c
1 /***************************************************************************
2 * Copyright (C) 2006 by Magnus Lundin *
3 * lundin@mlu.mine.nu *
4 * *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
23
24 /***************************************************************************
25 * STELLARIS flash is tested on LM3S811, LM3S6965, LM3s3748, more.
26 ***************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "imp.h"
32 #include <target/algorithm.h>
33 #include <target/armv7m.h>
34
35
36 #define DID0_VER(did0) ((did0 >> 28)&0x07)
37
38 /* STELLARIS control registers */
39 #define SCB_BASE 0x400FE000
40 #define DID0 0x000
41 #define DID1 0x004
42 #define DC0 0x008
43 #define DC1 0x010
44 #define DC2 0x014
45 #define DC3 0x018
46 #define DC4 0x01C
47
48 #define RIS 0x050
49 #define RCC 0x060
50 #define PLLCFG 0x064
51 #define RCC2 0x070
52 #define NVMSTAT 0x1a0
53
54 /* "legacy" flash memory protection registers (64KB max) */
55 #define FMPRE 0x130
56 #define FMPPE 0x134
57
58 /* new flash memory protection registers (for more than 64KB) */
59 #define FMPRE0 0x200 /* PRE1 = PRE0 + 4, etc */
60 #define FMPPE0 0x400 /* PPE1 = PPE0 + 4, etc */
61
62 #define USECRL 0x140
63
64 #define FLASH_CONTROL_BASE 0x400FD000
65 #define FLASH_FMA (FLASH_CONTROL_BASE | 0x000)
66 #define FLASH_FMD (FLASH_CONTROL_BASE | 0x004)
67 #define FLASH_FMC (FLASH_CONTROL_BASE | 0x008)
68 #define FLASH_CRIS (FLASH_CONTROL_BASE | 0x00C)
69 #define FLASH_CIM (FLASH_CONTROL_BASE | 0x010)
70 #define FLASH_MISC (FLASH_CONTROL_BASE | 0x014)
71
72 #define AMISC 1
73 #define PMISC 2
74
75 #define AMASK 1
76 #define PMASK 2
77
78 /* Flash Controller Command bits */
79 #define FMC_WRKEY (0xA442 << 16)
80 #define FMC_COMT (1 << 3)
81 #define FMC_MERASE (1 << 2)
82 #define FMC_ERASE (1 << 1)
83 #define FMC_WRITE (1 << 0)
84
85 /* STELLARIS constants */
86
87 /* values to write in FMA to commit write-"once" values */
88 #define FLASH_FMA_PRE(x) (2 * (x)) /* for FMPPREx */
89 #define FLASH_FMA_PPE(x) (2 * (x) + 1) /* for FMPPPEx */
90
91
92 static void stellaris_read_clock_info(struct flash_bank *bank);
93 static int stellaris_mass_erase(struct flash_bank *bank);
94
95 struct stellaris_flash_bank
96 {
97 /* chip id register */
98 uint32_t did0;
99 uint32_t did1;
100 uint32_t dc0;
101 uint32_t dc1;
102
103 char * target_name;
104
105 uint32_t sramsiz;
106 uint32_t flshsz;
107 /* flash geometry */
108 uint32_t num_pages;
109 uint32_t pagesize;
110 uint32_t pages_in_lockregion;
111
112 /* nv memory bits */
113 uint16_t num_lockbits;
114
115 /* main clock status */
116 uint32_t rcc;
117 uint32_t rcc2;
118 uint8_t mck_valid;
119 uint8_t xtal_mask;
120 uint32_t iosc_freq;
121 uint32_t mck_freq;
122 const char *iosc_desc;
123 const char *mck_desc;
124 };
125
126 static struct {
127 uint32_t partno;
128 char *partname;
129 } StellarisParts[] =
130 {
131 {0x0001,"LM3S101"},
132 {0x0002,"LM3S102"},
133 {0x0019,"LM3S300"},
134 {0x0011,"LM3S301"},
135 {0x001A,"LM3S308"},
136 {0x0012,"LM3S310"},
137 {0x0013,"LM3S315"},
138 {0x0014,"LM3S316"},
139 {0x0017,"LM3S317"},
140 {0x0015,"LM3S328"},
141 {0x002A,"LM3S600"},
142 {0x0021,"LM3S601"},
143 {0x002B,"LM3S608"},
144 {0x0022,"LM3S610"},
145 {0x0023,"LM3S611"},
146 {0x0024,"LM3S612"},
147 {0x0025,"LM3S613"},
148 {0x0026,"LM3S615"},
149 {0x0028,"LM3S617"},
150 {0x0029,"LM3S618"},
151 {0x0027,"LM3S628"},
152 {0x0038,"LM3S800"},
153 {0x0031,"LM3S801"},
154 {0x0039,"LM3S808"},
155 {0x0032,"LM3S811"},
156 {0x0033,"LM3S812"},
157 {0x0034,"LM3S815"},
158 {0x0036,"LM3S817"},
159 {0x0037,"LM3S818"},
160 {0x0035,"LM3S828"},
161 {0x10BF,"LM3S1110"},
162 {0x10C3,"LM3S1133"},
163 {0x10C5,"LM3S1138"},
164 {0x10C1,"LM3S1150"},
165 {0x10C4,"LM3S1162"},
166 {0x10C2,"LM3S1165"},
167 {0x10C6,"LM3S1332"},
168 {0x10BC,"LM3S1435"},
169 {0x10BA,"LM3S1439"},
170 {0x10BB,"LM3S1512"},
171 {0x10C7,"LM3S1538"},
172 {0x10DB,"LM3S1601"},
173 {0x1006,"LM3S1607"},
174 {0x10DA,"LM3S1608"},
175 {0x10C0,"LM3S1620"},
176 {0x1003,"LM3S1625"},
177 {0x1004,"LM3S1626"},
178 {0x1005,"LM3S1627"},
179 {0x10B3,"LM3S1635"},
180 {0x10BD,"LM3S1637"},
181 {0x10B9,"LM3S1751"},
182 {0x1010,"LM3S1776"},
183 {0x1016,"LM3S1811"},
184 {0x103D,"LM3S1816"},
185 {0x10B4,"LM3S1850"},
186 {0x10DD,"LM3S1911"},
187 {0x10DC,"LM3S1918"},
188 {0x10B7,"LM3S1937"},
189 {0x10BE,"LM3S1958"},
190 {0x10B5,"LM3S1960"},
191 {0x10B8,"LM3S1968"},
192 {0x100F,"LM3S1J11"},
193 {0x103C,"LM3S1J16"},
194 {0x100E,"LM3S1N11"},
195 {0x103B,"LM3S1N16"},
196 {0x1030,"LM3S1W16"},
197 {0x102F,"LM3S1Z16"},
198 {0x1051,"LM3S2110"},
199 {0x1084,"LM3S2139"},
200 {0x1039,"LM3S2276"},
201 {0x10A2,"LM3S2410"},
202 {0x1059,"LM3S2412"},
203 {0x1056,"LM3S2432"},
204 {0x105A,"LM3S2533"},
205 {0x10E1,"LM3S2601"},
206 {0x10E0,"LM3S2608"},
207 {0x1033,"LM3S2616"},
208 {0x1057,"LM3S2620"},
209 {0x1085,"LM3S2637"},
210 {0x1053,"LM3S2651"},
211 {0x1080,"LM3S2671"},
212 {0x1050,"LM3S2678"},
213 {0x10A4,"LM3S2730"},
214 {0x1052,"LM3S2739"},
215 {0x103A,"LM3S2776"},
216 {0x106D,"LM3S2793"},
217 {0x10E3,"LM3S2911"},
218 {0x10E2,"LM3S2918"},
219 {0x1054,"LM3S2939"},
220 {0x108F,"LM3S2948"},
221 {0x1058,"LM3S2950"},
222 {0x1055,"LM3S2965"},
223 {0x106C,"LM3S2B93"},
224 {0x1043,"LM3S3651"},
225 {0x1044,"LM3S3739"},
226 {0x1049,"LM3S3748"},
227 {0x1045,"LM3S3749"},
228 {0x1042,"LM3S3826"},
229 {0x1041,"LM3S3J26"},
230 {0x1040,"LM3S3N26"},
231 {0x103F,"LM3S3W26"},
232 {0x103E,"LM3S3Z26"},
233 {0x1081,"LM3S5632"},
234 {0x100C,"LM3S5651"},
235 {0x108A,"LM3S5652"},
236 {0x104D,"LM3S5656"},
237 {0x1091,"LM3S5662"},
238 {0x1096,"LM3S5732"},
239 {0x1097,"LM3S5737"},
240 {0x10A0,"LM3S5739"},
241 {0x1099,"LM3S5747"},
242 {0x10A7,"LM3S5749"},
243 {0x109A,"LM3S5752"},
244 {0x109C,"LM3S5762"},
245 {0x1069,"LM3S5791"},
246 {0x100B,"LM3S5951"},
247 {0x104E,"LM3S5956"},
248 {0x1068,"LM3S5B91"},
249 {0x1009,"LM3S5K31"},
250 {0x104A,"LM3S5K36"},
251 {0x100A,"LM3S5P31"},
252 {0x1048,"LM3S5P36"},
253 {0x100D,"LM3S5P51"},
254 {0x104C,"LM3S5P56"},
255 {0x1007,"LM3S5R31"},
256 {0x104B,"LM3S5R36"},
257 {0x1047,"LM3S5T36"},
258 {0x1046,"LM3S5Y36"},
259 {0x10A1,"LM3S6100"},
260 {0x1074,"LM3S6110"},
261 {0x10A5,"LM3S6420"},
262 {0x1082,"LM3S6422"},
263 {0x1075,"LM3S6432"},
264 {0x1076,"LM3S6537"},
265 {0x1071,"LM3S6610"},
266 {0x10E7,"LM3S6611"},
267 {0x10E6,"LM3S6618"},
268 {0x1083,"LM3S6633"},
269 {0x108B,"LM3S6637"},
270 {0x10A3,"LM3S6730"},
271 {0x1077,"LM3S6753"},
272 {0x10E9,"LM3S6911"},
273 {0x10E8,"LM3S6918"},
274 {0x1089,"LM3S6938"},
275 {0x1072,"LM3S6950"},
276 {0x1078,"LM3S6952"},
277 {0x1073,"LM3S6965"},
278 {0x1064,"LM3S8530"},
279 {0x108E,"LM3S8538"},
280 {0x1061,"LM3S8630"},
281 {0x1063,"LM3S8730"},
282 {0x108D,"LM3S8733"},
283 {0x1086,"LM3S8738"},
284 {0x1065,"LM3S8930"},
285 {0x108C,"LM3S8933"},
286 {0x1088,"LM3S8938"},
287 {0x10A6,"LM3S8962"},
288 {0x1062,"LM3S8970"},
289 {0x10D7,"LM3S8971"},
290 {0x1067,"LM3S9790"},
291 {0x106B,"LM3S9792"},
292 {0x1020,"LM3S9997"},
293 {0x1066,"LM3S9B90"},
294 {0x106A,"LM3S9B92"},
295 {0x106E,"LM3S9B95"},
296 {0x106F,"LM3S9B96"},
297 {0x1018,"LM3S9L97"},
298 {0,"Unknown part"}
299 };
300
301 static char * StellarisClassname[5] =
302 {
303 "Sandstorm",
304 "Fury",
305 "Unknown",
306 "DustDevil",
307 "Tempest"
308 };
309
310 /***************************************************************************
311 * openocd command interface *
312 ***************************************************************************/
313
314 /* flash_bank stellaris <base> <size> 0 0 <target#>
315 */
316 FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command)
317 {
318 struct stellaris_flash_bank *stellaris_info;
319
320 if (CMD_ARGC < 6)
321 {
322 LOG_WARNING("incomplete flash_bank stellaris configuration");
323 return ERROR_FLASH_BANK_INVALID;
324 }
325
326 stellaris_info = calloc(sizeof(struct stellaris_flash_bank), 1);
327 bank->base = 0x0;
328 bank->driver_priv = stellaris_info;
329
330 stellaris_info->target_name = "Unknown target";
331
332 /* part wasn't probed for info yet */
333 stellaris_info->did1 = 0;
334
335 /* TODO Specify the main crystal speed in kHz using an optional
336 * argument; ditto, the speed of an external oscillator used
337 * instead of a crystal. Avoid programming flash using IOSC.
338 */
339 return ERROR_OK;
340 }
341
342 static int get_stellaris_info(struct flash_bank *bank, char *buf, int buf_size)
343 {
344 int printed, device_class;
345 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
346
347 if (stellaris_info->did1 == 0)
348 return ERROR_FLASH_BANK_NOT_PROBED;
349
350 /* Read main and master clock freqency register */
351 stellaris_read_clock_info(bank);
352
353 if (DID0_VER(stellaris_info->did0) > 0)
354 {
355 device_class = (stellaris_info->did0 >> 16) & 0xFF;
356 }
357 else
358 {
359 device_class = 0;
360 }
361 printed = snprintf(buf,
362 buf_size,
363 "\nTI/LMI Stellaris information: Chip is "
364 "class %i (%s) %s rev %c%i\n",
365 device_class,
366 StellarisClassname[device_class],
367 stellaris_info->target_name,
368 (int)('A' + ((stellaris_info->did0 >> 8) & 0xFF)),
369 (int)((stellaris_info->did0) & 0xFF));
370 buf += printed;
371 buf_size -= printed;
372
373 printed = snprintf(buf,
374 buf_size,
375 "did1: 0x%8.8" PRIx32 ", arch: 0x%4.4" PRIx32
376 ", eproc: %s, ramsize: %ik, flashsize: %ik\n",
377 stellaris_info->did1,
378 stellaris_info->did1,
379 "ARMv7M",
380 (int)((1 + ((stellaris_info->dc0 >> 16) & 0xFFFF))/4),
381 (int)((1 + (stellaris_info->dc0 & 0xFFFF))*2));
382 buf += printed;
383 buf_size -= printed;
384
385 printed = snprintf(buf,
386 buf_size,
387 "master clock: %ikHz%s, "
388 "rcc is 0x%" PRIx32 ", rcc2 is 0x%" PRIx32 "\n",
389 (int)(stellaris_info->mck_freq / 1000),
390 stellaris_info->mck_desc,
391 stellaris_info->rcc,
392 stellaris_info->rcc2);
393 buf += printed;
394 buf_size -= printed;
395
396 if (stellaris_info->num_lockbits > 0)
397 {
398 printed = snprintf(buf,
399 buf_size,
400 "pagesize: %" PRIi32 ", pages: %d, "
401 "lockbits: %i, pages per lockbit: %i\n",
402 stellaris_info->pagesize,
403 (unsigned) stellaris_info->num_pages,
404 stellaris_info->num_lockbits,
405 (unsigned) stellaris_info->pages_in_lockregion);
406 buf += printed;
407 buf_size -= printed;
408 }
409 return ERROR_OK;
410 }
411
412 /***************************************************************************
413 * chip identification and status *
414 ***************************************************************************/
415
416 /* Set the flash timimg register to match current clocking */
417 static void stellaris_set_flash_timing(struct flash_bank *bank)
418 {
419 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
420 struct target *target = bank->target;
421 uint32_t usecrl = (stellaris_info->mck_freq/1000000ul-1);
422
423 LOG_DEBUG("usecrl = %i",(int)(usecrl));
424 target_write_u32(target, SCB_BASE | USECRL, usecrl);
425 }
426
427 static const unsigned rcc_xtal[32] = {
428 [0x00] = 1000000, /* no pll */
429 [0x01] = 1843200, /* no pll */
430 [0x02] = 2000000, /* no pll */
431 [0x03] = 2457600, /* no pll */
432
433 [0x04] = 3579545,
434 [0x05] = 3686400,
435 [0x06] = 4000000, /* usb */
436 [0x07] = 4096000,
437
438 [0x08] = 4915200,
439 [0x09] = 5000000, /* usb */
440 [0x0a] = 5120000,
441 [0x0b] = 6000000, /* (reset) usb */
442
443 [0x0c] = 6144000,
444 [0x0d] = 7372800,
445 [0x0e] = 8000000, /* usb */
446 [0x0f] = 8192000,
447
448 /* parts before DustDevil use just 4 bits for xtal spec */
449
450 [0x10] = 10000000, /* usb */
451 [0x11] = 12000000, /* usb */
452 [0x12] = 12288000,
453 [0x13] = 13560000,
454
455 [0x14] = 14318180,
456 [0x15] = 16000000, /* usb */
457 [0x16] = 16384000,
458 };
459
460 /** Read clock configuration and set stellaris_info->usec_clocks. */
461 static void stellaris_read_clock_info(struct flash_bank *bank)
462 {
463 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
464 struct target *target = bank->target;
465 uint32_t rcc, rcc2, pllcfg, sysdiv, usesysdiv, bypass, oscsrc;
466 unsigned xtal;
467 unsigned long mainfreq;
468
469 target_read_u32(target, SCB_BASE | RCC, &rcc);
470 LOG_DEBUG("Stellaris RCC %" PRIx32 "", rcc);
471
472 target_read_u32(target, SCB_BASE | RCC2, &rcc2);
473 LOG_DEBUG("Stellaris RCC2 %" PRIx32 "", rcc);
474
475 target_read_u32(target, SCB_BASE | PLLCFG, &pllcfg);
476 LOG_DEBUG("Stellaris PLLCFG %" PRIx32 "", pllcfg);
477
478 stellaris_info->rcc = rcc;
479 stellaris_info->rcc = rcc2;
480
481 sysdiv = (rcc >> 23) & 0xF;
482 usesysdiv = (rcc >> 22) & 0x1;
483 bypass = (rcc >> 11) & 0x1;
484 oscsrc = (rcc >> 4) & 0x3;
485 xtal = (rcc >> 6) & stellaris_info->xtal_mask;
486
487 /* NOTE: post-Sandstorm parts have RCC2 which may override
488 * parts of RCC ... with more sysdiv options, option for
489 * 32768 Hz mainfreq, PLL controls. On Sandstorm it reads
490 * as zero, so the "use RCC2" flag is always clear.
491 */
492 if (rcc2 & (1 << 31)) {
493 sysdiv = (rcc2 >> 23) & 0x3F;
494 bypass = (rcc2 >> 11) & 0x1;
495 oscsrc = (rcc2 >> 4) & 0x7;
496
497 /* FIXME Tempest parts have an additional lsb for
498 * fractional sysdiv (200 MHz / 2.5 == 80 MHz)
499 */
500 }
501
502 stellaris_info->mck_desc = "";
503
504 switch (oscsrc)
505 {
506 case 0: /* MOSC */
507 mainfreq = rcc_xtal[xtal];
508 break;
509 case 1: /* IOSC */
510 mainfreq = stellaris_info->iosc_freq;
511 stellaris_info->mck_desc = stellaris_info->iosc_desc;
512 break;
513 case 2: /* IOSC/4 */
514 mainfreq = stellaris_info->iosc_freq / 4;
515 stellaris_info->mck_desc = stellaris_info->iosc_desc;
516 break;
517 case 3: /* lowspeed */
518 /* Sandstorm doesn't have this 30K +/- 30% osc */
519 mainfreq = 30000;
520 stellaris_info->mck_desc = " (±30%)";
521 break;
522 case 8: /* hibernation osc */
523 /* not all parts support hibernation */
524 mainfreq = 32768;
525 break;
526
527 default: /* NOTREACHED */
528 mainfreq = 0;
529 break;
530 }
531
532 /* PLL is used if it's not bypassed; its output is 200 MHz
533 * even when it runs at 400 MHz (adds divide-by-two stage).
534 */
535 if (!bypass)
536 mainfreq = 200000000;
537
538 if (usesysdiv)
539 stellaris_info->mck_freq = mainfreq/(1 + sysdiv);
540 else
541 stellaris_info->mck_freq = mainfreq;
542 }
543
544 /* Read device id register, main clock frequency register and fill in driver info structure */
545 static int stellaris_read_part_info(struct flash_bank *bank)
546 {
547 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
548 struct target *target = bank->target;
549 uint32_t did0, did1, ver, fam;
550 int i;
551
552 /* Read and parse chip identification register */
553 target_read_u32(target, SCB_BASE | DID0, &did0);
554 target_read_u32(target, SCB_BASE | DID1, &did1);
555 target_read_u32(target, SCB_BASE | DC0, &stellaris_info->dc0);
556 target_read_u32(target, SCB_BASE | DC1, &stellaris_info->dc1);
557 LOG_DEBUG("did0 0x%" PRIx32 ", did1 0x%" PRIx32 ", dc0 0x%" PRIx32 ", dc1 0x%" PRIx32 "",
558 did0, did1, stellaris_info->dc0, stellaris_info->dc1);
559
560 ver = did0 >> 28;
561 if ((ver != 0) && (ver != 1))
562 {
563 LOG_WARNING("Unknown did0 version, cannot identify target");
564 return ERROR_FLASH_OPERATION_FAILED;
565 }
566
567 if (did1 == 0)
568 {
569 LOG_WARNING("Cannot identify target as a Stellaris");
570 return ERROR_FLASH_OPERATION_FAILED;
571 }
572
573 ver = did1 >> 28;
574 fam = (did1 >> 24) & 0xF;
575 if (((ver != 0) && (ver != 1)) || (fam != 0))
576 {
577 LOG_WARNING("Unknown did1 version/family.");
578 return ERROR_FLASH_OPERATION_FAILED;
579 }
580
581 /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
582 * is 12 MHz, but some older parts have 15 MHz. A few data sheets
583 * even give _both_ numbers! We'll use current numbers; IOSC is
584 * always approximate.
585 *
586 * For Tempest: IOSC is calibrated, 16 MHz
587 */
588 stellaris_info->iosc_freq = 12000000;
589 stellaris_info->iosc_desc = " (±30%)";
590 stellaris_info->xtal_mask = 0x0f;
591
592 switch ((did0 >> 28) & 0x7) {
593 case 0: /* Sandstorm */
594 /*
595 * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
596 * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
597 * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
598 */
599 if (((did0 >> 8) & 0xff) < 2) {
600 stellaris_info->iosc_freq = 15000000;
601 stellaris_info->iosc_desc = " (±50%)";
602 }
603 break;
604 case 1:
605 switch ((did0 >> 16) & 0xff) {
606 case 1: /* Fury */
607 break;
608 case 4: /* Tempest */
609 stellaris_info->iosc_freq = 16000000; /* +/- 1% */
610 stellaris_info->iosc_desc = " (±1%)";
611 /* FALL THROUGH */
612 case 3: /* DustDevil */
613 stellaris_info->xtal_mask = 0x1f;
614 break;
615 default:
616 LOG_WARNING("Unknown did0 class");
617 }
618 break;
619 default:
620 LOG_WARNING("Unknown did0 version");
621 break;
622 }
623
624 for (i = 0; StellarisParts[i].partno; i++)
625 {
626 if (StellarisParts[i].partno == ((did1 >> 16) & 0xFFFF))
627 break;
628 }
629
630 stellaris_info->target_name = StellarisParts[i].partname;
631
632 stellaris_info->did0 = did0;
633 stellaris_info->did1 = did1;
634
635 stellaris_info->num_lockbits = 1 + (stellaris_info->dc0 & 0xFFFF);
636 stellaris_info->num_pages = 2 *(1 + (stellaris_info->dc0 & 0xFFFF));
637 stellaris_info->pagesize = 1024;
638 stellaris_info->pages_in_lockregion = 2;
639
640 /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too.
641 * That exposes a 32-word Flash Write Buffer ... enabling
642 * writes of more than one word at a time.
643 */
644
645 return ERROR_OK;
646 }
647
648 /***************************************************************************
649 * flash operations *
650 ***************************************************************************/
651
652 static int stellaris_protect_check(struct flash_bank *bank)
653 {
654 struct stellaris_flash_bank *stellaris = bank->driver_priv;
655 int status = ERROR_OK;
656 unsigned i;
657 unsigned page;
658
659 if (stellaris->did1 == 0)
660 return ERROR_FLASH_BANK_NOT_PROBED;
661
662 for (i = 0; i < (unsigned) bank->num_sectors; i++)
663 bank->sectors[i].is_protected = -1;
664
665 /* Read each Flash Memory Protection Program Enable (FMPPE) register
666 * to report any pages that we can't write. Ignore the Read Enable
667 * register (FMPRE).
668 */
669 for (i = 0, page = 0;
670 i < DIV_ROUND_UP(stellaris->num_lockbits, 32u);
671 i++) {
672 uint32_t lockbits;
673
674 status = target_read_u32(bank->target,
675 SCB_BASE + (i ? (FMPPE0 + 4 * i) : FMPPE),
676 &lockbits);
677 LOG_DEBUG("FMPPE%d = %#8.8x (status %d)", i,
678 (unsigned) lockbits, status);
679 if (status != ERROR_OK)
680 goto done;
681
682 for (unsigned j = 0; j < 32; j++) {
683 unsigned k;
684
685 for (k = 0; k < stellaris->pages_in_lockregion; k++) {
686 if (page >= (unsigned) bank->num_sectors)
687 goto done;
688 bank->sectors[page++].is_protected =
689 !(lockbits & (1 << j));
690 }
691 }
692 }
693
694 done:
695 return status;
696 }
697
698 static int stellaris_erase(struct flash_bank *bank, int first, int last)
699 {
700 int banknr;
701 uint32_t flash_fmc, flash_cris;
702 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
703 struct target *target = bank->target;
704
705 if (bank->target->state != TARGET_HALTED)
706 {
707 LOG_ERROR("Target not halted");
708 return ERROR_TARGET_NOT_HALTED;
709 }
710
711 if (stellaris_info->did1 == 0)
712 return ERROR_FLASH_BANK_NOT_PROBED;
713
714 if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages))
715 {
716 return ERROR_FLASH_SECTOR_INVALID;
717 }
718
719 if ((first == 0) && (last == ((int)stellaris_info->num_pages-1)))
720 {
721 return stellaris_mass_erase(bank);
722 }
723
724 /* Refresh flash controller timing */
725 stellaris_read_clock_info(bank);
726 stellaris_set_flash_timing(bank);
727
728 /* Clear and disable flash programming interrupts */
729 target_write_u32(target, FLASH_CIM, 0);
730 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
731
732 /* REVISIT this clobbers state set by any halted firmware ...
733 * it might want to process those IRQs.
734 */
735
736 for (banknr = first; banknr <= last; banknr++)
737 {
738 /* Address is first word in page */
739 target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize);
740 /* Write erase command */
741 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
742 /* Wait until erase complete */
743 do
744 {
745 target_read_u32(target, FLASH_FMC, &flash_fmc);
746 }
747 while (flash_fmc & FMC_ERASE);
748
749 /* Check acess violations */
750 target_read_u32(target, FLASH_CRIS, &flash_cris);
751 if (flash_cris & (AMASK))
752 {
753 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "", banknr, flash_cris);
754 target_write_u32(target, FLASH_CRIS, 0);
755 return ERROR_FLASH_OPERATION_FAILED;
756 }
757
758 bank->sectors[banknr].is_erased = 1;
759 }
760
761 return ERROR_OK;
762 }
763
764 static int stellaris_protect(struct flash_bank *bank, int set, int first, int last)
765 {
766 uint32_t fmppe, flash_fmc, flash_cris;
767 int lockregion;
768
769 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
770 struct target *target = bank->target;
771
772 if (bank->target->state != TARGET_HALTED)
773 {
774 LOG_ERROR("Target not halted");
775 return ERROR_TARGET_NOT_HALTED;
776 }
777
778 if (!set)
779 {
780 LOG_ERROR("Hardware doesn't suppport page-level unprotect. "
781 "Try the 'recover' command.");
782 return ERROR_INVALID_ARGUMENTS;
783 }
784
785 if (stellaris_info->did1 == 0)
786 return ERROR_FLASH_BANK_NOT_PROBED;
787
788 /* lockregions are 2 pages ... must protect [even..odd] */
789 if ((first < 0) || (first & 1)
790 || (last < first) || !(last & 1)
791 || (last >= 2 * stellaris_info->num_lockbits))
792 {
793 LOG_ERROR("Can't protect unaligned or out-of-range pages.");
794 return ERROR_FLASH_SECTOR_INVALID;
795 }
796
797 /* Refresh flash controller timing */
798 stellaris_read_clock_info(bank);
799 stellaris_set_flash_timing(bank);
800
801 /* convert from pages to lockregions */
802 first /= 2;
803 last /= 2;
804
805 /* FIXME this assumes single FMPPE, for a max of 64K of flash!!
806 * Current parts can be much bigger.
807 */
808 if (last >= 32) {
809 LOG_ERROR("No support yet for protection > 64K");
810 return ERROR_FLASH_OPERATION_FAILED;
811 }
812
813 target_read_u32(target, SCB_BASE | FMPPE, &fmppe);
814
815 for (lockregion = first; lockregion <= last; lockregion++)
816 fmppe &= ~(1 << lockregion);
817
818 /* Clear and disable flash programming interrupts */
819 target_write_u32(target, FLASH_CIM, 0);
820 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
821
822 /* REVISIT this clobbers state set by any halted firmware ...
823 * it might want to process those IRQs.
824 */
825
826 LOG_DEBUG("fmppe 0x%" PRIx32 "",fmppe);
827 target_write_u32(target, SCB_BASE | FMPPE, fmppe);
828
829 /* Commit FMPPE */
830 target_write_u32(target, FLASH_FMA, 1);
831
832 /* Write commit command */
833 /* REVISIT safety check, since this cannot be undone
834 * except by the "Recover a locked device" procedure.
835 * REVISIT DustDevil-A0 parts have an erratum making FMPPE commits
836 * inadvisable ... it makes future mass erase operations fail.
837 */
838 LOG_WARNING("Flash protection cannot be removed once commited, commit is NOT executed !");
839 /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
840
841 /* Wait until erase complete */
842 do
843 {
844 target_read_u32(target, FLASH_FMC, &flash_fmc);
845 }
846 while (flash_fmc & FMC_COMT);
847
848 /* Check acess violations */
849 target_read_u32(target, FLASH_CRIS, &flash_cris);
850 if (flash_cris & (AMASK))
851 {
852 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris);
853 target_write_u32(target, FLASH_CRIS, 0);
854 return ERROR_FLASH_OPERATION_FAILED;
855 }
856
857 return ERROR_OK;
858 }
859
860 /* see contib/loaders/flash/stellaris.s for src */
861
862 static const uint8_t stellaris_write_code[] =
863 {
864 /*
865 Call with :
866 r0 = buffer address
867 r1 = destination address
868 r2 = bytecount (in) - endaddr (work)
869
870 Used registers:
871 r3 = pFLASH_CTRL_BASE
872 r4 = FLASHWRITECMD
873 r5 = #1
874 r6 = bytes written
875 r7 = temp reg
876 */
877 0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */
878 0x08,0x4C, /* ldr r4,FLASHWRITECMD */
879 0x01,0x25, /* movs r5, 1 */
880 0x00,0x26, /* movs r6, #0 */
881 /* mainloop: */
882 0x19,0x60, /* str r1, [r3, #0] */
883 0x87,0x59, /* ldr r7, [r0, r6] */
884 0x5F,0x60, /* str r7, [r3, #4] */
885 0x9C,0x60, /* str r4, [r3, #8] */
886 /* waitloop: */
887 0x9F,0x68, /* ldr r7, [r3, #8] */
888 0x2F,0x42, /* tst r7, r5 */
889 0xFC,0xD1, /* bne waitloop */
890 0x04,0x31, /* adds r1, r1, #4 */
891 0x04,0x36, /* adds r6, r6, #4 */
892 0x96,0x42, /* cmp r6, r2 */
893 0xF4,0xD1, /* bne mainloop */
894 0x00,0xBE, /* bkpt #0 */
895 /* pFLASH_CTRL_BASE: */
896 0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */
897 /* FLASHWRITECMD: */
898 0x01,0x00,0x42,0xA4 /* .word 0xA4420001 */
899 };
900
901 static int stellaris_write_block(struct flash_bank *bank,
902 uint8_t *buffer, uint32_t offset, uint32_t wcount)
903 {
904 struct target *target = bank->target;
905 uint32_t buffer_size = 16384;
906 struct working_area *source;
907 struct working_area *write_algorithm;
908 uint32_t address = bank->base + offset;
909 struct reg_param reg_params[3];
910 struct armv7m_algorithm armv7m_info;
911 int retval = ERROR_OK;
912
913 /* power of two, and multiple of word size */
914 static const unsigned buf_min = 128;
915
916 /* for small buffers it's faster not to download an algorithm */
917 if (wcount * 4 < buf_min)
918 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
919
920 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " wcount=%08" PRIx32 "",
921 bank, buffer, offset, wcount);
922
923 /* flash write code */
924 if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK)
925 {
926 LOG_DEBUG("no working area for block memory writes");
927 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
928 };
929
930 /* plus a buffer big enough for this data */
931 if (wcount * 4 < buffer_size)
932 buffer_size = wcount * 4;
933
934 /* memory buffer */
935 while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
936 {
937 buffer_size /= 2;
938 if (buffer_size <= buf_min)
939 {
940 target_free_working_area(target, write_algorithm);
941 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
942 }
943 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
944 target_name(target), (unsigned) buffer_size);
945 };
946
947 retval = target_write_buffer(target, write_algorithm->address,
948 sizeof(stellaris_write_code),
949 (uint8_t *) stellaris_write_code);
950
951 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
952 armv7m_info.core_mode = ARMV7M_MODE_ANY;
953
954 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
955 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
956 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
957
958 while (wcount > 0)
959 {
960 uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
961
962 target_write_buffer(target, source->address, thisrun_count * 4, buffer);
963
964 buf_set_u32(reg_params[0].value, 0, 32, source->address);
965 buf_set_u32(reg_params[1].value, 0, 32, address);
966 buf_set_u32(reg_params[2].value, 0, 32, 4*thisrun_count);
967 LOG_DEBUG("Algorithm flash write %u words to 0x%" PRIx32
968 ", %u remaining",
969 (unsigned) thisrun_count, address,
970 (unsigned) (wcount - thisrun_count));
971 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
972 write_algorithm->address,
973 0,
974 10000, &armv7m_info);
975 if (retval != ERROR_OK)
976 {
977 LOG_ERROR("error %d executing stellaris "
978 "flash write algorithm",
979 retval);
980 retval = ERROR_FLASH_OPERATION_FAILED;
981 break;
982 }
983
984 buffer += thisrun_count * 4;
985 address += thisrun_count * 4;
986 wcount -= thisrun_count;
987 }
988
989 /* REVISIT we could speed up writing multi-section images by
990 * not freeing the initialized write_algorithm this way.
991 */
992
993 target_free_working_area(target, write_algorithm);
994 target_free_working_area(target, source);
995
996 destroy_reg_param(&reg_params[0]);
997 destroy_reg_param(&reg_params[1]);
998 destroy_reg_param(&reg_params[2]);
999
1000 return retval;
1001 }
1002
1003 static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
1004 {
1005 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
1006 struct target *target = bank->target;
1007 uint32_t address = offset;
1008 uint32_t flash_cris, flash_fmc;
1009 uint32_t words_remaining = (count / 4);
1010 uint32_t bytes_remaining = (count & 0x00000003);
1011 uint32_t bytes_written = 0;
1012 int retval;
1013
1014 if (bank->target->state != TARGET_HALTED)
1015 {
1016 LOG_ERROR("Target not halted");
1017 return ERROR_TARGET_NOT_HALTED;
1018 }
1019
1020 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " count=%08" PRIx32 "",
1021 bank, buffer, offset, count);
1022
1023 if (stellaris_info->did1 == 0)
1024 return ERROR_FLASH_BANK_NOT_PROBED;
1025
1026 if (offset & 0x3)
1027 {
1028 LOG_WARNING("offset size must be word aligned");
1029 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
1030 }
1031
1032 if (offset + count > bank->size)
1033 return ERROR_FLASH_DST_OUT_OF_BANK;
1034
1035 /* Refresh flash controller timing */
1036 stellaris_read_clock_info(bank);
1037 stellaris_set_flash_timing(bank);
1038
1039 /* Clear and disable flash programming interrupts */
1040 target_write_u32(target, FLASH_CIM, 0);
1041 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
1042
1043 /* REVISIT this clobbers state set by any halted firmware ...
1044 * it might want to process those IRQs.
1045 */
1046
1047 /* multiple words to be programmed? */
1048 if (words_remaining > 0)
1049 {
1050 /* try using a block write */
1051 retval = stellaris_write_block(bank, buffer, offset,
1052 words_remaining);
1053 if (retval != ERROR_OK)
1054 {
1055 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
1056 {
1057 LOG_DEBUG("writing flash word-at-a-time");
1058 }
1059 else if (retval == ERROR_FLASH_OPERATION_FAILED)
1060 {
1061 /* if an error occured, we examine the reason, and quit */
1062 target_read_u32(target, FLASH_CRIS, &flash_cris);
1063
1064 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris);
1065 return ERROR_FLASH_OPERATION_FAILED;
1066 }
1067 }
1068 else
1069 {
1070 buffer += words_remaining * 4;
1071 address += words_remaining * 4;
1072 words_remaining = 0;
1073 }
1074 }
1075
1076 while (words_remaining > 0)
1077 {
1078 if (!(address & 0xff))
1079 LOG_DEBUG("0x%" PRIx32 "", address);
1080
1081 /* Program one word */
1082 target_write_u32(target, FLASH_FMA, address);
1083 target_write_buffer(target, FLASH_FMD, 4, buffer);
1084 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
1085 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1086 /* Wait until write complete */
1087 do
1088 {
1089 target_read_u32(target, FLASH_FMC, &flash_fmc);
1090 } while (flash_fmc & FMC_WRITE);
1091
1092 buffer += 4;
1093 address += 4;
1094 words_remaining--;
1095 }
1096
1097 if (bytes_remaining)
1098 {
1099 uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
1100 int i = 0;
1101
1102 while (bytes_remaining > 0)
1103 {
1104 last_word[i++] = *(buffer + bytes_written);
1105 bytes_remaining--;
1106 bytes_written++;
1107 }
1108
1109 if (!(address & 0xff))
1110 LOG_DEBUG("0x%" PRIx32 "", address);
1111
1112 /* Program one word */
1113 target_write_u32(target, FLASH_FMA, address);
1114 target_write_buffer(target, FLASH_FMD, 4, last_word);
1115 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
1116 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1117 /* Wait until write complete */
1118 do
1119 {
1120 target_read_u32(target, FLASH_FMC, &flash_fmc);
1121 } while (flash_fmc & FMC_WRITE);
1122 }
1123
1124 /* Check access violations */
1125 target_read_u32(target, FLASH_CRIS, &flash_cris);
1126 if (flash_cris & (AMASK))
1127 {
1128 LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris);
1129 return ERROR_FLASH_OPERATION_FAILED;
1130 }
1131 return ERROR_OK;
1132 }
1133
1134 static int stellaris_probe(struct flash_bank *bank)
1135 {
1136 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
1137 int retval;
1138
1139 /* If this is a stellaris chip, it has flash; probe() is just
1140 * to figure out how much is present. Only do it once.
1141 */
1142 if (stellaris_info->did1 != 0)
1143 return ERROR_OK;
1144
1145 /* stellaris_read_part_info() already handled error checking and
1146 * reporting. Note that it doesn't write, so we don't care about
1147 * whether the target is halted or not.
1148 */
1149 retval = stellaris_read_part_info(bank);
1150 if (retval != ERROR_OK)
1151 return retval;
1152
1153 if (bank->sectors)
1154 {
1155 free(bank->sectors);
1156 bank->sectors = NULL;
1157 }
1158
1159 /* provide this for the benefit of the NOR flash framework */
1160 bank->size = 1024 * stellaris_info->num_pages;
1161 bank->num_sectors = stellaris_info->num_pages;
1162 bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
1163 for (int i = 0; i < bank->num_sectors; i++)
1164 {
1165 bank->sectors[i].offset = i * stellaris_info->pagesize;
1166 bank->sectors[i].size = stellaris_info->pagesize;
1167 bank->sectors[i].is_erased = -1;
1168 bank->sectors[i].is_protected = -1;
1169 }
1170
1171 return retval;
1172 }
1173
1174 static int stellaris_mass_erase(struct flash_bank *bank)
1175 {
1176 struct target *target = NULL;
1177 struct stellaris_flash_bank *stellaris_info = NULL;
1178 uint32_t flash_fmc;
1179
1180 stellaris_info = bank->driver_priv;
1181 target = bank->target;
1182
1183 if (target->state != TARGET_HALTED)
1184 {
1185 LOG_ERROR("Target not halted");
1186 return ERROR_TARGET_NOT_HALTED;
1187 }
1188
1189 if (stellaris_info->did1 == 0)
1190 return ERROR_FLASH_BANK_NOT_PROBED;
1191
1192 /* Refresh flash controller timing */
1193 stellaris_read_clock_info(bank);
1194 stellaris_set_flash_timing(bank);
1195
1196 /* Clear and disable flash programming interrupts */
1197 target_write_u32(target, FLASH_CIM, 0);
1198 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
1199
1200 /* REVISIT this clobbers state set by any halted firmware ...
1201 * it might want to process those IRQs.
1202 */
1203
1204 target_write_u32(target, FLASH_FMA, 0);
1205 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1206 /* Wait until erase complete */
1207 do
1208 {
1209 target_read_u32(target, FLASH_FMC, &flash_fmc);
1210 }
1211 while (flash_fmc & FMC_MERASE);
1212
1213 /* if device has > 128k, then second erase cycle is needed
1214 * this is only valid for older devices, but will not hurt */
1215 if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000)
1216 {
1217 target_write_u32(target, FLASH_FMA, 0x20000);
1218 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1219 /* Wait until erase complete */
1220 do
1221 {
1222 target_read_u32(target, FLASH_FMC, &flash_fmc);
1223 }
1224 while (flash_fmc & FMC_MERASE);
1225 }
1226
1227 return ERROR_OK;
1228 }
1229
1230 COMMAND_HANDLER(stellaris_handle_mass_erase_command)
1231 {
1232 int i;
1233
1234 if (CMD_ARGC < 1)
1235 {
1236 command_print(CMD_CTX, "stellaris mass_erase <bank>");
1237 return ERROR_OK;
1238 }
1239
1240 struct flash_bank *bank;
1241 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1242 if (ERROR_OK != retval)
1243 return retval;
1244
1245 if (stellaris_mass_erase(bank) == ERROR_OK)
1246 {
1247 /* set all sectors as erased */
1248 for (i = 0; i < bank->num_sectors; i++)
1249 {
1250 bank->sectors[i].is_erased = 1;
1251 }
1252
1253 command_print(CMD_CTX, "stellaris mass erase complete");
1254 }
1255 else
1256 {
1257 command_print(CMD_CTX, "stellaris mass erase failed");
1258 }
1259
1260 return ERROR_OK;
1261 }
1262
1263 /**
1264 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1265 * This performs a mass erase and then restores all nonvolatile registers
1266 * (including USER_* registers and flash lock bits) to their defaults.
1267 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1268 *
1269 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1270 * can affect this operation if flash protection has been enabled.
1271 */
1272 COMMAND_HANDLER(stellaris_handle_recover_command)
1273 {
1274 struct flash_bank *bank;
1275 int retval;
1276
1277 retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1278 if (retval != ERROR_OK)
1279 return retval;
1280
1281 /* REVISIT ... it may be worth sanity checking that the AP is
1282 * inactive before we start. ARM documents that switching a DP's
1283 * mode while it's active can cause fault modes that need a power
1284 * cycle to recover.
1285 */
1286
1287 /* assert SRST */
1288 if (!(jtag_get_reset_config() & RESET_HAS_SRST)) {
1289 LOG_ERROR("Can't recover Stellaris flash without SRST");
1290 return ERROR_FAIL;
1291 }
1292 jtag_add_reset(0, 1);
1293
1294 for (int i = 0; i < 5; i++) {
1295 retval = dap_to_swd(bank->target);
1296 if (retval != ERROR_OK)
1297 goto done;
1298
1299 retval = dap_to_jtag(bank->target);
1300 if (retval != ERROR_OK)
1301 goto done;
1302 }
1303
1304 /* de-assert SRST */
1305 jtag_add_reset(0, 0);
1306 retval = jtag_execute_queue();
1307
1308 /* wait 400+ msec ... OK, "1+ second" is simpler */
1309 usleep(1000);
1310
1311 /* USER INTERVENTION required for the power cycle
1312 * Restarting OpenOCD is likely needed because of mode switching.
1313 */
1314 LOG_INFO("USER ACTION: "
1315 "power cycle Stellaris chip, then restart OpenOCD.");
1316
1317 done:
1318 return retval;
1319 }
1320
1321 static const struct command_registration stellaris_exec_command_handlers[] = {
1322 {
1323 .name = "mass_erase",
1324 .handler = stellaris_handle_mass_erase_command,
1325 .mode = COMMAND_EXEC,
1326 .usage = "bank_id",
1327 .help = "erase entire device",
1328 },
1329 {
1330 .name = "recover",
1331 .handler = stellaris_handle_recover_command,
1332 .mode = COMMAND_EXEC,
1333 .usage = "bank_id",
1334 .help = "recover (and erase) locked device",
1335 },
1336 COMMAND_REGISTRATION_DONE
1337 };
1338 static const struct command_registration stellaris_command_handlers[] = {
1339 {
1340 .name = "stellaris",
1341 .mode = COMMAND_EXEC,
1342 .help = "Stellaris flash command group",
1343 .chain = stellaris_exec_command_handlers,
1344 },
1345 COMMAND_REGISTRATION_DONE
1346 };
1347
1348 struct flash_driver stellaris_flash = {
1349 .name = "stellaris",
1350 .commands = stellaris_command_handlers,
1351 .flash_bank_command = stellaris_flash_bank_command,
1352 .erase = stellaris_erase,
1353 .protect = stellaris_protect,
1354 .write = stellaris_write,
1355 .read = default_flash_read,
1356 .probe = stellaris_probe,
1357 .auto_probe = stellaris_probe,
1358 .erase_check = default_flash_mem_blank_check,
1359 .protect_check = stellaris_protect_check,
1360 .info = get_stellaris_info,
1361 };

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)