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

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)