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

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)