From c4d4c32a504f1a63f0200efdd175d21bfe8cc3af Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 26 Dec 2016 15:20:33 +0100 Subject: [PATCH] flash Kinetis: implement automatic bank creation based on device probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kinetis flash driver services huge number of MCU types. They have one, two or four flash banks with option of FlexNVM. It would require ~36 config files just for Kx series, more for KLx, KVx and KE1x. The change implements alternative approach: - configuration file creates just one pflash bank (common for all devices) - when a device is probed, additional pflash or flexnvm banks are created based on flash layout of the connected MCU - created banks have names with optional numbering e.g. kx.pflash0 kx.pflash1 kx.flexnvm0 kx.flexnvm1 - the first bank gets renamed if numbering is used Automatic bank creation is enabled by tcl command 'kinetis create_banks'. Used solution has a drawback: other banks than pflash0 are not accessible until pflash0 is probed. Fortunately gdb attach and standard programming accesses banks in right sequence. Change-Id: I5b9037cbefdb8a4176b7715fbcc3af4da4c1ab60 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3925 Tested-by: jenkins Reviewed-by: Joakim NohlgÄrd Reviewed-by: Freddie Chopin --- doc/openocd.texi | 6 +++ src/flash/nor/kinetis.c | 102 ++++++++++++++++++++++++++++++++++++++++ tcl/target/ke1xf.cfg | 2 - tcl/target/ke1xz.cfg | 2 - tcl/target/klx.cfg | 6 ++- tcl/target/kx.cfg | 6 ++- 6 files changed, 116 insertions(+), 8 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index ac09db5e2..5fd43009d 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5372,6 +5372,12 @@ Use kinetis_ke driver for KE0x devices. flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME @end example +@deffn Command {kinetis create_banks} +Configuration command enables automatic creation of additional flash banks +based on real flash layout of device. Banks are created during device probe. +Use 'flash probe 0' to force probe. +@end deffn + @deffn Command {kinetis fcf_source} [protection|write] Select what source is used when writing to a Flash Configuration Field. @option{protection} mode builds FCF content from protection bits previously diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 8ebdbbea6..dc3dc4597 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -356,6 +356,7 @@ static const struct kinetis_type kinetis_types_old[] = { static bool allow_fcf_writes; static uint8_t fcf_fopt = 0xff; +static bool create_banks; struct flash_driver kinetis_flash; @@ -859,6 +860,87 @@ FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command) return ERROR_OK; } + +static int kinetis_create_missing_banks(struct kinetis_chip *k_chip) +{ + unsigned bank_idx; + unsigned num_blocks; + struct kinetis_flash_bank *k_bank; + struct flash_bank *bank; + char base_name[80], name[80], num[4]; + char *class, *p; + + num_blocks = k_chip->num_pflash_blocks + k_chip->num_nvm_blocks; + if (num_blocks > KINETIS_MAX_BANKS) { + LOG_ERROR("Only %u Kinetis flash banks are supported", KINETIS_MAX_BANKS); + return ERROR_FAIL; + } + + bank = k_chip->banks[0].bank; + if (bank && bank->name) { + strncpy(base_name, bank->name, sizeof(base_name)); + p = strstr(base_name, ".pflash"); + if (p) { + *p = '\0'; + if (k_chip->num_pflash_blocks > 1) { + /* rename first bank if numbering is needed */ + snprintf(name, sizeof(name), "%s.pflash0", base_name); + free((void *)bank->name); + bank->name = strdup(name); + } + } + } else { + strncpy(base_name, target_name(k_chip->target), sizeof(base_name)); + p = strstr(base_name, ".cpu"); + if (p) + *p = '\0'; + } + + for (bank_idx = 1; bank_idx < num_blocks; bank_idx++) { + k_bank = &(k_chip->banks[bank_idx]); + bank = k_bank->bank; + + if (bank) + continue; + + num[0] = '\0'; + + if (bank_idx < k_chip->num_pflash_blocks) { + class = "pflash"; + if (k_chip->num_pflash_blocks > 1) + snprintf(num, sizeof(num), "%u", bank_idx); + } else { + class = "flexnvm"; + if (k_chip->num_nvm_blocks > 1) + snprintf(num, sizeof(num), "%u", + bank_idx - k_chip->num_pflash_blocks); + } + + bank = calloc(sizeof(struct flash_bank), 1); + if (bank == NULL) + return ERROR_FAIL; + + bank->target = k_chip->target; + bank->driver = &kinetis_flash; + bank->default_padded_value = bank->erased_value = 0xff; + + snprintf(name, sizeof(name), "%s.%s%s", + base_name, class, num); + bank->name = strdup(name); + + bank->driver_priv = k_bank = &(k_chip->banks[k_chip->num_banks]); + k_bank->k_chip = k_chip; + k_bank->bank_number = bank_idx; + k_bank->bank = bank; + if (k_chip->num_banks <= bank_idx) + k_chip->num_banks = bank_idx + 1; + + flash_bank_add(bank); + } + return ERROR_OK; +} + + /* Disable the watchdog on Kinetis devices */ int kinetis_disable_wdog(struct target *target, uint32_t sim_sdid) { @@ -2176,6 +2258,10 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) } k_chip->probed = true; + + if (create_banks) + kinetis_create_missing_banks(k_chip); + return ERROR_OK; } @@ -2596,6 +2682,16 @@ COMMAND_HANDLER(kinetis_fopt_handler) return ERROR_OK; } +COMMAND_HANDLER(kinetis_create_banks_handler) +{ + if (CMD_ARGC > 0) + return ERROR_COMMAND_SYNTAX_ERROR; + + create_banks = true; + + return ERROR_OK; +} + static const struct command_registration kinetis_security_command_handlers[] = { { @@ -2666,6 +2762,12 @@ static const struct command_registration kinetis_exec_command_handlers[] = { .usage = "[num]", .handler = kinetis_fopt_handler, }, + { + .name = "create_banks", + .mode = COMMAND_CONFIG, + .help = "Driver creates additional banks if device with two/four flash blocks is probed", + .handler = kinetis_create_banks_handler, + }, COMMAND_REGISTRATION_DONE }; diff --git a/tcl/target/ke1xf.cfg b/tcl/target/ke1xf.cfg index 94b175f2d..b1200cec2 100644 --- a/tcl/target/ke1xf.cfg +++ b/tcl/target/ke1xf.cfg @@ -5,5 +5,3 @@ set CHIPNAME ke source [find target/kx.cfg] - -flash bank flexnvm kinetis 0 0 0 0 $_TARGETNAME diff --git a/tcl/target/ke1xz.cfg b/tcl/target/ke1xz.cfg index db2d1a428..6a3f509ed 100644 --- a/tcl/target/ke1xz.cfg +++ b/tcl/target/ke1xz.cfg @@ -5,5 +5,3 @@ set CHIPNAME ke source [find target/klx.cfg] - -flash bank flexnvm kinetis 0 0 0 0 $_TARGETNAME diff --git a/tcl/target/klx.cfg b/tcl/target/klx.cfg index 0df6612f7..c2de9f7d5 100644 --- a/tcl/target/klx.cfg +++ b/tcl/target/klx.cfg @@ -1,5 +1,6 @@ # -# Freescale Kinetis KL series devices +# NXP (former Freescale) Kinetis KL series devices +# Also used for Cortex-M0+ equipped members of KVx and KE1xZ series # source [find target/swj-dp.tcl] @@ -31,8 +32,9 @@ target create $_TARGETNAME cortex_m -chain-position $_CHIPNAME.cpu $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 -set _FLASHNAME $_CHIPNAME.flash +set _FLASHNAME $_CHIPNAME.pflash 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. diff --git a/tcl/target/kx.cfg b/tcl/target/kx.cfg index b39ee3dd1..cf777135c 100644 --- a/tcl/target/kx.cfg +++ b/tcl/target/kx.cfg @@ -1,5 +1,6 @@ # -# Freescale Kinetis Kx series devices +# NXP (former Freescale) Kinetis Kx series devices +# Also used for Cortex-M4 equipped members of KVx and KE1xF series # source [find target/swj-dp.tcl] @@ -35,8 +36,9 @@ target create $_TARGETNAME cortex_m -chain-position $_CHIPNAME.cpu $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 -set _FLASHNAME $_CHIPNAME.flash +set _FLASHNAME $_CHIPNAME.pflash flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME +kinetis create_banks adapter_khz 1000