dc9de7425a947fa31da00bab189ef2ad45c58d8f
[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 target_t *target = bank->target;
395
396 fmc = FMC_WRKEY | cmd;
397 target_write_u32(target, FLASH_CONTROL_BASE|FLASH_FMC, fmc);
398 DEBUG("Flash command: 0x%x", fmc);
399
400 if (stellaris_wait_status_busy(bank, cmd, 100))
401 {
402 return ERROR_FLASH_OPERATION_FAILED;
403 }
404
405 return ERROR_OK;
406 }
407
408 /* Read device id register, main clock frequency register and fill in driver info structure */
409 int stellaris_read_part_info(struct flash_bank_s *bank)
410 {
411 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
412 target_t *target = bank->target;
413 u32 did0,did1, ver, fam, status;
414 int i;
415
416 /* Read and parse chip identification register */
417 target_read_u32(target, SCB_BASE|DID0, &did0);
418 target_read_u32(target, SCB_BASE|DID1, &did1);
419 target_read_u32(target, SCB_BASE|DC0, &stellaris_info->dc0);
420 target_read_u32(target, SCB_BASE|DC1, &stellaris_info->dc1);
421 DEBUG("did0 0x%x, did1 0x%x, dc0 0x%x, dc1 0x%x",did0, did1, stellaris_info->dc0,stellaris_info->dc1);
422
423 ver = did0 >> 28;
424 if((ver != 0) && (ver != 1))
425 {
426 WARNING("Unknown did0 version, cannot identify target");
427 return ERROR_FLASH_OPERATION_FAILED;
428 }
429
430 if (did1 == 0)
431 {
432 WARNING("Cannot identify target as a Stellaris");
433 return ERROR_FLASH_OPERATION_FAILED;
434 }
435
436 ver = did1 >> 28;
437 fam = (did1 >> 24) & 0xF;
438 if(((ver != 0) && (ver != 1)) || (fam != 0))
439 {
440 WARNING("Unknown did1 version/family, cannot positively identify target as a Stellaris");
441 }
442
443 for (i=0;StellarisParts[i].partno;i++)
444 {
445 if (StellarisParts[i].partno==((did1>>16)&0xFF))
446 break;
447 }
448
449 stellaris_info->target_name = StellarisParts[i].partname;
450
451 stellaris_info->did0 = did0;
452 stellaris_info->did1 = did1;
453
454 stellaris_info->num_lockbits = 1+stellaris_info->dc0&0xFFFF;
455 stellaris_info->num_pages = 2*(1+stellaris_info->dc0&0xFFFF);
456 stellaris_info->pagesize = 1024;
457 bank->size = 1024*stellaris_info->num_pages;
458 stellaris_info->pages_in_lockregion = 2;
459 target_read_u32(target, SCB_BASE|FMPPE, &stellaris_info->lockbits);
460
461 /* Read main and master clock freqency register */
462 stellaris_read_clock_info(bank);
463
464 status = stellaris_get_flash_status(bank);
465
466 return ERROR_OK;
467 }
468
469 /***************************************************************************
470 * flash operations *
471 ***************************************************************************/
472
473 int stellaris_erase_check(struct flash_bank_s *bank)
474 {
475 /*
476
477 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
478 target_t *target = bank->target;
479 int i;
480
481 */
482
483 return ERROR_OK;
484 }
485
486 int stellaris_protect_check(struct flash_bank_s *bank)
487 {
488 u32 status;
489
490 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
491
492 if (bank->target->state != TARGET_HALTED)
493 {
494 return ERROR_TARGET_NOT_HALTED;
495 }
496
497 if (stellaris_info->did1 == 0)
498 {
499 stellaris_read_part_info(bank);
500 }
501
502 if (stellaris_info->did1 == 0)
503 {
504 WARNING("Cannot identify target as an AT91SAM");
505 return ERROR_FLASH_OPERATION_FAILED;
506 }
507
508 status = stellaris_get_flash_status(bank);
509 stellaris_info->lockbits = status >> 16;
510
511 return ERROR_OK;
512 }
513
514 int stellaris_erase(struct flash_bank_s *bank, int first, int last)
515 {
516 int banknr;
517 u32 flash_fmc, flash_cris;
518 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
519 target_t *target = bank->target;
520
521 if (bank->target->state != TARGET_HALTED)
522 {
523 return ERROR_TARGET_NOT_HALTED;
524 }
525
526 if (stellaris_info->did1 == 0)
527 {
528 stellaris_read_part_info(bank);
529 }
530
531 if (stellaris_info->did1 == 0)
532 {
533 WARNING("Cannot identify target as Stellaris");
534 return ERROR_FLASH_OPERATION_FAILED;
535 }
536
537 if ((first < 0) || (last < first) || (last >= stellaris_info->num_pages))
538 {
539 return ERROR_FLASH_SECTOR_INVALID;
540 }
541
542 /* Configure the flash controller timing */
543 stellaris_read_clock_info(bank);
544 stellaris_set_flash_mode(bank,0);
545
546 /* Clear and disable flash programming interrupts */
547 target_write_u32(target, FLASH_CIM, 0);
548 target_write_u32(target, FLASH_MISC, PMISC|AMISC);
549
550 if ((first == 0) && (last == (stellaris_info->num_pages-1)))
551 {
552 target_write_u32(target, FLASH_FMA, 0);
553 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
554 /* Wait until erase complete */
555 do
556 {
557 target_read_u32(target, FLASH_FMC, &flash_fmc);
558 }
559 while(flash_fmc & FMC_MERASE);
560
561 /* if device has > 128k, then second erase cycle is needed */
562 if(stellaris_info->num_pages * stellaris_info->pagesize > 0x20000)
563 {
564 target_write_u32(target, FLASH_FMA, 0x20000);
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
574 return ERROR_OK;
575 }
576
577 for (banknr=first;banknr<=last;banknr++)
578 {
579 /* Address is first word in page */
580 target_write_u32(target, FLASH_FMA, banknr*stellaris_info->pagesize);
581 /* Write erase command */
582 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
583 /* Wait until erase complete */
584 do
585 {
586 target_read_u32(target, FLASH_FMC, &flash_fmc);
587 }
588 while(flash_fmc & FMC_ERASE);
589
590 /* Check acess violations */
591 target_read_u32(target, FLASH_CRIS, &flash_cris);
592 if(flash_cris & (AMASK))
593 {
594 WARNING("Error erasing flash page %i, flash_cris 0x%x", banknr, flash_cris);
595 target_write_u32(target, FLASH_CRIS, 0);
596 return ERROR_FLASH_OPERATION_FAILED;
597 }
598 }
599
600 return ERROR_OK;
601 }
602
603 int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last)
604 {
605 u32 fmppe, flash_fmc, flash_cris;
606 int lockregion;
607
608 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
609 target_t *target = bank->target;
610
611 if (bank->target->state != TARGET_HALTED)
612 {
613 return ERROR_TARGET_NOT_HALTED;
614 }
615
616 if ((first < 0) || (last < first) || (last >= stellaris_info->num_lockbits))
617 {
618 return ERROR_FLASH_SECTOR_INVALID;
619 }
620
621 if (stellaris_info->did1 == 0)
622 {
623 stellaris_read_part_info(bank);
624 }
625
626 if (stellaris_info->did1 == 0)
627 {
628 WARNING("Cannot identify target as an Stellaris MCU");
629 return ERROR_FLASH_OPERATION_FAILED;
630 }
631
632 /* Configure the flash controller timing */
633 stellaris_read_clock_info(bank);
634 stellaris_set_flash_mode(bank,0);
635
636 fmppe = stellaris_info->lockbits;
637 for (lockregion=first;lockregion<=last;lockregion++)
638 {
639 if (set)
640 fmppe &= ~(1<<lockregion);
641 else
642 fmppe |= (1<<lockregion);
643 }
644
645 /* Clear and disable flash programming interrupts */
646 target_write_u32(target, FLASH_CIM, 0);
647 target_write_u32(target, FLASH_MISC, PMISC|AMISC);
648
649 DEBUG("fmppe 0x%x",fmppe);
650 target_write_u32(target, SCB_BASE|FMPPE, fmppe);
651 /* Commit FMPPE */
652 target_write_u32(target, FLASH_FMA, 1);
653 /* Write commit command */
654 /* TODO safety check, sice this cannot be undone */
655 WARNING("Flash protection cannot be removed once commited, commit is NOT executed !");
656 /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
657 /* Wait until erase complete */
658 do
659 {
660 target_read_u32(target, FLASH_FMC, &flash_fmc);
661 }
662 while(flash_fmc & FMC_COMT);
663
664 /* Check acess violations */
665 target_read_u32(target, FLASH_CRIS, &flash_cris);
666 if(flash_cris & (AMASK))
667 {
668 WARNING("Error setting flash page protection, flash_cris 0x%x", flash_cris);
669 target_write_u32(target, FLASH_CRIS, 0);
670 return ERROR_FLASH_OPERATION_FAILED;
671 }
672
673 target_read_u32(target, SCB_BASE|FMPPE, &stellaris_info->lockbits);
674
675 return ERROR_OK;
676 }
677
678 u8 stellaris_write_code[] =
679 {
680 /*
681 Call with :
682 r0 = buffer address
683 r1 = destination address
684 r2 = bytecount (in) - endaddr (work)
685
686 Used registers:
687 r3 = pFLASH_CTRL_BASE
688 r4 = FLASHWRITECMD
689 r5 = #1
690 r6 = bytes written
691 r7 = temp reg
692 */
693 0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */
694 0x08,0x4C, /* ldr r4,FLASHWRITECMD */
695 0x01,0x25, /* movs r5, 1 */
696 0x00,0x26, /* movs r6, #0 */
697 /* mainloop: */
698 0x19,0x60, /* str r1, [r3, #0] */
699 0x87,0x59, /* ldr r7, [r0, r6] */
700 0x5F,0x60, /* str r7, [r3, #4] */
701 0x9C,0x60, /* str r4, [r3, #8] */
702 /* waitloop: */
703 0x9F,0x68, /* ldr r7, [r3, #8] */
704 0x2F,0x42, /* tst r7, r5 */
705 0xFC,0xD1, /* bne waitloop */
706 0x04,0x31, /* adds r1, r1, #4 */
707 0x04,0x36, /* adds r6, r6, #4 */
708 0x96,0x42, /* cmp r6, r2 */
709 0xF4,0xD1, /* bne mainloop */
710 0x00,0xBE, /* bkpt #0 */
711 /* pFLASH_CTRL_BASE: */
712 0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */
713 /* FLASHWRITECMD: */
714 0x01,0x00,0x42,0xA4 /* .word 0xA4420001 */
715 };
716
717 int stellaris_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 wcount)
718 {
719 target_t *target = bank->target;
720 u32 buffer_size = 8192;
721 working_area_t *source;
722 working_area_t *write_algorithm;
723 u32 address = bank->base + offset;
724 reg_param_t reg_params[8];
725 armv7m_algorithm_t armv7m_info;
726 int retval;
727
728 DEBUG("(bank=%08X buffer=%08X offset=%08X wcount=%08X)",
729 (unsigned int)bank, (unsigned int)buffer, offset, wcount);
730
731 /* flash write code */
732 if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK)
733 {
734 WARNING("no working area available, can't do block memory writes");
735 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
736 };
737
738 target_write_buffer(target, write_algorithm->address, sizeof(stellaris_write_code), stellaris_write_code);
739
740 /* memory buffer */
741 while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
742 {
743 DEBUG("called target_alloc_working_area(target=%08X buffer_size=%08X source=%08X)",
744 (unsigned int)target, buffer_size, (unsigned int)source);
745 buffer_size /= 2;
746 if (buffer_size <= 256)
747 {
748 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
749 if (write_algorithm)
750 target_free_working_area(target, write_algorithm);
751
752 WARNING("no large enough working area available, can't do block memory writes");
753 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
754 }
755 };
756
757 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
758 armv7m_info.core_mode = ARMV7M_MODE_ANY;
759 armv7m_info.core_state = ARMV7M_STATE_THUMB;
760
761 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
762 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
763 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
764 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
765 init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);
766 init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);
767 init_reg_param(&reg_params[6], "r6", 32, PARAM_OUT);
768 init_reg_param(&reg_params[7], "r7", 32, PARAM_OUT);
769
770 while (wcount > 0)
771 {
772 u32 thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
773
774 target_write_buffer(target, source->address, thisrun_count * 4, buffer);
775
776 buf_set_u32(reg_params[0].value, 0, 32, source->address);
777 buf_set_u32(reg_params[1].value, 0, 32, address);
778 buf_set_u32(reg_params[2].value, 0, 32, 4*thisrun_count);
779 WARNING("Algorithm flash write %i words to 0x%x, %i remaining",thisrun_count,address, wcount);
780 DEBUG("Algorithm flash write %i words to 0x%x, %i remaining",thisrun_count,address, wcount);
781 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)
782 {
783 ERROR("error executing stellaris flash write algorithm");
784 target_free_working_area(target, source);
785 destroy_reg_param(&reg_params[0]);
786 destroy_reg_param(&reg_params[1]);
787 destroy_reg_param(&reg_params[2]);
788 return ERROR_FLASH_OPERATION_FAILED;
789 }
790
791 buffer += thisrun_count * 4;
792 address += thisrun_count * 4;
793 wcount -= thisrun_count;
794 }
795
796
797 target_free_working_area(target, write_algorithm);
798 target_free_working_area(target, source);
799
800 destroy_reg_param(&reg_params[0]);
801 destroy_reg_param(&reg_params[1]);
802 destroy_reg_param(&reg_params[2]);
803 destroy_reg_param(&reg_params[3]);
804 destroy_reg_param(&reg_params[4]);
805 destroy_reg_param(&reg_params[5]);
806 destroy_reg_param(&reg_params[6]);
807 destroy_reg_param(&reg_params[7]);
808
809 return ERROR_OK;
810 }
811
812 int stellaris_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
813 {
814 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
815 target_t *target = bank->target;
816 u32 address = offset;
817 u32 flash_cris,flash_fmc;
818 u32 retval;
819
820 if (bank->target->state != TARGET_HALTED)
821 {
822 return ERROR_TARGET_NOT_HALTED;
823 }
824
825 DEBUG("(bank=%08X buffer=%08X offset=%08X count=%08X)",
826 (unsigned int)bank, (unsigned int)buffer, offset, count);
827
828 if (stellaris_info->did1 == 0)
829 {
830 stellaris_read_part_info(bank);
831 }
832
833 if (stellaris_info->did1 == 0)
834 {
835 WARNING("Cannot identify target as a Stellaris processor");
836 return ERROR_FLASH_OPERATION_FAILED;
837 }
838
839 if((offset & 3) || (count & 3))
840 {
841 WARNING("offset size must be word aligned");
842 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
843 }
844
845 if (offset + count > bank->size)
846 return ERROR_FLASH_DST_OUT_OF_BANK;
847
848 /* Configure the flash controller timing */
849 stellaris_read_clock_info(bank);
850 stellaris_set_flash_mode(bank,0);
851
852
853 /* Clear and disable flash programming interrupts */
854 target_write_u32(target, FLASH_CIM, 0);
855 target_write_u32(target, FLASH_MISC, PMISC|AMISC);
856
857 /* multiple words to be programmed? */
858 if (count > 0)
859 {
860 /* try using a block write */
861 if ((retval = stellaris_write_block(bank, buffer, offset, count/4)) != ERROR_OK)
862 {
863 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
864 {
865 /* if block write failed (no sufficient working area),
866 * we use normal (slow) single dword accesses */
867 WARNING("couldn't use block writes, falling back to single memory accesses");
868 }
869 else if (retval == ERROR_FLASH_OPERATION_FAILED)
870 {
871 /* if an error occured, we examine the reason, and quit */
872 target_read_u32(target, FLASH_CRIS, &flash_cris);
873
874 ERROR("flash writing failed with CRIS: 0x%x", flash_cris);
875 return ERROR_FLASH_OPERATION_FAILED;
876 }
877 }
878 else
879 {
880 buffer += count * 4;
881 address += count * 4;
882 count = 0;
883 }
884 }
885
886
887
888 while(count>0)
889 {
890 if (!(address&0xff)) DEBUG("0x%x",address);
891 /* Program one word */
892 target_write_u32(target, FLASH_FMA, address);
893 target_write_buffer(target, FLASH_FMD, 4, buffer);
894 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
895 /* DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
896 /* Wait until write complete */
897 do
898 {
899 target_read_u32(target, FLASH_FMC, &flash_fmc);
900 }
901 while(flash_fmc & FMC_WRITE);
902 buffer += 4;
903 address += 4;
904 count -= 4;
905 }
906 /* Check acess violations */
907 target_read_u32(target, FLASH_CRIS, &flash_cris);
908 if(flash_cris & (AMASK))
909 {
910 DEBUG("flash_cris 0x%x", flash_cris);
911 return ERROR_FLASH_OPERATION_FAILED;
912 }
913 return ERROR_OK;
914 }
915
916
917 int stellaris_probe(struct flash_bank_s *bank)
918 {
919 /* we can't probe on an stellaris
920 * if this is an stellaris, it has the configured flash
921 */
922
923 if (bank->target->state != TARGET_HALTED)
924 {
925 return ERROR_TARGET_NOT_HALTED;
926 }
927
928 /* stellaris_read_part_info() already takes care about error checking and reporting */
929 return stellaris_read_part_info(bank);
930 }
931
932 int stellaris_auto_probe(struct flash_bank_s *bank)
933 {
934 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
935 if (stellaris_info->did1)
936 return ERROR_OK;
937 return stellaris_probe(bank);
938 }

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)