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

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)