From: Tomas Vanek Date: Mon, 26 Dec 2016 14:20:33 +0000 (+0100) Subject: flash Kinetis: implement automatic bank creation based on device probe X-Git-Tag: v0.11.0-rc1~1375 X-Git-Url: https://review.openocd.org/gitweb?a=commitdiff_plain;h=c4d4c32a504f1a63f0200efdd175d21bfe8cc3af;p=openocd.git flash Kinetis: implement automatic bank creation based on device probe 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 --- diff --git a/doc/openocd.texi b/doc/openocd.texi index ac09db5e2c..5fd43009d8 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 8ebdbbea6b..dc3dc45976 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 94b175f2de..b1200cec2b 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 db2d1a4282..6a3f509ed2 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 0df6612f70..c2de9f7d50 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 b39ee3dd18..cf777135c6 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