diff options
-rw-r--r-- | contrib/loaders/watchdog/Makefile | 2 | ||||
-rw-r--r-- | contrib/loaders/watchdog/armv7m_kinetis_wdog.inc | 5 | ||||
-rw-r--r-- | contrib/loaders/watchdog/armv7m_kinetis_wdog.s | 14 | ||||
-rw-r--r-- | contrib/loaders/watchdog/armv7m_kinetis_wdog32.inc | 5 | ||||
-rw-r--r-- | contrib/loaders/watchdog/armv7m_kinetis_wdog32.s | 81 | ||||
-rw-r--r-- | src/flash/nor/kinetis.c | 273 | ||||
-rw-r--r-- | tcl/target/klx.cfg | 16 | ||||
-rw-r--r-- | tcl/target/kx.cfg | 8 |
8 files changed, 316 insertions, 88 deletions
diff --git a/contrib/loaders/watchdog/Makefile b/contrib/loaders/watchdog/Makefile index 623e744..ed6d8f4 100644 --- a/contrib/loaders/watchdog/Makefile +++ b/contrib/loaders/watchdog/Makefile @@ -6,7 +6,7 @@ ARM_OBJCOPY ?= $(ARM_CROSS_COMPILE)objcopy ARM_AFLAGS = -EL -mthumb -arm: armv7m_kinetis_wdog.inc +arm: armv7m_kinetis_wdog.inc armv7m_kinetis_wdog32.inc armv7m_%.elf: armv7m_%.s $(ARM_AS) $(ARM_AFLAGS) $< -o $@ diff --git a/contrib/loaders/watchdog/armv7m_kinetis_wdog.inc b/contrib/loaders/watchdog/armv7m_kinetis_wdog.inc index 4b6579e..317d084 100644 --- a/contrib/loaders/watchdog/armv7m_kinetis_wdog.inc +++ b/contrib/loaders/watchdog/armv7m_kinetis_wdog.inc @@ -1,4 +1,3 @@ /* Autogenerated with ../../../src/helper/bin2char.sh */ -0x04,0x4b,0x05,0x4a,0xda,0x81,0x05,0x4a,0xda,0x81,0x01,0x24,0x1a,0x88,0xa2,0x43, -0x1a,0x80,0x06,0xe0,0x00,0x20,0x05,0x40,0x20,0xc5,0x00,0x00,0x28,0xd9,0x00,0x00, -0x00,0x00,0x00,0xbe, +0x04,0x4a,0xc2,0x81,0x04,0x4a,0xc2,0x81,0x01,0x24,0x02,0x88,0xa2,0x43,0x02,0x80, +0x05,0xe0,0x00,0x00,0x20,0xc5,0x00,0x00,0x28,0xd9,0x00,0x00,0x00,0x00,0x00,0xbe, diff --git a/contrib/loaders/watchdog/armv7m_kinetis_wdog.s b/contrib/loaders/watchdog/armv7m_kinetis_wdog.s index bac924a..d724192 100644 --- a/contrib/loaders/watchdog/armv7m_kinetis_wdog.s +++ b/contrib/loaders/watchdog/armv7m_kinetis_wdog.s @@ -19,7 +19,9 @@ /* Disable watchdog for Kinetis Kx and KVx - Parameters: none + Parameters: + r0 ... WDOG base (in) + Used instruction set should work on both Cortex-M4 and M0+ */ @@ -28,7 +30,6 @@ .cpu cortex-m0 .thumb -WDOG_ADDR = 0x40052000 /* WDOG registers offsets */ WDOG_STCTRLH = 0 WDOG_UNLOCK = 0x0e @@ -39,17 +40,16 @@ WDOG_KEY2 = 0xd928 .thumb_func start: /* WDOG_UNLOCK = 0xC520 */ - ldr r3, =WDOG_ADDR ldr r2, =WDOG_KEY1 - strh r2, [r3, WDOG_UNLOCK] + strh r2, [r0, WDOG_UNLOCK] /* WDOG_UNLOCK = 0xD928 */ ldr r2, =WDOG_KEY2 - strh r2, [r3, WDOG_UNLOCK] + strh r2, [r0, WDOG_UNLOCK] /* WDOG_STCTRLH clear bit 0 */ movs r4, #1 - ldrh r2, [r3, WDOG_STCTRLH] + ldrh r2, [r0, WDOG_STCTRLH] bics r2, r4 - strh r2, [r3, WDOG_STCTRLH] + strh r2, [r0, WDOG_STCTRLH] /* OpenOCD checks exit point address. Jump to the very end. */ b done diff --git a/contrib/loaders/watchdog/armv7m_kinetis_wdog32.inc b/contrib/loaders/watchdog/armv7m_kinetis_wdog32.inc new file mode 100644 index 0000000..4ee06ed --- /dev/null +++ b/contrib/loaders/watchdog/armv7m_kinetis_wdog32.inc @@ -0,0 +1,5 @@ +/* Autogenerated with ../../../src/helper/bin2char.sh */ +0x02,0x68,0x08,0x4b,0x1a,0x42,0x08,0x4b,0x01,0xd0,0x43,0x60,0x02,0xe0,0x83,0x80, +0x1b,0x0c,0x83,0x80,0x80,0x24,0xa2,0x43,0x20,0x24,0x22,0x43,0x02,0x60,0x03,0x4b, +0x83,0x60,0x06,0xe0,0x00,0x20,0x00,0x00,0x20,0xc5,0x28,0xd9,0x00,0x04,0x00,0x00, +0x00,0x00,0x00,0xbe, diff --git a/contrib/loaders/watchdog/armv7m_kinetis_wdog32.s b/contrib/loaders/watchdog/armv7m_kinetis_wdog32.s new file mode 100644 index 0000000..bf58327 --- /dev/null +++ b/contrib/loaders/watchdog/armv7m_kinetis_wdog32.s @@ -0,0 +1,81 @@ +/*************************************************************************** + * Copyright (C) 2017 Tomas Vanek * + * vanekt@fbl.cz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc. * + ***************************************************************************/ + +/* + Disable watchdog, 32-bit version for newer Kinetis + Parameters: + r0 ... WDOG32 base (in) + + Used instruction set should work on both Cortex-M4 and M0+ +*/ + + .text + .syntax unified + .cpu cortex-m0 + .thumb + +/* WDOG registers offsets */ +WDOG_CS = 0 +WDOG_CNT = 4 +WDOG_TOVAL = 8 + +WDOG_KEY = 0xd928c520 + + .thumb_func +start: +/* test WDOG_CS bit CMD32EN */ + ldr r2, [r0, WDOG_CS] + ldr r3, =0x2000 + tst r2, r3 + ldr r3, =WDOG_KEY + beq cmd16 + +/* WDOG_CNT = key */ + str r3, [r0, WDOG_CNT] + b unlocked + +cmd16: +/* WDOG_CNT = key, halfword by halfword */ + strh r3, [r0, WDOG_CNT] + lsrs r3, r3, #16 + strh r3, [r0, WDOG_CNT] + +/* WDOG_CS: clear EN bit 7, set UPDATE bit 5 */ +unlocked: + movs r4, #0x80 + bics r2, r4 + movs r4, #0x20 + orrs r2, r4 + str r2, [r0, WDOG_CS] +/* All active WDOG registers have to be updated, set dummy timeout */ +/* WDOG_TOVAL = 0x400 */ + ldr r3, =0x400 + str r3, [r0, WDOG_TOVAL] +/* OpenOCD checks exit point address. Jump to the very end. */ + b done + + .pool + +/* Avoid padding at .text segment end. Otherwise exit point check fails. */ + .skip ( . - start + 2) & 2, 0 +done: + bkpt #0 + + .end + diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index dc3dc45..1f2383d 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -100,11 +100,18 @@ #define SIM_SOPT1 0x40047000 #define SIM_FCFG1 0x4004804c #define SIM_FCFG2 0x40048050 -#define WDOG_STCTRH 0x40052000 +#define SIM_COPC 0x40048100 +#define WDOG_BASE 0x40052000 +#define WDOG32_KE1X 0x40052000 +#define WDOG32_KL28 0x40076000 #define SMC_PMCTRL 0x4007E001 #define SMC_PMSTAT 0x4007E003 #define MCM_PLACR 0xF000300C +/* Offsets */ +#define WDOG_STCTRLH_OFFSET 0 +#define WDOG32_CS_OFFSET 0 + /* Values */ #define PM_STAT_RUN 0x01 #define PM_STAT_VLPR 0x04 @@ -270,13 +277,26 @@ struct kinetis_chip { FS_PROGRAM_SECTOR = 1, FS_PROGRAM_LONGWORD = 2, FS_PROGRAM_PHRASE = 4, /* Unsupported */ - FS_INVALIDATE_CACHE_K = 8, /* using FMC->PFB0CR/PFB01CR */ - FS_INVALIDATE_CACHE_L = 0x10, /* using MCM->PLACR */ - FS_INVALIDATE_CACHE_MSCM = 0x20, + FS_NO_CMD_BLOCKSTAT = 0x40, FS_WIDTH_256BIT = 0x80, } flash_support; + enum { + KINETIS_CACHE_NONE, + KINETIS_CACHE_K, /* invalidate using FMC->PFB0CR/PFB01CR */ + KINETIS_CACHE_L, /* invalidate using MCM->PLACR */ + KINETIS_CACHE_MSCM, /* devices like KE1xF, invalidate MSCM->OCMDR0 */ + } cache_type; + + enum { + KINETIS_WDOG_NONE, + KINETIS_WDOG_K, + KINETIS_WDOG_COP, + KINETIS_WDOG32_KE1X, + KINETIS_WDOG32_KL28, + } watchdog_type; + char name[40]; unsigned num_banks; @@ -362,6 +382,7 @@ static bool create_banks; struct flash_driver kinetis_flash; static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count); +static int kinetis_probe_chip(struct kinetis_chip *k_chip); static int kinetis_auto_probe(struct flash_bank *bank); @@ -941,11 +962,53 @@ static int kinetis_create_missing_banks(struct kinetis_chip *k_chip) } -/* Disable the watchdog on Kinetis devices */ -int kinetis_disable_wdog(struct target *target, uint32_t sim_sdid) +static int kinetis_disable_wdog_algo(struct target *target, size_t code_size, const uint8_t *code, uint32_t wdog_base) { struct working_area *wdog_algorithm; struct armv7m_algorithm armv7m_info; + struct reg_param reg_params[1]; + int retval; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + retval = target_alloc_working_area(target, code_size, &wdog_algorithm); + if (retval != ERROR_OK) + return retval; + + retval = target_write_buffer(target, wdog_algorithm->address, + code_size, code); + if (retval == ERROR_OK) { + armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; + armv7m_info.core_mode = ARM_MODE_THREAD; + + init_reg_param(®_params[0], "r0", 32, PARAM_IN); + buf_set_u32(reg_params[0].value, 0, 32, wdog_base); + + retval = target_run_algorithm(target, 0, NULL, 1, reg_params, + wdog_algorithm->address, + wdog_algorithm->address + code_size - 2, + 500, &armv7m_info); + + destroy_reg_param(®_params[0]); + + if (retval != ERROR_OK) + LOG_ERROR("Error executing Kinetis WDOG unlock algorithm"); + } + + target_free_working_area(target, wdog_algorithm); + + return retval; +} + +/* Disable the watchdog on Kinetis devices + * Standard Kx WDOG peripheral checks timing and therefore requires to run algo. + */ +static int kinetis_disable_wdog_kx(struct target *target) +{ + const uint32_t wdog_base = WDOG_BASE; uint16_t wdog; int retval; @@ -953,14 +1016,7 @@ int kinetis_disable_wdog(struct target *target, uint32_t sim_sdid) #include "../../../contrib/loaders/watchdog/armv7m_kinetis_wdog.inc" }; - /* Decide whether the connected device needs watchdog disabling. - * 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; - - /* The connected device requires watchdog disabling. */ - retval = target_read_u16(target, WDOG_STCTRH, &wdog); + retval = target_read_u16(target, wdog_base + WDOG_STCTRLH_OFFSET, &wdog); if (retval != ERROR_OK) return retval; @@ -968,60 +1024,116 @@ int kinetis_disable_wdog(struct target *target, uint32_t sim_sdid) /* watchdog already disabled */ return ERROR_OK; } - LOG_INFO("Disabling Kinetis watchdog (initial WDOG_STCTRLH = 0x%x)", wdog); + LOG_INFO("Disabling Kinetis watchdog (initial WDOG_STCTRLH = 0x%04" PRIx16 ")", wdog); - if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } + retval = kinetis_disable_wdog_algo(target, sizeof(kinetis_unlock_wdog_code), kinetis_unlock_wdog_code, wdog_base); + if (retval != ERROR_OK) + return retval; - retval = target_alloc_working_area(target, sizeof(kinetis_unlock_wdog_code), &wdog_algorithm); + retval = target_read_u16(target, wdog_base + WDOG_STCTRLH_OFFSET, &wdog); if (retval != ERROR_OK) return retval; - retval = target_write_buffer(target, wdog_algorithm->address, - sizeof(kinetis_unlock_wdog_code), (uint8_t *)kinetis_unlock_wdog_code); - if (retval != ERROR_OK) { - target_free_working_area(target, wdog_algorithm); + LOG_INFO("WDOG_STCTRLH = 0x%04" PRIx16, wdog); + return (wdog & 0x1) ? ERROR_FAIL : ERROR_OK; +} + +static int kinetis_disable_wdog32(struct target *target, uint32_t wdog_base) +{ + uint32_t wdog_cs; + int retval; + + static const uint8_t kinetis_unlock_wdog_code[] = { +#include "../../../contrib/loaders/watchdog/armv7m_kinetis_wdog32.inc" + }; + + retval = target_read_u32(target, wdog_base + WDOG32_CS_OFFSET, &wdog_cs); + if (retval != ERROR_OK) return retval; - } - armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; - armv7m_info.core_mode = ARM_MODE_THREAD; + if ((wdog_cs & 0x80) == 0) + return ERROR_OK; /* watchdog already disabled */ - retval = target_run_algorithm(target, 0, NULL, 0, NULL, wdog_algorithm->address, - wdog_algorithm->address + (sizeof(kinetis_unlock_wdog_code) - 2), - 10000, &armv7m_info); + LOG_INFO("Disabling Kinetis watchdog (initial WDOG_CS 0x%08" PRIx32 ")", wdog_cs); + retval = kinetis_disable_wdog_algo(target, sizeof(kinetis_unlock_wdog_code), kinetis_unlock_wdog_code, wdog_base); if (retval != ERROR_OK) - LOG_ERROR("error executing kinetis wdog unlock algorithm"); + return retval; - retval = target_read_u16(target, WDOG_STCTRH, &wdog); + retval = target_read_u32(target, wdog_base + WDOG32_CS_OFFSET, &wdog_cs); if (retval != ERROR_OK) return retval; - LOG_INFO("WDOG_STCTRLH = 0x%x", wdog); - target_free_working_area(target, wdog_algorithm); + if ((wdog_cs & 0x80) == 0) + return ERROR_OK; /* watchdog disabled successfully */ - return retval; + LOG_ERROR("Cannot disable Kinetis watchdog (WDOG_CS 0x%08" PRIx32 "), issue 'reset init'", wdog_cs); + return ERROR_FAIL; +} + +static int kinetis_disable_wdog(struct kinetis_chip *k_chip) +{ + struct target *target = k_chip->target; + uint8_t sim_copc; + int retval; + + if (!k_chip->probed) { + retval = kinetis_probe_chip(k_chip); + if (retval != ERROR_OK) + return retval; + } + + switch (k_chip->watchdog_type) { + case KINETIS_WDOG_K: + return kinetis_disable_wdog_kx(target); + + case KINETIS_WDOG_COP: + retval = target_read_u8(target, SIM_COPC, &sim_copc); + if (retval != ERROR_OK) + return retval; + + if ((sim_copc & 0xc) == 0) + return ERROR_OK; /* watchdog already disabled */ + + LOG_INFO("Disabling Kinetis watchdog (initial SIM_COPC 0x%02" PRIx8 ")", sim_copc); + retval = target_write_u8(target, SIM_COPC, sim_copc & ~0xc); + if (retval != ERROR_OK) + return retval; + + retval = target_read_u8(target, SIM_COPC, &sim_copc); + if (retval != ERROR_OK) + return retval; + + if ((sim_copc & 0xc) == 0) + return ERROR_OK; /* watchdog disabled successfully */ + + LOG_ERROR("Cannot disable Kinetis watchdog (SIM_COPC 0x%02" PRIx8 "), issue 'reset init'", sim_copc); + return ERROR_FAIL; + + case KINETIS_WDOG32_KE1X: + return kinetis_disable_wdog32(target, WDOG32_KE1X); + + case KINETIS_WDOG32_KL28: + return kinetis_disable_wdog32(target, WDOG32_KL28); + + default: + return ERROR_OK; + } } COMMAND_HANDLER(kinetis_disable_wdog_handler) { int result; - uint32_t sim_sdid; struct target *target = get_current_target(CMD_CTX); + struct kinetis_chip *k_chip = kinetis_get_chip(target); + + if (k_chip == NULL) + return ERROR_FAIL; if (CMD_ARGC > 0) return ERROR_COMMAND_SYNTAX_ERROR; - result = target_read_u32(target, SIM_SDID, &sim_sdid); - if (result != ERROR_OK) { - LOG_ERROR("Failed to read SIMSDID"); - return result; - } - - result = kinetis_disable_wdog(target, sim_sdid); + result = kinetis_disable_wdog(k_chip); return result; } @@ -1400,20 +1512,26 @@ static void kinetis_invalidate_flash_cache(struct kinetis_chip *k_chip) { struct target *target = k_chip->target; - if (k_chip->flash_support & FS_INVALIDATE_CACHE_K) + switch (k_chip->cache_type) { + case KINETIS_CACHE_K: target_write_u8(target, FMC_PFB01CR + 2, 0xf0); /* Set CINV_WAY bits - request invalidate of all cache ways */ /* FMC_PFB0CR has same address and CINV_WAY bits as FMC_PFB01CR */ + break; - else if (k_chip->flash_support & FS_INVALIDATE_CACHE_L) + case KINETIS_CACHE_L: target_write_u8(target, MCM_PLACR + 1, 0x04); /* set bit CFCC - Clear Flash Controller Cache */ + break; - else if (k_chip->flash_support & FS_INVALIDATE_CACHE_MSCM) + case KINETIS_CACHE_MSCM: target_write_u32(target, MSCM_OCMDR0, 0x30); /* disable data prefetch and flash speculate */ + break; - return; + default: + break; + } } @@ -1647,7 +1765,7 @@ static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, uint32_t words_remaining = count / 4; - kinetis_disable_wdog(bank->target, k_chip->sim_sdid); + kinetis_disable_wdog(k_chip); /* try using a block write */ result = kinetis_write_block(bank, buffer, offset, words_remaining); @@ -1791,6 +1909,8 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) if ((k_chip->sim_sdid & (~KINETIS_SDID_K_SERIES_MASK)) == 0) { /* older K-series MCU */ uint32_t mcu_type = k_chip->sim_sdid & KINETIS_K_SDID_TYPE_MASK; + k_chip->cache_type = KINETIS_CACHE_K; + k_chip->watchdog_type = KINETIS_WDOG_K; switch (mcu_type) { case KINETIS_K_SDID_K10_M50: @@ -1799,7 +1919,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->pflash_sector_size = 1<<10; k_chip->nvm_sector_size = 1<<10; num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR; break; case KINETIS_K_SDID_K10_M72: case KINETIS_K_SDID_K20_M72: @@ -1812,7 +1932,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->pflash_sector_size = 2<<10; k_chip->nvm_sector_size = 1<<10; num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR; k_chip->max_flash_prog_size = 1<<10; break; case KINETIS_K_SDID_K10_M100: @@ -1828,7 +1948,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->pflash_sector_size = 2<<10; k_chip->nvm_sector_size = 2<<10; num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR; break; case KINETIS_K_SDID_K21_M120: case KINETIS_K_SDID_K22_M120: @@ -1837,7 +1957,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->max_flash_prog_size = 1<<10; k_chip->nvm_sector_size = 4<<10; num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; break; case KINETIS_K_SDID_K10_M120: case KINETIS_K_SDID_K20_M120: @@ -1847,7 +1967,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->pflash_sector_size = 4<<10; k_chip->nvm_sector_size = 4<<10; num_blocks = 4; - k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; break; default: LOG_ERROR("Unsupported K-family FAMID"); @@ -1869,12 +1989,15 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) switch (k_chip->sim_sdid & KINETIS_SDID_SERIESID_MASK) { case KINETIS_SDID_SERIESID_K: use_nvm_marking = true; + k_chip->cache_type = KINETIS_CACHE_K; + k_chip->watchdog_type = KINETIS_WDOG_K; + switch (k_chip->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) { case KINETIS_SDID_FAMILYID_K0X | KINETIS_SDID_SUBFAMID_KX2: /* K02FN64, K02FN128: FTFA, 2kB sectors */ k_chip->pflash_sector_size = 2<<10; num_blocks = 1; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD; cpu_mhz = 100; break; @@ -1890,7 +2013,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) /* MK24FN1M */ k_chip->pflash_sector_size = 4<<10; num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; k_chip->max_flash_prog_size = 1<<10; subfamid = 4; /* errata 1N83J fix */ break; @@ -1901,7 +2024,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) /* K22 with new-style SDID - smaller pflash with FTFA, 2kB sectors */ k_chip->pflash_sector_size = 2<<10; /* autodetect 1 or 2 blocks */ - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD; break; } LOG_ERROR("Unsupported Kinetis K22 DIEID"); @@ -1912,12 +2035,12 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) if ((k_chip->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K24FN256) { /* K24FN256 - smaller pflash with FTFA */ num_blocks = 1; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD; break; } /* K24FN1M without errata 7534 */ num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; k_chip->max_flash_prog_size = 1<<10; break; @@ -1932,7 +2055,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->nvm_sector_size = 4<<10; k_chip->max_flash_prog_size = 1<<10; num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; break; case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX6: @@ -1943,7 +2066,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->nvm_sector_size = 4<<10; k_chip->max_flash_prog_size = 1<<10; num_blocks = 4; - k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; cpu_mhz = 180; break; @@ -1953,7 +2076,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) /* K80FN256, K81FN256, K82FN256 */ k_chip->pflash_sector_size = 4<<10; num_blocks = 1; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K | FS_NO_CMD_BLOCKSTAT; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_NO_CMD_BLOCKSTAT; cpu_mhz = 150; break; @@ -1962,7 +2085,9 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) /* KL81Z128, KL82Z128 */ k_chip->pflash_sector_size = 2<<10; num_blocks = 1; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L | FS_NO_CMD_BLOCKSTAT; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_NO_CMD_BLOCKSTAT; + k_chip->cache_type = KINETIS_CACHE_L; + use_nvm_marking = false; snprintf(name, sizeof(name), "MKL8%uZ%%s7", subfamid); @@ -1982,7 +2107,9 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->pflash_sector_size = 1<<10; k_chip->nvm_sector_size = 1<<10; /* autodetect 1 or 2 blocks */ - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; + k_chip->flash_support = FS_PROGRAM_LONGWORD; + k_chip->cache_type = KINETIS_CACHE_L; + k_chip->watchdog_type = KINETIS_WDOG_COP; cpu_mhz = 48; if (subfamid == 3 && (familyid == 1 || familyid == 2)) @@ -1993,12 +2120,14 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) case KINETIS_SDID_SERIESID_KV: /* KV-series */ + k_chip->watchdog_type = KINETIS_WDOG_K; switch (k_chip->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) { case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX0: /* KV10: FTFA, 1kB sectors */ k_chip->pflash_sector_size = 1<<10; num_blocks = 1; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; + k_chip->flash_support = FS_PROGRAM_LONGWORD; + k_chip->cache_type = KINETIS_CACHE_L; strcpy(name, "MKV10Z%s7"); break; @@ -2006,7 +2135,8 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) /* KV11: FTFA, 2kB sectors */ k_chip->pflash_sector_size = 2<<10; num_blocks = 1; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; + k_chip->flash_support = FS_PROGRAM_LONGWORD; + k_chip->cache_type = KINETIS_CACHE_L; strcpy(name, "MKV11Z%s7"); break; @@ -2016,7 +2146,8 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) /* KV31: FTFA, 2kB sectors, 2 blocks */ k_chip->pflash_sector_size = 2<<10; /* autodetect 1 or 2 blocks */ - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD; + k_chip->cache_type = KINETIS_CACHE_K; break; case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX2: @@ -2025,7 +2156,8 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) /* KV4x: FTFA, 4kB sectors */ k_chip->pflash_sector_size = 4<<10; num_blocks = 1; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD; + k_chip->cache_type = KINETIS_CACHE_K; cpu_mhz = 168; break; @@ -2053,6 +2185,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) case KINETIS_SDID_SERIESID_KE: /* KE1x-series */ + k_chip->watchdog_type = KINETIS_WDOG32_KE1X; switch (k_chip->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK | KINETIS_SDID_PROJECTID_MASK)) { case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX4 | KINETIS_SDID_PROJECTID_KE1xZ: @@ -2062,7 +2195,8 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->nvm_sector_size = 2<<10; k_chip->max_flash_prog_size = 1<<9; num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_L; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; + k_chip->cache_type = KINETIS_CACHE_L; cpu_mhz = 72; snprintf(name, sizeof(name), "MKE%u%uZ%%s%u", @@ -2077,7 +2211,8 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->nvm_sector_size = 2<<10; k_chip->max_flash_prog_size = 1<<10; num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_MSCM; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; + k_chip->cache_type = KINETIS_CACHE_MSCM; cpu_mhz = 168; snprintf(name, sizeof(name), "MKE%u%uF%%s%u", diff --git a/tcl/target/klx.cfg b/tcl/target/klx.cfg index c2de9f7..7dd0404 100644 --- a/tcl/target/klx.cfg +++ b/tcl/target/klx.cfg @@ -37,7 +37,8 @@ flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME kinetis create_banks # Table 5-1. Clock Summary of KL25 Sub-Family Reference Manual -# specifies up to 1MHz for VLPR mode. +# specifies up to 1MHz for VLPR mode and up to 24MHz for run mode; +# Table 17 of Sub-Family Data Sheet rev4 lists 25MHz as the maximum frequency. adapter_khz 1000 reset_config srst_nogate @@ -53,10 +54,9 @@ if {![using_hla]} { cortex_m reset_config sysresetreq } -# Table 5-1. Clock Summary of KL25 Sub-Family Reference Manual -# specifies up to 24MHz for run mode; Table 17 of Sub-Family Data -# Sheet rev4 lists 25MHz as the maximum frequency. -# Uncoment only if VLPR mode is not used -#$_TARGETNAME configure -event reset-init { -# adapter_khz 24000 -#} +# Disable watchdog not to disturb OpenOCD algorithms running on MCU +# (e.g. armv7m_checksum_memory() in verify_image) +# Flash driver also disables watchdog before FTFA flash programming. +$_TARGETNAME configure -event reset-init { + kinetis disable_wdog +} diff --git a/tcl/target/kx.cfg b/tcl/target/kx.cfg index cf77713..7b03517 100644 --- a/tcl/target/kx.cfg +++ b/tcl/target/kx.cfg @@ -54,3 +54,11 @@ if {![using_hla]} { # perform a soft reset cortex_m reset_config sysresetreq } + +# Disable watchdog not to disturb OpenOCD algorithms running on MCU +# (e.g. armv7m_checksum_memory() in verify_image) +# Flash driver also disables watchdog before FTFA flash programming. +$_TARGETNAME configure -event reset-init { + kinetis disable_wdog +} + |