7a77bb55b6ceaa385eb11dca03726f80164a7647
[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 Use an optional main oscillator clock rate in kHz from arg[6] */
261 return ERROR_OK;
262 }
263
264 static int stellaris_register_commands(struct command_context_s *cmd_ctx)
265 {
266 command_t *stm32x_cmd = register_command(cmd_ctx, NULL, "stellaris", NULL, COMMAND_ANY, "stellaris flash specific commands");
267
268 register_command(cmd_ctx, stm32x_cmd, "mass_erase", stellaris_handle_mass_erase_command, COMMAND_EXEC, "mass erase device");
269 return ERROR_OK;
270 }
271
272 static int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size)
273 {
274 int printed, device_class;
275 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
276
277 stellaris_read_part_info(bank);
278
279 if (stellaris_info->did1 == 0)
280 {
281 printed = snprintf(buf, buf_size, "Cannot identify target as a Stellaris\n");
282 buf += printed;
283 buf_size -= printed;
284 return ERROR_FLASH_OPERATION_FAILED;
285 }
286
287 if (DID0_VER(stellaris_info->did0) > 0)
288 {
289 device_class = (stellaris_info->did0>>16) & 0xFF;
290 }
291 else
292 {
293 device_class = 0;
294 }
295 printed = snprintf(buf,
296 buf_size,
297 "\nLMI Stellaris information: Chip is class %i(%s) %s v%c.%i\n",
298 device_class,
299 StellarisClassname[device_class],
300 stellaris_info->target_name,
301 (int)('A' + ((stellaris_info->did0>>8) & 0xFF)),
302 (int)((stellaris_info->did0) & 0xFF));
303 buf += printed;
304 buf_size -= printed;
305
306 printed = snprintf(buf,
307 buf_size,
308 "did1: 0x%8.8" PRIx32 ", arch: 0x%4.4" PRIx32 ", eproc: %s, ramsize:%ik, flashsize: %ik\n",
309 stellaris_info->did1,
310 stellaris_info->did1,
311 "ARMV7M",
312 (int)((1+((stellaris_info->dc0>>16) & 0xFFFF))/4),
313 (int)((1+(stellaris_info->dc0 & 0xFFFF))*2));
314 buf += printed;
315 buf_size -= printed;
316
317 printed = snprintf(buf,
318 buf_size,
319 "master clock(estimated): %ikHz, rcc is 0x%" PRIx32 " \n",
320 (int)(stellaris_info->mck_freq / 1000),
321 stellaris_info->rcc);
322 buf += printed;
323 buf_size -= printed;
324
325 if (stellaris_info->num_lockbits>0)
326 {
327 printed = snprintf(buf,
328 buf_size,
329 "pagesize: %" PRIi32 ", lockbits: %i 0x%4.4" PRIx32 ", pages in lock region: %i \n",
330 stellaris_info->pagesize,
331 stellaris_info->num_lockbits,
332 stellaris_info->lockbits,
333 (int)(stellaris_info->num_pages/stellaris_info->num_lockbits));
334 buf += printed;
335 buf_size -= printed;
336 }
337 return ERROR_OK;
338 }
339
340 /***************************************************************************
341 * chip identification and status *
342 ***************************************************************************/
343
344 static uint32_t stellaris_get_flash_status(flash_bank_t *bank)
345 {
346 target_t *target = bank->target;
347 uint32_t fmc;
348
349 target_read_u32(target, FLASH_CONTROL_BASE|FLASH_FMC, &fmc);
350
351 return fmc;
352 }
353
354 /** Read clock configuration and set stellaris_info->usec_clocks*/
355
356 static void stellaris_read_clock_info(flash_bank_t *bank)
357 {
358 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
359 target_t *target = bank->target;
360 uint32_t rcc, pllcfg, sysdiv, usesysdiv, bypass, oscsrc;
361 unsigned long mainfreq;
362
363 target_read_u32(target, SCB_BASE|RCC, &rcc);
364 LOG_DEBUG("Stellaris RCC %" PRIx32 "", rcc);
365 target_read_u32(target, SCB_BASE|PLLCFG, &pllcfg);
366 LOG_DEBUG("Stellaris PLLCFG %" PRIx32 "", pllcfg);
367 stellaris_info->rcc = rcc;
368
369 sysdiv = (rcc>>23) & 0xF;
370 usesysdiv = (rcc>>22) & 0x1;
371 bypass = (rcc>>11) & 0x1;
372 oscsrc = (rcc>>4) & 0x3;
373 /* xtal = (rcc>>6)&0xF; */
374 switch (oscsrc)
375 {
376 case 0:
377 mainfreq = 6000000; /* Default xtal */
378 break;
379 case 1:
380 mainfreq = 22500000; /* Internal osc. 15 MHz +- 50% */
381 break;
382 case 2:
383 mainfreq = 5625000; /* Internal osc. / 4 */
384 break;
385 case 3:
386 LOG_WARNING("Invalid oscsrc (3) in rcc register");
387 mainfreq = 6000000;
388 break;
389
390 default: /* NOTREACHED */
391 mainfreq = 0;
392 break;
393 }
394
395 if (!bypass)
396 mainfreq = 200000000; /* PLL out frec */
397
398 if (usesysdiv)
399 stellaris_info->mck_freq = mainfreq/(1+sysdiv);
400 else
401 stellaris_info->mck_freq = mainfreq;
402
403 /* Forget old flash timing */
404 stellaris_set_flash_mode(bank, 0);
405 }
406
407 /* Setup the timimg registers */
408 static void stellaris_set_flash_mode(flash_bank_t *bank,int mode)
409 {
410 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
411 target_t *target = bank->target;
412
413 uint32_t usecrl = (stellaris_info->mck_freq/1000000ul-1);
414 LOG_DEBUG("usecrl = %i",(int)(usecrl));
415 target_write_u32(target, SCB_BASE|USECRL, usecrl);
416 }
417
418 #if 0
419 static uint32_t stellaris_wait_status_busy(flash_bank_t *bank, uint32_t waitbits, int timeout)
420 {
421 uint32_t status;
422
423 /* Stellaris waits for cmdbit to clear */
424 while (((status = stellaris_get_flash_status(bank)) & waitbits) && (timeout-- > 0))
425 {
426 LOG_DEBUG("status: 0x%x", status);
427 alive_sleep(1);
428 }
429
430 /* Flash errors are reflected in the FLASH_CRIS register */
431
432 return status;
433 }
434
435 /* Send one command to the flash controller */
436 static int stellaris_flash_command(struct flash_bank_s *bank,uint8_t cmd,uint16_t pagen)
437 {
438 uint32_t fmc;
439 target_t *target = bank->target;
440
441 fmc = FMC_WRKEY | cmd;
442 target_write_u32(target, FLASH_CONTROL_BASE|FLASH_FMC, fmc);
443 LOG_DEBUG("Flash command: 0x%x", fmc);
444
445 if (stellaris_wait_status_busy(bank, cmd, 100))
446 {
447 return ERROR_FLASH_OPERATION_FAILED;
448 }
449
450 return ERROR_OK;
451 }
452 #endif
453
454 /* Read device id register, main clock frequency register and fill in driver info structure */
455 static int stellaris_read_part_info(struct flash_bank_s *bank)
456 {
457 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
458 target_t *target = bank->target;
459 uint32_t did0, did1, ver, fam, status;
460 int i;
461
462 /* Read and parse chip identification register */
463 target_read_u32(target, SCB_BASE|DID0, &did0);
464 target_read_u32(target, SCB_BASE|DID1, &did1);
465 target_read_u32(target, SCB_BASE|DC0, &stellaris_info->dc0);
466 target_read_u32(target, SCB_BASE|DC1, &stellaris_info->dc1);
467 LOG_DEBUG("did0 0x%" PRIx32 ", did1 0x%" PRIx32 ", dc0 0x%" PRIx32 ", dc1 0x%" PRIx32 "",
468 did0, did1, stellaris_info->dc0, stellaris_info->dc1);
469
470 ver = did0 >> 28;
471 if((ver != 0) && (ver != 1))
472 {
473 LOG_WARNING("Unknown did0 version, cannot identify target");
474 return ERROR_FLASH_OPERATION_FAILED;
475 }
476
477 if (did1 == 0)
478 {
479 LOG_WARNING("Cannot identify target as a Stellaris");
480 return ERROR_FLASH_OPERATION_FAILED;
481 }
482
483 ver = did1 >> 28;
484 fam = (did1 >> 24) & 0xF;
485 if(((ver != 0) && (ver != 1)) || (fam != 0))
486 {
487 LOG_WARNING("Unknown did1 version/family, cannot positively identify target as a Stellaris");
488 }
489
490 for (i = 0; StellarisParts[i].partno; i++)
491 {
492 if (StellarisParts[i].partno == ((did1 >> 16) & 0xFF))
493 break;
494 }
495
496 stellaris_info->target_name = StellarisParts[i].partname;
497
498 stellaris_info->did0 = did0;
499 stellaris_info->did1 = did1;
500
501 stellaris_info->num_lockbits = 1 + (stellaris_info->dc0 & 0xFFFF);
502 stellaris_info->num_pages = 2 *(1+(stellaris_info->dc0 & 0xFFFF));
503 stellaris_info->pagesize = 1024;
504 bank->size = 1024 * stellaris_info->num_pages;
505 stellaris_info->pages_in_lockregion = 2;
506 target_read_u32(target, SCB_BASE|FMPPE, &stellaris_info->lockbits);
507
508 /* provide this for the benefit of the higher flash driver layers */
509 bank->num_sectors = stellaris_info->num_pages;
510 bank->sectors = malloc(sizeof(flash_sector_t) * bank->num_sectors);
511 for (i = 0; i < bank->num_sectors; i++)
512 {
513 bank->sectors[i].offset = i * stellaris_info->pagesize;
514 bank->sectors[i].size = stellaris_info->pagesize;
515 bank->sectors[i].is_erased = -1;
516 bank->sectors[i].is_protected = -1;
517 }
518
519 /* Read main and master clock freqency register */
520 stellaris_read_clock_info(bank);
521
522 status = stellaris_get_flash_status(bank);
523
524 return ERROR_OK;
525 }
526
527 /***************************************************************************
528 * flash operations *
529 ***************************************************************************/
530
531 static int stellaris_protect_check(struct flash_bank_s *bank)
532 {
533 uint32_t status;
534
535 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
536
537 if (bank->target->state != TARGET_HALTED)
538 {
539 LOG_ERROR("Target not halted");
540 return ERROR_TARGET_NOT_HALTED;
541 }
542
543 if (stellaris_info->did1 == 0)
544 {
545 stellaris_read_part_info(bank);
546 }
547
548 if (stellaris_info->did1 == 0)
549 {
550 LOG_WARNING("Cannot identify target as an AT91SAM");
551 return ERROR_FLASH_OPERATION_FAILED;
552 }
553
554 status = stellaris_get_flash_status(bank);
555 stellaris_info->lockbits = status >> 16;
556
557 return ERROR_OK;
558 }
559
560 static int stellaris_erase(struct flash_bank_s *bank, int first, int last)
561 {
562 int banknr;
563 uint32_t flash_fmc, flash_cris;
564 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
565 target_t *target = bank->target;
566
567 if (bank->target->state != TARGET_HALTED)
568 {
569 LOG_ERROR("Target not halted");
570 return ERROR_TARGET_NOT_HALTED;
571 }
572
573 if (stellaris_info->did1 == 0)
574 {
575 stellaris_read_part_info(bank);
576 }
577
578 if (stellaris_info->did1 == 0)
579 {
580 LOG_WARNING("Cannot identify target as Stellaris");
581 return ERROR_FLASH_OPERATION_FAILED;
582 }
583
584 if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages))
585 {
586 return ERROR_FLASH_SECTOR_INVALID;
587 }
588
589 if ((first == 0) && (last == ((int)stellaris_info->num_pages-1)))
590 {
591 return stellaris_mass_erase(bank);
592 }
593
594 /* Configure the flash controller timing */
595 stellaris_read_clock_info(bank);
596 stellaris_set_flash_mode(bank,0);
597
598 /* Clear and disable flash programming interrupts */
599 target_write_u32(target, FLASH_CIM, 0);
600 target_write_u32(target, FLASH_MISC, PMISC|AMISC);
601
602 for (banknr = first; banknr <= last; banknr++)
603 {
604 /* Address is first word in page */
605 target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize);
606 /* Write erase command */
607 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
608 /* Wait until erase complete */
609 do
610 {
611 target_read_u32(target, FLASH_FMC, &flash_fmc);
612 }
613 while(flash_fmc & FMC_ERASE);
614
615 /* Check acess violations */
616 target_read_u32(target, FLASH_CRIS, &flash_cris);
617 if(flash_cris & (AMASK))
618 {
619 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "", banknr, flash_cris);
620 target_write_u32(target, FLASH_CRIS, 0);
621 return ERROR_FLASH_OPERATION_FAILED;
622 }
623
624 bank->sectors[banknr].is_erased = 1;
625 }
626
627 return ERROR_OK;
628 }
629
630 static int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last)
631 {
632 uint32_t fmppe, flash_fmc, flash_cris;
633 int lockregion;
634
635 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
636 target_t *target = bank->target;
637
638 if (bank->target->state != TARGET_HALTED)
639 {
640 LOG_ERROR("Target not halted");
641 return ERROR_TARGET_NOT_HALTED;
642 }
643
644 if ((first < 0) || (last < first) || (last >= stellaris_info->num_lockbits))
645 {
646 return ERROR_FLASH_SECTOR_INVALID;
647 }
648
649 if (stellaris_info->did1 == 0)
650 {
651 stellaris_read_part_info(bank);
652 }
653
654 if (stellaris_info->did1 == 0)
655 {
656 LOG_WARNING("Cannot identify target as an Stellaris MCU");
657 return ERROR_FLASH_OPERATION_FAILED;
658 }
659
660 /* Configure the flash controller timing */
661 stellaris_read_clock_info(bank);
662 stellaris_set_flash_mode(bank, 0);
663
664 fmppe = stellaris_info->lockbits;
665 for (lockregion = first; lockregion <= last; lockregion++)
666 {
667 if (set)
668 fmppe &= ~(1<<lockregion);
669 else
670 fmppe |= (1<<lockregion);
671 }
672
673 /* Clear and disable flash programming interrupts */
674 target_write_u32(target, FLASH_CIM, 0);
675 target_write_u32(target, FLASH_MISC, PMISC|AMISC);
676
677 LOG_DEBUG("fmppe 0x%" PRIx32 "",fmppe);
678 target_write_u32(target, SCB_BASE|FMPPE, fmppe);
679 /* Commit FMPPE */
680 target_write_u32(target, FLASH_FMA, 1);
681 /* Write commit command */
682 /* TODO safety check, sice this cannot be undone */
683 LOG_WARNING("Flash protection cannot be removed once commited, commit is NOT executed !");
684 /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
685 /* Wait until erase complete */
686 do
687 {
688 target_read_u32(target, FLASH_FMC, &flash_fmc);
689 }
690 while(flash_fmc & FMC_COMT);
691
692 /* Check acess violations */
693 target_read_u32(target, FLASH_CRIS, &flash_cris);
694 if(flash_cris & (AMASK))
695 {
696 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris);
697 target_write_u32(target, FLASH_CRIS, 0);
698 return ERROR_FLASH_OPERATION_FAILED;
699 }
700
701 target_read_u32(target, SCB_BASE|FMPPE, &stellaris_info->lockbits);
702
703 return ERROR_OK;
704 }
705
706 static uint8_t stellaris_write_code[] =
707 {
708 /*
709 Call with :
710 r0 = buffer address
711 r1 = destination address
712 r2 = bytecount (in) - endaddr (work)
713
714 Used registers:
715 r3 = pFLASH_CTRL_BASE
716 r4 = FLASHWRITECMD
717 r5 = #1
718 r6 = bytes written
719 r7 = temp reg
720 */
721 0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */
722 0x08,0x4C, /* ldr r4,FLASHWRITECMD */
723 0x01,0x25, /* movs r5, 1 */
724 0x00,0x26, /* movs r6, #0 */
725 /* mainloop: */
726 0x19,0x60, /* str r1, [r3, #0] */
727 0x87,0x59, /* ldr r7, [r0, r6] */
728 0x5F,0x60, /* str r7, [r3, #4] */
729 0x9C,0x60, /* str r4, [r3, #8] */
730 /* waitloop: */
731 0x9F,0x68, /* ldr r7, [r3, #8] */
732 0x2F,0x42, /* tst r7, r5 */
733 0xFC,0xD1, /* bne waitloop */
734 0x04,0x31, /* adds r1, r1, #4 */
735 0x04,0x36, /* adds r6, r6, #4 */
736 0x96,0x42, /* cmp r6, r2 */
737 0xF4,0xD1, /* bne mainloop */
738 /* exit: */
739 0xFE,0xE7, /* b exit */
740 /* pFLASH_CTRL_BASE: */
741 0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */
742 /* FLASHWRITECMD: */
743 0x01,0x00,0x42,0xA4 /* .word 0xA4420001 */
744 };
745
746 static int stellaris_write_block(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t wcount)
747 {
748 target_t *target = bank->target;
749 uint32_t buffer_size = 8192;
750 working_area_t *source;
751 working_area_t *write_algorithm;
752 uint32_t address = bank->base + offset;
753 reg_param_t reg_params[3];
754 armv7m_algorithm_t armv7m_info;
755 int retval = ERROR_OK;
756
757 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " wcount=%08" PRIx32 "",
758 bank, buffer, offset, wcount);
759
760 /* flash write code */
761 if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK)
762 {
763 LOG_WARNING("no working area available, can't do block memory writes");
764 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
765 };
766
767 target_write_buffer(target, write_algorithm->address, sizeof(stellaris_write_code), stellaris_write_code);
768
769 /* memory buffer */
770 while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
771 {
772 LOG_DEBUG("called target_alloc_working_area(target=%p buffer_size=%08" PRIx32 " source=%p)",
773 target, buffer_size, source);
774 buffer_size /= 2;
775 if (buffer_size <= 256)
776 {
777 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
778 if (write_algorithm)
779 target_free_working_area(target, write_algorithm);
780
781 LOG_WARNING("no large enough working area available, can't do block memory writes");
782 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
783 }
784 };
785
786 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
787 armv7m_info.core_mode = ARMV7M_MODE_ANY;
788
789 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
790 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
791 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
792
793 while (wcount > 0)
794 {
795 uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
796
797 target_write_buffer(target, source->address, thisrun_count * 4, buffer);
798
799 buf_set_u32(reg_params[0].value, 0, 32, source->address);
800 buf_set_u32(reg_params[1].value, 0, 32, address);
801 buf_set_u32(reg_params[2].value, 0, 32, 4*thisrun_count);
802 LOG_INFO("Algorithm flash write %" PRIi32 " words to 0x%" PRIx32 ", %" PRIi32 " remaining", thisrun_count, address, wcount);
803 LOG_DEBUG("Algorithm flash write %" PRIi32 " words to 0x%" PRIx32 ", %" PRIi32 " remaining", thisrun_count, address, wcount);
804 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)
805 {
806 LOG_ERROR("error executing stellaris flash write algorithm");
807 retval = ERROR_FLASH_OPERATION_FAILED;
808 break;
809 }
810
811 buffer += thisrun_count * 4;
812 address += thisrun_count * 4;
813 wcount -= thisrun_count;
814 }
815
816 target_free_working_area(target, write_algorithm);
817 target_free_working_area(target, source);
818
819 destroy_reg_param(&reg_params[0]);
820 destroy_reg_param(&reg_params[1]);
821 destroy_reg_param(&reg_params[2]);
822
823 return retval;
824 }
825
826 static int stellaris_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
827 {
828 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
829 target_t *target = bank->target;
830 uint32_t address = offset;
831 uint32_t flash_cris, flash_fmc;
832 uint32_t words_remaining = (count / 4);
833 uint32_t bytes_remaining = (count & 0x00000003);
834 uint32_t bytes_written = 0;
835 int retval;
836
837 if (bank->target->state != TARGET_HALTED)
838 {
839 LOG_ERROR("Target not halted");
840 return ERROR_TARGET_NOT_HALTED;
841 }
842
843 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " count=%08" PRIx32 "",
844 bank, buffer, offset, count);
845
846 if (stellaris_info->did1 == 0)
847 {
848 stellaris_read_part_info(bank);
849 }
850
851 if (stellaris_info->did1 == 0)
852 {
853 LOG_WARNING("Cannot identify target as a Stellaris processor");
854 return ERROR_FLASH_OPERATION_FAILED;
855 }
856
857 if (offset & 0x3)
858 {
859 LOG_WARNING("offset size must be word aligned");
860 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
861 }
862
863 if (offset + count > bank->size)
864 return ERROR_FLASH_DST_OUT_OF_BANK;
865
866 /* Configure the flash controller timing */
867 stellaris_read_clock_info(bank);
868 stellaris_set_flash_mode(bank, 0);
869
870 /* Clear and disable flash programming interrupts */
871 target_write_u32(target, FLASH_CIM, 0);
872 target_write_u32(target, FLASH_MISC, PMISC|AMISC);
873
874 /* multiple words to be programmed? */
875 if (words_remaining > 0)
876 {
877 /* try using a block write */
878 if ((retval = stellaris_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
879 {
880 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
881 {
882 /* if block write failed (no sufficient working area),
883 * we use normal (slow) single dword accesses */
884 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
885 }
886 else if (retval == ERROR_FLASH_OPERATION_FAILED)
887 {
888 /* if an error occured, we examine the reason, and quit */
889 target_read_u32(target, FLASH_CRIS, &flash_cris);
890
891 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris);
892 return ERROR_FLASH_OPERATION_FAILED;
893 }
894 }
895 else
896 {
897 buffer += words_remaining * 4;
898 address += words_remaining * 4;
899 words_remaining = 0;
900 }
901 }
902
903 while (words_remaining > 0)
904 {
905 if (!(address & 0xff))
906 LOG_DEBUG("0x%" PRIx32 "", address);
907
908 /* Program one word */
909 target_write_u32(target, FLASH_FMA, address);
910 target_write_buffer(target, FLASH_FMD, 4, buffer);
911 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
912 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
913 /* Wait until write complete */
914 do
915 {
916 target_read_u32(target, FLASH_FMC, &flash_fmc);
917 } while (flash_fmc & FMC_WRITE);
918
919 buffer += 4;
920 address += 4;
921 words_remaining--;
922 }
923
924 if (bytes_remaining)
925 {
926 uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
927 int i = 0;
928
929 while(bytes_remaining > 0)
930 {
931 last_word[i++] = *(buffer + bytes_written);
932 bytes_remaining--;
933 bytes_written++;
934 }
935
936 if (!(address & 0xff))
937 LOG_DEBUG("0x%" PRIx32 "", address);
938
939 /* Program one word */
940 target_write_u32(target, FLASH_FMA, address);
941 target_write_buffer(target, FLASH_FMD, 4, last_word);
942 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
943 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
944 /* Wait until write complete */
945 do
946 {
947 target_read_u32(target, FLASH_FMC, &flash_fmc);
948 } while (flash_fmc & FMC_WRITE);
949 }
950
951 /* Check access violations */
952 target_read_u32(target, FLASH_CRIS, &flash_cris);
953 if (flash_cris & (AMASK))
954 {
955 LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris);
956 return ERROR_FLASH_OPERATION_FAILED;
957 }
958 return ERROR_OK;
959 }
960
961 static int stellaris_probe(struct flash_bank_s *bank)
962 {
963 /* we can't probe on an stellaris
964 * if this is an stellaris, it has the configured flash
965 */
966
967 if (bank->target->state != TARGET_HALTED)
968 {
969 LOG_ERROR("Target not halted");
970 return ERROR_TARGET_NOT_HALTED;
971 }
972
973 /* stellaris_read_part_info() already takes care about error checking and reporting */
974 return stellaris_read_part_info(bank);
975 }
976
977 static int stellaris_auto_probe(struct flash_bank_s *bank)
978 {
979 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
980 if (stellaris_info->did1)
981 return ERROR_OK;
982 return stellaris_probe(bank);
983 }
984
985 static int stellaris_mass_erase(struct flash_bank_s *bank)
986 {
987 target_t *target = NULL;
988 stellaris_flash_bank_t *stellaris_info = NULL;
989 uint32_t flash_fmc;
990
991 stellaris_info = bank->driver_priv;
992 target = bank->target;
993
994 if (target->state != TARGET_HALTED)
995 {
996 LOG_ERROR("Target not halted");
997 return ERROR_TARGET_NOT_HALTED;
998 }
999
1000 if (stellaris_info->did1 == 0)
1001 {
1002 stellaris_read_part_info(bank);
1003 }
1004
1005 if (stellaris_info->did1 == 0)
1006 {
1007 LOG_WARNING("Cannot identify target as Stellaris");
1008 return ERROR_FLASH_OPERATION_FAILED;
1009 }
1010
1011 /* Configure the flash controller timing */
1012 stellaris_read_clock_info(bank);
1013 stellaris_set_flash_mode(bank, 0);
1014
1015 /* Clear and disable flash programming interrupts */
1016 target_write_u32(target, FLASH_CIM, 0);
1017 target_write_u32(target, FLASH_MISC, PMISC|AMISC);
1018
1019 target_write_u32(target, FLASH_FMA, 0);
1020 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1021 /* Wait until erase complete */
1022 do
1023 {
1024 target_read_u32(target, FLASH_FMC, &flash_fmc);
1025 }
1026 while (flash_fmc & FMC_MERASE);
1027
1028 /* if device has > 128k, then second erase cycle is needed
1029 * this is only valid for older devices, but will not hurt */
1030 if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000)
1031 {
1032 target_write_u32(target, FLASH_FMA, 0x20000);
1033 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1034 /* Wait until erase complete */
1035 do
1036 {
1037 target_read_u32(target, FLASH_FMC, &flash_fmc);
1038 }
1039 while (flash_fmc & FMC_MERASE);
1040 }
1041
1042 return ERROR_OK;
1043 }
1044
1045 static int stellaris_handle_mass_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1046 {
1047 flash_bank_t *bank;
1048 int i;
1049
1050 if (argc < 1)
1051 {
1052 command_print(cmd_ctx, "stellaris mass_erase <bank>");
1053 return ERROR_OK;
1054 }
1055
1056 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
1057 if (!bank)
1058 {
1059 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
1060 return ERROR_OK;
1061 }
1062
1063 if (stellaris_mass_erase(bank) == ERROR_OK)
1064 {
1065 /* set all sectors as erased */
1066 for (i = 0; i < bank->num_sectors; i++)
1067 {
1068 bank->sectors[i].is_erased = 1;
1069 }
1070
1071 command_print(cmd_ctx, "stellaris mass erase complete");
1072 }
1073 else
1074 {
1075 command_print(cmd_ctx, "stellaris mass erase failed");
1076 }
1077
1078 return ERROR_OK;
1079 }

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)