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

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)