diff --git a/src/command.c b/src/command.c index 2758d31b..caaaa57a 100644 --- a/src/command.c +++ b/src/command.c @@ -257,9 +257,18 @@ bool cmd_swdp_scan(target *t, int argc, char **argv) static void display_target(int i, target *t, void *context) { (void)context; - gdb_outf("%2d %c %s %s\n", i, target_attached(t)?'*':' ', - target_driver_name(t), - (target_core_name(t)) ? target_core_name(t): ""); + if (!strcmp(target_driver_name(t), "ARM Cortex-M")) { + gdb_outf("***%2d%sUnknown %s Designer %3x Partno %3x %s\n", + i, target_attached(t)?" * ":" ", + target_driver_name(t), + target_designer(t), + target_idcode(t), + (target_core_name(t)) ? target_core_name(t): ""); + } else { + gdb_outf("%2d %c %s %s\n", i, target_attached(t)?'*':' ', + target_driver_name(t), + (target_core_name(t)) ? target_core_name(t): ""); + } } bool cmd_targets(target *t, int argc, char **argv) diff --git a/src/include/target.h b/src/include/target.h index 106ac273..7c71340f 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -51,6 +51,8 @@ void target_detach(target *t); bool target_attached(target *t); const char *target_driver_name(target *t); const char *target_core_name(target *t); +unsigned int target_designer(target *t); +unsigned int target_idcode(target *t); /* Memory access functions */ bool target_mem_map(target *t, char *buf, size_t len); diff --git a/src/platforms/pc/cl_utils.c b/src/platforms/pc/cl_utils.c index f6efc7d3..60191f14 100644 --- a/src/platforms/pc/cl_utils.c +++ b/src/platforms/pc/cl_utils.c @@ -265,9 +265,18 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) static void display_target(int i, target *t, void *context) { (void)context; - DEBUG_INFO("*** %2d %c %s %s\n", i, target_attached(t)?'*':' ', - target_driver_name(t), - (target_core_name(t)) ? target_core_name(t): ""); + if (!strcmp(target_driver_name(t), "ARM Cortex-M")) { + DEBUG_INFO("***%2d%sUnknown %s Designer %3x Partno %3x %s\n", + i, target_attached(t)?" * ":" ", + target_driver_name(t), + target_designer(t), + target_idcode(t), + (target_core_name(t)) ? target_core_name(t): ""); + } else { + DEBUG_INFO("*** %2d %c %s %s\n", i, target_attached(t)?'*':' ', + target_driver_name(t), + (target_core_name(t)) ? target_core_name(t): ""); + } } int cl_execute(BMP_CL_OPTIONS_t *opt) diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 5f032a3b..49023eba 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -36,6 +36,13 @@ * are consistently named and accessible when needed in the codebase. */ +/* Values from ST RM0436 (STM32MP157), 66.9 APx_IDR + * and ST RM0438 (STM32L5) 52.3.1, AP_IDR */ +#define ARM_AP_TYPE_AHB 1 +#define ARM_AP_TYPE_APB 3 +#define ARM_AP_TYPE_AXI 4 +#define ARM_AP_TYPE_AHB5 5 + /* ROM table CIDR values */ #define CIDR0_OFFSET 0xFF0 /* DBGCID0 */ #define CIDR1_OFFSET 0xFF4 /* DBGCID1 */ @@ -191,10 +198,13 @@ static const struct { {0x00d, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight ETM11", "(Embedded Trace)")}, {0x00e, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M7 FBP", "(Flash Patch and Breakpoint)")}, {0x101, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("System TSGEN", "(Time Stamp Generator)")}, + {0x471, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M0 ROM", "(Cortex-M0 ROM)")}, {0x490, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A15 GIC", "(Generic Interrupt Controller)")}, + {0x4c0, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M0+ ROM", "(Cortex-M0+ ROM)")}, + {0x4c4, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M4 ROM", "(Cortex-M4 ROM)")}, {0x4c7, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M7 PPB", "(Private Peripheral Bus ROM Table)")}, {0x906, 0x14, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight CTI", "(Cross Trigger)")}, - {0x907, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight ETB", "(Trace Buffer)")}, + {0x907, 0x21, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight ETB", "(Trace Buffer)")}, {0x908, 0x12, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight CSTF", "(Trace Funnel)")}, {0x910, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight ETM9", "(Embedded Trace)")}, {0x912, 0x11, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight TPIU", "(Trace Port Interface Unit)")}, @@ -299,6 +309,99 @@ uint64_t adiv5_ap_read_pidr(ADIv5_AP_t *ap, uint32_t addr) return pidr; } +/* Prepare to read SYSROM and SYSROM PIDR + * + * Try hard to halt, if not connecting under reset + * Request TRCENA and default vector catch + * release from reset when connecting under reset. + * + * E.g. Stm32F7 + * - fails reading romtable in WFI + * - fails with some AP accesses when romtable is read under reset. + * - fails reading some ROMTABLE entries w/o TRCENA + * - fails reading outside SYSROM when halted from WFI and + * DBGMCU_CR not set. + * + * Keep a copy of DEMCR at startup to restore with exit, to + * not interrupt tracing initialed by the CPU. + */ +static bool cortexm_prepare(ADIv5_AP_t *ap) +{ + platform_timeout to ; + platform_timeout_set(&to, cortexm_wait_timeout); + uint32_t dhcsr_ctl = CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN | + CORTEXM_DHCSR_C_HALT; + uint32_t dhcsr_valid = CORTEXM_DHCSR_S_HALT | CORTEXM_DHCSR_C_DEBUGEN; +#ifdef PLATFORM_HAS_DEBUG + uint32_t start_time = platform_time_ms(); +#endif + uint32_t dhcsr; + bool reset_seen = false; + while (true) { + adiv5_mem_write(ap, CORTEXM_DHCSR, &dhcsr_ctl, sizeof(dhcsr_ctl)); + dhcsr = adiv5_mem_read32(ap, CORTEXM_DHCSR); + /* On a sleeping STM32F7, invalid DHCSR reads with e.g. 0xffffffff and + * 0x0xA05F0000 may happen. + * M23/33 will have S_SDE set when debug is allowed + */ + if ((dhcsr != 0xffffffff) && /* Invalid read */ + ((dhcsr & 0xf000fff0) == 0)) {/* Check RAZ bits */ + if ((dhcsr & CORTEXM_DHCSR_S_RESET_ST) && !reset_seen) { + if (connect_assert_srst) + break; + reset_seen = true; + continue; + } + if ((dhcsr & dhcsr_valid) == dhcsr_valid) { /* Halted */ + DEBUG_INFO("Halt via DHCSR: success %08" PRIx32 " after %" + PRId32 "ms\n", + dhcsr, platform_time_ms() - start_time); + break; + } + } + if (platform_timeout_is_expired(&to)) { + DEBUG_WARN("Halt via DHCSR: Failure DHCSR %08" PRIx32 " after % " + PRId32 "ms\nTry again, evt. with longer timeout or " + "connect under reset\n", + dhcsr, platform_time_ms() - start_time); + return false; + } + } + ap->ap_cortexm_demcr = adiv5_mem_read32(ap, CORTEXM_DEMCR); + uint32_t demcr = CORTEXM_DEMCR_TRCENA | CORTEXM_DEMCR_VC_HARDERR | + CORTEXM_DEMCR_VC_CORERESET; + adiv5_mem_write(ap, CORTEXM_DEMCR, &demcr, sizeof(demcr)); + platform_timeout_set(&to, cortexm_wait_timeout); + platform_srst_set_val(false); + while (1) { + dhcsr = adiv5_mem_read32(ap, CORTEXM_DHCSR); + if (!(dhcsr & CORTEXM_DHCSR_S_RESET_ST)) + break; + if (platform_timeout_is_expired(&to)) { + DEBUG_WARN("Error releasing from srst\n"); + return false; + } + } + /* Apply device specific settings for successfull Romtable scan + * + * STM32F7 in WFI will not read ROMTABLE when using WFI + */ + if ((ap->dp->targetid >> 1 & 0x7ff) == 0x20) { + uint32_t dbgmcu_cr = 7; + uint32_t dbgmcu_cr_addr = 0xE0042004; + switch ((ap->dp->targetid >> 16) & 0xfff) { + case 0x449: + case 0x451: + case 0x452: + ap->ap_storage = adiv5_mem_read32(ap, dbgmcu_cr_addr); + dbgmcu_cr = ap->ap_storage | 7; + adiv5_mem_write(ap, dbgmcu_cr_addr, &dbgmcu_cr, sizeof(dbgmcu_cr)); + break; + } + } + return true; +} + static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, int num_entry) { (void) num_entry; @@ -333,8 +436,10 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, /* ROM table */ if (cid_class == cidc_romtab) { + uint16_t designer = ((pidr >> 24) & 0xf00) | ((pidr >> 12) & 0x7f); + uint16_t partno = pidr & 0xfff; +#if defined(ENABLE_DEBUG) && defined(PLATFORM_HAS_DEBUG) /* Check SYSMEM bit */ -#if defined(ENABLE_DEBUG) uint32_t memtype = adiv5_mem_read32(ap, addr | ADIV5_ROM_MEMTYPE) & ADIV5_ROM_MEMTYPE_SYSMEM; @@ -342,11 +447,14 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, DEBUG_WARN("Fault reading ROM table entry\n"); } - DEBUG_INFO("ROM: Table BASE=0x%" PRIx32 " SYSMEM=0x%" PRIx32 - ", PIDR 0x%02" PRIx32 "%08" PRIx32 "\n", addr, - memtype, (uint32_t)(pidr >> 32), (uint32_t)pidr); + DEBUG_INFO("ROM: Table BASE=0x%" PRIx32 " SYSMEM=0x%08" PRIx32 + ", designer %3x Partno %3x\n", addr, memtype, designer, + partno); #endif - + if (recursion == 0) { + ap->ap_designer = designer; + ap->ap_partno = partno; + } for (int i = 0; i < 960; i++) { adiv5_dp_error(ap->dp); uint32_t entry = adiv5_mem_read32(ap, addr + i*4); @@ -365,7 +473,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, } /* Probe recursively */ - res |= adiv5_component_probe( + adiv5_component_probe( ap, addr + (entry & ADIV5_ROM_ROMENTRY_OFFSET), recursion + 1, i); } @@ -424,7 +532,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, switch (pidr_pn_bits[i].arch) { case aa_cortexm: DEBUG_INFO("%s-> cortexm_probe\n", indent + 1); - cortexm_probe(ap, false); + cortexm_probe(ap); break; case aa_cortexa: DEBUG_INFO("\n -> cortexa_probe\n"); @@ -490,12 +598,31 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel) DEBUG_INFO("AP %3d: IDR=%08"PRIx32" CFG=%08"PRIx32" BASE=%08" PRIx32 " CSW=%08"PRIx32"\n", apsel, ap->idr, cfg, ap->base, ap->csw); #endif + if (!apsel && ((ap->idr & 0xf) == ARM_AP_TYPE_AHB)) { + /* Test for protected Atmel devices. Access outside DSU fails. + * For protected device, continue with Rom Table anyways. + */ + adiv5_dp_error(ap->dp); + adiv5_mem_read32(ap, CORTEXM_DHCSR); + if ( adiv5_dp_error(ap->dp) & ADIV5_DP_CTRLSTAT_STICKYERR) { + uint32_t err = adiv5_dp_error(ap->dp); + if (err & ADIV5_DP_CTRLSTAT_STICKYERR) { + DEBUG_WARN("...\nHit error on DHCSR read. Suspect protected Atmel " + "part, skipping to PIDR check.\n"); + } + } else { + if (!cortexm_prepare(ap)) { + free(ap); + return NULL; + } + } + } + adiv5_ap_ref(ap); return ap; } void adiv5_dp_init(ADIv5_DP_t *dp) { - volatile bool probed = false; volatile uint32_t ctrlstat = 0; adiv5_dp_ref(dp); #if PC_HOSTED == 1 @@ -625,12 +752,7 @@ void adiv5_dp_init(ADIv5_DP_t *dp) */ /* The rest should only be added after checking ROM table */ - probed |= adiv5_component_probe(ap, ap->base, 0, 0); - if (!probed && (dp->idcode & 0xfff) == 0x477) { - DEBUG_INFO("-> cortexm_probe forced\n"); - cortexm_probe(ap, true); - probed = true; - } + adiv5_component_probe(ap, ap->base, 0, 0); } adiv5_dp_unref(dp); } diff --git a/src/target/adiv5.h b/src/target/adiv5.h index e337e3de..39d4d5ab 100644 --- a/src/target/adiv5.h +++ b/src/target/adiv5.h @@ -86,6 +86,19 @@ #define ADIV5_AP_BASE ADIV5_AP_REG(0xF8) #define ADIV5_AP_IDR ADIV5_AP_REG(0xFC) +/* Known designers seen in SYSROM-PIDR. Ignore Bit 7 from the designer bits*/ +#define AP_DESIGNER_FREESCALE 0x00e +#define AP_DESIGNER_TEXAS 0x017 +#define AP_DESIGNER_ATMEL 0x01f +#define AP_DESIGNER_STM 0x020 +#define AP_DESIGNER_CYPRESS 0x034 +#define AP_DESIGNER_INFINEON 0x041 +#define AP_DESIGNER_NORDIC 0x244 +#define AP_DESIGNER_ARM 0x43b +/*LPC845 with designer 501. Strange!? */ +#define AP_DESIGNER_SPECULAR 0x501 +#define AP_DESIGNER_ENERGY_MICRO 0x673 + /* AP Control and Status Word (CSW) */ #define ADIV5_AP_CSW_DBGSWENABLE (1u << 31) /* Bits 30:24 - Prot, Implementation defined, for Cortex-M3: */ @@ -181,6 +194,10 @@ struct ADIv5_AP_s { uint32_t idr; uint32_t base; uint32_t csw; + uint32_t ap_cortexm_demcr; /* Copy of demcr when starting */ + uint32_t ap_storage; /* E.g to hold STM32F7 initial DBGMCU_CR value.*/ + uint16_t ap_designer; + uint16_t ap_partno; }; #if PC_HOSTED == 0 diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 840200d1..f2bf5259 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -1,9 +1,9 @@ /* * This file is part of the Black Magic Debug project. * - * Copyright (C) 2012 Black Sphere Technologies Ltd. + * Copyright (C) 2012-2020 Black Sphere Technologies Ltd. * Written by Gareth McMullin , - * Koen De Vleeschauwer and Uwe Bonne + * Koen De Vleeschauwer and Uwe Bonnes * * 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 @@ -35,6 +35,7 @@ #include "cortexm.h" #include "platform.h" #include "command.h" +#include "gdb_packet.h" #include @@ -263,28 +264,7 @@ static void cortexm_priv_free(void *priv) free(priv); } -static bool cortexm_forced_halt(target *t) -{ - target_halt_request(t); - platform_srst_set_val(false); - uint32_t dhcsr = 0; - uint32_t start_time = platform_time_ms(); - const uint32_t dhcsr_halted_bits = CORTEXM_DHCSR_S_HALT | CORTEXM_DHCSR_S_REGRDY | - CORTEXM_DHCSR_C_HALT | CORTEXM_DHCSR_C_DEBUGEN; - /* Try hard to halt the target. STM32F7 in WFI - needs multiple writes!*/ - while (platform_time_ms() < start_time + cortexm_wait_timeout) { - dhcsr = target_mem_read32(t, CORTEXM_DHCSR); - if ((dhcsr & dhcsr_halted_bits) == dhcsr_halted_bits) - break; - target_halt_request(t); - } - if ((dhcsr & dhcsr_halted_bits) != dhcsr_halted_bits) - return false; - return true; -} - -bool cortexm_probe(ADIv5_AP_t *ap, bool forced) +bool cortexm_probe(ADIv5_AP_t *ap) { target *t; @@ -294,6 +274,8 @@ bool cortexm_probe(ADIv5_AP_t *ap, bool forced) } adiv5_ap_ref(ap); + t->t_designer = ap->ap_designer; + t->idcode = ap->ap_partno; struct cortexm_priv *priv = calloc(1, sizeof(*priv)); if (!priv) { /* calloc failed: heap exhaustion */ DEBUG_WARN("calloc: failed in %s\n", __func__); @@ -391,40 +373,65 @@ bool cortexm_probe(ADIv5_AP_t *ap, bool forced) } else { target_check_error(t); } - - /* Only force halt if read ROM Table failed and there is no DPv2 - * targetid! - * So long, only STM32L0 is expected to enter this cause. - */ - if (forced && !ap->dp->targetid) - if (!cortexm_forced_halt(t)) - return false; - #define PROBE(x) \ do { if ((x)(t)) {target_halt_resume(t, 0); return true;} else target_check_error(t); } while (0) - PROBE(stm32f1_probe); - PROBE(stm32f4_probe); - PROBE(stm32h7_probe); - PROBE(stm32l0_probe); /* STM32L0xx & STM32L1xx */ - PROBE(stm32l4_probe); - PROBE(lpc11xx_probe); - PROBE(lpc15xx_probe); - PROBE(lpc43xx_probe); - PROBE(lpc546xx_probe); - PROBE(sam3x_probe); - PROBE(sam4l_probe); - PROBE(nrf51_probe); - PROBE(samd_probe); - PROBE(samx5x_probe); - PROBE(lmi_probe); - PROBE(kinetis_probe); - PROBE(efm32_probe); - PROBE(msp432_probe); - PROBE(ke04_probe); - PROBE(lpc17xx_probe); + switch (ap->ap_designer) { + case AP_DESIGNER_FREESCALE: + PROBE(kinetis_probe); + break; + case AP_DESIGNER_STM: + PROBE(stm32f1_probe); + PROBE(stm32f4_probe); + PROBE(stm32h7_probe); + PROBE(stm32l0_probe); + PROBE(stm32l4_probe); + break; + case AP_DESIGNER_CYPRESS: + DEBUG_WARN("Unhandled Cypress device\n"); + break; + case AP_DESIGNER_INFINEON: + DEBUG_WARN("Unhandled Infineon device\n"); + break; + case AP_DESIGNER_NORDIC: + PROBE(nrf51_probe); + break; + case AP_DESIGNER_ATMEL: + PROBE(sam4l_probe); + PROBE(samd_probe); + PROBE(samx5x_probe); + break; + case AP_DESIGNER_ARM: + if (ap->ap_partno == 0x4c3) /* Care for STM32F1 clones */ + PROBE(stm32f1_probe); + PROBE(sam3x_probe); + PROBE(lpc11xx_probe); /* LPC24C11 */ + break; + case AP_DESIGNER_ENERGY_MICRO: + PROBE(efm32_probe); + break; + case AP_DESIGNER_TEXAS: + PROBE(msp432_probe); + break; + case AP_DESIGNER_SPECULAR: + PROBE(lpc11xx_probe); /* LPC845 */ + break; + default: +#if PC_HOSTED == 0 + gdb_outf("Please report Designer %3x and Partno %3x and the probed " + "device\n", ap->ap_designer, ap->ap_partno); +#else + DEBUG_WARN("Please report Designer %3x and Partno %3x and the probed " + "device\n", ap->ap_designer, ap->ap_partno); +#endif + PROBE(lpc11xx_probe); /* Let's get feedback if LPC11 is also Specular*/ + PROBE(lpc15xx_probe); + PROBE(lpc43xx_probe); + PROBE(lmi_probe); + PROBE(ke04_probe); + PROBE(lpc17xx_probe); + } #undef PROBE - return true; } @@ -438,9 +445,6 @@ bool cortexm_attach(target *t) target_check_error(t); target_halt_request(t); - if (!cortexm_forced_halt(t)) - return false; - /* Request halt on reset */ target_mem_write32(t, CORTEXM_DEMCR, priv->demcr); @@ -474,6 +478,22 @@ bool cortexm_attach(target *t) target_mem_write32(t, CORTEXM_FPB_CTRL, CORTEXM_FPB_CTRL_KEY | CORTEXM_FPB_CTRL_ENABLE); + uint32_t dhcsr = target_mem_read32(t, CORTEXM_DHCSR); + dhcsr = target_mem_read32(t, CORTEXM_DHCSR); + if (dhcsr & CORTEXM_DHCSR_S_RESET_ST) { + platform_srst_set_val(false); + platform_timeout timeout; + platform_timeout_set(&timeout, 1000); + while (1) { + uint32_t dhcsr = target_mem_read32(t, CORTEXM_DHCSR); + if (!(dhcsr & CORTEXM_DHCSR_S_RESET_ST)) + break; + if (platform_timeout_is_expired(&timeout)) { + DEBUG_WARN("Error releasing from srst\n"); + return false; + } + } + } return true; } @@ -490,6 +510,9 @@ void cortexm_detach(target *t) for(i = 0; i < priv->hw_watchpoint_max; i++) target_mem_write32(t, CORTEXM_DWT_FUNC(i), 0); + /* Restort DEMCR*/ + ADIv5_AP_t *ap = cortexm_ap(t); + target_mem_write32(t, CORTEXM_DEMCR, ap->ap_cortexm_demcr); /* Disable debug */ target_mem_write32(t, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY); /* Add some clock cycles to get the CPU running again.*/ diff --git a/src/target/cortexm.h b/src/target/cortexm.h index 95952f5b..f230e0b5 100644 --- a/src/target/cortexm.h +++ b/src/target/cortexm.h @@ -171,7 +171,7 @@ extern long cortexm_wait_timeout; #define CORTEXM_TOPT_INHIBIT_SRST (1 << 2) -bool cortexm_probe(ADIv5_AP_t *ap, bool forced); +bool cortexm_probe(ADIv5_AP_t *ap); ADIv5_AP_t *cortexm_ap(target *t); bool cortexm_attach(target *t); diff --git a/src/target/lpc11xx.c b/src/target/lpc11xx.c index ba2dc6a4..5cad1e77 100644 --- a/src/target/lpc11xx.c +++ b/src/target/lpc11xx.c @@ -137,7 +137,7 @@ lpc11xx_probe(target *t) target_add_commands(t, lpc11xx_cmd_list, "LPC8N04"); return true; } - if (idcode) { + if ((t->t_designer != AP_DESIGNER_SPECULAR) && !idcode) { DEBUG_INFO("LPC11xx: Unknown IDCODE 0x%08" PRIx32 "\n", idcode); } idcode = target_mem_read32(t, LPC8XX_DEVICE_ID); diff --git a/src/target/nrf51.c b/src/target/nrf51.c index 9fa73580..e8a02b09 100644 --- a/src/target/nrf51.c +++ b/src/target/nrf51.c @@ -132,7 +132,6 @@ bool nrf51_probe(target *t) if ((info_part != 0xffffffff) && (info_part != 0) && ((info_part & 0x00ff000) == 0x52000)) { uint32_t ram_size = target_mem_read32(t, NRF52_INFO_RAM); - t->idcode = info_part; t->driver = "Nordic nRF52"; t->target_options |= CORTEXM_TOPT_INHIBIT_SRST; target_add_ram(t, 0x20000000, ram_size * 1024); diff --git a/src/target/sam3x.c b/src/target/sam3x.c index 0537c11a..c869d722 100644 --- a/src/target/sam3x.c +++ b/src/target/sam3x.c @@ -170,9 +170,9 @@ static void sam4_add_flash(target *t, target_add_flash(t, f); } -static size_t sam_flash_size(uint32_t idcode) +static size_t sam_flash_size(uint32_t cidr) { - switch (idcode & CHIPID_CIDR_NVPSIZ_MASK) { + switch (cidr & CHIPID_CIDR_NVPSIZ_MASK) { case CHIPID_CIDR_NVPSIZ_8K: return 0x2000; case CHIPID_CIDR_NVPSIZ_16K: @@ -197,9 +197,9 @@ static size_t sam_flash_size(uint32_t idcode) bool sam3x_probe(target *t) { - t->idcode = target_mem_read32(t, SAM3X_CHIPID_CIDR); - size_t size = sam_flash_size(t->idcode); - switch (t->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { + uint32_t cidr = target_mem_read32(t, SAM3X_CHIPID_CIDR); + size_t size = sam_flash_size(cidr); + switch (cidr & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { case CHIPID_CIDR_ARCH_SAM3XxC | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3XxE | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3XxG | CHIPID_CIDR_EPROC_CM3: @@ -212,9 +212,9 @@ bool sam3x_probe(target *t) return true; } - t->idcode = target_mem_read32(t, SAM34NSU_CHIPID_CIDR); - size = sam_flash_size(t->idcode); - switch (t->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { + cidr = target_mem_read32(t, SAM34NSU_CHIPID_CIDR); + size = sam_flash_size(cidr); + switch (cidr & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { case CHIPID_CIDR_ARCH_SAM3NxA | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3NxB | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3NxC | CHIPID_CIDR_EPROC_CM3: @@ -224,7 +224,7 @@ bool sam3x_probe(target *t) t->driver = "Atmel SAM3N/S"; target_add_ram(t, 0x20000000, 0x200000); /* These devices only have a single bank */ - size = sam_flash_size(t->idcode); + size = sam_flash_size(cidr); sam3_add_flash(t, SAM3N_EEFC_BASE, 0x400000, size); target_add_commands(t, sam3x_cmd_list, "SAM3N/S"); return true; @@ -248,7 +248,7 @@ bool sam3x_probe(target *t) case CHIPID_CIDR_ARCH_SAM4SDC | CHIPID_CIDR_EPROC_CM4: t->driver = "Atmel SAM4S"; target_add_ram(t, 0x20000000, 0x400000); - size_t size = sam_flash_size(t->idcode); + size_t size = sam_flash_size(cidr); if (size <= 0x80000) { /* Smaller devices have a single bank */ sam4_add_flash(t, SAM4S_EEFC_BASE(0), 0x400000, size); diff --git a/src/target/sam4l.c b/src/target/sam4l.c index 06b96db1..bab336cd 100644 --- a/src/target/sam4l.c +++ b/src/target/sam4l.c @@ -186,13 +186,13 @@ static void sam4l_add_flash(target *t, uint32_t addr, size_t length) } /* Return size of RAM */ -static size_t sam_ram_size(uint32_t idcode) { - return __ram_size[((idcode >> CHIPID_CIDR_SRAMSIZ_SHIFT) & CHIPID_CIDR_SRAMSIZ_MASK)]; +static size_t sam_ram_size(uint32_t cidr) { + return __ram_size[((cidr >> CHIPID_CIDR_SRAMSIZ_SHIFT) & CHIPID_CIDR_SRAMSIZ_MASK)]; } /* Return size of FLASH */ -static size_t sam_nvp_size(uint32_t idcode) { - return __nvp_size[((idcode >> CHIPID_CIDR_NVPSIZ_SHIFT) & CHIPID_CIDR_NVPSIZ_MASK)]; +static size_t sam_nvp_size(uint32_t cidr) { + return __nvp_size[((cidr >> CHIPID_CIDR_NVPSIZ_SHIFT) & CHIPID_CIDR_NVPSIZ_MASK)]; } #define SMAP_BASE 0x400a3000 @@ -228,14 +228,14 @@ bool sam4l_probe(target *t) { size_t ram_size, flash_size; - t->idcode = target_mem_read32(t, SAM4L_CHIPID_CIDR); - if (((t->idcode >> CHIPID_CIDR_ARCH_SHIFT) & CHIPID_CIDR_ARCH_MASK) == SAM4L_ARCH) { + uint32_t cidr = target_mem_read32(t, SAM4L_CHIPID_CIDR); + if (((cidr >> CHIPID_CIDR_ARCH_SHIFT) & CHIPID_CIDR_ARCH_MASK) == SAM4L_ARCH) { t->driver = "Atmel SAM4L"; /* this function says we need to do "extra" stuff after reset */ t->extended_reset = sam4l_extended_reset; - ram_size = sam_ram_size(t->idcode); + ram_size = sam_ram_size(cidr); target_add_ram(t, 0x20000000, ram_size); - flash_size = sam_nvp_size(t->idcode); + flash_size = sam_nvp_size(cidr); sam4l_add_flash(t, 0x0, flash_size); DEBUG_INFO("\nSAM4L: RAM = 0x%x (%dK), FLASH = 0x%x (%dK)\n", (unsigned int) ram_size, (unsigned int) (ram_size / 1024), diff --git a/src/target/stm32f1.c b/src/target/stm32f1.c index 4aac170d..731973d1 100644 --- a/src/target/stm32f1.c +++ b/src/target/stm32f1.c @@ -118,9 +118,10 @@ static void stm32f1_add_flash(target *t, bool stm32f1_probe(target *t) { + if (t->t_designer == AP_DESIGNER_ARM) + t->idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff; size_t flash_size; size_t block_size = 0x400; - t->idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff; switch(t->idcode) { case 0x410: /* Medium density */ case 0x412: /* Low density */ @@ -167,10 +168,6 @@ bool stm32f1_probe(target *t) stm32f1_add_flash(t, 0x8000000, 0x80000, 0x800); target_add_commands(t, stm32f1_cmd_list, "STM32F3"); return true; - } - - t->idcode = target_mem_read32(t, DBGMCU_IDCODE_F0) & 0xfff; - switch(t->idcode) { case 0x444: /* STM32F03 RM0091 Rev.7, STM32F030x[4|6] RM0360 Rev. 4*/ t->driver = "STM32F03"; flash_size = 0x8000; diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index a593dd37..33691c7b 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -197,28 +197,22 @@ char *stm32f4_get_chip_name(uint32_t idcode) static void stm32f7_detach(target *t) { - target_mem_write32(t, DBGMCU_CR, t->target_storage); + ADIv5_AP_t *ap = cortexm_ap(t); + target_mem_write32(t, DBGMCU_CR, ap->ap_storage); cortexm_detach(t); } bool stm32f4_probe(target *t) { - ADIv5_AP_t *ap = cortexm_ap(t); - uint32_t idcode; - - idcode = (ap->dp->targetid >> 16) & 0xfff; - if (!idcode) - idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xFFF; - - if (idcode == ID_STM32F20X) { + if (t->idcode == ID_STM32F20X) { /* F405 revision A have a wrong IDCODE, use ARM_CPUID to make the * distinction with F205. Revision is also wrong (0x2000 instead * of 0x1000). See F40x/F41x errata. */ uint32_t cpuid = target_mem_read32(t, ARM_CPUID); if ((cpuid & 0xFFF0) == 0xC240) - idcode = ID_STM32F40X; + t->idcode = ID_STM32F40X; } - switch(idcode) { + switch(t->idcode) { case ID_STM32F74X: /* F74x RM0385 Rev.4 */ case ID_STM32F76X: /* F76x F77x RM0410 */ case ID_STM32F72X: /* F72x F73x RM0431 */ @@ -234,8 +228,7 @@ bool stm32f4_probe(target *t) case ID_STM32F412: /* F412 RM0402 Rev.4, 256 kB Ram */ case ID_STM32F401E: /* F401 D/E RM0368 Rev.3 */ case ID_STM32F413: /* F413 RM0430 Rev.2, 320 kB Ram, 1.5 MB flash. */ - t->idcode = idcode; - t->driver = stm32f4_get_chip_name(idcode); + t->driver = stm32f4_get_chip_name(t->idcode); t->attach = stm32f4_attach; target_add_commands(t, stm32f4_cmd_list, t->driver); return true; @@ -306,8 +299,6 @@ static bool stm32f4_attach(target *t) bool use_dual_bank = false; target_mem_map_free(t); if (is_f7) { - t->target_storage = target_mem_read32(t, DBGMCU_CR); - target_mem_write32(t, DBGMCU_CR, DBG_SLEEP); target_add_ram(t, 0x00000000, 0x4000); /* 16 k ITCM Ram */ target_add_ram(t, 0x20000000, 0x20000); /* 128 k DTCM Ram */ target_add_ram(t, 0x20020000, 0x60000); /* 384 k Ram */ diff --git a/src/target/stm32h7.c b/src/target/stm32h7.c index d71393cf..e72d99ae 100644 --- a/src/target/stm32h7.c +++ b/src/target/stm32h7.c @@ -188,11 +188,6 @@ static bool stm32h7_attach(target *t) { if (!cortexm_attach(t)) return false; - /* RM0433 Rev 4 is not really clear, what bits are needed. - * Set all possible relevant bits for now. */ - uint32_t dbgmcu_cr = target_mem_read32(t, DBGMCU_CR); - t->target_storage = dbgmcu_cr; - target_mem_write32(t, DBGMCU_CR, DBGSLEEP_D1 | D1DBGCKEN); /* If IWDG runs as HARDWARE watchdog (44.3.4) erase * will be aborted by the Watchdog and erase fails! * Setting IWDG_KR to 0xaaaa does not seem to help!*/ @@ -226,14 +221,17 @@ static void stm32h7_detach(target *t) bool stm32h7_probe(target *t) { - ADIv5_AP_t *ap = cortexm_ap(t); - uint32_t idcode = (ap->dp->targetid >> 16) & 0xfff; - if (idcode == ID_STM32H74x) { - t->idcode = idcode; + if (t->idcode == ID_STM32H74x) { t->driver = stm32h74_driver_str; t->attach = stm32h7_attach; t->detach = stm32h7_detach; target_add_commands(t, stm32h7_cmd_list, stm32h74_driver_str); + t->target_storage = target_mem_read32(t, DBGMCU_CR); + /* RM0433 Rev 4 is not really clear, what bits are needed in DBGMCU_CR. + * Maybe more flags needed? + */ + uint32_t dbgmcu_cr = DBGSLEEP_D1 | D1DBGCKEN; + target_mem_write32(t, DBGMCU_CR, dbgmcu_cr); return true; } return false; diff --git a/src/target/stm32l0.c b/src/target/stm32l0.c index 088bd03b..54b21596 100644 --- a/src/target/stm32l0.c +++ b/src/target/stm32l0.c @@ -268,31 +268,22 @@ static void stm32l_add_eeprom(target *t, uint32_t addr, size_t length) STM32L0xx parts as well as the STM32L1xx's. */ bool stm32l0_probe(target* t) { - uint32_t idcode; - - idcode = target_mem_read32(t, STM32L1_DBGMCU_IDCODE_PHYS) & 0xfff; - switch (idcode) { + switch (t->idcode) { case 0x416: /* CAT. 1 device */ case 0x429: /* CAT. 2 device */ case 0x427: /* CAT. 3 device */ case 0x436: /* CAT. 4 device */ case 0x437: /* CAT. 5 device */ - t->idcode = idcode; t->driver = "STM32L1x"; target_add_ram(t, 0x20000000, 0x14000); stm32l_add_flash(t, 0x8000000, 0x80000, 0x100); //stm32l_add_eeprom(t, 0x8080000, 0x4000); target_add_commands(t, stm32lx_cmd_list, "STM32L1x"); return true; - } - - idcode = target_mem_read32(t, STM32L0_DBGMCU_IDCODE_PHYS) & 0xfff; - switch (idcode) { case 0x457: /* STM32L0xx Cat1 */ case 0x425: /* STM32L0xx Cat2 */ case 0x417: /* STM32L0xx Cat3 */ case 0x447: /* STM32L0xx Cat5 */ - t->idcode = idcode; t->driver = "STM32L0x"; target_add_ram(t, 0x20000000, 0x5000); stm32l_add_flash(t, 0x8000000, 0x10000, 0x80); diff --git a/src/target/stm32l4.c b/src/target/stm32l4.c index f3d91631..7d47f84a 100644 --- a/src/target/stm32l4.c +++ b/src/target/stm32l4.c @@ -373,18 +373,11 @@ static void stm32l4_detach(target *t) bool stm32l4_probe(target *t) { - uint32_t idcode_reg = STM32L4_DBGMCU_IDCODE_PHYS; - ADIv5_AP_t *ap = cortexm_ap(t); - if (ap->dp->idcode == 0x0BC11477) - idcode_reg = STM32G0_DBGMCU_IDCODE_PHYS; - uint32_t idcode = target_mem_read32(t, idcode_reg) & 0xfff; - - struct stm32l4_info const *chip = stm32l4_get_chip_info(idcode); + struct stm32l4_info const *chip = stm32l4_get_chip_info(t->idcode); if( !chip->idcode ) /* Not found */ return false; - t->idcode = idcode; t->driver = chip->designator; t->attach = stm32l4_attach; t->detach = stm32l4_detach; diff --git a/src/target/target.c b/src/target/target.c index e1f7a657..5a5ec388 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -502,6 +502,16 @@ const char *target_core_name(target *t) return t->core; } +unsigned int target_designer(target *t) +{ + return t->t_designer; +} + +unsigned int target_idcode(target *t) +{ + return t->idcode; +} + uint32_t target_mem_read32(target *t, uint32_t addr) { uint32_t ret; diff --git a/src/target/target_internal.h b/src/target/target_internal.h index c2288af2..66ff2019 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -111,7 +111,8 @@ struct target_s { /* target-defined options */ unsigned target_options; - uint32_t idcode; + uint16_t t_designer; + uint16_t idcode; uint32_t target_storage; struct target_ram *ram;