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

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)