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

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)