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

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)