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

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)