reg_param_t -> struct reg_param
[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
35
36 #define DID0_VER(did0) ((did0 >> 28)&0x07)
37
38 static int stellaris_read_part_info(struct flash_bank_s *bank);
39 static uint32_t stellaris_get_flash_status(flash_bank_t *bank);
40 static void stellaris_set_flash_mode(flash_bank_t *bank,int mode);
41 //static uint32_t stellaris_wait_status_busy(flash_bank_t *bank, uint32_t waitbits, int timeout);
42
43 static int stellaris_mass_erase(struct flash_bank_s *bank);
44
45 static struct {
46 uint32_t partno;
47 char *partname;
48 } StellarisParts[] =
49 {
50 {0x01,"LM3S101"},
51 {0x02,"LM3S102"},
52 {0x03,"LM3S1625"},
53 {0x04,"LM3S1626"},
54 {0x05,"LM3S1627"},
55 {0x06,"LM3S1607"},
56 {0x10,"LM3S1776"},
57 {0x19,"LM3S300"},
58 {0x11,"LM3S301"},
59 {0x12,"LM3S310"},
60 {0x1A,"LM3S308"},
61 {0x13,"LM3S315"},
62 {0x14,"LM3S316"},
63 {0x17,"LM3S317"},
64 {0x18,"LM3S318"},
65 {0x15,"LM3S328"},
66 {0x2A,"LM3S600"},
67 {0x21,"LM3S601"},
68 {0x2B,"LM3S608"},
69 {0x22,"LM3S610"},
70 {0x23,"LM3S611"},
71 {0x24,"LM3S612"},
72 {0x25,"LM3S613"},
73 {0x26,"LM3S615"},
74 {0x28,"LM3S617"},
75 {0x29,"LM3S618"},
76 {0x27,"LM3S628"},
77 {0x38,"LM3S800"},
78 {0x31,"LM3S801"},
79 {0x39,"LM3S808"},
80 {0x32,"LM3S811"},
81 {0x33,"LM3S812"},
82 /*{0x33,"LM3S2616"},*/
83 {0x34,"LM3S815"},
84 {0x36,"LM3S817"},
85 {0x37,"LM3S818"},
86 {0x35,"LM3S828"},
87 {0x39,"LM3S2276"},
88 {0x3A,"LM3S2776"},
89 {0x43,"LM3S3651"},
90 {0x44,"LM3S3739"},
91 {0x45,"LM3S3749"},
92 {0x46,"LM3S3759"},
93 {0x48,"LM3S3768"},
94 {0x49,"LM3S3748"},
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 (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_s *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 ", lockbits: %i 0x%4.4" PRIx32 ", pages in lock region: %i \n",
305 stellaris_info->pagesize,
306 stellaris_info->num_lockbits,
307 stellaris_info->lockbits,
308 (int)(stellaris_info->num_pages/stellaris_info->num_lockbits));
309 buf += printed;
310 buf_size -= printed;
311 }
312 return ERROR_OK;
313 }
314
315 /***************************************************************************
316 * chip identification and status *
317 ***************************************************************************/
318
319 static uint32_t stellaris_get_flash_status(flash_bank_t *bank)
320 {
321 target_t *target = bank->target;
322 uint32_t fmc;
323
324 target_read_u32(target, FLASH_CONTROL_BASE | FLASH_FMC, &fmc);
325
326 return fmc;
327 }
328
329 /** Read clock configuration and set stellaris_info->usec_clocks*/
330
331 static const unsigned rcc_xtal[32] = {
332 [0x00] = 1000000, /* no pll */
333 [0x01] = 1843200, /* no pll */
334 [0x02] = 2000000, /* no pll */
335 [0x03] = 2457600, /* no pll */
336
337 [0x04] = 3579545,
338 [0x05] = 3686400,
339 [0x06] = 4000000, /* usb */
340 [0x07] = 4096000,
341
342 [0x08] = 4915200,
343 [0x09] = 5000000, /* usb */
344 [0x0a] = 5120000,
345 [0x0b] = 6000000, /* (reset) usb */
346
347 [0x0c] = 6144000,
348 [0x0d] = 7372800,
349 [0x0e] = 8000000, /* usb */
350 [0x0f] = 8192000,
351
352 /* parts before DustDevil use just 4 bits for xtal spec */
353
354 [0x10] = 10000000, /* usb */
355 [0x11] = 12000000, /* usb */
356 [0x12] = 12288000,
357 [0x13] = 13560000,
358
359 [0x14] = 14318180,
360 [0x15] = 16000000, /* usb */
361 [0x16] = 16384000,
362 };
363
364 static void stellaris_read_clock_info(flash_bank_t *bank)
365 {
366 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
367 target_t *target = bank->target;
368 uint32_t rcc, rcc2, pllcfg, sysdiv, usesysdiv, bypass, oscsrc;
369 unsigned xtal;
370 unsigned long mainfreq;
371
372 target_read_u32(target, SCB_BASE | RCC, &rcc);
373 LOG_DEBUG("Stellaris RCC %" PRIx32 "", rcc);
374
375 target_read_u32(target, SCB_BASE | RCC2, &rcc2);
376 LOG_DEBUG("Stellaris RCC2 %" PRIx32 "", rcc);
377
378 target_read_u32(target, SCB_BASE | PLLCFG, &pllcfg);
379 LOG_DEBUG("Stellaris PLLCFG %" PRIx32 "", pllcfg);
380
381 stellaris_info->rcc = rcc;
382 stellaris_info->rcc = rcc2;
383
384 sysdiv = (rcc >> 23) & 0xF;
385 usesysdiv = (rcc >> 22) & 0x1;
386 bypass = (rcc >> 11) & 0x1;
387 oscsrc = (rcc >> 4) & 0x3;
388 xtal = (rcc >> 6) & stellaris_info->xtal_mask;
389
390 /* NOTE: post-Sandstorm parts have RCC2 which may override
391 * parts of RCC ... with more sysdiv options, option for
392 * 32768 Hz mainfreq, PLL controls. On Sandstorm it reads
393 * as zero, so the "use RCC2" flag is always clear.
394 */
395 if (rcc2 & (1 << 31)) {
396 sysdiv = (rcc2 >> 23) & 0x3F;
397 bypass = (rcc2 >> 11) & 0x1;
398 oscsrc = (rcc2 >> 4) & 0x7;
399
400 /* FIXME Tempest parts have an additional lsb for
401 * fractional sysdiv (200 MHz / 2.5 == 80 MHz)
402 */
403 }
404
405 stellaris_info->mck_desc = "";
406
407 switch (oscsrc)
408 {
409 case 0: /* MOSC */
410 mainfreq = rcc_xtal[xtal];
411 break;
412 case 1: /* IOSC */
413 mainfreq = stellaris_info->iosc_freq;
414 stellaris_info->mck_desc = stellaris_info->iosc_desc;
415 break;
416 case 2: /* IOSC/4 */
417 mainfreq = stellaris_info->iosc_freq / 4;
418 stellaris_info->mck_desc = stellaris_info->iosc_desc;
419 break;
420 case 3: /* lowspeed */
421 /* Sandstorm doesn't have this 30K +/- 30% osc */
422 mainfreq = 30000;
423 stellaris_info->mck_desc = " (±30%)";
424 break;
425 case 8: /* hibernation osc */
426 /* not all parts support hibernation */
427 mainfreq = 32768;
428 break;
429
430 default: /* NOTREACHED */
431 mainfreq = 0;
432 break;
433 }
434
435 /* PLL is used if it's not bypassed; its output is 200 MHz
436 * even when it runs at 400 MHz (adds divide-by-two stage).
437 */
438 if (!bypass)
439 mainfreq = 200000000;
440
441 if (usesysdiv)
442 stellaris_info->mck_freq = mainfreq/(1 + sysdiv);
443 else
444 stellaris_info->mck_freq = mainfreq;
445
446 /* Forget old flash timing */
447 stellaris_set_flash_mode(bank, 0);
448 }
449
450 /* Setup the timimg registers */
451 static void stellaris_set_flash_mode(flash_bank_t *bank,int mode)
452 {
453 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
454 target_t *target = bank->target;
455
456 uint32_t usecrl = (stellaris_info->mck_freq/1000000ul-1);
457 LOG_DEBUG("usecrl = %i",(int)(usecrl));
458 target_write_u32(target, SCB_BASE | USECRL, usecrl);
459 }
460
461 #if 0
462 static uint32_t stellaris_wait_status_busy(flash_bank_t *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_s *bank,uint8_t cmd,uint16_t pagen)
480 {
481 uint32_t fmc;
482 target_t *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_s *bank)
499 {
500 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
501 target_t *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 target_read_u32(target, SCB_BASE | FMPPE, &stellaris_info->lockbits);
592
593 /* provide this for the benefit of the higher flash driver layers */
594 bank->num_sectors = stellaris_info->num_pages;
595 bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
596 for (i = 0; i < bank->num_sectors; i++)
597 {
598 bank->sectors[i].offset = i * stellaris_info->pagesize;
599 bank->sectors[i].size = stellaris_info->pagesize;
600 bank->sectors[i].is_erased = -1;
601 bank->sectors[i].is_protected = -1;
602 }
603
604 /* Read main and master clock freqency register */
605 stellaris_read_clock_info(bank);
606
607 status = stellaris_get_flash_status(bank);
608
609 return ERROR_OK;
610 }
611
612 /***************************************************************************
613 * flash operations *
614 ***************************************************************************/
615
616 static int stellaris_protect_check(struct flash_bank_s *bank)
617 {
618 uint32_t status;
619
620 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
621
622 if (bank->target->state != TARGET_HALTED)
623 {
624 LOG_ERROR("Target not halted");
625 return ERROR_TARGET_NOT_HALTED;
626 }
627
628 if (stellaris_info->did1 == 0)
629 {
630 stellaris_read_part_info(bank);
631 }
632
633 if (stellaris_info->did1 == 0)
634 {
635 LOG_WARNING("Cannot identify target as Stellaris");
636 return ERROR_FLASH_OPERATION_FAILED;
637 }
638
639 status = stellaris_get_flash_status(bank);
640 stellaris_info->lockbits = status >> 16;
641
642 return ERROR_OK;
643 }
644
645 static int stellaris_erase(struct flash_bank_s *bank, int first, int last)
646 {
647 int banknr;
648 uint32_t flash_fmc, flash_cris;
649 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
650 target_t *target = bank->target;
651
652 if (bank->target->state != TARGET_HALTED)
653 {
654 LOG_ERROR("Target not halted");
655 return ERROR_TARGET_NOT_HALTED;
656 }
657
658 if (stellaris_info->did1 == 0)
659 {
660 stellaris_read_part_info(bank);
661 }
662
663 if (stellaris_info->did1 == 0)
664 {
665 LOG_WARNING("Cannot identify target as Stellaris");
666 return ERROR_FLASH_OPERATION_FAILED;
667 }
668
669 if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages))
670 {
671 return ERROR_FLASH_SECTOR_INVALID;
672 }
673
674 if ((first == 0) && (last == ((int)stellaris_info->num_pages-1)))
675 {
676 return stellaris_mass_erase(bank);
677 }
678
679 /* Configure the flash controller timing */
680 stellaris_read_clock_info(bank);
681 stellaris_set_flash_mode(bank,0);
682
683 /* Clear and disable flash programming interrupts */
684 target_write_u32(target, FLASH_CIM, 0);
685 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
686
687 for (banknr = first; banknr <= last; banknr++)
688 {
689 /* Address is first word in page */
690 target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize);
691 /* Write erase command */
692 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
693 /* Wait until erase complete */
694 do
695 {
696 target_read_u32(target, FLASH_FMC, &flash_fmc);
697 }
698 while (flash_fmc & FMC_ERASE);
699
700 /* Check acess violations */
701 target_read_u32(target, FLASH_CRIS, &flash_cris);
702 if (flash_cris & (AMASK))
703 {
704 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "", banknr, flash_cris);
705 target_write_u32(target, FLASH_CRIS, 0);
706 return ERROR_FLASH_OPERATION_FAILED;
707 }
708
709 bank->sectors[banknr].is_erased = 1;
710 }
711
712 return ERROR_OK;
713 }
714
715 static int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last)
716 {
717 uint32_t fmppe, flash_fmc, flash_cris;
718 int lockregion;
719
720 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
721 target_t *target = bank->target;
722
723 if (bank->target->state != TARGET_HALTED)
724 {
725 LOG_ERROR("Target not halted");
726 return ERROR_TARGET_NOT_HALTED;
727 }
728
729 if ((first < 0) || (last < first) || (last >= stellaris_info->num_lockbits))
730 {
731 return ERROR_FLASH_SECTOR_INVALID;
732 }
733
734 if (stellaris_info->did1 == 0)
735 {
736 stellaris_read_part_info(bank);
737 }
738
739 if (stellaris_info->did1 == 0)
740 {
741 LOG_WARNING("Cannot identify target as an Stellaris MCU");
742 return ERROR_FLASH_OPERATION_FAILED;
743 }
744
745 /* Configure the flash controller timing */
746 stellaris_read_clock_info(bank);
747 stellaris_set_flash_mode(bank, 0);
748
749 fmppe = stellaris_info->lockbits;
750 for (lockregion = first; lockregion <= last; lockregion++)
751 {
752 if (set)
753 fmppe &= ~(1 << lockregion);
754 else
755 fmppe |= (1 << lockregion);
756 }
757
758 /* Clear and disable flash programming interrupts */
759 target_write_u32(target, FLASH_CIM, 0);
760 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
761
762 LOG_DEBUG("fmppe 0x%" PRIx32 "",fmppe);
763 target_write_u32(target, SCB_BASE | FMPPE, fmppe);
764 /* Commit FMPPE */
765 target_write_u32(target, FLASH_FMA, 1);
766 /* Write commit command */
767 /* TODO safety check, sice this cannot be undone */
768 LOG_WARNING("Flash protection cannot be removed once commited, commit is NOT executed !");
769 /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
770 /* Wait until erase complete */
771 do
772 {
773 target_read_u32(target, FLASH_FMC, &flash_fmc);
774 }
775 while (flash_fmc & FMC_COMT);
776
777 /* Check acess violations */
778 target_read_u32(target, FLASH_CRIS, &flash_cris);
779 if (flash_cris & (AMASK))
780 {
781 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris);
782 target_write_u32(target, FLASH_CRIS, 0);
783 return ERROR_FLASH_OPERATION_FAILED;
784 }
785
786 target_read_u32(target, SCB_BASE | FMPPE, &stellaris_info->lockbits);
787
788 return ERROR_OK;
789 }
790
791 static uint8_t stellaris_write_code[] =
792 {
793 /*
794 Call with :
795 r0 = buffer address
796 r1 = destination address
797 r2 = bytecount (in) - endaddr (work)
798
799 Used registers:
800 r3 = pFLASH_CTRL_BASE
801 r4 = FLASHWRITECMD
802 r5 = #1
803 r6 = bytes written
804 r7 = temp reg
805 */
806 0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */
807 0x08,0x4C, /* ldr r4,FLASHWRITECMD */
808 0x01,0x25, /* movs r5, 1 */
809 0x00,0x26, /* movs r6, #0 */
810 /* mainloop: */
811 0x19,0x60, /* str r1, [r3, #0] */
812 0x87,0x59, /* ldr r7, [r0, r6] */
813 0x5F,0x60, /* str r7, [r3, #4] */
814 0x9C,0x60, /* str r4, [r3, #8] */
815 /* waitloop: */
816 0x9F,0x68, /* ldr r7, [r3, #8] */
817 0x2F,0x42, /* tst r7, r5 */
818 0xFC,0xD1, /* bne waitloop */
819 0x04,0x31, /* adds r1, r1, #4 */
820 0x04,0x36, /* adds r6, r6, #4 */
821 0x96,0x42, /* cmp r6, r2 */
822 0xF4,0xD1, /* bne mainloop */
823 /* exit: */
824 0xFE,0xE7, /* b exit */
825 /* pFLASH_CTRL_BASE: */
826 0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */
827 /* FLASHWRITECMD: */
828 0x01,0x00,0x42,0xA4 /* .word 0xA4420001 */
829 };
830
831 static int stellaris_write_block(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t wcount)
832 {
833 target_t *target = bank->target;
834 uint32_t buffer_size = 8192;
835 working_area_t *source;
836 working_area_t *write_algorithm;
837 uint32_t address = bank->base + offset;
838 struct reg_param reg_params[3];
839 armv7m_algorithm_t armv7m_info;
840 int retval = ERROR_OK;
841
842 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " wcount=%08" PRIx32 "",
843 bank, buffer, offset, wcount);
844
845 /* flash write code */
846 if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK)
847 {
848 LOG_WARNING("no working area available, can't do block memory writes");
849 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
850 };
851
852 target_write_buffer(target, write_algorithm->address, sizeof(stellaris_write_code), stellaris_write_code);
853
854 /* memory buffer */
855 while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
856 {
857 LOG_DEBUG("called target_alloc_working_area(target=%p buffer_size=%08" PRIx32 " source=%p)",
858 target, buffer_size, source);
859 buffer_size /= 2;
860 if (buffer_size <= 256)
861 {
862 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
863 if (write_algorithm)
864 target_free_working_area(target, write_algorithm);
865
866 LOG_WARNING("no large enough working area available, can't do block memory writes");
867 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
868 }
869 };
870
871 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
872 armv7m_info.core_mode = ARMV7M_MODE_ANY;
873
874 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
875 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
876 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
877
878 while (wcount > 0)
879 {
880 uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
881
882 target_write_buffer(target, source->address, thisrun_count * 4, buffer);
883
884 buf_set_u32(reg_params[0].value, 0, 32, source->address);
885 buf_set_u32(reg_params[1].value, 0, 32, address);
886 buf_set_u32(reg_params[2].value, 0, 32, 4*thisrun_count);
887 LOG_INFO("Algorithm flash write %" PRIi32 " words to 0x%" PRIx32 ", %" PRIi32 " remaining", thisrun_count, address, (wcount - thisrun_count));
888 LOG_DEBUG("Algorithm flash write %" PRIi32 " words to 0x%" PRIx32 ", %" PRIi32 " remaining", thisrun_count, address, (wcount - thisrun_count));
889 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)
890 {
891 LOG_ERROR("error executing stellaris flash write algorithm");
892 retval = ERROR_FLASH_OPERATION_FAILED;
893 break;
894 }
895
896 buffer += thisrun_count * 4;
897 address += thisrun_count * 4;
898 wcount -= thisrun_count;
899 }
900
901 target_free_working_area(target, write_algorithm);
902 target_free_working_area(target, source);
903
904 destroy_reg_param(&reg_params[0]);
905 destroy_reg_param(&reg_params[1]);
906 destroy_reg_param(&reg_params[2]);
907
908 return retval;
909 }
910
911 static int stellaris_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
912 {
913 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
914 target_t *target = bank->target;
915 uint32_t address = offset;
916 uint32_t flash_cris, flash_fmc;
917 uint32_t words_remaining = (count / 4);
918 uint32_t bytes_remaining = (count & 0x00000003);
919 uint32_t bytes_written = 0;
920 int retval;
921
922 if (bank->target->state != TARGET_HALTED)
923 {
924 LOG_ERROR("Target not halted");
925 return ERROR_TARGET_NOT_HALTED;
926 }
927
928 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " count=%08" PRIx32 "",
929 bank, buffer, offset, count);
930
931 if (stellaris_info->did1 == 0)
932 {
933 stellaris_read_part_info(bank);
934 }
935
936 if (stellaris_info->did1 == 0)
937 {
938 LOG_WARNING("Cannot identify target as a Stellaris processor");
939 return ERROR_FLASH_OPERATION_FAILED;
940 }
941
942 if (offset & 0x3)
943 {
944 LOG_WARNING("offset size must be word aligned");
945 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
946 }
947
948 if (offset + count > bank->size)
949 return ERROR_FLASH_DST_OUT_OF_BANK;
950
951 /* Configure the flash controller timing */
952 stellaris_read_clock_info(bank);
953 stellaris_set_flash_mode(bank, 0);
954
955 /* Clear and disable flash programming interrupts */
956 target_write_u32(target, FLASH_CIM, 0);
957 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
958
959 /* multiple words to be programmed? */
960 if (words_remaining > 0)
961 {
962 /* try using a block write */
963 if ((retval = stellaris_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
964 {
965 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
966 {
967 /* if block write failed (no sufficient working area),
968 * we use normal (slow) single dword accesses */
969 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
970 }
971 else if (retval == ERROR_FLASH_OPERATION_FAILED)
972 {
973 /* if an error occured, we examine the reason, and quit */
974 target_read_u32(target, FLASH_CRIS, &flash_cris);
975
976 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris);
977 return ERROR_FLASH_OPERATION_FAILED;
978 }
979 }
980 else
981 {
982 buffer += words_remaining * 4;
983 address += words_remaining * 4;
984 words_remaining = 0;
985 }
986 }
987
988 while (words_remaining > 0)
989 {
990 if (!(address & 0xff))
991 LOG_DEBUG("0x%" PRIx32 "", address);
992
993 /* Program one word */
994 target_write_u32(target, FLASH_FMA, address);
995 target_write_buffer(target, FLASH_FMD, 4, buffer);
996 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
997 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
998 /* Wait until write complete */
999 do
1000 {
1001 target_read_u32(target, FLASH_FMC, &flash_fmc);
1002 } while (flash_fmc & FMC_WRITE);
1003
1004 buffer += 4;
1005 address += 4;
1006 words_remaining--;
1007 }
1008
1009 if (bytes_remaining)
1010 {
1011 uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
1012 int i = 0;
1013
1014 while (bytes_remaining > 0)
1015 {
1016 last_word[i++] = *(buffer + bytes_written);
1017 bytes_remaining--;
1018 bytes_written++;
1019 }
1020
1021 if (!(address & 0xff))
1022 LOG_DEBUG("0x%" PRIx32 "", address);
1023
1024 /* Program one word */
1025 target_write_u32(target, FLASH_FMA, address);
1026 target_write_buffer(target, FLASH_FMD, 4, last_word);
1027 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
1028 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1029 /* Wait until write complete */
1030 do
1031 {
1032 target_read_u32(target, FLASH_FMC, &flash_fmc);
1033 } while (flash_fmc & FMC_WRITE);
1034 }
1035
1036 /* Check access violations */
1037 target_read_u32(target, FLASH_CRIS, &flash_cris);
1038 if (flash_cris & (AMASK))
1039 {
1040 LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris);
1041 return ERROR_FLASH_OPERATION_FAILED;
1042 }
1043 return ERROR_OK;
1044 }
1045
1046 static int stellaris_probe(struct flash_bank_s *bank)
1047 {
1048 /* we can't probe on an stellaris
1049 * if this is an stellaris, it has the configured flash
1050 */
1051
1052 if (bank->target->state != TARGET_HALTED)
1053 {
1054 LOG_ERROR("Target not halted");
1055 return ERROR_TARGET_NOT_HALTED;
1056 }
1057
1058 /* stellaris_read_part_info() already takes care about error checking and reporting */
1059 return stellaris_read_part_info(bank);
1060 }
1061
1062 static int stellaris_auto_probe(struct flash_bank_s *bank)
1063 {
1064 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
1065 if (stellaris_info->did1)
1066 return ERROR_OK;
1067 return stellaris_probe(bank);
1068 }
1069
1070 static int stellaris_mass_erase(struct flash_bank_s *bank)
1071 {
1072 target_t *target = NULL;
1073 struct stellaris_flash_bank *stellaris_info = NULL;
1074 uint32_t flash_fmc;
1075
1076 stellaris_info = bank->driver_priv;
1077 target = bank->target;
1078
1079 if (target->state != TARGET_HALTED)
1080 {
1081 LOG_ERROR("Target not halted");
1082 return ERROR_TARGET_NOT_HALTED;
1083 }
1084
1085 if (stellaris_info->did1 == 0)
1086 {
1087 stellaris_read_part_info(bank);
1088 }
1089
1090 if (stellaris_info->did1 == 0)
1091 {
1092 LOG_WARNING("Cannot identify target as Stellaris");
1093 return ERROR_FLASH_OPERATION_FAILED;
1094 }
1095
1096 /* Configure the flash controller timing */
1097 stellaris_read_clock_info(bank);
1098 stellaris_set_flash_mode(bank, 0);
1099
1100 /* Clear and disable flash programming interrupts */
1101 target_write_u32(target, FLASH_CIM, 0);
1102 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
1103
1104 target_write_u32(target, FLASH_FMA, 0);
1105 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1106 /* Wait until erase complete */
1107 do
1108 {
1109 target_read_u32(target, FLASH_FMC, &flash_fmc);
1110 }
1111 while (flash_fmc & FMC_MERASE);
1112
1113 /* if device has > 128k, then second erase cycle is needed
1114 * this is only valid for older devices, but will not hurt */
1115 if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000)
1116 {
1117 target_write_u32(target, FLASH_FMA, 0x20000);
1118 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1119 /* Wait until erase complete */
1120 do
1121 {
1122 target_read_u32(target, FLASH_FMC, &flash_fmc);
1123 }
1124 while (flash_fmc & FMC_MERASE);
1125 }
1126
1127 return ERROR_OK;
1128 }
1129
1130 COMMAND_HANDLER(stellaris_handle_mass_erase_command)
1131 {
1132 int i;
1133
1134 if (argc < 1)
1135 {
1136 command_print(cmd_ctx, "stellaris mass_erase <bank>");
1137 return ERROR_OK;
1138 }
1139
1140 flash_bank_t *bank;
1141 int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
1142 if (ERROR_OK != retval)
1143 return retval;
1144
1145 if (stellaris_mass_erase(bank) == ERROR_OK)
1146 {
1147 /* set all sectors as erased */
1148 for (i = 0; i < bank->num_sectors; i++)
1149 {
1150 bank->sectors[i].is_erased = 1;
1151 }
1152
1153 command_print(cmd_ctx, "stellaris mass erase complete");
1154 }
1155 else
1156 {
1157 command_print(cmd_ctx, "stellaris mass erase failed");
1158 }
1159
1160 return ERROR_OK;
1161 }
1162
1163 static int stellaris_register_commands(struct command_context_s *cmd_ctx)
1164 {
1165 command_t *stm32x_cmd = register_command(cmd_ctx, NULL, "stellaris",
1166 NULL, COMMAND_ANY, "stellaris flash specific commands");
1167
1168 register_command(cmd_ctx, stm32x_cmd, "mass_erase",
1169 stellaris_handle_mass_erase_command, COMMAND_EXEC,
1170 "mass erase device");
1171 return ERROR_OK;
1172 }
1173
1174
1175 struct flash_driver stellaris_flash = {
1176 .name = "stellaris",
1177 .register_commands = &stellaris_register_commands,
1178 .flash_bank_command = &stellaris_flash_bank_command,
1179 .erase = &stellaris_erase,
1180 .protect = &stellaris_protect,
1181 .write = &stellaris_write,
1182 .probe = &stellaris_probe,
1183 .auto_probe = &stellaris_auto_probe,
1184 .erase_check = &default_flash_mem_blank_check,
1185 .protect_check = &stellaris_protect_check,
1186 .info = &stellaris_info,
1187 };

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)