- Added support for native MinGW builds (thanks to Spencer Oliver and Michael Fischer...
[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 u8 at91sam7_wait_status_busy(flash_bank_t *bank, 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 long fsr;
137
138 target->type->read_memory(target, MC_FSR, 4, 1, (u8 *)&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 unsigned long mckr, mcfr, pllr, tmp, status, mainfreq;
149 unsigned int css, pres, mul, div;
150
151 /* Read main clock freqency register */
152 target->type->read_memory(target, CKGR_MCFR, 4, 1, (u8 *)&mcfr);
153 /* Read master clock register */
154 target->type->read_memory(target, PMC_MCKR, 4, 1, (u8 *)&mckr);
155 /* Read Clock Generator PLL Register */
156 target->type->read_memory(target, CKGR_PLLR, 4, 1, (u8 *)&pllr);
157
158 pres = (mckr>>2)&0x7;
159 mul = (pllr>>16)&0x7FF;
160 div = pllr&0xFF;
161
162 at91sam7_info->mck_valid = 0;
163 switch (mckr & PMC_MCKR_CSS) {
164 case 0: /* Slow Clock */
165 at91sam7_info->mck_valid = 1;
166 tmp = RC_FREQ;
167 break;
168 case 1: /* Main Clock */
169 if (mcfr & CKGR_MCFR_MAINRDY)
170 {
171 at91sam7_info->mck_valid = 1;
172 mainfreq = RC_FREQ / 16ul * (mcfr & 0xffff);
173 tmp = mainfreq;
174 }
175 break;
176
177 case 2: /* Reserved */
178 break;
179 case 3: /* PLL Clock */
180 if (mcfr & CKGR_MCFR_MAINRDY)
181 {
182 target->type->read_memory(target, CKGR_PLLR, 4, 1,
183 (u8 *)&pllr);
184 if (!(pllr & CKGR_PLLR_DIV))
185 break; /* 0 Hz */
186 at91sam7_info->mck_valid = 1;
187 mainfreq = RC_FREQ / 16ul * (mcfr & 0xffff);
188 /* Integer arithmetic should have sufficient precision
189 as long as PLL is properly configured. */
190 tmp = mainfreq / (pllr & CKGR_PLLR_DIV) *
191 (((pllr & CKGR_PLLR_MUL) >> 16) + 1);
192 }
193 break;
194 }
195
196 /* Prescaler adjust */
197 if (((mckr & PMC_MCKR_PRES) >> 2) == 7)
198 at91sam7_info->mck_valid = 0;
199 else
200 at91sam7_info->mck_freq = tmp >> ((mckr & PMC_MCKR_PRES) >> 2);
201
202 /* Forget old flash timing */
203 at91sam7_set_flash_mode(bank,0);
204 }
205
206 /* Setup the timimg registers for nvbits or normal flash */
207 void at91sam7_set_flash_mode(flash_bank_t *bank,int mode)
208 {
209 u32 fmcn, fmr;
210 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
211 target_t *target = at91sam7_info->target;
212
213 if (mode && (mode != at91sam7_info->flashmode)) {
214 /* Always round up (ceil) */
215 if (mode==1)
216 /* main clocks in 1uS */
217 fmcn = (at91sam7_info->mck_freq/1000000ul)+1;
218 else if (mode==2)
219 /* main clocks in 1.5uS */
220 fmcn = (at91sam7_info->mck_freq/666666ul)+1;
221
222 /* Only allow fmcn=0 if clock period is > 30 us. */
223 if (at91sam7_info->mck_freq <= 33333)
224 fmcn = 0;
225
226 DEBUG("fmcn: %i", fmcn);
227 fmr = fmcn<<16;
228 target->type->write_memory(target, MC_FSR, 4, 1, (u8 *)&fmr);
229 }
230 at91sam7_info->flashmode = mode;
231 }
232
233 u8 at91sam7_wait_status_busy(flash_bank_t *bank, int timeout)
234 {
235 u32 status;
236
237 while ((!((status = at91sam7_get_flash_status(bank)) & 0x01)) && (timeout-- > 0))
238 {
239 DEBUG("status: 0x%x", status);
240 usleep(1000);
241 }
242
243 DEBUG("status: 0x%x", status);
244
245 if (status&0x0C)
246 {
247 ERROR("status register: 0x%x", status);
248 if (status & 0x4)
249 ERROR("Lock Error Bit Detected, Operation Abort");
250 if (status & 0x8)
251 ERROR("Invalid command and/or bad keyword, Operation Abort");
252 if (status & 0x10)
253 ERROR("Security Bit Set, Operation Abort");
254 }
255
256 return status;
257 }
258
259 /* Send one command to the AT91SAM flash controller */
260 int at91sam7_flash_command(struct flash_bank_s *bank,u8 cmd,u16 pagen)
261 {
262 u32 fcr;
263 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
264 target_t *target = at91sam7_info->target;
265
266 fcr = (0x5A<<24) | (pagen<<8) | cmd;
267 target->type->write_memory(target, MC_FCR, 4, 1, (u8 *)&fcr);
268 DEBUG("Flash command: 0x%x, pagenumber:", fcr, pagen);
269
270 if (at91sam7_wait_status_busy(bank, 10)&0x0C)
271 {
272 return ERROR_FLASH_OPERATION_FAILED;
273 }
274 return ERROR_OK;
275 }
276
277 /* Read device id register, main clock frequency register and fill in driver info structure */
278 int at91sam7_read_part_info(struct flash_bank_s *bank)
279 {
280 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
281 target_t *target = at91sam7_info->target;
282 unsigned long cidr, mcfr, status;
283
284 if (at91sam7_info->target->state != TARGET_HALTED)
285 {
286 return ERROR_TARGET_NOT_HALTED;
287 }
288
289 /* Read and parse chip identification register */
290 target->type->read_memory(target, DBGU_CIDR, 4, 1, (u8 *)&cidr);
291
292 if (cidr == 0)
293 {
294 WARNING("Cannot identify target as an AT91SAM");
295 return ERROR_FLASH_OPERATION_FAILED;
296 }
297
298 at91sam7_info->cidr = cidr;
299 at91sam7_info->cidr_ext = (cidr>>31)&0x0001;
300 at91sam7_info->cidr_nvptyp = (cidr>>28)&0x0007;
301 at91sam7_info->cidr_arch = (cidr>>20)&0x00FF;
302 at91sam7_info->cidr_sramsiz = (cidr>>16)&0x000F;
303 at91sam7_info->cidr_nvpsiz2 = (cidr>>12)&0x000F;
304 at91sam7_info->cidr_nvpsiz = (cidr>>8)&0x000F;
305 at91sam7_info->cidr_eproc = (cidr>>5)&0x0007;
306 at91sam7_info->cidr_version = cidr&0x001F;
307 bank->size = NVPSIZ[at91sam7_info->cidr_nvpsiz];
308 at91sam7_info->target_name = "Unknown";
309
310 DEBUG("nvptyp: 0x%3.3x, arch: 0x%4.4x, alt_id: 0x%4.4x, alt_addr: 0x%4.4x", at91sam7_info->cidr_nvptyp, at91sam7_info->cidr_arch );
311
312 /* Read main and master clock freqency register */
313 at91sam7_read_clock_info(bank);
314
315 status = at91sam7_get_flash_status(bank);
316 at91sam7_info->lockbits = status>>16;
317 at91sam7_info->securitybit = (status>>4)&0x01;
318
319 if (at91sam7_info->cidr_arch == 0x70 )
320 {
321 at91sam7_info->num_nvmbits = 2;
322 at91sam7_info->nvmbits = (status>>8)&0x03;
323 bank->base = 0x100000;
324 bank->bus_width = 4;
325 if (bank->size==0x40000) /* AT91SAM7S256 */
326 {
327 at91sam7_info->target_name = "AT91SAM7S256";
328 at91sam7_info->num_lockbits = 16;
329 at91sam7_info->pagesize = 256;
330 at91sam7_info->pages_in_lockregion = 64;
331 at91sam7_info->num_pages = 16*64;
332 }
333 if (bank->size==0x20000) /* AT91SAM7S128 */
334 {
335 at91sam7_info->target_name = "AT91SAM7S128";
336 at91sam7_info->num_lockbits = 8;
337 at91sam7_info->pagesize = 256;
338 at91sam7_info->pages_in_lockregion = 64;
339 at91sam7_info->num_pages = 8*64;
340 }
341 if (bank->size==0x10000) /* AT91SAM7S64 */
342 {
343 at91sam7_info->target_name = "AT91SAM7S64";
344 at91sam7_info->num_lockbits = 16;
345 at91sam7_info->pagesize = 128;
346 at91sam7_info->pages_in_lockregion = 32;
347 at91sam7_info->num_pages = 16*32;
348 }
349 if (bank->size==0x08000) /* AT91SAM7S321/32 */
350 {
351 at91sam7_info->target_name = "AT91SAM7S321/32";
352 at91sam7_info->num_lockbits = 8;
353 at91sam7_info->pagesize = 128;
354 at91sam7_info->pages_in_lockregion = 32;
355 at91sam7_info->num_pages = 8*32;
356 }
357
358 return ERROR_OK;
359 }
360
361 if (at91sam7_info->cidr_arch == 0x71 )
362 {
363 at91sam7_info->num_nvmbits = 2;
364 at91sam7_info->nvmbits = (status>>8)&0x03;
365 bank->base = 0x100000;
366 bank->bus_width = 4;
367 if (bank->size==0x40000) /* AT91SAM7XC256 */
368 {
369 at91sam7_info->target_name = "AT91SAM7XC256";
370 at91sam7_info->num_lockbits = 16;
371 at91sam7_info->pagesize = 256;
372 at91sam7_info->pages_in_lockregion = 64;
373 at91sam7_info->num_pages = 16*64;
374 }
375 if (bank->size==0x20000) /* AT91SAM7XC128 */
376 {
377 at91sam7_info->target_name = "AT91SAM7XC128";
378 at91sam7_info->num_lockbits = 8;
379 at91sam7_info->pagesize = 256;
380 at91sam7_info->pages_in_lockregion = 64;
381 at91sam7_info->num_pages = 8*64;
382 }
383
384 return ERROR_OK;
385 }
386
387 if (at91sam7_info->cidr_arch == 0x75 )
388 {
389 at91sam7_info->num_nvmbits = 3;
390 at91sam7_info->nvmbits = (status>>8)&0x07;
391 bank->base = 0x100000;
392 bank->bus_width = 4;
393 if (bank->size==0x40000) /* AT91SAM7X256 */
394 {
395 at91sam7_info->target_name = "AT91SAM7X256";
396 at91sam7_info->num_lockbits = 16;
397 at91sam7_info->pagesize = 256;
398 at91sam7_info->pages_in_lockregion = 64;
399 at91sam7_info->num_pages = 16*64;
400 }
401 if (bank->size==0x20000) /* AT91SAM7X128 */
402 {
403 at91sam7_info->target_name = "AT91SAM7X128";
404 at91sam7_info->num_lockbits = 8;
405 at91sam7_info->pagesize = 256;
406 at91sam7_info->pages_in_lockregion = 64;
407 at91sam7_info->num_pages = 8*64;
408 }
409
410 return ERROR_OK;
411 }
412
413 if (at91sam7_info->cidr_arch == 0x60 )
414 {
415 at91sam7_info->num_nvmbits = 3;
416 at91sam7_info->nvmbits = (status>>8)&0x07;
417 bank->base = 0x100000;
418 bank->bus_width = 4;
419
420 if (bank->size == 0x40000) /* AT91SAM7A3 */
421 {
422 at91sam7_info->target_name = "AT91SAM7A3";
423 at91sam7_info->num_lockbits = 16;
424 at91sam7_info->pagesize = 256;
425 at91sam7_info->pages_in_lockregion = 64;
426 at91sam7_info->num_pages = 16*64;
427 }
428 return ERROR_OK;
429 }
430
431 WARNING("at91sam7 flash only tested for AT91SAM7Sxx series");
432
433 return ERROR_OK;
434 }
435
436 int at91sam7_erase_check(struct flash_bank_s *bank)
437 {
438 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
439 target_t *target = at91sam7_info->target;
440 int i;
441
442 if (!at91sam7_info->working_area_size)
443 {
444 }
445 else
446 {
447 }
448
449 return ERROR_OK;
450 }
451
452 int at91sam7_protect_check(struct flash_bank_s *bank)
453 {
454 u32 status;
455
456 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
457 target_t *target = at91sam7_info->target;
458
459 if (at91sam7_info->cidr == 0)
460 {
461 at91sam7_read_part_info(bank);
462 }
463
464 if (at91sam7_info->cidr == 0)
465 {
466 WARNING("Cannot identify target as an AT91SAM");
467 return ERROR_FLASH_OPERATION_FAILED;
468 }
469
470 status = at91sam7_get_flash_status(bank);
471 at91sam7_info->lockbits = status>>16;
472
473 return ERROR_OK;
474 }
475
476 int at91sam7_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
477 {
478 at91sam7_flash_bank_t *at91sam7_info;
479
480 if (argc < 6)
481 {
482 WARNING("incomplete flash_bank at91sam7 configuration");
483 return ERROR_FLASH_BANK_INVALID;
484 }
485
486 at91sam7_info = malloc(sizeof(at91sam7_flash_bank_t));
487 bank->driver_priv = at91sam7_info;
488
489 at91sam7_info->target = get_target_by_num(strtoul(args[5], NULL, 0));
490 if (!at91sam7_info->target)
491 {
492 ERROR("no target '%i' configured", args[5]);
493 exit(-1);
494 }
495
496
497 /* part wasn't probed for info yet */
498 at91sam7_info->cidr = 0;
499
500 return ERROR_OK;
501 }
502
503 int at91sam7_erase(struct flash_bank_s *bank, int first, int last)
504 {
505 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
506
507 if (at91sam7_info->target->state != TARGET_HALTED)
508 {
509 return ERROR_TARGET_NOT_HALTED;
510 }
511
512 if (at91sam7_info->cidr == 0)
513 {
514 at91sam7_read_part_info(bank);
515 }
516
517 if (at91sam7_info->cidr == 0)
518 {
519 WARNING("Cannot identify target as an AT91SAM");
520 return ERROR_FLASH_OPERATION_FAILED;
521 }
522
523 if ((first < 0) || (last < first) || (last >= at91sam7_info->num_lockbits))
524 {
525 return ERROR_FLASH_SECTOR_INVALID;
526 }
527
528 /* Configure the flash controller timing */
529 at91sam7_read_clock_info(bank);
530 at91sam7_set_flash_mode(bank,2);
531
532 if ((first == 0) && (last == (at91sam7_info->num_lockbits-1)))
533 {
534 return at91sam7_flash_command(bank, EA, 0);
535 }
536
537 WARNING("Can only erase the whole flash area, pages are autoerased on write");
538 return ERROR_FLASH_OPERATION_FAILED;
539 }
540
541 int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last)
542 {
543 u32 cmd, pagen, status;
544 int lockregion;
545
546 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
547 target_t *target = at91sam7_info->target;
548
549 if (at91sam7_info->target->state != TARGET_HALTED)
550 {
551 return ERROR_TARGET_NOT_HALTED;
552 }
553
554 if ((first < 0) || (last < first) || (last >= at91sam7_info->num_lockbits))
555 {
556 return ERROR_FLASH_SECTOR_INVALID;
557 }
558
559 if (at91sam7_info->cidr == 0)
560 {
561 at91sam7_read_part_info(bank);
562 }
563
564 if (at91sam7_info->cidr == 0)
565 {
566 WARNING("Cannot identify target as an AT91SAM");
567 return ERROR_FLASH_OPERATION_FAILED;
568 }
569
570 /* Configure the flash controller timing */
571 at91sam7_read_clock_info(bank);
572 at91sam7_set_flash_mode(bank,1);
573
574 for (lockregion=first;lockregion<=last;lockregion++)
575 {
576 pagen = lockregion*at91sam7_info->pages_in_lockregion;
577 if (set)
578 cmd = SLB;
579 else
580 cmd = CLB;
581 if (at91sam7_flash_command(bank, cmd, pagen) != ERROR_OK)
582 {
583 return ERROR_FLASH_OPERATION_FAILED;
584 }
585 }
586
587 status = at91sam7_get_flash_status(bank);
588 at91sam7_info->lockbits = status>>16;
589
590 return ERROR_OK;
591 }
592
593
594 int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
595 {
596 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
597 target_t *target = at91sam7_info->target;
598 u32 dst_min_alignment, wcount, bytes_remaining = count;
599 u32 first_page, last_page, pagen, buffer_pos;
600 u32 fcr;
601
602 if (at91sam7_info->target->state != TARGET_HALTED)
603 {
604 return ERROR_TARGET_NOT_HALTED;
605 }
606
607 if (at91sam7_info->cidr == 0)
608 {
609 at91sam7_read_part_info(bank);
610 }
611
612 if (at91sam7_info->cidr == 0)
613 {
614 WARNING("Cannot identify target as an AT91SAM");
615 return ERROR_FLASH_OPERATION_FAILED;
616 }
617
618 if (offset + count > bank->size)
619 return ERROR_FLASH_DST_OUT_OF_BANK;
620
621 dst_min_alignment = at91sam7_info->pagesize;
622
623 if (offset % dst_min_alignment)
624 {
625 WARNING("offset 0x%x breaks required alignment 0x%x", offset, dst_min_alignment);
626 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
627 }
628
629 if (offset + count > bank->size)
630 return ERROR_FLASH_DST_OUT_OF_BANK;
631
632 if (at91sam7_info->cidr_arch == 0)
633 return ERROR_FLASH_BANK_NOT_PROBED;
634
635 first_page = offset/dst_min_alignment;
636 last_page = CEIL(offset + count, dst_min_alignment);
637
638 DEBUG("first_page: %i, last_page: %i, count %i", first_page, last_page, count);
639
640 /* Configure the flash controller timing */
641 at91sam7_read_clock_info(bank);
642 at91sam7_set_flash_mode(bank,2);
643
644 for (pagen=first_page; pagen<last_page; pagen++) {
645 if (bytes_remaining<dst_min_alignment)
646 count = bytes_remaining;
647 else
648 count = dst_min_alignment;
649 bytes_remaining -= count;
650
651 /* Write one block to the PageWriteBuffer */
652 buffer_pos = (pagen-first_page)*dst_min_alignment;
653 wcount = CEIL(count,4);
654 target->type->write_memory(target, bank->base, 4, wcount, buffer+buffer_pos);
655
656 /* Send Write Page command to Flash Controller */
657 if (at91sam7_flash_command(bank, WP, pagen) != ERROR_OK)
658 {
659 return ERROR_FLASH_OPERATION_FAILED;
660 }
661 DEBUG("Flash command: 0x%x, pagenumber:", fcr, pagen);
662 }
663
664 return ERROR_OK;
665 }
666
667
668 int at91sam7_probe(struct flash_bank_s *bank)
669 {
670 /* we can't probe on an at91sam7
671 * if this is an at91sam7, it has the configured flash
672 */
673 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
674
675 if (at91sam7_info->cidr == 0)
676 {
677 at91sam7_read_part_info(bank);
678 }
679
680 if (at91sam7_info->cidr == 0)
681 {
682 WARNING("Cannot identify target as an AT91SAM");
683 return ERROR_FLASH_OPERATION_FAILED;
684 }
685 return ERROR_OK;
686 }
687
688 int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size)
689 {
690 int printed;
691 at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
692
693 at91sam7_read_part_info(bank);
694
695 if (at91sam7_info->cidr == 0)
696 {
697 printed = snprintf(buf, buf_size, "Cannot identify target as an AT91SAM\n");
698 buf += printed;
699 buf_size -= printed;
700 return ERROR_FLASH_OPERATION_FAILED;
701 }
702
703 printed = snprintf(buf, buf_size, "\nat91sam7 information:\n");
704 buf += printed;
705 buf_size -= printed;
706
707 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);
708 buf += printed;
709 buf_size -= printed;
710
711 printed = snprintf(buf, buf_size, "master clock(estimated): %ikHz \n", at91sam7_info->mck_freq / 1000);
712 buf += printed;
713 buf_size -= printed;
714
715 if (at91sam7_info->num_lockbits>0) {
716 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);
717 buf += printed;
718 buf_size -= printed;
719 }
720
721 printed = snprintf(buf, buf_size, "securitybit: %i, nvmbits: 0x%1.1x\n", at91sam7_info->securitybit, at91sam7_info->nvmbits);
722 buf += printed;
723 buf_size -= printed;
724
725 return ERROR_OK;
726 }
727
728 /*
729 * On AT91SAM7S: When the gpnmv bits are set with
730 * > at91sam7 gpnvm 0 bitnr set
731 * the changes are not visible in the flash controller status register MC_FSR
732 * until the processor has been reset.
733 * On the Olimex board this requires a power cycle.
734 * Note that the AT91SAM7S has the following errata (doc6175.pdf sec 14.1.3):
735 * The maximum number of write/erase cycles for Non Volatile Memory bits is 100. This includes
736 * Lock Bits (LOCKx), General Purpose NVM bits (GPNVMx) and the Security Bit.
737 */
738 int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
739 {
740 flash_bank_t *bank;
741 int bit;
742 u8 flashcmd;
743 u32 status;
744 char *value;
745 at91sam7_flash_bank_t *at91sam7_info;
746
747 if (argc < 3)
748 {
749 command_print(cmd_ctx, "at91sam7 gpnvm <num> <bit> <set|clear>");
750 return ERROR_OK;
751 }
752
753 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
754 bit = atoi(args[1]);
755 value = args[2];
756
757 if (!bank)
758 {
759 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
760 return ERROR_OK;
761 }
762
763 at91sam7_info = bank->driver_priv;
764
765 if (at91sam7_info->target->state != TARGET_HALTED)
766 {
767 return ERROR_TARGET_NOT_HALTED;
768 }
769
770 if (at91sam7_info->cidr == 0)
771 {
772 at91sam7_read_part_info(bank);
773 }
774
775 if (at91sam7_info->cidr == 0)
776 {
777 WARNING("Cannot identify target as an AT91SAM");
778 return ERROR_FLASH_OPERATION_FAILED;
779 }
780
781 if ((bit<0) || (at91sam7_info->num_nvmbits <= bit))
782 {
783 command_print(cmd_ctx, "gpnvm bit '#%s' is out of bounds for target %s", args[1],at91sam7_info->target_name);
784 return ERROR_OK;
785 }
786
787 if (strcmp(value, "set") == 0)
788 {
789 flashcmd = SGPB;
790 }
791 else if (strcmp(value, "clear") == 0)
792 {
793 flashcmd = CGPB;
794 }
795 else
796 {
797 command_print(cmd_ctx, "usage: at91sam7 gpnvm <num> <bit> <set|clear>");
798 return ERROR_OK;
799 }
800
801 /* Configure the flash controller timing */
802 at91sam7_read_clock_info(bank);
803 at91sam7_set_flash_mode(bank,1);
804
805 if (at91sam7_flash_command(bank, flashcmd, (u16)(bit)) != ERROR_OK)
806 {
807 return ERROR_FLASH_OPERATION_FAILED;
808 }
809
810 status = at91sam7_get_flash_status(bank);
811 DEBUG("at91sam7_handle_gpnvm_command: cmd 0x%x, value 0x%x, status 0x%x \n",flashcmd,bit,status);
812 at91sam7_info->nvmbits = (status>>8)&((1<<at91sam7_info->num_nvmbits)-1);
813
814 return ERROR_OK;
815 }

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)