flash Kinetis: new KVx family added
[openocd.git] / src / flash / nor / kinetis.c
index db098bbb27872b593721ed828ec4e548ac34588a..4749c7bbd6864616960c852c86b99e99217526e6 100644 (file)
 #define SIM_FCFG1      0x4004804c
 #define SIM_FCFG2      0x40048050
 #define WDOG_STCTRH    0x40052000
+#define SMC_PMCTRL     0x4007E001
+#define SMC_PMSTAT     0x4007E003
+
+/* Values */
+#define PM_STAT_RUN            0x01
+#define PM_STAT_VLPR           0x04
+#define PM_CTRL_RUNM_RUN       0x00
 
 /* Commands */
 #define FTFx_CMD_BLOCKSTAT  0x00
@@ -548,30 +555,11 @@ int kinetis_disable_wdog(struct target *target, uint32_t sim_sdid)
        int retval;
 
        static const uint8_t kinetis_unlock_wdog_code[] = {
-               /* WDOG_UNLOCK = 0xC520 */
-               0x4f, 0xf4, 0x00, 0x53,    /* mov.w   r3, #8192     ; 0x2000  */
-               0xc4, 0xf2, 0x05, 0x03,    /* movt    r3, #16389    ; 0x4005  */
-               0x4c, 0xf2, 0x20, 0x52,   /* movw    r2, #50464    ; 0xc520  */
-               0xda, 0x81,               /* strh    r2, [r3, #14]  */
-
-               /* WDOG_UNLOCK = 0xD928 */
-               0x4f, 0xf4, 0x00, 0x53,   /* mov.w   r3, #8192     ; 0x2000  */
-               0xc4, 0xf2, 0x05, 0x03,   /* movt    r3, #16389    ; 0x4005  */
-               0x4d, 0xf6, 0x28, 0x12,   /* movw    r2, #55592    ; 0xd928  */
-               0xda, 0x81,               /* strh    r2, [r3, #14]  */
-
-               /* WDOG_SCR = 0x1d2 */
-               0x4f, 0xf4, 0x00, 0x53,   /* mov.w   r3, #8192     ; 0x2000  */
-               0xc4, 0xf2, 0x05, 0x03,   /* movt    r3, #16389    ; 0x4005  */
-               0x4f, 0xf4, 0xe9, 0x72,   /* mov.w   r2, #466      ; 0x1d2  */
-               0x1a, 0x80,               /* strh    r2, [r3, #0]  */
-
-               /* END */
-               0x00, 0xBE,               /* bkpt #0 */
+#include "../../../contrib/loaders/watchdog/armv7m_kinetis_wdog.inc"
        };
 
        /* Decide whether the connected device needs watchdog disabling.
-        * Disable for all Kx devices, i.e., return if it is a KLx */
+        * Disable for all Kx and KVx devices, return if it is a KLx */
 
        if ((sim_sdid & KINETIS_SDID_SERIESID_MASK) == KINETIS_SDID_SERIESID_KL)
                return ERROR_OK;
@@ -951,6 +939,47 @@ static int kinetis_ftfx_command(struct target *target, uint8_t fcmd, uint32_t fa
 }
 
 
+static int kinetis_check_run_mode(struct target *target)
+{
+       int result, i;
+       uint8_t pmctrl, pmstat;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       result = target_read_u8(target, SMC_PMSTAT, &pmstat);
+       if (result != ERROR_OK)
+               return result;
+
+       if (pmstat == PM_STAT_RUN)
+               return ERROR_OK;
+
+       if (pmstat == PM_STAT_VLPR) {
+               /* It is safe to switch from VLPR to RUN mode without changing clock */
+               LOG_INFO("Switching from VLPR to RUN mode.");
+               pmctrl = PM_CTRL_RUNM_RUN;
+               result = target_write_u8(target, SMC_PMCTRL, pmctrl);
+               if (result != ERROR_OK)
+                       return result;
+
+               for (i = 100; i; i--) {
+                       result = target_read_u8(target, SMC_PMSTAT, &pmstat);
+                       if (result != ERROR_OK)
+                               return result;
+
+                       if (pmstat == PM_STAT_RUN)
+                               return ERROR_OK;
+               }
+       }
+
+       LOG_ERROR("Flash operation not possible in current run mode: SMC_PMSTAT: 0x%x", pmstat);
+       LOG_ERROR("Issue a 'reset init' command.");
+       return ERROR_TARGET_NOT_HALTED;
+}
+
+
 static void kinetis_invalidate_flash_cache(struct flash_bank *bank)
 {
        struct kinetis_flash_bank *kinfo = bank->driver_priv;
@@ -969,10 +998,9 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last)
        int result, i;
        struct kinetis_flash_bank *kinfo = bank->driver_priv;
 
-       if (bank->target->state != TARGET_HALTED) {
-               LOG_ERROR("Target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
+       result = kinetis_check_run_mode(bank->target);
+       if (result != ERROR_OK)
+               return result;
 
        if ((first > bank->num_sectors) || (last > bank->num_sectors))
                return ERROR_FLASH_OPERATION_FAILED;
@@ -1045,10 +1073,9 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer,
        struct kinetis_flash_bank *kinfo = bank->driver_priv;
        uint8_t *new_buffer = NULL;
 
-       if (bank->target->state != TARGET_HALTED) {
-               LOG_ERROR("Target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
+       result = kinetis_check_run_mode(bank->target);
+       if (result != ERROR_OK)
+               return result;
 
        if (!(kinfo->flash_support & FS_PROGRAM_SECTOR)) {
                /* fallback to longword write */
@@ -1201,7 +1228,7 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer,
        return ERROR_OK;
 }
 
-static int kinetis_read_part_info(struct flash_bank *bank)
+static int kinetis_probe(struct flash_bank *bank)
 {
        int result, i;
        uint32_t offset = 0;
@@ -1364,6 +1391,7 @@ static int kinetis_read_part_info(struct flash_bank *bank)
                                LOG_ERROR("Unsupported Kinetis FAMILYID SUBFAMID");
                        }
                        break;
+
                case KINETIS_SDID_SERIESID_KL:
                        /* KL-series */
                        pflash_sector_size_bytes = 1<<10;
@@ -1371,6 +1399,47 @@ static int kinetis_read_part_info(struct flash_bank *bank)
                        /* autodetect 1 or 2 blocks */
                        kinfo->flash_support = FS_PROGRAM_LONGWORD;
                        break;
+
+               case KINETIS_SDID_SERIESID_KV:
+                       /* KV-series */
+                       switch (kinfo->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) {
+                       case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX0:
+                               /* KV10: FTFA, 1kB sectors */
+                               pflash_sector_size_bytes = 1<<10;
+                               num_blocks = 1;
+                               kinfo->flash_support = FS_PROGRAM_LONGWORD;
+                               break;
+
+                       case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX1:
+                               /* KV11: FTFA, 2kB sectors */
+                               pflash_sector_size_bytes = 2<<10;
+                               num_blocks = 1;
+                               kinfo->flash_support = FS_PROGRAM_LONGWORD;
+                               break;
+
+                       case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX0:
+                               /* KV30: FTFA, 2kB sectors, 1 block */
+                       case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX1:
+                               /* KV31: FTFA, 2kB sectors, 2 blocks */
+                               pflash_sector_size_bytes = 2<<10;
+                               /* autodetect 1 or 2 blocks */
+                               kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE;
+                               break;
+
+                       case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX2:
+                       case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX4:
+                       case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX6:
+                               /* KV4x: FTFA, 4kB sectors */
+                               pflash_sector_size_bytes = 4<<10;
+                               num_blocks = 1;
+                               kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE;
+                               break;
+
+                       default:
+                               LOG_ERROR("Unsupported KV FAMILYID SUBFAMID");
+                       }
+                       break;
+
                default:
                        LOG_ERROR("Unsupported K-series");
                }
@@ -1527,7 +1596,10 @@ static int kinetis_read_part_info(struct flash_bank *bank)
                bank->base = 0x00000000 + bank->size * bank->bank_number;
                kinfo->prog_base = bank->base;
                kinfo->sector_size = pflash_sector_size_bytes;
-               kinfo->protection_size = pf_size / 32;
+               /* pflash is divided into 32 protection areas for
+                * parts with more than 32K of PFlash. For parts with
+                * less the protection unit is set to 1024 bytes */
+               kinfo->protection_size = MAX(pf_size / 32, 1024);
                kinfo->protection_block = (32 / num_pflash_blocks) * bank->bank_number;
 
        } else if ((unsigned)bank->bank_number < num_blocks) {
@@ -1623,16 +1695,6 @@ static int kinetis_read_part_info(struct flash_bank *bank)
        return ERROR_OK;
 }
 
-static int kinetis_probe(struct flash_bank *bank)
-{
-       if (bank->target->state != TARGET_HALTED) {
-               LOG_WARNING("Cannot communicate... target not halted.");
-               return ERROR_TARGET_NOT_HALTED;
-       }
-
-       return kinetis_read_part_info(bank);
-}
-
 static int kinetis_auto_probe(struct flash_bank *bank)
 {
        struct kinetis_flash_bank *kinfo = bank->driver_priv;
@@ -1662,14 +1724,14 @@ static int kinetis_info(struct flash_bank *bank, char *buf, int buf_size)
 static int kinetis_blank_check(struct flash_bank *bank)
 {
        struct kinetis_flash_bank *kinfo = bank->driver_priv;
+       int result;
 
-       if (bank->target->state != TARGET_HALTED) {
-               LOG_ERROR("Target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
+       /* suprisingly blank check does not work in VLPR and HSRUN modes */
+       result = kinetis_check_run_mode(bank->target);
+       if (result != ERROR_OK)
+               return result;
 
        if (kinfo->flash_class == FC_PFLASH || kinfo->flash_class == FC_FLEX_NVM) {
-               int result;
                bool block_dirty = false;
                uint8_t ftfx_fstat;
 
@@ -1831,10 +1893,9 @@ COMMAND_HANDLER(kinetis_nvm_partition)
        LOG_INFO("DEPART 0x%" PRIx8 ", EEPROM size code 0x%" PRIx8,
                 flex_nvm_partition_code, ee_size_code);
 
-       if (target->state != TARGET_HALTED) {
-               LOG_ERROR("Target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
+       result = kinetis_check_run_mode(target);
+       if (result != ERROR_OK)
+               return result;
 
        result = kinetis_ftfx_command(target, FTFx_CMD_PGMPART, load_flex_ram,
                                      ee_size_code, flex_nvm_partition_code, 0, 0,

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)