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

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)