This device differs a lot from others in KL series.
Unfortunately the System Integration Module, where device
identification resides, moved to a new address so probe now have
to try both addresses of SIM_SDID.
Introduce a new bank creation option: -sim-base to ensure error free probe.
WDOG32 is slightly different from KE1x and on different address.
System Mode Controler changed layout to word aligned.
Change-Id: I2c9dca0c4ad4228fcc941d6078d15f5e394833ff
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: http://openocd.zylin.com/4059
Tested-by: jenkins
Reviewed-by: Joakim NohlgÄrd <joakim.nohlgard@eistec.se>
Reviewed-by: Freddie Chopin <freddie.chopin@gmail.com>
identification register, and autoconfigures itself.
Use kinetis_ke driver for KE0x devices.
identification register, and autoconfigures itself.
Use kinetis_ke driver for KE0x devices.
+The @var{kinetis} driver defines option:
+@itemize
+@item -sim-base @var{addr} ... base of System Integration Module where chip identification resides. Driver tries two known locations if option is omitted.
+@end itemize
+
@example
flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME
@end example
@example
flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME
@end example
#define FTFx_FCCOB3 0x40020004
#define FTFx_FPROT3 0x40020010
#define FTFx_FDPROT 0x40020017
#define FTFx_FCCOB3 0x40020004
#define FTFx_FPROT3 0x40020010
#define FTFx_FDPROT 0x40020017
-#define SIM_SDID 0x40048024
-#define SIM_SOPT1 0x40047000
-#define SIM_FCFG1 0x4004804c
-#define SIM_FCFG2 0x40048050
+#define SIM_BASE 0x40047000
+#define SIM_BASE_KL28 0x40074000
#define SIM_COPC 0x40048100
#define SIM_COPC 0x40048100
+ /* SIM_COPC does not exist on devices with changed SIM_BASE */
#define WDOG_BASE 0x40052000
#define WDOG32_KE1X 0x40052000
#define WDOG32_KL28 0x40076000
#define SMC_PMCTRL 0x4007E001
#define SMC_PMSTAT 0x4007E003
#define WDOG_BASE 0x40052000
#define WDOG32_KE1X 0x40052000
#define WDOG32_KL28 0x40076000
#define SMC_PMCTRL 0x4007E001
#define SMC_PMSTAT 0x4007E003
+#define SMC32_PMCTRL 0x4007E00C
+#define SMC32_PMSTAT 0x4007E014
#define MCM_PLACR 0xF000300C
/* Offsets */
#define MCM_PLACR 0xF000300C
/* Offsets */
+#define SIM_SOPT1_OFFSET 0x0000
+#define SIM_SDID_OFFSET 0x1024
+#define SIM_FCFG1_OFFSET 0x104c
+#define SIM_FCFG2_OFFSET 0x1050
+
#define WDOG_STCTRLH_OFFSET 0
#define WDOG32_CS_OFFSET 0
#define WDOG_STCTRLH_OFFSET 0
#define WDOG32_CS_OFFSET 0
uint32_t dflash_size; /* accessible rest of FlexNVM if EEPROM backup uses part of FlexNVM */
uint32_t progr_accel_ram;
uint32_t dflash_size; /* accessible rest of FlexNVM if EEPROM backup uses part of FlexNVM */
uint32_t progr_accel_ram;
enum {
FS_PROGRAM_SECTOR = 1,
enum {
FS_PROGRAM_SECTOR = 1,
KINETIS_WDOG32_KL28,
} watchdog_type;
KINETIS_WDOG32_KL28,
} watchdog_type;
+ enum {
+ KINETIS_SMC,
+ KINETIS_SMC32,
+ } sysmodectrlr_type;
+
char name[40];
unsigned num_banks;
char name[40];
unsigned num_banks;
+static int kinetis_chip_options(struct kinetis_chip *k_chip, int argc, const char *argv[])
+{
+ int i;
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i], "-sim-base") == 0) {
+ if (i + 1 < argc)
+ k_chip->sim_base = strtoul(argv[++i], NULL, 0);
+ } else
+ LOG_ERROR("Unsupported flash bank option %s", argv[i]);
+ }
+ return ERROR_OK;
+}
+
FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command)
{
struct target *target = bank->target;
struct kinetis_chip *k_chip;
struct kinetis_flash_bank *k_bank;
FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command)
{
struct target *target = bank->target;
struct kinetis_chip *k_chip;
struct kinetis_flash_bank *k_bank;
if (CMD_ARGC < 6)
return ERROR_COMMAND_SYNTAX_ERROR;
if (CMD_ARGC < 6)
return ERROR_COMMAND_SYNTAX_ERROR;
}
k_chip->target = target;
}
k_chip->target = target;
+
+ /* only the first defined bank can define chip options */
+ retval = kinetis_chip_options(k_chip, CMD_ARGC - 6, CMD_ARGV + 6);
+ if (retval != ERROR_OK)
+ return retval;
}
if (k_chip->num_banks >= KINETIS_MAX_BANKS) {
}
if (k_chip->num_banks >= KINETIS_MAX_BANKS) {
-static int kinetis_check_run_mode(struct target *target)
+static int kinetis_read_pmstat(struct kinetis_chip *k_chip, uint8_t *pmstat)
+{
+ int result;
+ uint32_t stat32;
+ struct target *target = k_chip->target;
+
+ switch (k_chip->sysmodectrlr_type) {
+ case KINETIS_SMC:
+ result = target_read_u8(target, SMC_PMSTAT, pmstat);
+ return result;
+
+ case KINETIS_SMC32:
+ result = target_read_u32(target, SMC32_PMSTAT, &stat32);
+ if (result == ERROR_OK)
+ *pmstat = stat32 & 0xff;
+ return result;
+ }
+ return ERROR_FAIL;
+}
+
+static int kinetis_check_run_mode(struct kinetis_chip *k_chip)
- uint8_t pmctrl, pmstat;
+ uint8_t pmstat;
+ struct target *target;
+
+ if (k_chip == NULL) {
+ LOG_ERROR("Chip not probed.");
+ return ERROR_FAIL;
+ }
+ target = k_chip->target;
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
- result = target_read_u8(target, SMC_PMSTAT, &pmstat);
+ result = kinetis_read_pmstat(k_chip, &pmstat);
if (result != ERROR_OK)
return result;
if (result != ERROR_OK)
return result;
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.");
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);
+
+ switch (k_chip->sysmodectrlr_type) {
+ case KINETIS_SMC:
+ result = target_write_u8(target, SMC_PMCTRL, PM_CTRL_RUNM_RUN);
+ break;
+
+ case KINETIS_SMC32:
+ result = target_write_u32(target, SMC32_PMCTRL, PM_CTRL_RUNM_RUN);
+ break;
+ }
if (result != ERROR_OK)
return result;
for (i = 100; i; i--) {
if (result != ERROR_OK)
return result;
for (i = 100; i; i--) {
- result = target_read_u8(target, SMC_PMSTAT, &pmstat);
+ result = kinetis_read_pmstat(k_chip, &pmstat);
if (result != ERROR_OK)
return result;
if (result != ERROR_OK)
return result;
{
int result, i;
struct kinetis_flash_bank *k_bank = bank->driver_priv;
{
int result, i;
struct kinetis_flash_bank *k_bank = bank->driver_priv;
+ struct kinetis_chip *k_chip = k_bank->k_chip;
- result = kinetis_check_run_mode(bank->target);
+ result = kinetis_check_run_mode(k_chip);
if (result != ERROR_OK)
return result;
if (result != ERROR_OK)
return result;
bool set_fcf = false;
int sect = 0;
struct kinetis_flash_bank *k_bank = bank->driver_priv;
bool set_fcf = false;
int sect = 0;
struct kinetis_flash_bank *k_bank = bank->driver_priv;
+ struct kinetis_chip *k_chip = k_bank->k_chip;
- result = kinetis_check_run_mode(bank->target);
+ result = kinetis_check_run_mode(k_chip);
if (result != ERROR_OK)
return result;
if (result != ERROR_OK)
return result;
- result = target_read_u32(target, SIM_SDID, &k_chip->sim_sdid);
+ if (k_chip->sim_base)
+ result = target_read_u32(target, k_chip->sim_base + SIM_SDID_OFFSET, &k_chip->sim_sdid);
+ else {
+ result = target_read_u32(target, SIM_BASE + SIM_SDID_OFFSET, &k_chip->sim_sdid);
+ if (result == ERROR_OK)
+ k_chip->sim_base = SIM_BASE;
+ else {
+ result = target_read_u32(target, SIM_BASE_KL28 + SIM_SDID_OFFSET, &k_chip->sim_sdid);
+ if (result == ERROR_OK)
+ k_chip->sim_base = SIM_BASE_KL28;
+ }
+ }
if (result != ERROR_OK)
return result;
if (result != ERROR_OK)
return result;
case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX2: {
/* MK24FN1M reports as K22, this should detect it (according to errata note 1N83J) */
uint32_t sopt1;
case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX2: {
/* MK24FN1M reports as K22, this should detect it (according to errata note 1N83J) */
uint32_t sopt1;
- result = target_read_u32(target, SIM_SOPT1, &sopt1);
+ result = target_read_u32(target, k_chip->sim_base + SIM_SOPT1_OFFSET, &sopt1);
if (result != ERROR_OK)
return result;
if (result != ERROR_OK)
return result;
k_chip->watchdog_type = KINETIS_WDOG_COP;
cpu_mhz = 48;
k_chip->watchdog_type = KINETIS_WDOG_COP;
cpu_mhz = 48;
- if (subfamid == 3 && (familyid == 1 || familyid == 2))
+ switch (k_chip->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) {
+ case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX3:
+ case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX3:
+ break;
+
+ case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX8:
+ cpu_mhz = 72;
+ k_chip->pflash_sector_size = 2<<10;
+ num_blocks = 2;
+ k_chip->watchdog_type = KINETIS_WDOG32_KL28;
+ k_chip->sysmodectrlr_type = KINETIS_SMC32;
+ break;
+ }
+
snprintf(name, sizeof(name), "MKL%u%uZ%%s%u",
familyid, subfamid, cpu_mhz / 10);
break;
snprintf(name, sizeof(name), "MKL%u%uZ%%s%u",
familyid, subfamid, cpu_mhz / 10);
break;
return ERROR_FLASH_OPER_UNSUPPORTED;
}
return ERROR_FLASH_OPER_UNSUPPORTED;
}
- result = target_read_u32(target, SIM_FCFG1, &k_chip->sim_fcfg1);
+ result = target_read_u32(target, k_chip->sim_base + SIM_FCFG1_OFFSET, &k_chip->sim_fcfg1);
if (result != ERROR_OK)
return result;
if (result != ERROR_OK)
return result;
- result = target_read_u32(target, SIM_FCFG2, &k_chip->sim_fcfg2);
+ result = target_read_u32(target, k_chip->sim_base + SIM_FCFG2_OFFSET, &k_chip->sim_fcfg2);
if (result != ERROR_OK)
return result;
if (result != ERROR_OK)
return result;
int result;
/* suprisingly blank check does not work in VLPR and HSRUN modes */
int result;
/* suprisingly blank check does not work in VLPR and HSRUN modes */
- result = kinetis_check_run_mode(bank->target);
+ result = kinetis_check_run_mode(k_chip);
if (result != ERROR_OK)
return result;
if (result != ERROR_OK)
return result;
struct kinetis_chip *k_chip;
uint32_t sim_fcfg1;
struct kinetis_chip *k_chip;
uint32_t sim_fcfg1;
+ k_chip = kinetis_get_chip(target);
+
if (CMD_ARGC >= 2) {
if (strcmp(CMD_ARGV[0], "dataflash") == 0)
sz_type = DF_SIZE;
if (CMD_ARGC >= 2) {
if (strcmp(CMD_ARGV[0], "dataflash") == 0)
sz_type = DF_SIZE;
}
switch (sz_type) {
case SHOW_INFO:
}
switch (sz_type) {
case SHOW_INFO:
- result = target_read_u32(target, SIM_FCFG1, &sim_fcfg1);
+ if (k_chip == NULL) {
+ LOG_ERROR("Chip not probed.");
+ return ERROR_FAIL;
+ }
+ result = target_read_u32(target, k_chip->sim_base + SIM_FCFG1_OFFSET, &sim_fcfg1);
if (result != ERROR_OK)
return result;
if (result != ERROR_OK)
return result;
LOG_INFO("DEPART 0x%" PRIx8 ", EEPROM size code 0x%" PRIx8,
flex_nvm_partition_code, ee_size_code);
LOG_INFO("DEPART 0x%" PRIx8 ", EEPROM size code 0x%" PRIx8,
flex_nvm_partition_code, ee_size_code);
- result = kinetis_check_run_mode(target);
+ result = kinetis_check_run_mode(k_chip);
if (result != ERROR_OK)
return result;
if (result != ERROR_OK)
return result;
command_print(CMD_CTX, "FlexNVM partition set. Please reset MCU.");
command_print(CMD_CTX, "FlexNVM partition set. Please reset MCU.");
- k_chip = kinetis_get_chip(target);
if (k_chip) {
first_nvm_bank = k_chip->num_pflash_blocks;
num_blocks = k_chip->num_pflash_blocks + k_chip->num_nvm_blocks;
if (k_chip) {
first_nvm_bank = k_chip->num_pflash_blocks;
num_blocks = k_chip->num_pflash_blocks + k_chip->num_nvm_blocks;
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)