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 ) {
248 at91sam7_info
->num_nvmbits
= 2;
249 at91sam7_info
->nvmbits
= (status
>>8)&0x03;
250 bank
->base
= 0x100000;
252 if (bank
->size
==0x40000) /* AT91SAM7S256 */
254 at91sam7_info
->num_lockbits
= 16;
255 at91sam7_info
->pagesize
= 256;
256 at91sam7_info
->pages_in_lockregion
= 64;
257 at91sam7_info
->num_pages
= 16*64;
259 if (bank
->size
==0x20000) /* AT91SAM7S128 */
261 at91sam7_info
->num_lockbits
= 8;
262 at91sam7_info
->pagesize
= 256;
263 at91sam7_info
->pages_in_lockregion
= 64;
264 at91sam7_info
->num_pages
= 8*64;
266 if (bank
->size
==0x10000) /* AT91SAM7S64 */
268 at91sam7_info
->num_lockbits
= 16;
269 at91sam7_info
->pagesize
= 128;
270 at91sam7_info
->pages_in_lockregion
= 32;
271 at91sam7_info
->num_pages
= 16*32;
273 if (bank
->size
==0x08000) /* AT91SAM7S321/32 */
275 at91sam7_info
->num_lockbits
= 8;
276 at91sam7_info
->pagesize
= 128;
277 at91sam7_info
->pages_in_lockregion
= 32;
278 at91sam7_info
->num_pages
= 8*32;
284 if (at91sam7_info
->cidr_arch
== 0x71 ) {
285 at91sam7_info
->num_nvmbits
= 2;
286 at91sam7_info
->nvmbits
= (status
>>8)&0x03;
287 bank
->base
= 0x100000;
289 if (bank
->size
==0x40000) /* AT91SAM7XC256 */
291 at91sam7_info
->num_lockbits
= 16;
292 at91sam7_info
->pagesize
= 256;
293 at91sam7_info
->pages_in_lockregion
= 64;
294 at91sam7_info
->num_pages
= 16*64;
296 if (bank
->size
==0x20000) /* AT91SAM7XC128 */
298 at91sam7_info
->num_lockbits
= 8;
299 at91sam7_info
->pagesize
= 256;
300 at91sam7_info
->pages_in_lockregion
= 64;
301 at91sam7_info
->num_pages
= 8*64;
307 if (at91sam7_info
->cidr_arch
== 0x75 ) {
308 at91sam7_info
->num_nvmbits
= 3;
309 at91sam7_info
->nvmbits
= (status
>>8)&0x07;
310 bank
->base
= 0x100000;
312 if (bank
->size
==0x40000) /* AT91SAM7X256 */
314 at91sam7_info
->num_lockbits
= 16;
315 at91sam7_info
->pagesize
= 256;
316 at91sam7_info
->pages_in_lockregion
= 64;
317 at91sam7_info
->num_pages
= 16*64;
319 if (bank
->size
==0x20000) /* AT91SAM7X128 */
321 at91sam7_info
->num_lockbits
= 8;
322 at91sam7_info
->pagesize
= 256;
323 at91sam7_info
->pages_in_lockregion
= 64;
324 at91sam7_info
->num_pages
= 8*64;
330 if (at91sam7_info
->cidr_arch
!= 0x70 )
332 WARNING("at91sam7 flash only tested for AT91SAM7Sxx series");
337 int at91sam7_erase_check(struct flash_bank_s
*bank
)
339 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
340 target_t
*target
= at91sam7_info
->target
;
343 if (!at91sam7_info
->working_area_size
)
353 int at91sam7_protect_check(struct flash_bank_s
*bank
)
357 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
358 target_t
*target
= at91sam7_info
->target
;
360 if (at91sam7_info
->cidr
== 0)
362 at91sam7_read_part_info(bank
);
365 if (at91sam7_info
->cidr
== 0)
367 WARNING("Cannot identify target as an AT91SAM");
368 return ERROR_FLASH_OPERATION_FAILED
;
371 status
= at91sam7_get_flash_status(bank
);
372 at91sam7_info
->lockbits
= status
>>16;
378 int at91sam7_register_commands(struct command_context_s
*cmd_ctx
)
380 command_t
*at91sam7_cmd
= register_command(cmd_ctx
, NULL
, "cfi", NULL
, COMMAND_ANY
, NULL
);
385 int at91sam7_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
)
387 at91sam7_flash_bank_t
*at91sam7_info
;
391 WARNING("incomplete flash_bank at91sam7 configuration");
392 return ERROR_FLASH_BANK_INVALID
;
395 at91sam7_info
= malloc(sizeof(at91sam7_flash_bank_t
));
396 bank
->driver_priv
= at91sam7_info
;
398 at91sam7_info
->target
= get_target_by_num(strtoul(args
[5], NULL
, 0));
399 if (!at91sam7_info
->target
)
401 ERROR("no target '%i' configured", args
[5]);
406 /* part wasn't probed for info yet */
407 at91sam7_info
->cidr
= 0;
412 int at91sam7_erase(struct flash_bank_s
*bank
, int first
, int last
)
414 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
416 if (at91sam7_info
->target
->state
!= TARGET_HALTED
)
418 return ERROR_TARGET_NOT_HALTED
;
421 if (at91sam7_info
->cidr
== 0)
423 at91sam7_read_part_info(bank
);
426 if (at91sam7_info
->cidr
== 0)
428 WARNING("Cannot identify target as an AT91SAM");
429 return ERROR_FLASH_OPERATION_FAILED
;
432 if ((first
< 0) || (last
< first
) || (last
>= at91sam7_info
->num_lockbits
))
434 return ERROR_FLASH_SECTOR_INVALID
;
437 if ((first
== 0) && (last
== (at91sam7_info
->num_lockbits
-1)))
439 return at91sam7_flash_command(bank
, EA
, 0);
442 WARNING("Can only erase the whole flash area, pages are autoerased on write");
443 return ERROR_FLASH_OPERATION_FAILED
;
446 int at91sam7_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
448 u32 cmd
, pagen
, status
;
451 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
452 target_t
*target
= at91sam7_info
->target
;
454 if (at91sam7_info
->target
->state
!= TARGET_HALTED
)
456 return ERROR_TARGET_NOT_HALTED
;
459 if ((first
< 0) || (last
< first
) || (last
>= at91sam7_info
->num_lockbits
))
461 return ERROR_FLASH_SECTOR_INVALID
;
464 if (at91sam7_info
->cidr
== 0)
466 at91sam7_read_part_info(bank
);
469 if (at91sam7_info
->cidr
== 0)
471 WARNING("Cannot identify target as an AT91SAM");
472 return ERROR_FLASH_OPERATION_FAILED
;
475 /* Configure the flash controller timing */
476 at91sam7_set_flash_mode(bank
,1);
478 for (lockregion
=first
;lockregion
<=last
;lockregion
++)
480 pagen
= lockregion
*at91sam7_info
->pages_in_lockregion
;
485 if (at91sam7_flash_command(bank
, cmd
, pagen
) != ERROR_OK
)
487 return ERROR_FLASH_OPERATION_FAILED
;
491 status
= at91sam7_get_flash_status(bank
);
492 at91sam7_info
->lockbits
= status
>>16;
498 int at91sam7_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
500 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
501 target_t
*target
= at91sam7_info
->target
;
502 u32 dst_min_alignment
, wcount
, bytes_remaining
= count
;
503 u32 first_page
, last_page
, pagen
, buffer_pos
;
506 if (at91sam7_info
->target
->state
!= TARGET_HALTED
)
508 return ERROR_TARGET_NOT_HALTED
;
511 if (at91sam7_info
->cidr
== 0)
513 at91sam7_read_part_info(bank
);
516 if (at91sam7_info
->cidr
== 0)
518 WARNING("Cannot identify target as an AT91SAM");
519 return ERROR_FLASH_OPERATION_FAILED
;
522 if (offset
+ count
> bank
->size
)
523 return ERROR_FLASH_DST_OUT_OF_BANK
;
525 dst_min_alignment
= at91sam7_info
->pagesize
;
527 if (offset
% dst_min_alignment
)
529 WARNING("offset 0x%x breaks required alignment 0x%x", offset
, dst_min_alignment
);
530 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
533 if (offset
+ count
> bank
->size
)
534 return ERROR_FLASH_DST_OUT_OF_BANK
;
536 if (at91sam7_info
->cidr_arch
== 0)
537 return ERROR_FLASH_BANK_NOT_PROBED
;
539 first_page
= offset
/dst_min_alignment
;
540 last_page
= CEIL(offset
+ count
, dst_min_alignment
);
542 DEBUG("first_page: %i, last_page: %i, count %i", first_page
, last_page
, count
);
544 /* Configure the flash controller timing */
545 at91sam7_set_flash_mode(bank
,2);
547 for (pagen
=first_page
; pagen
<last_page
; pagen
++) {
548 if (bytes_remaining
<dst_min_alignment
)
549 count
= bytes_remaining
;
551 count
= dst_min_alignment
;
552 bytes_remaining
-= count
;
554 /* Write one block to the PageWriteBuffer */
555 buffer_pos
= (pagen
-first_page
)*dst_min_alignment
;
556 wcount
= CEIL(count
,4);
557 target
->type
->write_memory(target
, bank
->base
, 4, wcount
, buffer
+buffer_pos
);
559 /* Send Write Page command to Flash Controller */
560 if (at91sam7_flash_command(bank
, WP
, pagen
) != ERROR_OK
)
562 return ERROR_FLASH_OPERATION_FAILED
;
564 DEBUG("Flash command: 0x%x, pagenumber:", fcr
, pagen
);
571 int at91sam7_probe(struct flash_bank_s
*bank
)
573 /* we can't probe on an at91sam7
574 * if this is an at91sam7, it has the configured flash
576 at91sam7_flash_bank_t
*at91sam7_info
= bank
->driver_priv
;
578 if (at91sam7_info
->cidr
== 0)
580 at91sam7_read_part_info(bank
);
583 if (at91sam7_info
->cidr
== 0)
585 WARNING("Cannot identify target as an AT91SAM");
586 return ERROR_FLASH_OPERATION_FAILED
;
591 int at91sam7_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
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 printed
= snprintf(buf
, buf_size
, "Cannot identify target as an AT91SAM\n");
606 return ERROR_FLASH_OPERATION_FAILED
;
609 printed
= snprintf(buf
, buf_size
, "\nat91sam7 information:\n");
613 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
);
617 printed
= snprintf(buf
, buf_size
, "main clock(estimated): %ikHz \n", at91sam7_info
->mainf
*2);
621 if (at91sam7_info
->num_lockbits
>0) {
622 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
);
627 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)