Work around silicon bug in the SAM3 family flash waitstates
authorAttila Kinali <attila@kinali.ch>
Thu, 27 Oct 2011 10:14:55 +0000 (12:14 +0200)
committerSpencer Oliver <spen@spen-soft.co.uk>
Thu, 10 Nov 2011 15:41:44 +0000 (15:41 +0000)
* Add flash waitstate support for Atmel SAM3 chips.
* Set default waitstates to 6, to workaround a silicon bug in the SAM3 family

This code has been tested on SAM3U4, SAM3N4 and SAM3N1

based on Change-Id: I477446f9bfb3e910ea3e2414a6e9a75beb14a214
by Jim Norris <u17263@att.net>

Change-Id: I8d360080f6968979ca5e197ad638282cadd18fb7
Signed-off-by: Attila Kinali <attila@kinali.ch>
Signed-off-by: Spencer Oliver <spen@spen-soft.co.uk>
Reviewed-on: http://openocd.zylin.com/128
Tested-by: jenkins
src/flash/nor/at91sam3.c

index 43db51d8bf6469304b69dab716329443aa0ec8e6..a5fbd43ab0a7ef61c8a25278570d148e9b41482a 100644 (file)
@@ -167,6 +167,15 @@ struct sam3_cfg {
        uint32_t PMC_FSPR;
 };
 
+/*
+ * The AT91SAM3N data sheet 04-Oct-2010, AT91SAM3U data sheet 22-Aug-2011
+ * and AT91SAM3S data sheet 09-Feb-2011 state that for flash writes
+ * the flash wait state (FWS) should be set to 6. It seems like that the
+ * cause of the problem is not the flash itself, but the flash write
+ * buffer. Ie the wait states have to be set before writing into the
+ * buffer.
+ * Tested and confirmed with SAM3N and SAM3U
+ */
 
 struct sam3_bank_private {
        int probed;
@@ -183,6 +192,7 @@ struct sam3_bank_private {
        unsigned bank_number;
        uint32_t controller_address;
        uint32_t base_address;
+       uint32_t flash_wait_states;
        bool present;
        unsigned size_bytes;
        unsigned nsectors;
@@ -298,6 +308,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK0_BASE_U,
                        .controller_address = 0x400e0800,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes = 128 * 1024,
                        .nsectors   = 16,
@@ -313,6 +324,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 1,
                        .base_address = FLASH_BANK1_BASE_U,
                        .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes = 128 * 1024,
                        .nsectors   = 16,
@@ -347,6 +359,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK0_BASE_U,
                        .controller_address = 0x400e0800,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes = 128 * 1024,
                        .nsectors   = 16,
@@ -388,6 +401,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK0_BASE_U,
                        .controller_address = 0x400e0800,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes =  64 * 1024,
                        .nsectors   =  8,
@@ -436,6 +450,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK0_BASE_U,
                        .controller_address = 0x400e0800,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes = 128 * 1024,
                        .nsectors   = 16,
@@ -450,6 +465,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 1,
                        .base_address = FLASH_BANK1_BASE_U,
                        .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes = 128 * 1024,
                        .nsectors   = 16,
@@ -484,6 +500,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK0_BASE_U,
                        .controller_address = 0x400e0800,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes = 128 * 1024,
                        .nsectors   = 16,
@@ -525,6 +542,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK0_BASE_U,
                        .controller_address = 0x400e0800,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes =  64 * 1024,
                        .nsectors   =  8,
@@ -561,8 +579,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .pBank  = NULL,
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_S,
-
                        .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes =  256 * 1024,
                        .nsectors   =  32,
@@ -594,8 +612,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .pBank  = NULL,
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_S,
-
                        .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes =  256 * 1024,
                        .nsectors   =  32,
@@ -626,8 +644,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .pBank  = NULL,
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_S,
-
                        .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes =  256 * 1024,
                        .nsectors   =  32,
@@ -658,8 +676,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .pBank  = NULL,
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_S,
-
                        .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes =  128 * 1024,
                        .nsectors   =  16,
@@ -690,8 +708,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .pBank  = NULL,
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_S,
-
                        .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes =  128 * 1024,
                        .nsectors   =  16,
@@ -722,8 +740,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .pBank  = NULL,
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_S,
-
                        .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes =  128 * 1024,
                        .nsectors   =  16,
@@ -754,8 +772,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .pBank  = NULL,
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_S,
-
                        .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes =  64 * 1024,
                        .nsectors   =  8,
@@ -786,8 +804,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .pBank  = NULL,
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_S,
-
                        .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes =  64 * 1024,
                        .nsectors   =  8,
@@ -818,8 +836,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .pBank  = NULL,
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_S,
-
                        .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes =  64 * 1024,
                        .nsectors   =  8,
@@ -869,6 +887,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_N,
                        .controller_address = 0x400e0A00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes = 256 * 1024,
                        .nsectors   = 16,
@@ -917,6 +936,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_N,
                        .controller_address = 0x400e0A00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes = 256 * 1024,
                        .nsectors   = 16,
@@ -965,6 +985,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_N,
                        .controller_address = 0x400e0A00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes = 256 * 1024,
                        .nsectors   = 16,
@@ -1013,6 +1034,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_N,
                        .controller_address = 0x400e0A00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes = 128 * 1024,
                        .nsectors   = 8,
@@ -1061,6 +1083,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_N,
                        .controller_address = 0x400e0A00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes = 128 * 1024,
                        .nsectors   = 8,
@@ -1109,6 +1132,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_N,
                        .controller_address = 0x400e0A00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes = 128 * 1024,
                        .nsectors   = 8,
@@ -1157,6 +1181,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_N,
                        .controller_address = 0x400e0A00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes = 64 * 1024,
                        .nsectors   = 4,
@@ -1205,6 +1230,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_N,
                        .controller_address = 0x400e0A00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes = 64 * 1024,
                        .nsectors   = 4,
@@ -1253,6 +1279,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_N,
                        .controller_address = 0x400e0A00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
                        .present = 1,
                        .size_bytes = 64 * 1024,
                        .nsectors   = 4,
@@ -2391,11 +2418,13 @@ FLASH_BANK_COMMAND_HANDLER(sam3_flash_bank_command)
        switch (bank->base) {
        default:
                LOG_ERROR("Address 0x%08x invalid bank address (try 0x%08x or 0x%08x \
-                       [at91sam3u series] or 0x%08x [at91sam3s series])",
+                       [at91sam3u series] or 0x%08x [at91sam3s series] or \
+                       0x%08x [at91sam3n series])",
                                  ((unsigned int)(bank->base)),
                                  ((unsigned int)(FLASH_BANK0_BASE_U)),
                                  ((unsigned int)(FLASH_BANK1_BASE_U)),
-                                 ((unsigned int)(FLASH_BANK_BASE_S)));
+                                 ((unsigned int)(FLASH_BANK_BASE_S)),
+                                 ((unsigned int)(FLASH_BANK_BASE_N)));
                return ERROR_FAIL;
                break;
 
@@ -2413,7 +2442,7 @@ FLASH_BANK_COMMAND_HANDLER(sam3_flash_bank_command)
                pChip->details.bank[1].pBank = bank;
                break;
 
-       // at91sam3s series
+       /* at91sam3s and at91sam3n series */
        case FLASH_BANK_BASE_S:
                bank->driver_priv = &(pChip->details.bank[0]);
                bank->bank_number = 0;
@@ -2771,11 +2800,28 @@ sam3_page_write(struct sam3_bank_private *pPrivate, unsigned pagenum, uint8_t *b
 {
        uint32_t adr;
        uint32_t status;
+       uint32_t fmr; /* EEFC Flash Mode Register */
        int r;
 
        adr = pagenum * pPrivate->page_size;
        adr += (adr + pPrivate->base_address);
 
+       /* Get flash mode register value */
+       r = target_read_u32(pPrivate->pChip->target, pPrivate->controller_address, &fmr);
+       if (r != ERROR_OK)
+               LOG_DEBUG("Error Read failed: read flash mode register");
+
+       /* Clear flash wait state field */
+       fmr &= 0xfffff0ff;
+
+       /* set FWS (flash wait states) field in the FMR (flash mode register) */
+       fmr |= (pPrivate->flash_wait_states << 8);
+
+       LOG_DEBUG("Flash Mode: 0x%08x", ((unsigned int)(fmr)));
+       r = target_write_u32(pPrivate->pBank->target, pPrivate->controller_address, fmr);
+       if (r != ERROR_OK)
+               LOG_DEBUG("Error Write failed: set flash mode register");
+
        LOG_DEBUG("Wr Page %u @ phys address: 0x%08x", pagenum, (unsigned int)(adr));
        r = target_write_memory(pPrivate->pChip->target,
                                                         adr,

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)