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

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)