wi-9c target scripts
[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 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 DEBUG("Stellaris RCC %x",rcc);
320 target_read_u32(target, SCB_BASE|PLLCFG, &pllcfg);
321 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 WARNING("Invalid oscsrc (3) in rcc register");
342 mainfreq = 6000000;
343 break;
344 }
345
346 if (!bypass)
347 mainfreq = 200000000; /* PLL out frec */
348
349 if (usesysdiv)
350 stellaris_info->mck_freq = mainfreq/(1+sysdiv);
351 else
352 stellaris_info->mck_freq = mainfreq;
353
354 /* Forget old flash timing */
355 stellaris_set_flash_mode(bank,0);
356 }
357
358 /* Setup the timimg registers */
359 void stellaris_set_flash_mode(flash_bank_t *bank,int mode)
360 {
361 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
362 target_t *target = bank->target;
363
364 u32 usecrl = (stellaris_info->mck_freq/1000000ul-1);
365 DEBUG("usecrl = %i",usecrl);
366 target_write_u32(target, SCB_BASE|USECRL , usecrl);
367
368 }
369
370 u32 stellaris_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout)
371 {
372 u32 status;
373
374 /* Stellaris waits for cmdbit to clear */
375 while (((status = stellaris_get_flash_status(bank)) & waitbits) && (timeout-- > 0))
376 {
377 DEBUG("status: 0x%x", status);
378 usleep(1000);
379 }
380
381 /* Flash errors are reflected in the FLASH_CRIS register */
382
383 return status;
384 }
385
386
387 /* Send one command to the flash controller */
388 int stellaris_flash_command(struct flash_bank_s *bank,u8 cmd,u16 pagen)
389 {
390 u32 fmc;
391 target_t *target = bank->target;
392
393 fmc = FMC_WRKEY | cmd;
394 target_write_u32(target, FLASH_CONTROL_BASE|FLASH_FMC, fmc);
395 DEBUG("Flash command: 0x%x", fmc);
396
397 if (stellaris_wait_status_busy(bank, cmd, 100))
398 {
399 return ERROR_FLASH_OPERATION_FAILED;
400 }
401
402 return ERROR_OK;
403 }
404
405 /* Read device id register, main clock frequency register and fill in driver info structure */
406 int stellaris_read_part_info(struct flash_bank_s *bank)
407 {
408 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
409 target_t *target = bank->target;
410 u32 did0,did1, ver, fam, status;
411 int i;
412
413 /* Read and parse chip identification register */
414 target_read_u32(target, SCB_BASE|DID0, &did0);
415 target_read_u32(target, SCB_BASE|DID1, &did1);
416 target_read_u32(target, SCB_BASE|DC0, &stellaris_info->dc0);
417 target_read_u32(target, SCB_BASE|DC1, &stellaris_info->dc1);
418 DEBUG("did0 0x%x, did1 0x%x, dc0 0x%x, dc1 0x%x",did0, did1, stellaris_info->dc0,stellaris_info->dc1);
419
420 ver = did0 >> 28;
421 if((ver != 0) && (ver != 1))
422 {
423 WARNING("Unknown did0 version, cannot identify target");
424 return ERROR_FLASH_OPERATION_FAILED;
425 }
426
427 if (did1 == 0)
428 {
429 WARNING("Cannot identify target as a Stellaris");
430 return ERROR_FLASH_OPERATION_FAILED;
431 }
432
433 ver = did1 >> 28;
434 fam = (did1 >> 24) & 0xF;
435 if(((ver != 0) && (ver != 1)) || (fam != 0))
436 {
437 WARNING("Unknown did1 version/family, cannot positively identify target as a Stellaris");
438 }
439
440 for (i=0;StellarisParts[i].partno;i++)
441 {
442 if (StellarisParts[i].partno==((did1>>16)&0xFF))
443 break;
444 }
445
446 stellaris_info->target_name = StellarisParts[i].partname;
447
448 stellaris_info->did0 = did0;
449 stellaris_info->did1 = did1;
450
451 stellaris_info->num_lockbits = 1+stellaris_info->dc0&0xFFFF;
452 stellaris_info->num_pages = 2*(1+stellaris_info->dc0&0xFFFF);
453 stellaris_info->pagesize = 1024;
454 bank->size = 1024*stellaris_info->num_pages;
455 stellaris_info->pages_in_lockregion = 2;
456 target_read_u32(target, SCB_BASE|FMPPE, &stellaris_info->lockbits);
457
458 /* Read main and master clock freqency register */
459 stellaris_read_clock_info(bank);
460
461 status = stellaris_get_flash_status(bank);
462
463 return ERROR_OK;
464 }
465
466 /***************************************************************************
467 * flash operations *
468 ***************************************************************************/
469
470 int stellaris_erase_check(struct flash_bank_s *bank)
471 {
472 /*
473
474 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
475 target_t *target = bank->target;
476 int i;
477
478 */
479
480 return ERROR_OK;
481 }
482
483 int stellaris_protect_check(struct flash_bank_s *bank)
484 {
485 u32 status;
486
487 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
488
489 if (bank->target->state != TARGET_HALTED)
490 {
491 return ERROR_TARGET_NOT_HALTED;
492 }
493
494 if (stellaris_info->did1 == 0)
495 {
496 stellaris_read_part_info(bank);
497 }
498
499 if (stellaris_info->did1 == 0)
500 {
501 WARNING("Cannot identify target as an AT91SAM");
502 return ERROR_FLASH_OPERATION_FAILED;
503 }
504
505 status = stellaris_get_flash_status(bank);
506 stellaris_info->lockbits = status >> 16;
507
508 return ERROR_OK;
509 }
510
511 int stellaris_erase(struct flash_bank_s *bank, int first, int last)
512 {
513 int banknr;
514 u32 flash_fmc, flash_cris;
515 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
516 target_t *target = bank->target;
517
518 if (bank->target->state != TARGET_HALTED)
519 {
520 return ERROR_TARGET_NOT_HALTED;
521 }
522
523 if (stellaris_info->did1 == 0)
524 {
525 stellaris_read_part_info(bank);
526 }
527
528 if (stellaris_info->did1 == 0)
529 {
530 WARNING("Cannot identify target as Stellaris");
531 return ERROR_FLASH_OPERATION_FAILED;
532 }
533
534 if ((first < 0) || (last < first) || (last >= stellaris_info->num_pages))
535 {
536 return ERROR_FLASH_SECTOR_INVALID;
537 }
538
539 /* Configure the flash controller timing */
540 stellaris_read_clock_info(bank);
541 stellaris_set_flash_mode(bank,0);
542
543 /* Clear and disable flash programming interrupts */
544 target_write_u32(target, FLASH_CIM, 0);
545 target_write_u32(target, FLASH_MISC, PMISC|AMISC);
546
547 if ((first == 0) && (last == (stellaris_info->num_pages-1)))
548 {
549 target_write_u32(target, FLASH_FMA, 0);
550 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
551 /* Wait until erase complete */
552 do
553 {
554 target_read_u32(target, FLASH_FMC, &flash_fmc);
555 }
556 while(flash_fmc & FMC_MERASE);
557
558 /* if device has > 128k, then second erase cycle is needed */
559 if(stellaris_info->num_pages * stellaris_info->pagesize > 0x20000)
560 {
561 target_write_u32(target, FLASH_FMA, 0x20000);
562 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
563 /* Wait until erase complete */
564 do
565 {
566 target_read_u32(target, FLASH_FMC, &flash_fmc);
567 }
568 while(flash_fmc & FMC_MERASE);
569 }
570
571 return ERROR_OK;
572 }
573
574 for (banknr=first;banknr<=last;banknr++)
575 {
576 /* Address is first word in page */
577 target_write_u32(target, FLASH_FMA, banknr*stellaris_info->pagesize);
578 /* Write erase command */
579 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
580 /* Wait until erase complete */
581 do
582 {
583 target_read_u32(target, FLASH_FMC, &flash_fmc);
584 }
585 while(flash_fmc & FMC_ERASE);
586
587 /* Check acess violations */
588 target_read_u32(target, FLASH_CRIS, &flash_cris);
589 if(flash_cris & (AMASK))
590 {
591 WARNING("Error erasing flash page %i, flash_cris 0x%x", banknr, flash_cris);
592 target_write_u32(target, FLASH_CRIS, 0);
593 return ERROR_FLASH_OPERATION_FAILED;
594 }
595 }
596
597 return ERROR_OK;
598 }
599
600 int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last)
601 {
602 u32 fmppe, flash_fmc, flash_cris;
603 int lockregion;
604
605 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
606 target_t *target = bank->target;
607
608 if (bank->target->state != TARGET_HALTED)
609 {
610 return ERROR_TARGET_NOT_HALTED;
611 }
612
613 if ((first < 0) || (last < first) || (last >= stellaris_info->num_lockbits))
614 {
615 return ERROR_FLASH_SECTOR_INVALID;
616 }
617
618 if (stellaris_info->did1 == 0)
619 {
620 stellaris_read_part_info(bank);
621 }
622
623 if (stellaris_info->did1 == 0)
624 {
625 WARNING("Cannot identify target as an Stellaris MCU");
626 return ERROR_FLASH_OPERATION_FAILED;
627 }
628
629 /* Configure the flash controller timing */
630 stellaris_read_clock_info(bank);
631 stellaris_set_flash_mode(bank,0);
632
633 fmppe = stellaris_info->lockbits;
634 for (lockregion=first;lockregion<=last;lockregion++)
635 {
636 if (set)
637 fmppe &= ~(1<<lockregion);
638 else
639 fmppe |= (1<<lockregion);
640 }
641
642 /* Clear and disable flash programming interrupts */
643 target_write_u32(target, FLASH_CIM, 0);
644 target_write_u32(target, FLASH_MISC, PMISC|AMISC);
645
646 DEBUG("fmppe 0x%x",fmppe);
647 target_write_u32(target, SCB_BASE|FMPPE, fmppe);
648 /* Commit FMPPE */
649 target_write_u32(target, FLASH_FMA, 1);
650 /* Write commit command */
651 /* TODO safety check, sice this cannot be undone */
652 WARNING("Flash protection cannot be removed once commited, commit is NOT executed !");
653 /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
654 /* Wait until erase complete */
655 do
656 {
657 target_read_u32(target, FLASH_FMC, &flash_fmc);
658 }
659 while(flash_fmc & FMC_COMT);
660
661 /* Check acess violations */
662 target_read_u32(target, FLASH_CRIS, &flash_cris);
663 if(flash_cris & (AMASK))
664 {
665 WARNING("Error setting flash page protection, flash_cris 0x%x", flash_cris);
666 target_write_u32(target, FLASH_CRIS, 0);
667 return ERROR_FLASH_OPERATION_FAILED;
668 }
669
670 target_read_u32(target, SCB_BASE|FMPPE, &stellaris_info->lockbits);
671
672 return ERROR_OK;
673 }
674
675 u8 stellaris_write_code[] =
676 {
677 /*
678 Call with :
679 r0 = buffer address
680 r1 = destination address
681 r2 = bytecount (in) - endaddr (work)
682
683 Used registers:
684 r3 = pFLASH_CTRL_BASE
685 r4 = FLASHWRITECMD
686 r5 = #1
687 r6 = bytes written
688 r7 = temp reg
689 */
690 0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */
691 0x08,0x4C, /* ldr r4,FLASHWRITECMD */
692 0x01,0x25, /* movs r5, 1 */
693 0x00,0x26, /* movs r6, #0 */
694 /* mainloop: */
695 0x19,0x60, /* str r1, [r3, #0] */
696 0x87,0x59, /* ldr r7, [r0, r6] */
697 0x5F,0x60, /* str r7, [r3, #4] */
698 0x9C,0x60, /* str r4, [r3, #8] */
699 /* waitloop: */
700 0x9F,0x68, /* ldr r7, [r3, #8] */
701 0x2F,0x42, /* tst r7, r5 */
702 0xFC,0xD1, /* bne waitloop */
703 0x04,0x31, /* adds r1, r1, #4 */
704 0x04,0x36, /* adds r6, r6, #4 */
705 0x96,0x42, /* cmp r6, r2 */
706 0xF4,0xD1, /* bne mainloop */
707 0x00,0xBE, /* bkpt #0 */
708 /* pFLASH_CTRL_BASE: */
709 0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */
710 /* FLASHWRITECMD: */
711 0x01,0x00,0x42,0xA4 /* .word 0xA4420001 */
712 };
713
714 int stellaris_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 wcount)
715 {
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 if (bank->target->state != TARGET_HALTED)
818 {
819 return ERROR_TARGET_NOT_HALTED;
820 }
821
822 DEBUG("(bank=%08X buffer=%08X offset=%08X count=%08X)",
823 (unsigned int)bank, (unsigned int)buffer, offset, count);
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
920 if (bank->target->state != TARGET_HALTED)
921 {
922 return ERROR_TARGET_NOT_HALTED;
923 }
924
925 /* stellaris_read_part_info() already takes care about error checking and reporting */
926 return stellaris_read_part_info(bank);
927 }
928
929 int stellaris_auto_probe(struct flash_bank_s *bank)
930 {
931 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
932 if (stellaris_info->did1)
933 return ERROR_OK;
934 return stellaris_probe(bank);
935 }

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)