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

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)