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

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)