Added patch for Luminar Micors Fury class devices (Joe Kroesche)
[openocd.git] / src / flash / at91sam7.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 There are some things to notice
23
24 * AT91SAM7S64 is tested
25 * All AT91SAM7Sxx and AT91SAM7Xxx should work but is not tested
26 * All parameters are identified from onchip configuartion registers
27 *
28 * The flash controller handles erases automatically on a page (128/265 byte) basis
29 * Only an EraseAll command is supported by the controller
30 * Partial erases can be implemented in software by writing one 0xFFFFFFFF word to
31 * some location in every page in the region to be erased
32 *
33 * Lock regions (sectors) are 32 or 64 pages
34 *
35 ***************************************************************************/
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include "replacements.h"
41
42 #include "at91sam7.h"
43
44 #include "flash.h"
45 #include "target.h"
46 #include "log.h"
47 #include "binarybuffer.h"
48 #include "types.h"
49
50 #include <stdlib.h>
51 #include <string.h>
52 #include <unistd.h>
53
54 int at91sam7_register_commands(struct command_context_s *cmd_ctx);
55 int at91sam7_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
56 int at91sam7_erase(struct flash_bank_s *bank, int first, int last);
57 int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last);
58 int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
59 int at91sam7_probe(struct flash_bank_s *bank);
60 int at91sam7_erase_check(struct flash_bank_s *bank);
61 int at91sam7_protect_check(struct flash_bank_s *bank);
62 int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size);
63
64 u32 at91sam7_get_flash_status(flash_bank_t *bank);
65 void at91sam7_set_flash_mode(flash_bank_t *bank,int mode);
66 u32 at91sam7_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout);
67 int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
68
69 flash_driver_t at91sam7_flash =
70 {
71 .name = "at91sam7",
72 .register_commands = at91sam7_register_commands,
73 .flash_bank_command = at91sam7_flash_bank_command,
74 .erase = at91sam7_erase,
75 .protect = at91sam7_protect,
76 .write = at91sam7_write,
77 .probe = at91sam7_probe,
78 .erase_check = at91sam7_erase_check,
79 .protect_check = at91sam7_protect_check,
80 .info = at91sam7_info
81 };
82
83
84 char * EPROC[8]= {"Unknown","ARM946-E","ARM7TDMI","Unknown","ARM920T","ARM926EJ-S","Unknown","Unknown"};
85 long NVPSIZ[16] = {
86 0,
87 0x2000, /* 8K */
88 0x4000, /* 16K */
89 0x8000, /* 32K */
90 -1,
91 0x10000, /* 64K */
92 -1,
93 0x20000, /* 128K */
94 -1,
95 0x40000, /* 256K */
96 0x80000, /* 512K */
97 -1,
98 0x100000, /* 1024K */
99 -1,
100 0x200000, /* 2048K */
101 -1
102 };
103
104 long SRAMSIZ[16] = {
105 -1,
106 0x0400, /* 1K */
107 0x0800, /* 2K */
108 -1,
109 0x1c000, /* 112K */
110 0x1000, /* 4K */
111 0x14000, /* 80K */
112 0x28000, /* 160K */
113 0x2000, /* 8K */
114 0x4000, /* 16K */
115 0x8000, /* 32K */
116 0x10000, /* 64K */
117 0x20000, /* 128K */
118 0x40000, /* 256K */
119 0x18000, /* 96K */
120 0x80000, /* 512K */
121 };
122
123 int at91sam7_register_commands(struct command_context_s *cmd_ctx)
124 {
125 command_t *at91sam7_cmd = register_command(cmd_ctx, NULL, "at91sam7", NULL, COMMAND_ANY, NULL);
126 register_command(cmd_ctx, at91sam7_cmd, "gpnvm", at91sam7_handle_gpnvm_command, COMMAND_EXEC,
127 "at91sam7 gpnvm <num> <bit> set|clear, set or clear at91sam7 gpnvm bit");
128
129 return ERROR_OK;
130 }
131
132 u32 at91sam7_get_flash_status(flash_bank_t *bank)
133 {
134 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
135 target_t *target = at91sam7_info->target;
136 u32 fsr;
137
138 target_read_u32(target, MC_FSR, &fsr);
139
140 return fsr;
141 }
142
143 /** Read clock configuration and set at91sam7_info->usec_clocks*/
144 void at91sam7_read_clock_info(flash_bank_t *bank)
145 {
146 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
147 target_t *target = at91sam7_info->target;
148 u32 mckr, mcfr, pllr;
149 unsigned long tmp = 0, mainfreq;
150
151 /* Read main clock freqency register */
152 target_read_u32(target, CKGR_MCFR, &mcfr);
153 /* Read master clock register */
154 target_read_u32(target, PMC_MCKR, &mckr);
155 /* Read Clock Generator PLL Register */
156 target_read_u32(target, CKGR_PLLR, &pllr);
157
158 at91sam7_info->mck_valid = 0;
159 switch (mckr & PMC_MCKR_CSS) {
160 case 0: /* Slow Clock */
161 at91sam7_info->mck_valid = 1;
162 tmp = RC_FREQ;
163 break;
164 case 1: /* Main Clock */
165 if (mcfr & CKGR_MCFR_MAINRDY)
166 {
167 at91sam7_info->mck_valid = 1;
168 mainfreq = RC_FREQ / 16ul * (mcfr & 0xffff);
169 tmp = mainfreq;
170 }
171 break;
172
173 case 2: /* Reserved */
174 break;
175 case 3: /* PLL Clock */
176 if (mcfr & CKGR_MCFR_MAINRDY)
177 {
178 target_read_u32(target, CKGR_PLLR, &pllr);
179 if (!(pllr & CKGR_PLLR_DIV))
180 break; /* 0 Hz */
181 at91sam7_info->mck_valid = 1;
182 mainfreq = RC_FREQ / 16ul * (mcfr & 0xffff);
183 /* Integer arithmetic should have sufficient precision
184 as long as PLL is properly configured. */
185 tmp = mainfreq / (pllr & CKGR_PLLR_DIV) *
186 (((pllr & CKGR_PLLR_MUL) >> 16) + 1);
187 }
188 break;
189 }
190
191 /* Prescaler adjust */
192 if (((mckr & PMC_MCKR_PRES) >> 2) == 7)
193 at91sam7_info->mck_valid = 0;
194 else
195 at91sam7_info->mck_freq = tmp >> ((mckr & PMC_MCKR_PRES) >> 2);
196
197 /* Forget old flash timing */
198 at91sam7_set_flash_mode(bank,FMR_TIMING_NONE);
199 }
200
201 /* Setup the timimg registers for nvbits or normal flash */
202 void at91sam7_set_flash_mode(flash_bank_t *bank,int mode)
203 {
204 u32 fmr, fmcn = 0, fws = 0;
205 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
206 target_t *target = at91sam7_info->target;
207
208 if (mode && (mode != at91sam7_info->flashmode))
209 {
210 /* Always round up (ceil) */
211 if (mode==FMR_TIMING_NVBITS)
212 {
213 if (at91sam7_info->cidr_arch == 0x60)
214 {
215 /* AT91SAM7A3 uses master clocks in 100 ns */
216 fmcn = (at91sam7_info->mck_freq/10000000ul)+1;
217 }
218 else
219 {
220 /* master clocks in 1uS for ARCH 0x7 types */
221 fmcn = (at91sam7_info->mck_freq/1000000ul)+1;
222 }
223 }
224 else if (mode==FMR_TIMING_FLASH)
225 /* main clocks in 1.5uS */
226 fmcn = (at91sam7_info->mck_freq/666666ul)+1;
227
228 /* Only allow fmcn=0 if clock period is > 30 us = 33kHz. */
229 if (at91sam7_info->mck_freq <= 33333ul)
230 fmcn = 0;
231 /* Only allow fws=0 if clock frequency is < 30 MHz. */
232 if (at91sam7_info->mck_freq > 30000000ul)
233 fws = 1;
234
235 DEBUG("fmcn: %i", fmcn);
236 fmr = fmcn << 16 | fws << 8;
237 target_write_u32(target, MC_FMR, fmr);
238 }
239
240 at91sam7_info->flashmode = mode;
241 }
242
243 u32 at91sam7_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout)
244 {
245 u32 status;
246
247 while ((!((status = at91sam7_get_flash_status(bank)) & waitbits)) && (timeout-- > 0))
248 {
249 DEBUG("status: 0x%x", status);
250 usleep(1000);
251 }
252
253 DEBUG("status: 0x%x", status);
254
255 if (status & 0x0C)
256 {
257 ERROR("status register: 0x%x", status);
258 if (status & 0x4)
259 ERROR("Lock Error Bit Detected, Operation Abort");
260 if (status & 0x8)
261 ERROR("Invalid command and/or bad keyword, Operation Abort");
262 if (status & 0x10)
263 ERROR("Security Bit Set, Operation Abort");
264 }
265
266 return status;
267 }
268
269
270 /* Send one command to the AT91SAM flash controller */
271 int at91sam7_flash_command(struct flash_bank_s *bank,u8 cmd,u16 pagen)
272 {
273 u32 fcr;
274 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
275 target_t *target = at91sam7_info->target;
276
277 fcr = (0x5A<<24) | (pagen<<8) | cmd;
278 target_write_u32(target, MC_FCR, fcr);
279 DEBUG("Flash command: 0x%x, pagenumber:%u", fcr, pagen);
280
281 if ((at91sam7_info->cidr_arch == 0x60)&&((cmd==SLB)|(cmd==CLB)))
282 {
283 /* Lock bit manipulation on AT91SAM7A3 waits for FC_FSR bit 1, EOL */
284 if (at91sam7_wait_status_busy(bank, MC_FSR_EOL, 10)&0x0C)
285 {
286 return ERROR_FLASH_OPERATION_FAILED;
287 }
288 return ERROR_OK;
289 }
290
291 if (at91sam7_wait_status_busy(bank, MC_FSR_FRDY, 10)&0x0C)
292 {
293 return ERROR_FLASH_OPERATION_FAILED;
294 }
295 return ERROR_OK;
296 }
297
298 /* Read device id register, main clock frequency register and fill in driver info structure */
299 int at91sam7_read_part_info(struct flash_bank_s *bank)
300 {
301 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
302 target_t *target = at91sam7_info->target;
303 u32 cidr, status;
304
305 if (at91sam7_info->target->state != TARGET_HALTED)
306 {
307 return ERROR_TARGET_NOT_HALTED;
308 }
309
310 /* Read and parse chip identification register */
311 target_read_u32(target, DBGU_CIDR, &cidr);
312
313 if (cidr == 0)
314 {
315 WARNING("Cannot identify target as an AT91SAM");
316 return ERROR_FLASH_OPERATION_FAILED;
317 }
318
319 at91sam7_info->cidr = cidr;
320 at91sam7_info->cidr_ext = (cidr>>31)&0x0001;
321 at91sam7_info->cidr_nvptyp = (cidr>>28)&0x0007;
322 at91sam7_info->cidr_arch = (cidr>>20)&0x00FF;
323 at91sam7_info->cidr_sramsiz = (cidr>>16)&0x000F;
324 at91sam7_info->cidr_nvpsiz2 = (cidr>>12)&0x000F;
325 at91sam7_info->cidr_nvpsiz = (cidr>>8)&0x000F;
326 at91sam7_info->cidr_eproc = (cidr>>5)&0x0007;
327 at91sam7_info->cidr_version = cidr&0x001F;
328 bank->size = NVPSIZ[at91sam7_info->cidr_nvpsiz];
329 at91sam7_info->target_name = "Unknown";
330
331 DEBUG("nvptyp: 0x%3.3x, arch: 0x%4.4x", at91sam7_info->cidr_nvptyp, at91sam7_info->cidr_arch );
332
333 /* Read main and master clock freqency register */
334 at91sam7_read_clock_info(bank);
335
336 status = at91sam7_get_flash_status(bank);
337 at91sam7_info->lockbits = status>>16;
338 at91sam7_info->securitybit = (status>>4)&0x01;
339
340 if (at91sam7_info->cidr_arch == 0x70 )
341 {
342 at91sam7_info->num_nvmbits = 2;
343 at91sam7_info->nvmbits = (status>>8)&0x03;
344 bank->base = 0x100000;
345 bank->bus_width = 4;
346 if (bank->size==0x40000) /* AT91SAM7S256 */
347 {
348 at91sam7_info->target_name = "AT91SAM7S256";
349 at91sam7_info->num_lockbits = 16;
350 at91sam7_info->pagesize = 256;
351 at91sam7_info->pages_in_lockregion = 64;
352 at91sam7_info->num_pages = 16*64;
353 }
354 if (bank->size==0x20000) /* AT91SAM7S128 */
355 {
356 at91sam7_info->target_name = "AT91SAM7S128";
357 at91sam7_info->num_lockbits = 8;
358 at91sam7_info->pagesize = 256;
359 at91sam7_info->pages_in_lockregion = 64;
360 at91sam7_info->num_pages = 8*64;
361 }
362 if (bank->size==0x10000) /* AT91SAM7S64 */
363 {
364 at91sam7_info->target_name = "AT91SAM7S64";
365 at91sam7_info->num_lockbits = 16;
366 at91sam7_info->pagesize = 128;
367 at91sam7_info->pages_in_lockregion = 32;
368 at91sam7_info->num_pages = 16*32;
369 }
370 if (bank->size==0x08000) /* AT91SAM7S321/32 */
371 {
372 at91sam7_info->target_name = "AT91SAM7S321/32";
373 at91sam7_info->num_lockbits = 8;
374 at91sam7_info->pagesize = 128;
375 at91sam7_info->pages_in_lockregion = 32;
376 at91sam7_info->num_pages = 8*32;
377 }
378
379 return ERROR_OK;
380 }
381
382 if (at91sam7_info->cidr_arch == 0x71 )
383 {
384 at91sam7_info->num_nvmbits = 3;
385 at91sam7_info->nvmbits = (status>>8)&0x07;
386 bank->base = 0x100000;
387 bank->bus_width = 4;
388 if (bank->size==0x40000) /* AT91SAM7XC256 */
389 {
390 at91sam7_info->target_name = "AT91SAM7XC256";
391 at91sam7_info->num_lockbits = 16;
392 at91sam7_info->pagesize = 256;
393 at91sam7_info->pages_in_lockregion = 64;
394 at91sam7_info->num_pages = 16*64;
395 }
396 if (bank->size==0x20000) /* AT91SAM7XC128 */
397 {
398 at91sam7_info->target_name = "AT91SAM7XC128";
399 at91sam7_info->num_lockbits = 8;
400 at91sam7_info->pagesize = 256;
401 at91sam7_info->pages_in_lockregion = 64;
402 at91sam7_info->num_pages = 8*64;
403 }
404
405 return ERROR_OK;
406 }
407
408 if (at91sam7_info->cidr_arch == 0x72 )
409 {
410 at91sam7_info->num_nvmbits = 2;
411 at91sam7_info->nvmbits = (status>>8)&0x03;
412 bank->base = 0x100000;
413 bank->bus_width = 4;
414 if (bank->size==0x80000) /* AT91SAM7SE512 */
415 {
416 at91sam7_info->target_name = "AT91SAM7SE512";
417 at91sam7_info->num_lockbits = 32;
418 at91sam7_info->pagesize = 256;
419 at91sam7_info->pages_in_lockregion = 64;
420 at91sam7_info->num_pages = 32*64;
421 }
422 if (bank->size==0x40000)
423 {
424 at91sam7_info->target_name = "AT91SAM7SE256";
425 at91sam7_info->num_lockbits = 16;
426 at91sam7_info->pagesize = 256;
427 at91sam7_info->pages_in_lockregion = 64;
428 at91sam7_info->num_pages = 16*64;
429 }
430 if (bank->size==0x08000)
431 {
432 at91sam7_info->target_name = "AT91SAM7SE32";
433 at91sam7_info->num_lockbits = 8;
434 at91sam7_info->pagesize = 128;
435 at91sam7_info->pages_in_lockregion = 32;
436 at91sam7_info->num_pages = 8*32;
437 }
438
439 return ERROR_OK;
440 }
441
442 if (at91sam7_info->cidr_arch == 0x75 )
443 {
444 at91sam7_info->num_nvmbits = 3;
445 at91sam7_info->nvmbits = (status>>8)&0x07;
446 bank->base = 0x100000;
447 bank->bus_width = 4;
448 if (bank->size==0x40000) /* AT91SAM7X256 */
449 {
450 at91sam7_info->target_name = "AT91SAM7X256";
451 at91sam7_info->num_lockbits = 16;
452 at91sam7_info->pagesize = 256;
453 at91sam7_info->pages_in_lockregion = 64;
454 at91sam7_info->num_pages = 16*64;
455 }
456 if (bank->size==0x20000) /* AT91SAM7X128 */
457 {
458 at91sam7_info->target_name = "AT91SAM7X128";
459 at91sam7_info->num_lockbits = 8;
460 at91sam7_info->pagesize = 256;
461 at91sam7_info->pages_in_lockregion = 64;
462 at91sam7_info->num_pages = 8*64;
463 }
464
465 return ERROR_OK;
466 }
467
468 if (at91sam7_info->cidr_arch == 0x60 )
469 {
470 at91sam7_info->num_nvmbits = 3;
471 at91sam7_info->nvmbits = (status>>8)&0x07;
472 bank->base = 0x100000;
473 bank->bus_width = 4;
474
475 if (bank->size == 0x40000) /* AT91SAM7A3 */
476 {
477 at91sam7_info->target_name = "AT91SAM7A3";
478 at91sam7_info->num_lockbits = 16;
479 at91sam7_info->pagesize = 256;
480 at91sam7_info->pages_in_lockregion = 16;
481 at91sam7_info->num_pages = 16*64;
482 }
483 return ERROR_OK;
484 }
485
486 WARNING("at91sam7 flash only tested for AT91SAM7Sxx series");
487
488 return ERROR_OK;
489 }
490
491 int at91sam7_erase_check(struct flash_bank_s *bank)
492 {
493 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
494
495 if (!at91sam7_info->working_area_size)
496 {
497 }
498 else
499 {
500 }
501
502 return ERROR_OK;
503 }
504
505 int at91sam7_protect_check(struct flash_bank_s *bank)
506 {
507 u32 status;
508
509 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
510
511 if (at91sam7_info->cidr == 0)
512 {
513 at91sam7_read_part_info(bank);
514 }
515
516 if (at91sam7_info->cidr == 0)
517 {
518 WARNING("Cannot identify target as an AT91SAM");
519 return ERROR_FLASH_OPERATION_FAILED;
520 }
521
522 status = at91sam7_get_flash_status(bank);
523 at91sam7_info->lockbits = status >> 16;
524
525 return ERROR_OK;
526 }
527
528 int at91sam7_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
529 {
530 at91sam7_flash_bank_t *at91sam7_info;
531
532 if (argc < 6)
533 {
534 WARNING("incomplete flash_bank at91sam7 configuration");
535 return ERROR_FLASH_BANK_INVALID;
536 }
537
538 at91sam7_info = malloc(sizeof(at91sam7_flash_bank_t));
539 bank->driver_priv = at91sam7_info;
540
541 at91sam7_info->target = get_target_by_num(strtoul(args[5], NULL, 0));
542 if (!at91sam7_info->target)
543 {
544 ERROR("no target '%s' configured", args[5]);
545 exit(-1);
546 }
547
548 /* part wasn't probed for info yet */
549 at91sam7_info->cidr = 0;
550
551 return ERROR_OK;
552 }
553
554 int at91sam7_erase(struct flash_bank_s *bank, int first, int last)
555 {
556 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
557
558 if (at91sam7_info->target->state != TARGET_HALTED)
559 {
560 return ERROR_TARGET_NOT_HALTED;
561 }
562
563 if (at91sam7_info->cidr == 0)
564 {
565 at91sam7_read_part_info(bank);
566 }
567
568 if (at91sam7_info->cidr == 0)
569 {
570 WARNING("Cannot identify target as an AT91SAM");
571 return ERROR_FLASH_OPERATION_FAILED;
572 }
573
574 if ((first < 0) || (last < first) || (last >= at91sam7_info->num_lockbits))
575 {
576 return ERROR_FLASH_SECTOR_INVALID;
577 }
578
579 /* Configure the flash controller timing */
580 at91sam7_read_clock_info(bank);
581 at91sam7_set_flash_mode(bank,FMR_TIMING_FLASH);
582
583 if ((first == 0) && (last == (at91sam7_info->num_lockbits-1)))
584 {
585 return at91sam7_flash_command(bank, EA, 0);
586 }
587
588 WARNING("Can only erase the whole flash area, pages are autoerased on write");
589 return ERROR_FLASH_OPERATION_FAILED;
590 }
591
592 int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last)
593 {
594 u32 cmd, pagen, status;
595 int lockregion;
596
597 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
598
599 if (at91sam7_info->target->state != TARGET_HALTED)
600 {
601 return ERROR_TARGET_NOT_HALTED;
602 }
603
604 if ((first < 0) || (last < first) || (last >= at91sam7_info->num_lockbits))
605 {
606 return ERROR_FLASH_SECTOR_INVALID;
607 }
608
609 if (at91sam7_info->cidr == 0)
610 {
611 at91sam7_read_part_info(bank);
612 }
613
614 if (at91sam7_info->cidr == 0)
615 {
616 WARNING("Cannot identify target as an AT91SAM");
617 return ERROR_FLASH_OPERATION_FAILED;
618 }
619
620 /* Configure the flash controller timing */
621 at91sam7_read_clock_info(bank);
622 at91sam7_set_flash_mode(bank,FMR_TIMING_NVBITS);
623
624 for (lockregion=first;lockregion<=last;lockregion++)
625 {
626 pagen = lockregion*at91sam7_info->pages_in_lockregion;
627 if (set)
628 cmd = SLB;
629 else
630 cmd = CLB;
631 if (at91sam7_flash_command(bank, cmd, pagen) != ERROR_OK)
632 {
633 return ERROR_FLASH_OPERATION_FAILED;
634 }
635 }
636
637 status = at91sam7_get_flash_status(bank);
638 at91sam7_info->lockbits = status>>16;
639
640 return ERROR_OK;
641 }
642
643
644 int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
645 {
646 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
647 target_t *target = at91sam7_info->target;
648 u32 dst_min_alignment, wcount, bytes_remaining = count;
649 u32 first_page, last_page, pagen, buffer_pos;
650
651 if (at91sam7_info->target->state != TARGET_HALTED)
652 {
653 return ERROR_TARGET_NOT_HALTED;
654 }
655
656 if (at91sam7_info->cidr == 0)
657 {
658 at91sam7_read_part_info(bank);
659 }
660
661 if (at91sam7_info->cidr == 0)
662 {
663 WARNING("Cannot identify target as an AT91SAM");
664 return ERROR_FLASH_OPERATION_FAILED;
665 }
666
667 if (offset + count > bank->size)
668 return ERROR_FLASH_DST_OUT_OF_BANK;
669
670 dst_min_alignment = at91sam7_info->pagesize;
671
672 if (offset % dst_min_alignment)
673 {
674 WARNING("offset 0x%x breaks required alignment 0x%x", offset, dst_min_alignment);
675 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
676 }
677
678 if (offset + count > bank->size)
679 return ERROR_FLASH_DST_OUT_OF_BANK;
680
681 if (at91sam7_info->cidr_arch == 0)
682 return ERROR_FLASH_BANK_NOT_PROBED;
683
684 first_page = offset/dst_min_alignment;
685 last_page = CEIL(offset + count, dst_min_alignment);
686
687 DEBUG("first_page: %i, last_page: %i, count %i", first_page, last_page, count);
688
689 /* Configure the flash controller timing */
690 at91sam7_read_clock_info(bank);
691 at91sam7_set_flash_mode(bank,FMR_TIMING_FLASH);
692
693 for (pagen=first_page; pagen<last_page; pagen++) {
694 if (bytes_remaining<dst_min_alignment)
695 count = bytes_remaining;
696 else
697 count = dst_min_alignment;
698 bytes_remaining -= count;
699
700 /* Write one block to the PageWriteBuffer */
701 buffer_pos = (pagen-first_page)*dst_min_alignment;
702 wcount = CEIL(count,4);
703 target->type->write_memory(target, bank->base, 4, wcount, buffer+buffer_pos);
704
705 /* Send Write Page command to Flash Controller */
706 if (at91sam7_flash_command(bank, WP, pagen) != ERROR_OK)
707 {
708 return ERROR_FLASH_OPERATION_FAILED;
709 }
710 DEBUG("Write page number:%i", pagen);
711 }
712
713 return ERROR_OK;
714 }
715
716
717 int at91sam7_probe(struct flash_bank_s *bank)
718 {
719 /* we can't probe on an at91sam7
720 * if this is an at91sam7, it has the configured flash
721 */
722 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
723
724 if (at91sam7_info->cidr == 0)
725 {
726 at91sam7_read_part_info(bank);
727 }
728
729 if (at91sam7_info->cidr == 0)
730 {
731 WARNING("Cannot identify target as an AT91SAM");
732 return ERROR_FLASH_OPERATION_FAILED;
733 }
734
735 return ERROR_OK;
736 }
737
738 int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size)
739 {
740 int printed;
741 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
742
743 at91sam7_read_part_info(bank);
744
745 if (at91sam7_info->cidr == 0)
746 {
747 printed = snprintf(buf, buf_size, "Cannot identify target as an AT91SAM\n");
748 buf += printed;
749 buf_size -= printed;
750 return ERROR_FLASH_OPERATION_FAILED;
751 }
752
753 printed = snprintf(buf, buf_size, "\nat91sam7 information: Chip is %s\n",at91sam7_info->target_name);
754 buf += printed;
755 buf_size -= printed;
756
757 printed = snprintf(buf, buf_size, "cidr: 0x%8.8x, arch: 0x%4.4x, eproc: %s, version:0x%3.3x, flashsize: 0x%8.8x\n", at91sam7_info->cidr, at91sam7_info->cidr_arch, EPROC[at91sam7_info->cidr_eproc], at91sam7_info->cidr_version, bank->size);
758 buf += printed;
759 buf_size -= printed;
760
761 printed = snprintf(buf, buf_size, "master clock(estimated): %ikHz \n", at91sam7_info->mck_freq / 1000);
762 buf += printed;
763 buf_size -= printed;
764
765 if (at91sam7_info->num_lockbits>0) {
766 printed = snprintf(buf, buf_size, "pagesize: %i, lockbits: %i 0x%4.4x, pages in lock region: %i \n", at91sam7_info->pagesize, at91sam7_info->num_lockbits, at91sam7_info->lockbits,at91sam7_info->num_pages/at91sam7_info->num_lockbits);
767 buf += printed;
768 buf_size -= printed;
769 }
770
771 printed = snprintf(buf, buf_size, "securitybit: %i, nvmbits: 0x%1.1x\n", at91sam7_info->securitybit, at91sam7_info->nvmbits);
772 buf += printed;
773 buf_size -= printed;
774
775 return ERROR_OK;
776 }
777
778 /*
779 * On AT91SAM7S: When the gpnmv bits are set with
780 * > at91sam7 gpnvm 0 bitnr set
781 * the changes are not visible in the flash controller status register MC_FSR
782 * until the processor has been reset.
783 * On the Olimex board this requires a power cycle.
784 * Note that the AT91SAM7S has the following errata (doc6175.pdf sec 14.1.3):
785 * The maximum number of write/erase cycles for Non Volatile Memory bits is 100. This includes
786 * Lock Bits (LOCKx), General Purpose NVM bits (GPNVMx) and the Security Bit.
787 */
788 int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
789 {
790 flash_bank_t *bank;
791 int bit;
792 u8 flashcmd;
793 u32 status;
794 char *value;
795 at91sam7_flash_bank_t *at91sam7_info;
796
797 if (argc < 3)
798 {
799 command_print(cmd_ctx, "at91sam7 gpnvm <num> <bit> <set|clear>");
800 return ERROR_OK;
801 }
802
803 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
804 bit = atoi(args[1]);
805 value = args[2];
806
807 if (!bank)
808 {
809 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
810 return ERROR_OK;
811 }
812
813 at91sam7_info = bank->driver_priv;
814
815 if (at91sam7_info->target->state != TARGET_HALTED)
816 {
817 return ERROR_TARGET_NOT_HALTED;
818 }
819
820 if (at91sam7_info->cidr == 0)
821 {
822 at91sam7_read_part_info(bank);
823 }
824
825 if (at91sam7_info->cidr == 0)
826 {
827 WARNING("Cannot identify target as an AT91SAM");
828 return ERROR_FLASH_OPERATION_FAILED;
829 }
830
831 if ((bit<0) || (at91sam7_info->num_nvmbits <= bit))
832 {
833 command_print(cmd_ctx, "gpnvm bit '#%s' is out of bounds for target %s", args[1],at91sam7_info->target_name);
834 return ERROR_OK;
835 }
836
837 if (strcmp(value, "set") == 0)
838 {
839 flashcmd = SGPB;
840 }
841 else if (strcmp(value, "clear") == 0)
842 {
843 flashcmd = CGPB;
844 }
845 else
846 {
847 command_print(cmd_ctx, "usage: at91sam7 gpnvm <num> <bit> <set|clear>");
848 return ERROR_OK;
849 }
850
851 /* Configure the flash controller timing */
852 at91sam7_read_clock_info(bank);
853 at91sam7_set_flash_mode(bank,FMR_TIMING_NVBITS);
854
855 if (at91sam7_flash_command(bank, flashcmd, (u16)(bit)) != ERROR_OK)
856 {
857 return ERROR_FLASH_OPERATION_FAILED;
858 }
859
860 status = at91sam7_get_flash_status(bank);
861 DEBUG("at91sam7_handle_gpnvm_command: cmd 0x%x, value 0x%x, status 0x%x \n",flashcmd,bit,status);
862 at91sam7_info->nvmbits = (status>>8)&((1<<at91sam7_info->num_nvmbits)-1);
863
864 return ERROR_OK;
865 }

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)