diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/flash/nor/kinetis.c | 84 |
1 files changed, 59 insertions, 25 deletions
diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index ecc60bec..18975498 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -1,7 +1,10 @@ /*************************************************************************** - * Copyright (C) 2011 by Mathias Kuester * + * Copyright (C) 2011 by Mathias Kuester * * kesmtp@freenet.de * * * + * Copyright (C) 2011 sleep(5) ltd * + * tomas@sleepfive.com * + * * * 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 * @@ -24,6 +27,10 @@ #include "imp.h" #include "helper/binarybuffer.h" +struct kinetis_flash_bank { + uint32_t nvm_start; +}; + static int kinetis_get_master_bank(struct flash_bank *bank, struct flash_bank **master_bank) { @@ -60,6 +67,8 @@ static int kinetis_update_bank_info(struct flash_bank *bank) FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command) { + struct kinetis_flash_bank *bank_info; + if (CMD_ARGC < 6) { LOG_ERROR("incomplete flash_bank kinetis configuration %d", CMD_ARGC); @@ -68,6 +77,12 @@ FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command) LOG_INFO("add flash_bank kinetis %s", bank->name); + bank_info = malloc(sizeof(struct kinetis_flash_bank)); + + memset(bank_info, 0, sizeof(struct kinetis_flash_bank)); + + bank->driver_priv = bank_info; + return ERROR_OK; } @@ -264,9 +279,11 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer, uint32_t offset, uint32_t count) { struct flash_bank *master_bank; - unsigned int i, result, fallback = 0; + unsigned int i, result, fallback = 0, nvm = 0; uint8_t buf[8]; uint32_t wc, w0 = 0, w1 = 0, w2 = 0; + struct kinetis_flash_bank * kbank = (struct kinetis_flash_bank *) + bank->driver_priv; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); @@ -279,31 +296,48 @@ static int kinetis_write(struct flash_bank *bank, uint8_t * buffer, return result; } - /* make flex ram available */ - w0 = (0x81 << 24) | 0x00ff0000; + if (offset >= kbank->nvm_start) + nvm = 1; - result = kinetis_ftfl_command(bank, w0, w1, w2); - - if (result != ERROR_OK) { - return ERROR_FLASH_OPERATION_FAILED; + if (!nvm && (offset + count) > kbank->nvm_start) { + /* we could flash this in two goes, but if the segment + spans across the pflash/nvm boundary, something is probably + not right. + */ + LOG_ERROR("Segment spans NVM boundary"); + return ERROR_FLASH_DST_OUT_OF_BANK; } - /* check if ram ready */ - result = target_read_memory(bank->target, 0x40020001, 1, 1, buf); + if (nvm) { + LOG_DEBUG("flash write into NVM @%08X", offset); - if (result != ERROR_OK) { - return result; - } + /* make flex ram available */ + w0 = (0x81 << 24) | 0x00ff0000; - if (!(buf[0] & (1 << 1))) { - /* fallback to longword write */ - fallback = 1; + result = kinetis_ftfl_command(bank, w0, w1, w2); - LOG_WARNING - ("ram not ready, fallback to slow longword write (FCNFG: %02X)", - buf[0]); + if (result != ERROR_OK) + return ERROR_FLASH_OPERATION_FAILED; + + /* check if ram ready */ + result = target_read_memory(bank->target, 0x40020001, 1, 1, buf); + + if (result != ERROR_OK) + return result; + + if (!(buf[0] & (1 << 1))) { + /* fallback to longword write */ + fallback = 1; + + LOG_WARNING("ram not ready, fallback to slow longword write (FCNFG: %02X)", + buf[0]); + } + } else { + LOG_DEBUG("flash write into PFLASH @08%X", offset); + fallback = 1; } + /* program section command */ if (fallback == 0) { for (i = 0; i < count; i += (2 * 1024)) { @@ -364,7 +398,7 @@ static int kinetis_probe(struct flash_bank *bank) int result, i; uint8_t buf[4]; uint32_t sim_sdid, sim_fcfg1, sim_fcfg2, offset = 0; - uint32_t nvm_size, pf_size, flash_size, ee_size; + uint32_t nvm_size, pf_size, ee_size; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); @@ -425,9 +459,6 @@ static int kinetis_probe(struct flash_bank *bank) break; } - /* pf_size is the total size */ - flash_size = pf_size - nvm_size; - switch ((sim_fcfg1 >> 16) & 0x0f) { case 0x02: ee_size = 4 * 1024; @@ -458,11 +489,14 @@ static int kinetis_probe(struct flash_bank *bank) break; } + ((struct kinetis_flash_bank *) bank->driver_priv)->nvm_start = + pf_size - nvm_size; + LOG_DEBUG("NVM: %d PF: %d EE: %d BL1: %d", nvm_size, pf_size, ee_size, (sim_fcfg2 >> 23) & 1); - if (flash_size != bank->size) { - LOG_WARNING("flash size is different %d != %d", flash_size, + if (pf_size != bank->size) { + LOG_WARNING("flash size is different %d != %d", pf_size, bank->size); } |