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

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)