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

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)