1 /***************************************************************************
2 * Copyright (C) 2006 by Magnus Lundin *
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. *
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. *
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 ***************************************************************************/
21 /***************************************************************************
22 There are some things to notice
24 * AT91SAM7S64 is tested
25 * All AT91SAM7Sxx and AT91SAM7Xxx should work but is not tested
26 * All parameters are identified from onchip configuartion registers
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
33 * Lock regions (sectors) are 32 or 64 pages
35 ***************************************************************************/
42 #include "binarybuffer.h"
49 int at91sam7_register_commands(struct command_context_s
*cmd_ctx
);
50 int at91sam7_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
);
51 int at91sam7_erase(struct flash_bank_s
*bank
, int first
, int last
);
52 int at91sam7_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
);
53 int at91sam7_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
);
54 int at91sam7_probe(struct flash_bank_s
*bank
);
55 int at91sam7_erase_check(struct flash_bank_s
*bank
);
56 int at91sam7_protect_check(struct flash_bank_s
*bank
);
57 int at91sam7_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
);
59 u32
at91sam7_get_flash_status(flash_bank_t
*bank
);
60 void at91sam7_set_flash_mode(flash_bank_t
*bank
,int mode
);
61 u8
at91sam7_wait_status_busy(flash_bank_t
*bank
, int timeout
);
62 int at91sam7_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
64 flash_driver_t at91sam7_flash
=
67 .register_commands
= at91sam7_register_commands
,
68 .flash_bank_command
= at91sam7_flash_bank_command
,
69 .erase
= at91sam7_erase
,
70 .protect
= at91sam7_protect
,
71 .write
= at91sam7_write
,
72 .probe
= at91sam7_probe
,
73 .erase_check
= at91sam7_erase_check
,
74 .protect_check
= at91sam7_protect_check
,
79 char * EPROC
[8]= {"Unknown","ARM946-E","ARM7TDMI","Unknown","ARM920T","ARM926EJ-S","Unknown","Unknown"};
118 u32
at91sam7_get_flash_status(flash_bank_t
*bank
)
120 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
121 target_t
*target
= at91sam7_info
->target
;
124 target
->type
->read_memory(target
, MC_FSR
, 4, 1, (u8
*)&fsr
);
129 /* Setup the timimg registers for nvbits or normal flash */
130 void at91sam7_set_flash_mode(flash_bank_t
*bank
,int mode
)
133 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
134 target_t
*target
= at91sam7_info
->target
;
136 if (mode
!= at91sam7_info
->flashmode
) {
137 /* mainf contains the number of main clocks in approx 500uS */
139 /* main clocks in 1uS */
140 fmcn
= (at91sam7_info
->mainf
>>9)+1;
142 /* main clocks in 1.5uS */
143 fmcn
= (at91sam7_info
->mainf
>>9)+(at91sam7_info
->mainf
>>10)+1;
144 DEBUG("fmcn: %i", fmcn
);
146 target
->type
->write_memory(target
, MC_FSR
, 4, 1, (u8
*)&fmr
);
147 at91sam7_info
->flashmode
= mode
;
151 u8
at91sam7_wait_status_busy(flash_bank_t
*bank
, int timeout
)
155 while ((!((status
= at91sam7_get_flash_status(bank
)) & 0x01)) && (timeout
-- > 0))
157 DEBUG("status: 0x%x", status
);
161 DEBUG("status: 0x%x", status
);
165 ERROR("status register: 0x%x", status
);
167 ERROR("Lock Error Bit Detected, Operation Abort");
169 ERROR("Invalid command and/or bad keyword, Operation Abort");
171 ERROR("Security Bit Set, Operation Abort");
177 int at91sam7_flash_command(struct flash_bank_s
*bank
,u8 cmd
,u16 pagen
)
180 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
181 target_t
*target
= at91sam7_info
->target
;
183 fcr
= (0x5A<<24) | (pagen
<<8) | cmd
;
184 target
->type
->write_memory(target
, MC_FCR
, 4, 1, (u8
*)&fcr
);
185 DEBUG("Flash command: 0x%x, pagenumber:", fcr
, pagen
);
187 if (at91sam7_wait_status_busy(bank
, 10)&0x0C)
189 return ERROR_FLASH_OPERATION_FAILED
;
194 /* Read device id register, main clock frequency register and fill in driver info structure */
195 int at91sam7_read_part_info(struct flash_bank_s
*bank
)
197 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
198 target_t
*target
= at91sam7_info
->target
;
199 unsigned long cidr
, mcfr
, status
;
201 if (at91sam7_info
->target
->state
!= TARGET_HALTED
)
203 return ERROR_TARGET_NOT_HALTED
;
206 /* Read and parse chip identification register */
207 target
->type
->read_memory(target
, DBGU_CIDR
, 4, 1, (u8
*)&cidr
);
211 WARNING("Cannot identify target as an AT91SAM");
212 return ERROR_FLASH_OPERATION_FAILED
;
215 at91sam7_info
->cidr
= cidr
;
216 at91sam7_info
->cidr_ext
= (cidr
>>31)&0x0001;
217 at91sam7_info
->cidr_nvptyp
= (cidr
>>28)&0x0007;
218 at91sam7_info
->cidr_arch
= (cidr
>>20)&0x00FF;
219 at91sam7_info
->cidr_sramsiz
= (cidr
>>16)&0x000F;
220 at91sam7_info
->cidr_nvpsiz2
= (cidr
>>12)&0x000F;
221 at91sam7_info
->cidr_nvpsiz
= (cidr
>>8)&0x000F;
222 at91sam7_info
->cidr_eproc
= (cidr
>>5)&0x0007;
223 at91sam7_info
->cidr_version
= cidr
&0x001F;
224 bank
->size
= NVPSIZ
[at91sam7_info
->cidr_nvpsiz
];
226 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
);
228 /* Read main clock freqency register */
229 target
->type
->read_memory(target
, CKGR_MCFR
, 4, 1, (u8
*)&mcfr
);
232 at91sam7_info
->mainrdy
= 1;
233 at91sam7_info
->mainf
= mcfr
&0xFFFF;
234 at91sam7_info
->usec_clocks
= mcfr
>>9;
238 at91sam7_info
->mainrdy
= 0;
239 at91sam7_info
->mainf
= 0;
240 at91sam7_info
->usec_clocks
= 0;
243 status
= at91sam7_get_flash_status(bank
);
244 at91sam7_info
->lockbits
= status
>>16;
245 at91sam7_info
->securitybit
= (status
>>4)&0x01;
247 if (at91sam7_info
->cidr_arch
== 0x70 )
249 at91sam7_info
->num_nvmbits
= 2;
250 at91sam7_info
->nvmbits
= (status
>>8)&0x03;
251 bank
->base
= 0x100000;
253 if (bank
->size
==0x40000) /* AT91SAM7S256 */
255 at91sam7_info
->num_lockbits
= 16;
256 at91sam7_info
->pagesize
= 256;
257 at91sam7_info
->pages_in_lockregion
= 64;
258 at91sam7_info
->num_pages
= 16*64;
260 if (bank
->size
==0x20000) /* AT91SAM7S128 */
262 at91sam7_info
->num_lockbits
= 8;
263 at91sam7_info
->pagesize
= 256;
264 at91sam7_info
->pages_in_lockregion
= 64;
265 at91sam7_info
->num_pages
= 8*64;
267 if (bank
->size
==0x10000) /* AT91SAM7S64 */
269 at91sam7_info
->num_lockbits
= 16;
270 at91sam7_info
->pagesize
= 128;
271 at91sam7_info
->pages_in_lockregion
= 32;
272 at91sam7_info
->num_pages
= 16*32;
274 if (bank
->size
==0x08000) /* AT91SAM7S321/32 */
276 at91sam7_info
->num_lockbits
= 8;
277 at91sam7_info
->pagesize
= 128;
278 at91sam7_info
->pages_in_lockregion
= 32;
279 at91sam7_info
->num_pages
= 8*32;
285 if (at91sam7_info
->cidr_arch
== 0x71 )
287 at91sam7_info
->num_nvmbits
= 2;
288 at91sam7_info
->nvmbits
= (status
>>8)&0x03;
289 bank
->base
= 0x100000;
291 if (bank
->size
==0x40000) /* AT91SAM7XC256 */
293 at91sam7_info
->num_lockbits
= 16;
294 at91sam7_info
->pagesize
= 256;
295 at91sam7_info
->pages_in_lockregion
= 64;
296 at91sam7_info
->num_pages
= 16*64;
298 if (bank
->size
==0x20000) /* AT91SAM7XC128 */
300 at91sam7_info
->num_lockbits
= 8;
301 at91sam7_info
->pagesize
= 256;
302 at91sam7_info
->pages_in_lockregion
= 64;
303 at91sam7_info
->num_pages
= 8*64;
309 if (at91sam7_info
->cidr_arch
== 0x75 )
311 at91sam7_info
->num_nvmbits
= 3;
312 at91sam7_info
->nvmbits
= (status
>>8)&0x07;
313 bank
->base
= 0x100000;
315 if (bank
->size
==0x40000) /* AT91SAM7X256 */
317 at91sam7_info
->num_lockbits
= 16;
318 at91sam7_info
->pagesize
= 256;
319 at91sam7_info
->pages_in_lockregion
= 64;
320 at91sam7_info
->num_pages
= 16*64;
322 if (bank
->size
==0x20000) /* AT91SAM7X128 */
324 at91sam7_info
->num_lockbits
= 8;
325 at91sam7_info
->pagesize
= 256;
326 at91sam7_info
->pages_in_lockregion
= 64;
327 at91sam7_info
->num_pages
= 8*64;
333 if (at91sam7_info
->cidr_arch
== 0x60 )
335 at91sam7_info
->num_nvmbits
= 3;
336 at91sam7_info
->nvmbits
= (status
>>8)&0x07;
337 bank
->base
= 0x100000;
340 if (bank
->size
== 0x40000) /* AT91SAM7A3 */
342 at91sam7_info
->num_lockbits
= 16;
343 at91sam7_info
->pagesize
= 256;
344 at91sam7_info
->pages_in_lockregion
= 64;
345 at91sam7_info
->num_pages
= 16*64;
350 WARNING("at91sam7 flash only tested for AT91SAM7Sxx series");
355 int at91sam7_erase_check(struct flash_bank_s
*bank
)
357 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
358 target_t
*target
= at91sam7_info
->target
;
361 if (!at91sam7_info
->working_area_size
)
371 int at91sam7_protect_check(struct flash_bank_s
*bank
)
375 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
376 target_t
*target
= at91sam7_info
->target
;
378 if (at91sam7_info
->cidr
== 0)
380 at91sam7_read_part_info(bank
);
383 if (at91sam7_info
->cidr
== 0)
385 WARNING("Cannot identify target as an AT91SAM");
386 return ERROR_FLASH_OPERATION_FAILED
;
389 status
= at91sam7_get_flash_status(bank
);
390 at91sam7_info
->lockbits
= status
>>16;
396 int at91sam7_register_commands(struct command_context_s
*cmd_ctx
)
398 command_t
*at91sam7_cmd
= register_command(cmd_ctx
, NULL
, "at91sam7", NULL
, COMMAND_ANY
, "at91sam7 specific commands");
403 int at91sam7_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
)
405 at91sam7_flash_bank_t
*at91sam7_info
;
409 WARNING("incomplete flash_bank at91sam7 configuration");
410 return ERROR_FLASH_BANK_INVALID
;
413 at91sam7_info
= malloc(sizeof(at91sam7_flash_bank_t
));
414 bank
->driver_priv
= at91sam7_info
;
416 at91sam7_info
->target
= get_target_by_num(strtoul(args
[5], NULL
, 0));
417 if (!at91sam7_info
->target
)
419 ERROR("no target '%i' configured", args
[5]);
424 /* part wasn't probed for info yet */
425 at91sam7_info
->cidr
= 0;
430 int at91sam7_erase(struct flash_bank_s
*bank
, int first
, int last
)
432 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
434 if (at91sam7_info
->target
->state
!= TARGET_HALTED
)
436 return ERROR_TARGET_NOT_HALTED
;
439 if (at91sam7_info
->cidr
== 0)
441 at91sam7_read_part_info(bank
);
444 if (at91sam7_info
->cidr
== 0)
446 WARNING("Cannot identify target as an AT91SAM");
447 return ERROR_FLASH_OPERATION_FAILED
;
450 if ((first
< 0) || (last
< first
) || (last
>= at91sam7_info
->num_lockbits
))
452 return ERROR_FLASH_SECTOR_INVALID
;
455 if ((first
== 0) && (last
== (at91sam7_info
->num_lockbits
-1)))
457 return at91sam7_flash_command(bank
, EA
, 0);
460 WARNING("Can only erase the whole flash area, pages are autoerased on write");
461 return ERROR_FLASH_OPERATION_FAILED
;
464 int at91sam7_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
466 u32 cmd
, pagen
, status
;
469 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
470 target_t
*target
= at91sam7_info
->target
;
472 if (at91sam7_info
->target
->state
!= TARGET_HALTED
)
474 return ERROR_TARGET_NOT_HALTED
;
477 if ((first
< 0) || (last
< first
) || (last
>= at91sam7_info
->num_lockbits
))
479 return ERROR_FLASH_SECTOR_INVALID
;
482 if (at91sam7_info
->cidr
== 0)
484 at91sam7_read_part_info(bank
);
487 if (at91sam7_info
->cidr
== 0)
489 WARNING("Cannot identify target as an AT91SAM");
490 return ERROR_FLASH_OPERATION_FAILED
;
493 /* Configure the flash controller timing */
494 at91sam7_set_flash_mode(bank
,1);
496 for (lockregion
=first
;lockregion
<=last
;lockregion
++)
498 pagen
= lockregion
*at91sam7_info
->pages_in_lockregion
;
503 if (at91sam7_flash_command(bank
, cmd
, pagen
) != ERROR_OK
)
505 return ERROR_FLASH_OPERATION_FAILED
;
509 status
= at91sam7_get_flash_status(bank
);
510 at91sam7_info
->lockbits
= status
>>16;
516 int at91sam7_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
518 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
519 target_t
*target
= at91sam7_info
->target
;
520 u32 dst_min_alignment
, wcount
, bytes_remaining
= count
;
521 u32 first_page
, last_page
, pagen
, buffer_pos
;
524 if (at91sam7_info
->target
->state
!= TARGET_HALTED
)
526 return ERROR_TARGET_NOT_HALTED
;
529 if (at91sam7_info
->cidr
== 0)
531 at91sam7_read_part_info(bank
);
534 if (at91sam7_info
->cidr
== 0)
536 WARNING("Cannot identify target as an AT91SAM");
537 return ERROR_FLASH_OPERATION_FAILED
;
540 if (offset
+ count
> bank
->size
)
541 return ERROR_FLASH_DST_OUT_OF_BANK
;
543 dst_min_alignment
= at91sam7_info
->pagesize
;
545 if (offset
% dst_min_alignment
)
547 WARNING("offset 0x%x breaks required alignment 0x%x", offset
, dst_min_alignment
);
548 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
551 if (offset
+ count
> bank
->size
)
552 return ERROR_FLASH_DST_OUT_OF_BANK
;
554 if (at91sam7_info
->cidr_arch
== 0)
555 return ERROR_FLASH_BANK_NOT_PROBED
;
557 first_page
= offset
/dst_min_alignment
;
558 last_page
= CEIL(offset
+ count
, dst_min_alignment
);
560 DEBUG("first_page: %i, last_page: %i, count %i", first_page
, last_page
, count
);
562 /* Configure the flash controller timing */
563 at91sam7_set_flash_mode(bank
,2);
565 for (pagen
=first_page
; pagen
<last_page
; pagen
++) {
566 if (bytes_remaining
<dst_min_alignment
)
567 count
= bytes_remaining
;
569 count
= dst_min_alignment
;
570 bytes_remaining
-= count
;
572 /* Write one block to the PageWriteBuffer */
573 buffer_pos
= (pagen
-first_page
)*dst_min_alignment
;
574 wcount
= CEIL(count
,4);
575 target
->type
->write_memory(target
, bank
->base
, 4, wcount
, buffer
+buffer_pos
);
577 /* Send Write Page command to Flash Controller */
578 if (at91sam7_flash_command(bank
, WP
, pagen
) != ERROR_OK
)
580 return ERROR_FLASH_OPERATION_FAILED
;
582 DEBUG("Flash command: 0x%x, pagenumber:", fcr
, pagen
);
589 int at91sam7_probe(struct flash_bank_s
*bank
)
591 /* we can't probe on an at91sam7
592 * if this is an at91sam7, it has the configured flash
594 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
596 if (at91sam7_info
->cidr
== 0)
598 at91sam7_read_part_info(bank
);
601 if (at91sam7_info
->cidr
== 0)
603 WARNING("Cannot identify target as an AT91SAM");
604 return ERROR_FLASH_OPERATION_FAILED
;
609 int at91sam7_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
612 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
614 if (at91sam7_info
->cidr
== 0)
616 at91sam7_read_part_info(bank
);
619 if (at91sam7_info
->cidr
== 0)
621 printed
= snprintf(buf
, buf_size
, "Cannot identify target as an AT91SAM\n");
624 return ERROR_FLASH_OPERATION_FAILED
;
627 printed
= snprintf(buf
, buf_size
, "\nat91sam7 information:\n");
631 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
);
635 printed
= snprintf(buf
, buf_size
, "main clock(estimated): %ikHz \n", at91sam7_info
->mainf
*2);
639 if (at91sam7_info
->num_lockbits
>0) {
640 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
);
645 printed
= snprintf(buf
, buf_size
, "securitybit: %i, nvmbits: 0x%1.1x\n", at91sam7_info
->securitybit
, at91sam7_info
->nvmbits
);
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)