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

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)