From: Tomas Vanek Date: Mon, 12 Oct 2015 22:15:16 +0000 (+0200) Subject: Kinetis: check/switch run mode before flash operation X-Git-Tag: v0.10.0-rc1~256 X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=commitdiff_plain;h=69db898b3b71eeeaa7aa6f3593467b3a61f11e88;hp=b32b2fcadf59986e18bf3c24171be5e17d60447d Kinetis: check/switch run mode before flash operation FTFx flash controller requires MCU in normal RUN mode. Flash cannot be erased, programmed or blank checked in VLPR or HSRUN modes. VLPR mode is switched to RUN mode as it does not require any changes in clock generator setting. VLPR can be active from reset on some KLx devices (with some FOPT setting) so 'reset init' might not be sufficient to get device to normal RUN. Any other mode than RUN or VLPR is reported as an error. Change-Id: I60f494ce0d534b04870c6219d9b05f66f7244433 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3012 Tested-by: jenkins --- diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index db098bbb27..7907b8c386 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -94,6 +94,13 @@ #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 @@ -951,6 +958,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 +1017,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 +1092,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 */ @@ -1662,14 +1708,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 +1877,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,