1 /***************************************************************************
2 * Copyright (C) 2013 by Andrey Yurovsky *
3 * Andrey Yurovsky <yurovsky@gmail.com> *
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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
19 ***************************************************************************/
27 /* At this time, the SAM4L Flash is available in these capacities:
28 * ATSAM4Lx4xx: 256KB (512 pages)
29 * ATSAM4Lx2xx: 128KB (256 pages)
30 * ATSAM4Lx8xx: 512KB (1024 pages)
33 /* There are 16 lockable regions regardless of overall capacity. The number
34 * of pages per sector is therefore dependant on capacity. */
35 #define SAM4L_NUM_SECTORS 16
37 /* Locations in memory map */
38 #define SAM4L_FLASH ((uint32_t)0x00000000) /* Flash region */
39 #define SAM4L_FLASH_USER 0x00800000 /* Flash user page region */
40 #define SAM4L_FLASHCALW 0x400A0000 /* Flash controller */
41 #define SAM4L_CHIPID 0x400E0740 /* Chip Identification */
43 /* Offsets from SAM4L_FLASHCALW */
44 #define SAM4L_FCR 0x00 /* Flash Control Register (RW) */
45 #define SAM4L_FCMD 0x04 /* Flash Command Register (RW) */
46 #define SAM4L_FSR 0x08 /* Flash Status Register (RO) */
47 #define SAM4L_FPR 0x0C /* Flash Parameter Register (RO) */
48 #define SAM4L_FVR 0x10 /* Flash Version Register (RO) */
49 #define SAM4L_FGPFRHI 0x14 /* Flash General Purpose Register High (RO) */
50 #define SAM4L_FGPFRLO 0x18 /* Flash General Purpose Register Low (RO) */
52 /* Offsets from SAM4L_CHIPID */
53 #define SAM4L_CIDR 0x00 /* Chip ID Register (RO) */
54 #define SAM4L_EXID 0x04 /* Chip ID Extension Register (RO) */
56 /* Flash commands (for SAM4L_FCMD), see Table 14-5 */
57 #define SAM4L_FCMD_NOP 0 /* No Operation */
58 #define SAM4L_FCMD_WP 1 /* Write Page */
59 #define SAM4L_FCMD_EP 2 /* Erase Page */
60 #define SAM4L_FCMD_CPB 3 /* Clear Page Buffer */
61 #define SAM4L_FCMD_LP 4 /* Lock region containing given page */
62 #define SAM4L_FCMD_UP 5 /* Unlock region containing given page */
63 #define SAM4L_FCMD_EA 6 /* Erase All */
64 #define SAM4L_FCMD_WGPB 7 /* Write general-purpose fuse bit */
65 #define SAM4L_FCMD_EGPB 8 /* Erase general-purpose fuse bit */
66 #define SAM4L_FCMD_SSB 9 /* Set security fuses */
67 #define SAM4L_FCMD_PGPFB 10 /* Program general-purpose fuse byte */
68 #define SAM4L_FCMD_EAGPF 11 /* Erase all general-purpose fuse bits */
69 #define SAM4L_FCMD_QPR 12 /* Quick page read */
70 #define SAM4L_FCMD_WUP 13 /* Write user page */
71 #define SAM4L_FCMD_EUP 14 /* Erase user page */
72 #define SAM4L_FCMD_QPRUP 15 /* Quick page read (user page) */
73 #define SAM4L_FCMD_HSEN 16 /* High speed mode enable */
74 #define SAM4L_FCMD_HSDIS 17 /* High speed mode disable */
76 #define SAM4L_FMCD_CMDKEY 0xA5UL /* 'key' to issue commands, see 14.10.2 */
78 struct sam4l_chip_info
{
84 /* These are taken from Table 9-1 in 42023E-SAM-07/2013 */
85 static const struct sam4l_chip_info sam4l_known_chips
[] = {
86 { 0xAB0B0AE0, 0x1400000F, "ATSAM4LC8C" },
87 { 0xAB0A09E0, 0x0400000F, "ATSAM4LC4C" },
88 { 0xAB0A07E0, 0x0400000F, "ATSAM4LC2C" },
89 { 0xAB0B0AE0, 0x1300000F, "ATSAM4LC8B" },
90 { 0xAB0A09E0, 0x0300000F, "ATSAM4LC4B" },
91 { 0xAB0A07E0, 0x0300000F, "ATSAM4LC2B" },
92 { 0xAB0B0AE0, 0x1200000F, "ATSAM4LC8A" },
93 { 0xAB0A09E0, 0x0200000F, "ATSAM4LC4A" },
94 { 0xAB0A07E0, 0x0200000F, "ATSAM4LC2A" },
95 { 0xAB0B0AE0, 0x14000002, "ATSAM4LS8C" },
96 { 0xAB0A09E0, 0x04000002, "ATSAM4LS4C" },
97 { 0xAB0A07E0, 0x04000002, "ATSAM4LS2C" },
98 { 0xAB0B0AE0, 0x13000002, "ATSAM4LS8B" },
99 { 0xAB0A09E0, 0x03000002, "ATSAM4LS4B" },
100 { 0xAB0A07E0, 0x03000002, "ATSAM4LS2B" },
101 { 0xAB0B0AE0, 0x12000002, "ATSAM4LS8A" },
102 { 0xAB0A09E0, 0x02000002, "ATSAM4LS4A" },
103 { 0xAB0A07E0, 0x02000002, "ATSAM4LS2A" },
106 /* Meaning of SRAMSIZ field in CHIPID, see 9.3.1 in 42023E-SAM-07/2013 */
107 static const uint16_t sam4l_ram_sizes
[16] = { 48, 1, 2, 6, 24, 4, 80, 160, 8, 16, 32, 64, 128, 256, 96, 512 };
109 /* Meaning of PSZ field in FPR, see 14.10.4 in 42023E-SAM-07/2013 */
110 static const uint16_t sam4l_page_sizes
[8] = { 32, 64, 128, 256, 512, 1024, 2048, 4096 };
113 const struct sam4l_chip_info
*details
;
120 int pages_per_sector
;
123 struct target
*target
;
124 struct sam4l_info
*next
;
127 static struct sam4l_info
*sam4l_chips
;
129 static int sam4l_flash_wait_until_ready(struct target
*target
)
131 volatile unsigned int t
= 0;
135 /* Poll the status register until the FRDY bit is set */
137 res
= target_read_u32(target
, SAM4L_FLASHCALW
+ SAM4L_FSR
, &st
);
138 } while (res
== ERROR_OK
&& !(st
& (1<<0)) && ++t
< 10);
143 static int sam4l_flash_check_error(struct target
*target
, uint32_t *err
)
148 res
= target_read_u32(target
, SAM4L_FLASHCALW
+ SAM4L_FSR
, &st
);
151 *err
= st
& ((1<<3) | (1<<2)); /* grab PROGE and LOCKE bits */
156 static int sam4l_flash_command(struct target
*target
, uint8_t cmd
, int page
)
162 res
= sam4l_flash_wait_until_ready(target
);
167 /* Set the page number. For some commands, the page number is just an
168 * argument (ex: fuse bit number). */
169 fcmd
= (SAM4L_FMCD_CMDKEY
<< 24) | ((page
& 0xFFFF) << 8) | (cmd
& 0x3F);
171 /* Reuse the page number that was read from the flash command register. */
172 res
= target_read_u32(target
, SAM4L_FLASHCALW
+ SAM4L_FCMD
, &fcmd
);
176 fcmd
&= ~0x3F; /* clear out the command code */
177 fcmd
|= (SAM4L_FMCD_CMDKEY
<< 24) | (cmd
& 0x3F);
180 /* Send the command */
181 res
= target_write_u32(target
, SAM4L_FLASHCALW
+ SAM4L_FCMD
, fcmd
);
185 res
= sam4l_flash_check_error(target
, &err
);
190 LOG_ERROR("%s got error status 0x%08" PRIx32
, __func__
, err
);
192 res
= sam4l_flash_wait_until_ready(target
);
197 FLASH_BANK_COMMAND_HANDLER(sam4l_flash_bank_command
)
199 struct sam4l_info
*chip
= sam4l_chips
;
202 if (chip
->target
== bank
->target
)
208 /* Create a new chip */
209 chip
= calloc(1, sizeof(*chip
));
213 chip
->target
= bank
->target
;
214 chip
->probed
= false;
216 bank
->driver_priv
= chip
;
218 /* Insert it into the chips list (at head) */
219 chip
->next
= sam4l_chips
;
223 if (bank
->base
!= SAM4L_FLASH
) {
224 LOG_ERROR("Address 0x%08" PRIx32
" invalid bank address (try 0x%08" PRIx32
225 "[at91sam4l series] )",
226 bank
->base
, SAM4L_FLASH
);
233 static const struct sam4l_chip_info
*sam4l_find_chip_name(uint32_t id
, uint32_t exid
)
239 for (i
= 0; i
< ARRAY_SIZE(sam4l_known_chips
); i
++) {
240 if (sam4l_known_chips
[i
].id
== id
&& sam4l_known_chips
[i
].exid
== exid
)
241 return &sam4l_known_chips
[i
];
247 static int sam4l_check_page_erased(struct flash_bank
*bank
, uint32_t pn
,
253 /* Issue a quick page read to verify that we've erased this page */
254 res
= sam4l_flash_command(bank
->target
, SAM4L_FCMD_QPR
, pn
);
255 if (res
!= ERROR_OK
) {
256 LOG_ERROR("Quick page read %" PRIu32
" failed", pn
);
260 /* Retrieve the flash status */
261 res
= target_read_u32(bank
->target
, SAM4L_FLASHCALW
+ SAM4L_FSR
, &st
);
262 if (res
!= ERROR_OK
) {
263 LOG_ERROR("Couldn't read erase status");
267 /* Is the page in question really erased? */
268 *is_erased_p
= !!(st
& (1<<5));
273 static int sam4l_probe(struct flash_bank
*bank
)
275 uint32_t id
, exid
, param
;
277 struct sam4l_info
*chip
= (struct sam4l_info
*)bank
->driver_priv
;
282 res
= target_read_u32(bank
->target
, SAM4L_CHIPID
+ SAM4L_CIDR
, &id
);
283 if (res
!= ERROR_OK
) {
284 LOG_ERROR("Couldn't read chip ID");
288 res
= target_read_u32(bank
->target
, SAM4L_CHIPID
+ SAM4L_EXID
, &exid
);
289 if (res
!= ERROR_OK
) {
290 LOG_ERROR("Couldn't read extended chip ID");
294 chip
->details
= sam4l_find_chip_name(id
, exid
);
296 /* The RAM capacity is in a lookup table. */
297 chip
->ram_kb
= sam4l_ram_sizes
[0xF & (id
>> 16)];
299 switch (0xF & (id
>> 8)) {
301 chip
->flash_kb
= 128;
304 chip
->flash_kb
= 256;
307 chip
->flash_kb
= 512;
310 LOG_ERROR("Unknown flash size (chip ID is %08" PRIx32
"), assuming 128K", id
);
311 chip
->flash_kb
= 128;
315 /* Retrieve the Flash parameters */
316 res
= target_read_u32(bank
->target
, SAM4L_FLASHCALW
+ SAM4L_FPR
, ¶m
);
317 if (res
!= ERROR_OK
) {
318 LOG_ERROR("Couldn't read Flash parameters");
322 /* Fetch the page size from the parameter register. Technically the flash
323 * capacity is there too though the manual mentions that not all parts will
324 * have it set so we use the Chip ID capacity information instead. */
325 chip
->page_size
= sam4l_page_sizes
[0x7 & (param
>> 8)];
326 assert(chip
->page_size
);
327 chip
->num_pages
= chip
->flash_kb
* 1024 / chip
->page_size
;
329 chip
->sector_size
= (chip
->flash_kb
* 1024) / SAM4L_NUM_SECTORS
;
330 chip
->pages_per_sector
= chip
->sector_size
/ chip
->page_size
;
332 /* Make sure the bank size is correct */
333 bank
->size
= chip
->flash_kb
* 1024;
335 /* Allocate the sector table. */
336 bank
->num_sectors
= SAM4L_NUM_SECTORS
;
337 bank
->sectors
= calloc(bank
->num_sectors
, (sizeof((bank
->sectors
)[0])));
341 /* Fill out the sector information: all SAM4L sectors are the same size and
342 * there is always a fixed number of them. */
343 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
344 bank
->sectors
[i
].size
= chip
->sector_size
;
345 bank
->sectors
[i
].offset
= i
* chip
->sector_size
;
346 /* mark as unknown */
347 bank
->sectors
[i
].is_erased
= -1;
348 bank
->sectors
[i
].is_protected
= -1;
354 LOG_INFO("SAM4L MCU: %s (Rev %c) (%" PRIu32
"KB Flash with %d %" PRId32
"B pages, %" PRIu32
"KB RAM)",
355 chip
->details
? chip
->details
->name
: "unknown", (char)('A' + (id
& 0xF)),
356 chip
->flash_kb
, chip
->num_pages
, chip
->page_size
, chip
->ram_kb
);
361 static int sam4l_protect_check(struct flash_bank
*bank
)
365 struct sam4l_info
*chip
= (struct sam4l_info
*)bank
->driver_priv
;
367 if (bank
->target
->state
!= TARGET_HALTED
) {
368 LOG_ERROR("Target not halted");
370 return ERROR_TARGET_NOT_HALTED
;
374 if (sam4l_probe(bank
) != ERROR_OK
)
375 return ERROR_FLASH_BANK_NOT_PROBED
;
378 res
= target_read_u32(bank
->target
, SAM4L_FLASHCALW
+ SAM4L_FSR
, &st
);
382 st
>>= 16; /* There are 16 lock region bits in the upper half word */
383 for (int i
= 0; i
< bank
->num_sectors
; i
++)
384 bank
->sectors
[i
].is_protected
= !!(st
& (1<<i
));
389 static int sam4l_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
391 struct sam4l_info
*chip
= sam4l_chips
;
393 if (bank
->target
->state
!= TARGET_HALTED
) {
394 LOG_ERROR("Target not halted");
396 return ERROR_TARGET_NOT_HALTED
;
400 if (sam4l_probe(bank
) != ERROR_OK
)
401 return ERROR_FLASH_BANK_NOT_PROBED
;
404 /* Make sure the pages make sense. */
405 if (first
>= bank
->num_sectors
|| last
>= bank
->num_sectors
) {
406 LOG_ERROR("Protect range %d - %d not valid (%d sectors total)", first
, last
,
411 /* Try to lock or unlock each sector in the range. This is done by locking
412 * a region containing one page in that sector, we arbitrarily choose the 0th
413 * page in the sector. */
414 for (int i
= first
; i
<= last
; i
++) {
417 res
= sam4l_flash_command(bank
->target
,
418 set
? SAM4L_FCMD_LP
: SAM4L_FCMD_UP
, i
* chip
->pages_per_sector
);
419 if (res
!= ERROR_OK
) {
420 LOG_ERROR("Can't %slock region containing page %d", set
? "" : "un", i
);
428 static int sam4l_erase(struct flash_bank
*bank
, int first
, int last
)
431 struct sam4l_info
*chip
= (struct sam4l_info
*)bank
->driver_priv
;
433 if (bank
->target
->state
!= TARGET_HALTED
) {
434 LOG_ERROR("Target not halted");
436 return ERROR_TARGET_NOT_HALTED
;
440 if (sam4l_probe(bank
) != ERROR_OK
)
441 return ERROR_FLASH_BANK_NOT_PROBED
;
444 /* Make sure the pages make sense. */
445 if (first
>= bank
->num_sectors
|| last
>= bank
->num_sectors
) {
446 LOG_ERROR("Erase range %d - %d not valid (%d sectors total)", first
, last
,
452 if ((first
== 0) && ((last
+ 1) == bank
->num_sectors
)) {
453 LOG_DEBUG("Erasing the whole chip");
455 ret
= sam4l_flash_command(bank
->target
, SAM4L_FCMD_EA
, -1);
456 if (ret
!= ERROR_OK
) {
457 LOG_ERROR("Erase All failed");
461 LOG_DEBUG("Erasing sectors %d through %d...\n", first
, last
);
463 /* For each sector... */
464 for (int i
= first
; i
<= last
; i
++) {
465 /* For each page in that sector... */
466 for (int j
= 0; j
< chip
->pages_per_sector
; j
++) {
467 int pn
= i
* chip
->pages_per_sector
+ j
;
468 bool is_erased
= false;
470 /* Issue the page erase */
471 ret
= sam4l_flash_command(bank
->target
, SAM4L_FCMD_EP
, pn
);
472 if (ret
!= ERROR_OK
) {
473 LOG_ERROR("Erasing page %d failed", pn
);
477 ret
= sam4l_check_page_erased(bank
, pn
, &is_erased
);
482 LOG_DEBUG("Page %d was not erased.", pn
);
487 /* This sector is definitely erased. */
488 bank
->sectors
[i
].is_erased
= 1;
495 /* Write an entire page from host buffer 'buf' to page-aligned 'address' in the
497 static int sam4l_write_page(struct sam4l_info
*chip
, struct target
*target
,
498 uint32_t address
, const uint8_t *buf
)
502 LOG_DEBUG("sam4l_write_page address=%08" PRIx32
, address
);
504 /* Clear the page buffer before we write to it */
505 res
= sam4l_flash_command(target
, SAM4L_FCMD_CPB
, -1);
506 if (res
!= ERROR_OK
) {
507 LOG_ERROR("%s: can't clear page buffer", __func__
);
511 /* Write the modified page back to the target's page buffer */
512 res
= target_write_memory(target
, address
, 4, chip
->page_size
/ 4, buf
);
514 if (res
!= ERROR_OK
) {
515 LOG_ERROR("%s: %d", __func__
, __LINE__
);
519 /* Commit the page contents to Flash: erase the current page and then
521 res
= sam4l_flash_command(target
, SAM4L_FCMD_EP
, -1);
524 res
= sam4l_flash_command(target
, SAM4L_FCMD_WP
, -1);
529 /* Write partial contents into page-aligned 'address' on the Flash from host
530 * buffer 'buf' by writing 'nb' of 'buf' at 'offset' into the Flash page. */
531 static int sam4l_write_page_partial(struct sam4l_info
*chip
,
532 struct flash_bank
*bank
, uint32_t address
, const uint8_t *buf
,
533 uint32_t page_offset
, uint32_t nb
)
536 uint8_t *pg
= malloc(chip
->page_size
);
540 LOG_DEBUG("sam4l_write_page_partial address=%08" PRIx32
" nb=%08" PRIx32
, address
, nb
);
542 assert(page_offset
+ nb
< chip
->page_size
);
543 assert((address
% chip
->page_size
) == 0);
545 /* Retrieve the full page contents from Flash */
546 res
= target_read_memory(bank
->target
, address
, 4,
547 chip
->page_size
/ 4, pg
);
548 if (res
!= ERROR_OK
) {
553 /* Insert our partial page over the data from Flash */
554 memcpy(pg
+ (page_offset
% chip
->page_size
), buf
, nb
);
556 /* Write the page back out */
557 res
= sam4l_write_page(chip
, bank
->target
, address
, pg
);
563 static int sam4l_write(struct flash_bank
*bank
, const uint8_t *buffer
,
564 uint32_t offset
, uint32_t count
)
568 struct sam4l_info
*chip
= (struct sam4l_info
*)bank
->driver_priv
;
570 LOG_DEBUG("sam4l_write offset=%08" PRIx32
" count=%08" PRIx32
, offset
, count
);
572 if (bank
->target
->state
!= TARGET_HALTED
) {
573 LOG_ERROR("Target not halted");
575 return ERROR_TARGET_NOT_HALTED
;
579 if (sam4l_probe(bank
) != ERROR_OK
)
580 return ERROR_FLASH_BANK_NOT_PROBED
;
583 if (offset
% chip
->page_size
) {
584 /* We're starting at an unaligned offset so we'll write a partial page
585 * comprising that offset and up to the end of that page. */
586 nb
= chip
->page_size
- (offset
% chip
->page_size
);
589 } else if (count
< chip
->page_size
) {
590 /* We're writing an aligned but partial page. */
595 res
= sam4l_write_page_partial(chip
, bank
,
596 (offset
/ chip
->page_size
) * chip
->page_size
+ bank
->base
,
598 offset
% chip
->page_size
, nb
);
602 /* We're done with the page contents */
607 /* There's at least one aligned page to write out. */
608 if (count
>= chip
->page_size
) {
609 int np
= count
/ chip
->page_size
+ ((count
% chip
->page_size
) ? 1 : 0);
611 for (int i
= 0; i
< np
; i
++) {
612 if (count
>= chip
->page_size
) {
613 res
= sam4l_write_page(chip
, bank
->target
,
615 buffer
+ (i
* chip
->page_size
));
616 /* Advance one page */
617 offset
+= chip
->page_size
;
618 count
-= chip
->page_size
;
620 res
= sam4l_write_page_partial(chip
, bank
,
622 buffer
+ (i
* chip
->page_size
), 0, count
);
623 /* We're done after this. */
636 COMMAND_HANDLER(sam4l_handle_info_command
)
641 static const struct command_registration at91sam4l_exec_command_handlers
[] = {
644 .handler
= sam4l_handle_info_command
,
645 .mode
= COMMAND_EXEC
,
646 .help
= "Print information about the current at91sam4l chip"
647 "and its flash configuration.",
649 COMMAND_REGISTRATION_DONE
651 static const struct command_registration at91sam4l_command_handlers
[] = {
655 .help
= "at91sam4l flash command group",
657 .chain
= at91sam4l_exec_command_handlers
,
659 COMMAND_REGISTRATION_DONE
662 struct flash_driver at91sam4l_flash
= {
664 .commands
= at91sam4l_command_handlers
,
665 .flash_bank_command
= sam4l_flash_bank_command
,
666 .erase
= sam4l_erase
,
667 .protect
= sam4l_protect
,
668 .write
= sam4l_write
,
669 .read
= default_flash_read
,
670 .probe
= sam4l_probe
,
671 .auto_probe
= sam4l_probe
,
672 .erase_check
= default_flash_blank_check
,
673 .protect_check
= sam4l_protect_check
,
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)