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

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)