- renamed M5960 USB JTAG to "flyswatter"
[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 *
25 *
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 int stellaris_register_commands(struct command_context_s *cmd_ctx);
47 int stellaris_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
48 int stellaris_erase(struct flash_bank_s *bank, int first, int last);
49 int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last);
50 int stellaris_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
51 int stellaris_probe(struct flash_bank_s *bank);
52 int stellaris_erase_check(struct flash_bank_s *bank);
53 int stellaris_protect_check(struct flash_bank_s *bank);
54 int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size);
55
56 u32 stellaris_get_flash_status(flash_bank_t *bank);
57 void stellaris_set_flash_mode(flash_bank_t *bank,int mode);
58 u32 stellaris_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout);
59
60 int stellaris_read_part_info(struct flash_bank_s *bank);
61
62 flash_driver_t stellaris_flash =
63 {
64 .name = "stellaris",
65 .register_commands = stellaris_register_commands,
66 .flash_bank_command = stellaris_flash_bank_command,
67 .erase = stellaris_erase,
68 .protect = stellaris_protect,
69 .write = stellaris_write,
70 .probe = stellaris_probe,
71 .erase_check = stellaris_erase_check,
72 .protect_check = stellaris_protect_check,
73 .info = stellaris_info
74 };
75
76
77 struct {
78 u32 partno;
79 char *partname;
80 } StellarisParts[] =
81 {
82 {0x01,"LM3S101"},
83 {0x02,"LM3S102"},
84 {0x11,"LM3S301"},
85 {0x12,"LM3S310"},
86 {0x13,"LM3S315"},
87 {0x14,"LM3S316"},
88 {0x15,"LM3S328"},
89 {0x21,"LM3S601"},
90 {0x22,"LM3S610"},
91 {0x23,"LM3S611"},
92 {0x24,"LM3S612"},
93 {0x25,"LM3S613"},
94 {0x26,"LM3S615"},
95 {0x27,"LM3S628"},
96 {0x31,"LM3S801"},
97 {0x32,"LM3S811"},
98 {0x33,"LM3S812"},
99 {0x34,"LM3S815"},
100 {0x35,"LM3S828"},
101 {0x51,"LM3S2110"},
102 {0x84,"LM3S2139"},
103 {0xa2,"LM3S2410"},
104 {0x59,"LM3S2412"},
105 {0x56,"LM3S2432"},
106 {0x5a,"LM3S2533"},
107 {0x57,"LM3S2620"},
108 {0x85,"LM3S2637"},
109 {0x53,"LM3S2651"},
110 {0xa4,"LM3S2730"},
111 {0x52,"LM3S2739"},
112 {0x54,"LM3S2939"},
113 {0x8f,"LM3S2948"},
114 {0x58,"LM3S2950"},
115 {0x55,"LM3S2965"},
116 {0xa1,"LM3S6100"},
117 {0x74,"LM3S6110"},
118 {0xa5,"LM3S6420"},
119 {0x82,"LM3S6422"},
120 {0x75,"LM3S6432"},
121 {0x71,"LM3S6610"},
122 {0x83,"LM3S6633"},
123 {0x8b,"LM3S6637"},
124 {0xa3,"LM3S6730"},
125 {0x89,"LM3S6938"},
126 {0x78,"LM3S6952"},
127 {0x73,"LM3S6965"},
128 {0,"Unknown part"}
129 };
130
131 /***************************************************************************
132 * openocd command interface *
133 ***************************************************************************/
134
135 /* flash_bank stellaris <base> <size> 0 0 <target#>
136 */
137 int stellaris_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
138 {
139 stellaris_flash_bank_t *stellaris_info;
140
141 if (argc < 6)
142 {
143 WARNING("incomplete flash_bank stellaris configuration");
144 return ERROR_FLASH_BANK_INVALID;
145 }
146
147 stellaris_info = calloc(sizeof(stellaris_flash_bank_t),1);
148 bank->base = 0x0;
149 bank->driver_priv = stellaris_info;
150
151 stellaris_info->target_name = "Unknown target";
152
153 /* part wasn't probed for info yet */
154 stellaris_info->did1 = 0;
155
156 /* TODO Use an optional main oscillator clock rate in kHz from arg[6] */
157 return ERROR_OK;
158 }
159
160 int stellaris_register_commands(struct command_context_s *cmd_ctx)
161 {
162 /*
163 command_t *stellaris_cmd = register_command(cmd_ctx, NULL, "stellaris", NULL, COMMAND_ANY, NULL);
164 register_command(cmd_ctx, stellaris_cmd, "gpnvm", stellaris_handle_gpnvm_command, COMMAND_EXEC,
165 "stellaris gpnvm <num> <bit> set|clear, set or clear stellaris gpnvm bit");
166 */
167 return ERROR_OK;
168 }
169
170 int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size)
171 {
172 int printed;
173 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
174
175 stellaris_read_part_info(bank);
176
177 if (stellaris_info->did1 == 0)
178 {
179 printed = snprintf(buf, buf_size, "Cannot identify target as a Stellaris\n");
180 buf += printed;
181 buf_size -= printed;
182 return ERROR_FLASH_OPERATION_FAILED;
183 }
184
185 printed = snprintf(buf, buf_size, "\nLMI Stellaris information: Chip is class %i %s v%c.%i\n",
186 (stellaris_info->did0>>16)&0xff, stellaris_info->target_name,
187 'A' + (stellaris_info->did0>>8)&0xFF, (stellaris_info->did0)&0xFF);
188 buf += printed;
189 buf_size -= printed;
190
191 printed = snprintf(buf, buf_size, "did1: 0x%8.8x, arch: 0x%4.4x, eproc: %s, ramsize:%ik, flashsize: %ik\n",
192 stellaris_info->did1, stellaris_info->did1, "ARMV7M", (1+(stellaris_info->dc0>>16)&0xFFFF)/4, (1+stellaris_info->dc0&0xFFFF)*2);
193 buf += printed;
194 buf_size -= printed;
195
196 printed = snprintf(buf, buf_size, "master clock(estimated): %ikHz, rcc is 0x%x \n", stellaris_info->mck_freq / 1000, stellaris_info->rcc);
197 buf += printed;
198 buf_size -= printed;
199
200 if (stellaris_info->num_lockbits>0) {
201 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);
202 buf += printed;
203 buf_size -= printed;
204 }
205 return ERROR_OK;
206 }
207
208 /***************************************************************************
209 * chip identification and status *
210 ***************************************************************************/
211
212 u32 stellaris_get_flash_status(flash_bank_t *bank)
213 {
214 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
215 target_t *target = bank->target;
216 u32 fmc;
217
218 target_read_u32(target, FLASH_CONTROL_BASE|FLASH_FMC, &fmc);
219
220 return fmc;
221 }
222
223 /** Read clock configuration and set stellaris_info->usec_clocks*/
224
225 void stellaris_read_clock_info(flash_bank_t *bank)
226 {
227 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
228 target_t *target = bank->target;
229 u32 rcc, pllcfg, sysdiv, usesysdiv, bypass, oscsrc;
230 unsigned long tmp, mainfreq;
231
232 target_read_u32(target, SCB_BASE|RCC, &rcc);
233 DEBUG("Stellaris RCC %x",rcc);
234 target_read_u32(target, SCB_BASE|PLLCFG, &pllcfg);
235 DEBUG("Stellaris PLLCFG %x",pllcfg);
236 stellaris_info->rcc = rcc;
237
238 sysdiv = (rcc>>23)&0xF;
239 usesysdiv = (rcc>>22)&0x1;
240 bypass = (rcc>>11)&0x1;
241 oscsrc = (rcc>>4)&0x3;
242 /* xtal = (rcc>>6)&0xF; */
243 switch (oscsrc)
244 {
245 case 0:
246 mainfreq = 6000000; /* Default xtal */
247 break;
248 case 1:
249 mainfreq = 22500000; /* Internal osc. 15 MHz +- 50% */
250 break;
251 case 2:
252 mainfreq = 5625000; /* Internal osc. / 4 */
253 break;
254 case 3:
255 WARNING("Invalid oscsrc (3) in rcc register");
256 mainfreq = 6000000;
257 break;
258 }
259
260 if (!bypass)
261 mainfreq = 200000000; /* PLL out frec */
262
263 if (usesysdiv)
264 stellaris_info->mck_freq = mainfreq/(1+sysdiv);
265 else
266 stellaris_info->mck_freq = mainfreq;
267
268 /* Forget old flash timing */
269 stellaris_set_flash_mode(bank,0);
270 }
271
272 /* Setup the timimg registers */
273 void stellaris_set_flash_mode(flash_bank_t *bank,int mode)
274 {
275 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
276 target_t *target = bank->target;
277
278 u32 usecrl = (stellaris_info->mck_freq/1000000ul-1);
279 DEBUG("usecrl = %i",usecrl);
280 target_write_u32(target, SCB_BASE|USECRL , usecrl);
281
282 }
283
284 u32 stellaris_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout)
285 {
286 u32 status;
287
288 /* Stellaris waits for cmdbit to clear */
289 while (((status = stellaris_get_flash_status(bank)) & waitbits) && (timeout-- > 0))
290 {
291 DEBUG("status: 0x%x", status);
292 usleep(1000);
293 }
294
295 /* Flash errors are reflected in the FLASH_CRIS register */
296
297 return status;
298 }
299
300
301 /* Send one command to the flash controller */
302 int stellaris_flash_command(struct flash_bank_s *bank,u8 cmd,u16 pagen)
303 {
304 u32 fmc;
305 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
306 target_t *target = bank->target;
307
308 fmc = FMC_WRKEY | cmd;
309 target_write_u32(target, FLASH_CONTROL_BASE|FLASH_FMC, fmc);
310 DEBUG("Flash command: 0x%x", fmc);
311
312 if (stellaris_wait_status_busy(bank, cmd, 100))
313 {
314 return ERROR_FLASH_OPERATION_FAILED;
315 }
316
317 return ERROR_OK;
318 }
319
320 /* Read device id register, main clock frequency register and fill in driver info structure */
321 int stellaris_read_part_info(struct flash_bank_s *bank)
322 {
323 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
324 target_t *target = bank->target;
325 u32 did0,did1, ver, fam, status;
326 int i;
327
328 /* Read and parse chip identification register */
329 target_read_u32(target, SCB_BASE|DID0, &did0);
330 target_read_u32(target, SCB_BASE|DID1, &did1);
331 target_read_u32(target, SCB_BASE|DC0, &stellaris_info->dc0);
332 target_read_u32(target, SCB_BASE|DC1, &stellaris_info->dc1);
333 DEBUG("did0 0x%x, did1 0x%x, dc0 0x%x, dc1 0x%x",did0, did1, stellaris_info->dc0,stellaris_info->dc1);
334
335 ver = did0 >> 28;
336 if((ver != 0) && (ver != 1))
337 {
338 WARNING("Unknown did0 version, cannot identify target");
339 return ERROR_FLASH_OPERATION_FAILED;
340
341 }
342
343 ver = did1 >> 28;
344 fam = (did1 >> 24) & 0xF;
345 if(((ver != 0) && (ver != 1)) || (fam != 0))
346 {
347 WARNING("Unknown did1 version/family, cannot positively identify target as a Stellaris");
348 }
349
350 if (did1 == 0)
351 {
352 WARNING("Cannot identify target as a Stellaris");
353 return ERROR_FLASH_OPERATION_FAILED;
354 }
355
356 for (i=0;StellarisParts[i].partno;i++)
357 {
358 if (StellarisParts[i].partno==((did1>>16)&0xFF))
359 break;
360 }
361
362 stellaris_info->target_name = StellarisParts[i].partname;
363
364 stellaris_info->did0 = did0;
365 stellaris_info->did1 = did1;
366
367 stellaris_info->num_lockbits = 1+stellaris_info->dc0&0xFFFF;
368 stellaris_info->num_pages = 2*(1+stellaris_info->dc0&0xFFFF);
369 stellaris_info->pagesize = 1024;
370 bank->size = 1024*stellaris_info->num_pages;
371 stellaris_info->pages_in_lockregion = 2;
372 target_read_u32(target, SCB_BASE|FMPPE, &stellaris_info->lockbits);
373
374 // Read main and master clock freqency register
375 stellaris_read_clock_info(bank);
376
377 status = stellaris_get_flash_status(bank);
378
379 WARNING("stellaris flash only tested for LM3S811 series");
380
381 return ERROR_OK;
382 }
383
384 /***************************************************************************
385 * flash operations *
386 ***************************************************************************/
387
388 int stellaris_erase_check(struct flash_bank_s *bank)
389 {
390 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
391 target_t *target = bank->target;
392 int i;
393
394 /* */
395
396 return ERROR_OK;
397 }
398
399 int stellaris_protect_check(struct flash_bank_s *bank)
400 {
401 u32 status;
402
403 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
404 target_t *target = bank->target;
405
406 if (stellaris_info->did1 == 0)
407 {
408 stellaris_read_part_info(bank);
409 }
410
411 if (stellaris_info->did1 == 0)
412 {
413 WARNING("Cannot identify target as an AT91SAM");
414 return ERROR_FLASH_OPERATION_FAILED;
415 }
416
417 status = stellaris_get_flash_status(bank);
418 stellaris_info->lockbits = status >> 16;
419
420 return ERROR_OK;
421 }
422
423 int stellaris_erase(struct flash_bank_s *bank, int first, int last)
424 {
425 int banknr;
426 u32 flash_fmc, flash_cris;
427 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
428 target_t *target = bank->target;
429
430 if (bank->target->state != TARGET_HALTED)
431 {
432 return ERROR_TARGET_NOT_HALTED;
433 }
434
435 if (stellaris_info->did1 == 0)
436 {
437 stellaris_read_part_info(bank);
438 }
439
440 if (stellaris_info->did1 == 0)
441 {
442 WARNING("Cannot identify target as Stellaris");
443 return ERROR_FLASH_OPERATION_FAILED;
444 }
445
446 if ((first < 0) || (last < first) || (last >= stellaris_info->num_pages))
447 {
448 return ERROR_FLASH_SECTOR_INVALID;
449 }
450
451 /* Configure the flash controller timing */
452 stellaris_read_clock_info(bank);
453 stellaris_set_flash_mode(bank,0);
454
455 /* Clear and disable flash programming interrupts */
456 target_write_u32(target, FLASH_CIM, 0);
457 target_write_u32(target, FLASH_MISC, PMISC|AMISC);
458
459 if ((first == 0) && (last == (stellaris_info->num_pages-1)))
460 {
461 target_write_u32(target, FLASH_FMA, 0);
462 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
463 /* Wait until erase complete */
464 do
465 {
466 target_read_u32(target, FLASH_FMC, &flash_fmc);
467 }
468 while(flash_fmc & FMC_MERASE);
469
470 /* if device has > 128k, then second erase cycle is needed */
471 if(stellaris_info->num_pages * stellaris_info->pagesize > 0x20000)
472 {
473 target_write_u32(target, FLASH_FMA, 0x20000);
474 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
475 /* Wait until erase complete */
476 do
477 {
478 target_read_u32(target, FLASH_FMC, &flash_fmc);
479 }
480 while(flash_fmc & FMC_MERASE);
481 }
482
483 return ERROR_OK;
484 }
485
486 for (banknr=first;banknr<=last;banknr++)
487 {
488 /* Address is first word in page */
489 target_write_u32(target, FLASH_FMA, banknr*stellaris_info->pagesize);
490 /* Write erase command */
491 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
492 /* Wait until erase complete */
493 do
494 {
495 target_read_u32(target, FLASH_FMC, &flash_fmc);
496 }
497 while(flash_fmc & FMC_ERASE);
498
499 /* Check acess violations */
500 target_read_u32(target, FLASH_CRIS, &flash_cris);
501 if(flash_cris & (AMASK))
502 {
503 WARNING("Error erasing flash page %i, flash_cris 0x%x", banknr, flash_cris);
504 target_write_u32(target, FLASH_CRIS, 0);
505 return ERROR_FLASH_OPERATION_FAILED;
506 }
507 }
508
509 return ERROR_OK;
510 }
511
512 int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last)
513 {
514 u32 cmd, fmppe, flash_fmc, flash_cris;
515 int lockregion;
516
517 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
518 target_t *target = bank->target;
519
520 if (bank->target->state != TARGET_HALTED)
521 {
522 return ERROR_TARGET_NOT_HALTED;
523 }
524
525 if ((first < 0) || (last < first) || (last >= stellaris_info->num_lockbits))
526 {
527 return ERROR_FLASH_SECTOR_INVALID;
528 }
529
530 if (stellaris_info->did1 == 0)
531 {
532 stellaris_read_part_info(bank);
533 }
534
535 if (stellaris_info->did1 == 0)
536 {
537 WARNING("Cannot identify target as an Stellaris MCU");
538 return ERROR_FLASH_OPERATION_FAILED;
539 }
540
541 /* Configure the flash controller timing */
542 stellaris_read_clock_info(bank);
543 stellaris_set_flash_mode(bank,0);
544
545 fmppe = stellaris_info->lockbits;
546 for (lockregion=first;lockregion<=last;lockregion++)
547 {
548 if (set)
549 fmppe &= ~(1<<lockregion);
550 else
551 fmppe |= (1<<lockregion);
552 }
553
554 /* Clear and disable flash programming interrupts */
555 target_write_u32(target, FLASH_CIM, 0);
556 target_write_u32(target, FLASH_MISC, PMISC|AMISC);
557
558 DEBUG("fmppe 0x%x",fmppe);
559 target_write_u32(target, SCB_BASE|FMPPE, fmppe);
560 /* Commit FMPPE */
561 target_write_u32(target, FLASH_FMA, 1);
562 /* Write commit command */
563 /* TODO safety check, sice this cannot be undone */
564 WARNING("Flash protection cannot be removed once commited, commit is NOT executed !");
565 /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
566 /* Wait until erase complete */
567 do
568 {
569 target_read_u32(target, FLASH_FMC, &flash_fmc);
570 }
571 while(flash_fmc & FMC_COMT);
572
573 /* Check acess violations */
574 target_read_u32(target, FLASH_CRIS, &flash_cris);
575 if(flash_cris & (AMASK))
576 {
577 WARNING("Error setting flash page protection, flash_cris 0x%x", flash_cris);
578 target_write_u32(target, FLASH_CRIS, 0);
579 return ERROR_FLASH_OPERATION_FAILED;
580 }
581
582 target_read_u32(target, SCB_BASE|FMPPE, &stellaris_info->lockbits);
583
584 return ERROR_OK;
585 }
586
587 u8 stellaris_write_code[] =
588 {
589 /* Call with :
590 r0 = buffer address
591 r1 = destination address
592 r2 = bytecount (in) - endaddr (work)
593 r3 = pFLASH_CTRL_BASE
594 r4 = FLASHWRITECMD
595 r5 = #1
596 r6 = scratch
597 r7
598 */
599 0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */
600 0x08,0x4C, /* ldr r4,FLASHWRITECMD */
601 0x01,0x25, /* movs r5, 1 */
602 0x00,0x26, /* movs r6, #0 */
603 /* mainloop: */
604 0x19,0x60, /* str r1, [r3, #0] */
605 0x87,0x59, /* ldr r7, [r0, r6] */
606 0x5F,0x60, /* str r7, [r3, #4] */
607 0x9C,0x60, /* str r4, [r3, #8] */
608 /* waitloop: */
609 0x9F,0x68, /* ldr r7, [r3, #8] */
610 0x2F,0x42, /* tst r7, r5 */
611 0xFC,0xD1, /* bne waitloop */
612 0x04,0x31, /* adds r1, r1, #4 */
613 0x04,0x36, /* adds r6, r6, #4 */
614 0x96,0x42, /* cmp r6, r2 */
615 0xF4,0xD1, /* bne mainloop */
616 0x00,0xBE, /* bkpt #0 */
617 /* pFLASH_CTRL_BASE: */
618 0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */
619 /* FLASHWRITECMD: */
620 0x01,0x00,0x42,0xA4 /* .word 0xA4420001 */
621 };
622
623 int stellaris_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 wcount)
624 {
625 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
626 target_t *target = bank->target;
627 u32 buffer_size = 8192;
628 working_area_t *source;
629 working_area_t *write_algorithm;
630 u32 address = bank->base + offset;
631 reg_param_t reg_params[8];
632 armv7m_algorithm_t armv7m_info;
633 int retval;
634
635 DEBUG("(bank=%08X buffer=%08X offset=%08X wcount=%08X)",
636 bank, buffer, offset, wcount);
637
638 /* flash write code */
639 if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK)
640 {
641 WARNING("no working area available, can't do block memory writes");
642 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
643 };
644
645 target_write_buffer(target, write_algorithm->address, sizeof(stellaris_write_code), stellaris_write_code);
646
647 /* memory buffer */
648 while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
649 {
650 DEBUG("called target_alloc_working_area(target=%08X buffer_size=%08X source=%08X)",
651 target, buffer_size, source);
652 buffer_size /= 2;
653 if (buffer_size <= 256)
654 {
655 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
656 if (write_algorithm)
657 target_free_working_area(target, write_algorithm);
658
659 WARNING("no large enough working area available, can't do block memory writes");
660 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
661 }
662 };
663
664 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
665 armv7m_info.core_mode = ARMV7M_MODE_ANY;
666 armv7m_info.core_state = ARMV7M_STATE_THUMB;
667
668 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
669 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
670 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
671 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
672 init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);
673 init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);
674 init_reg_param(&reg_params[6], "r6", 32, PARAM_OUT);
675 init_reg_param(&reg_params[7], "r7", 32, PARAM_OUT);
676
677 while (wcount > 0)
678 {
679 u32 thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
680
681 target_write_buffer(target, source->address, thisrun_count * 4, buffer);
682
683 buf_set_u32(reg_params[0].value, 0, 32, source->address);
684 buf_set_u32(reg_params[1].value, 0, 32, address);
685 buf_set_u32(reg_params[2].value, 0, 32, 4*thisrun_count);
686 WARNING("Algorithm flash write %i words to 0x%x, %i remaining",thisrun_count,address, wcount);
687 DEBUG("Algorithm flash write %i words to 0x%x, %i remaining",thisrun_count,address, wcount);
688 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)
689 {
690 ERROR("error executing stellaris flash write algorithm");
691 target_free_working_area(target, source);
692 destroy_reg_param(&reg_params[0]);
693 destroy_reg_param(&reg_params[1]);
694 destroy_reg_param(&reg_params[2]);
695 return ERROR_FLASH_OPERATION_FAILED;
696 }
697
698 buffer += thisrun_count * 4;
699 address += thisrun_count * 4;
700 wcount -= thisrun_count;
701 }
702
703
704 target_free_working_area(target, write_algorithm);
705 target_free_working_area(target, source);
706
707 destroy_reg_param(&reg_params[0]);
708 destroy_reg_param(&reg_params[1]);
709 destroy_reg_param(&reg_params[2]);
710 destroy_reg_param(&reg_params[3]);
711 destroy_reg_param(&reg_params[4]);
712 destroy_reg_param(&reg_params[5]);
713 destroy_reg_param(&reg_params[6]);
714 destroy_reg_param(&reg_params[7]);
715
716 return ERROR_OK;
717 }
718
719 int stellaris_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
720 {
721 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
722 target_t *target = bank->target;
723 u32 dst_min_alignment, wcount, bytes_remaining = count;
724 u32 address = offset;
725 u32 fcr,flash_cris,flash_fmc;
726 u32 retval;
727
728 DEBUG("(bank=%08X buffer=%08X offset=%08X count=%08X)",
729 bank, buffer, offset, count);
730
731 if (bank->target->state != TARGET_HALTED)
732 {
733 return ERROR_TARGET_NOT_HALTED;
734 }
735
736 if (stellaris_info->did1 == 0)
737 {
738 stellaris_read_part_info(bank);
739 }
740
741 if (stellaris_info->did1 == 0)
742 {
743 WARNING("Cannot identify target as a Stellaris processor");
744 return ERROR_FLASH_OPERATION_FAILED;
745 }
746
747 if((offset & 3) || (count & 3))
748 {
749 WARNING("offset size must be word aligned");
750 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
751 }
752
753 if (offset + count > bank->size)
754 return ERROR_FLASH_DST_OUT_OF_BANK;
755
756 /* Configure the flash controller timing */
757 stellaris_read_clock_info(bank);
758 stellaris_set_flash_mode(bank,0);
759
760
761 /* Clear and disable flash programming interrupts */
762 target_write_u32(target, FLASH_CIM, 0);
763 target_write_u32(target, FLASH_MISC, PMISC|AMISC);
764
765 /* multiple words to be programmed? */
766 if (count > 0)
767 {
768 /* try using a block write */
769 if ((retval = stellaris_write_block(bank, buffer, offset, count/4)) != ERROR_OK)
770 {
771 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
772 {
773 /* if block write failed (no sufficient working area),
774 * we use normal (slow) single dword accesses */
775 WARNING("couldn't use block writes, falling back to single memory accesses");
776 }
777 else if (retval == ERROR_FLASH_OPERATION_FAILED)
778 {
779 /* if an error occured, we examine the reason, and quit */
780 target_read_u32(target, FLASH_CRIS, &flash_cris);
781
782 ERROR("flash writing failed with CRIS: 0x%x", flash_cris);
783 return ERROR_FLASH_OPERATION_FAILED;
784 }
785 }
786 else
787 {
788 buffer += count * 4;
789 address += count * 4;
790 count = 0;
791 }
792 }
793
794
795
796 while(count>0)
797 {
798 if (!(address&0xff)) DEBUG("0x%x",address);
799 /* Program one word */
800 target_write_u32(target, FLASH_FMA, address);
801 target_write_buffer(target, FLASH_FMD, 4, buffer);
802 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
803 //DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE);
804 /* Wait until write complete */
805 do
806 {
807 target_read_u32(target, FLASH_FMC, &flash_fmc);
808 }
809 while(flash_fmc & FMC_WRITE);
810 buffer += 4;
811 address += 4;
812 count -= 4;
813 }
814 /* Check acess violations */
815 target_read_u32(target, FLASH_CRIS, &flash_cris);
816 if(flash_cris & (AMASK))
817 {
818 DEBUG("flash_cris 0x%x", flash_cris);
819 return ERROR_FLASH_OPERATION_FAILED;
820 }
821 return ERROR_OK;
822 }
823
824
825 int stellaris_probe(struct flash_bank_s *bank)
826 {
827 /* we can't probe on an stellaris
828 * if this is an stellaris, it has the configured flash
829 */
830 stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
831
832 if (stellaris_info->did1 == 0)
833 {
834 stellaris_read_part_info(bank);
835 }
836
837 if (stellaris_info->did1 == 0)
838 {
839 WARNING("Cannot identify target as a LMI Stellaris");
840 return ERROR_FLASH_OPERATION_FAILED;
841 }
842
843 return ERROR_OK;
844 }

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)