Kinetis: Symbolic names for Addresses and Commands
[openocd.git] / src / flash / nor / kinetis.c
index e0bb5c20ba59784c1faf5c221ce8069bdf0b2025..43075fe1b17a17d4d50b0baa9f99f555947457d0 100644 (file)
@@ -95,6 +95,24 @@ const struct {
        { 4<<10, 4<<10, 4 }
 };
 
+/* Addressess */
+#define FLEXRAM                0x14000000
+#define FTFx_FSTAT     0x40020000
+#define FTFx_FCNFG     0x40020001
+#define FTFx_FCCOB3    0x40020004
+#define FTFx_FPROT3    0x40020010
+#define SIM_SDID       0x40048024
+#define SIM_FCFG1      0x4004804c
+#define SIM_FCFG2      0x40048050
+
+/* Commands */
+#define FTFx_CMD_BLOCKSTAT 0x00
+#define FTFx_CMD_SECTSTAT 0x01
+#define FTFx_CMD_LWORDPROG 0x06
+#define FTFx_CMD_SECTERASE 0x09
+#define FTFx_CMD_SECTWRITE 0x0b
+#define FTFx_CMD_SETFLEXRAM 0x81
+
 struct kinetis_flash_bank {
        unsigned granularity;
        unsigned bank_ordinal;
@@ -160,8 +178,8 @@ static int kinetis_protect_check(struct flash_bank *bank)
                uint32_t fprot, psec;
                int i, b;
 
-               /* read protection register FTFx_FPROT */
-               result = target_read_memory(bank->target, 0x40020010, 1, 4, buffer);
+               /* read protection register */
+               result = target_read_memory(bank->target, FTFx_FPROT3, 1, 4, buffer);
 
                if (result != ERROR_OK)
                        return result;
@@ -204,7 +222,7 @@ static int kinetis_ftfx_command(struct flash_bank *bank, uint32_t w0,
        /* wait for done */
        for (i = 0; i < 50; i++) {
                result =
-                       target_read_memory(bank->target, 0x40020000, 1, 1, buffer);
+                       target_read_memory(bank->target, FTFx_FSTAT, 1, 1, buffer);
 
                if (result != ERROR_OK)
                        return result;
@@ -219,7 +237,7 @@ static int kinetis_ftfx_command(struct flash_bank *bank, uint32_t w0,
                /* reset error flags */
                buffer[0] = 0x30;
                result =
-                       target_write_memory(bank->target, 0x40020000, 1, 1, buffer);
+                       target_write_memory(bank->target, FTFx_FSTAT, 1, 1, buffer);
                if (result != ERROR_OK)
                        return result;
        }
@@ -228,21 +246,21 @@ static int kinetis_ftfx_command(struct flash_bank *bank, uint32_t w0,
        target_buffer_set_u32(bank->target, buffer + 4, w1);
        target_buffer_set_u32(bank->target, buffer + 8, w2);
 
-       result = target_write_memory(bank->target, 0x40020004, 4, 3, buffer);
+       result = target_write_memory(bank->target, FTFx_FCCOB3, 4, 3, buffer);
 
        if (result != ERROR_OK)
                return result;
 
        /* start command */
        buffer[0] = 0x80;
-       result = target_write_memory(bank->target, 0x40020000, 1, 1, buffer);
+       result = target_write_memory(bank->target, FTFx_FSTAT, 1, 1, buffer);
        if (result != ERROR_OK)
                return result;
 
        /* wait for done */
        for (i = 0; i < 50; i++) {
                result =
-                       target_read_memory(bank->target, 0x40020000, 1, 1, ftfx_fstat);
+                       target_read_memory(bank->target, FTFx_FSTAT, 1, 1, ftfx_fstat);
 
                if (result != ERROR_OK)
                        return result;
@@ -283,7 +301,7 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last)
        for (i = first; i <= last; i++) {
                uint8_t ftfx_fstat;
                /* set command and sector address */
-               w0 = (0x09 << 24) | (bank->base + bank->sectors[i].offset);
+               w0 = (FTFx_CMD_SECTERASE << 24) | (bank->base + bank->sectors[i].offset);
 
                result = kinetis_ftfx_command(bank, w0, w1, w2, &ftfx_fstat);
 
@@ -322,7 +340,7 @@ static int kinetis_write(struct flash_bank *bank, uint8_t *buffer,
                LOG_DEBUG("flash write into FlexNVM @%08X", offset);
 
                /* make flex ram available */
-               w0 = (0x81 << 24) | 0x00ff0000;
+               w0 = (FTFx_CMD_SETFLEXRAM << 24) | 0x00ff0000;
 
                result = kinetis_ftfx_command(bank, w0, w1, w2, &ftfx_fstat);
 
@@ -330,7 +348,7 @@ static int kinetis_write(struct flash_bank *bank, uint8_t *buffer,
                        return ERROR_FLASH_OPERATION_FAILED;
 
                /* check if ram ready */
-               result = target_read_memory(bank->target, 0x40020001, 1, 1, buf);
+               result = target_read_memory(bank->target, FTFx_FCNFG, 1, 1, buf);
 
                if (result != ERROR_OK)
                        return result;
@@ -351,32 +369,75 @@ static int kinetis_write(struct flash_bank *bank, uint8_t *buffer,
        if (fallback == 0) {
                unsigned prog_section_bytes = kinfo->sector_size >> 8;
                for (i = 0; i < count; i += kinfo->sector_size) {
+                       /*
+                        * The largest possible Kinetis "section" is
+                        * 16 bytes.  A full Kinetis sector is always
+                        * 256 "section"s.
+                        */
+                       uint8_t residual_buffer[16];
                        uint8_t ftfx_fstat;
+                       uint32_t section_count = 256;
+                       uint32_t residual_wc = 0;
 
+                       /*
+                        * Assume the word count covers an entire
+                        * sector.
+                        */
                        wc = kinfo->sector_size / 4;
 
+                       /*
+                        * If bytes to be programmed are less than the
+                        * full sector, then determine the number of
+                        * full-words to program, and put together the
+                        * residual buffer so that a full "section"
+                        * may always be programmed.
+                        */
                        if ((count - i) < kinfo->sector_size) {
-                               wc = count - i;
-                               wc /= 4;
+                               /* number of bytes to program beyond full section */
+                               unsigned residual_bc = (count-i) % prog_section_bytes;
+
+                               /* number of complete words to copy directly from buffer */
+                               wc = (count - i) / 4;
+
+                               /* number of total sections to write, including residual */
+                               section_count = DIV_ROUND_UP((count-i), prog_section_bytes);
+
+                               /* any residual bytes delivers a whole residual section */
+                               residual_wc = (residual_bc ? prog_section_bytes : 0)/4;
+
+                               /* clear residual buffer then populate residual bytes */
+                               (void) memset(residual_buffer, 0xff, prog_section_bytes);
+                               (void) memcpy(residual_buffer, &buffer[i+4*wc], residual_bc);
                        }
 
-                       LOG_DEBUG("write section @ %08X with length %d",
-                                 offset + i, wc * 4);
+                       LOG_DEBUG("write section @ %08X with length %d bytes",
+                                 offset + i, (count - i));
 
-                       /* write data to flexram */
-                       result =
-                               target_write_memory(bank->target, 0x14000000, 4, wc,
-                                                   buffer + i);
+                       /* write data to flexram as whole-words */
+                       result = target_write_memory(bank->target, FLEXRAM, 4, wc,
+                                                    buffer + i);
 
                        if (result != ERROR_OK) {
                                LOG_ERROR("target_write_memory failed");
-
                                return result;
                        }
 
-                       /* execute section command */
-                       w0 = (0x0b << 24) | (bank->base + offset + i);
-                       w1 = ((wc * 4 / prog_section_bytes) << 16);
+                       /* write the residual words to the flexram */
+                       if (residual_wc) {
+                               result = target_write_memory(bank->target,
+                                                            FLEXRAM+4*wc,
+                                                            4, residual_wc,
+                                                            residual_buffer);
+
+                               if (result != ERROR_OK) {
+                                       LOG_ERROR("target_write_memory failed");
+                                       return result;
+                               }
+                       }
+
+                       /* execute section-write command */
+                       w0 = (FTFx_CMD_SECTWRITE << 24) | (bank->base + offset + i);
+                       w1 = section_count << 16;
 
                        result = kinetis_ftfx_command(bank, w0, w1, w2, &ftfx_fstat);
 
@@ -391,8 +452,14 @@ static int kinetis_write(struct flash_bank *bank, uint8_t *buffer,
 
                        LOG_DEBUG("write longword @ %08X", offset + i);
 
-                       w0 = (0x06 << 24) | (bank->base + offset + i);
-                       w1 = buf_get_u32(buffer + offset + i, 0, 32);
+                       w0 = (FTFx_CMD_LWORDPROG << 24) | (bank->base + offset + i);
+                       if (count - i < 4) {
+                               uint32_t padding = 0xffffffff;
+                               memcpy(&padding, buffer + i, count - i);
+                               w1 = buf_get_u32(&padding, 0, 32);
+                       } else {
+                               w1 = buf_get_u32(buffer + i, 0, 32);
+                       }
 
                        result = kinetis_ftfx_command(bank, w0, w1, w2, &ftfx_fstat);
 
@@ -418,16 +485,18 @@ static int kinetis_read_part_info(struct flash_bank *bank)
                first_nvm_bank = 0, reassign = 0;
        struct kinetis_flash_bank *kinfo = bank->driver_priv;
 
-       result = target_read_memory(bank->target, 0x40048024, 1, 4, buf);
+       result = target_read_memory(bank->target, SIM_SDID, 1, 4, buf);
        if (result != ERROR_OK)
                return result;
        kinfo->sim_sdid = target_buffer_get_u32(bank->target, buf);
        granularity = (kinfo->sim_sdid >> 7) & 0x03;
-       result = target_read_memory(bank->target, 0x4004804c, 1, 4, buf);
+
+       result = target_read_memory(bank->target, SIM_FCFG1, 1, 4, buf);
        if (result != ERROR_OK)
                return result;
        kinfo->sim_fcfg1 = target_buffer_get_u32(bank->target, buf);
-       result = target_read_memory(bank->target, 0x40048050, 1, 4, buf);
+
+       result = target_read_memory(bank->target, SIM_FCFG2, 1, 4, buf);
        if (result != ERROR_OK)
                return result;
        kinfo->sim_fcfg2 = target_buffer_get_u32(bank->target, buf);
@@ -576,7 +645,7 @@ static int kinetis_read_part_info(struct flash_bank *bank)
                                } else if (bank->size != ee_size) {
                                        LOG_WARNING("FlexRAM size mismatch");
                                        reassign = 1;
-                               } else if (bank->base != 0x14000000) {
+                               } else if (bank->base != FLEXRAM) {
                                        LOG_WARNING("FlexRAM address mismatch");
                                        reassign = 1;
                                } else if (kinfo->sector_size !=
@@ -699,7 +768,7 @@ static int kinetis_blank_check(struct flash_bank *bank)
                uint8_t ftfx_fstat;
 
                /* check if whole bank is blank */
-               w0 = (0x00 << 24) | bank->base;
+               w0 = (FTFx_CMD_BLOCKSTAT << 24) | bank->base;
                w1 = 0; /* "normal margin" */
 
                result = kinetis_ftfx_command(bank, w0, w1, w2, &ftfx_fstat);
@@ -711,7 +780,7 @@ static int kinetis_blank_check(struct flash_bank *bank)
                        /* the whole bank is not erased, check sector-by-sector */
                        int i;
                        for (i = 0; i < bank->num_sectors; i++) {
-                               w0 = (0x01 << 24) | (bank->base + bank->sectors[i].offset);
+                               w0 = (FTFx_CMD_SECTSTAT << 24) | (bank->base + bank->sectors[i].offset);
                                w1 = (0x100 << 16) | 0; /* normal margin */
 
                                result = kinetis_ftfx_command(bank, w0, w1, w2, &ftfx_fstat);

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)