Merge pull request #507 from UweBonnes/cortexm_romtable
Cortexm romtable
This commit is contained in:
commit
817c62d7fd
@ -257,9 +257,18 @@ bool cmd_swdp_scan(target *t, int argc, char **argv)
|
|||||||
static void display_target(int i, target *t, void *context)
|
static void display_target(int i, target *t, void *context)
|
||||||
{
|
{
|
||||||
(void)context;
|
(void)context;
|
||||||
|
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)?'*':' ',
|
gdb_outf("%2d %c %s %s\n", i, target_attached(t)?'*':' ',
|
||||||
target_driver_name(t),
|
target_driver_name(t),
|
||||||
(target_core_name(t)) ? target_core_name(t): "");
|
(target_core_name(t)) ? target_core_name(t): "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cmd_targets(target *t, int argc, char **argv)
|
bool cmd_targets(target *t, int argc, char **argv)
|
||||||
|
@ -51,6 +51,8 @@ void target_detach(target *t);
|
|||||||
bool target_attached(target *t);
|
bool target_attached(target *t);
|
||||||
const char *target_driver_name(target *t);
|
const char *target_driver_name(target *t);
|
||||||
const char *target_core_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 */
|
/* Memory access functions */
|
||||||
bool target_mem_map(target *t, char *buf, size_t len);
|
bool target_mem_map(target *t, char *buf, size_t len);
|
||||||
|
@ -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)
|
static void display_target(int i, target *t, void *context)
|
||||||
{
|
{
|
||||||
(void)context;
|
(void)context;
|
||||||
|
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)?'*':' ',
|
DEBUG_INFO("*** %2d %c %s %s\n", i, target_attached(t)?'*':' ',
|
||||||
target_driver_name(t),
|
target_driver_name(t),
|
||||||
(target_core_name(t)) ? target_core_name(t): "");
|
(target_core_name(t)) ? target_core_name(t): "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int cl_execute(BMP_CL_OPTIONS_t *opt)
|
int cl_execute(BMP_CL_OPTIONS_t *opt)
|
||||||
|
@ -36,6 +36,13 @@
|
|||||||
* are consistently named and accessible when needed in the codebase.
|
* 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 */
|
/* ROM table CIDR values */
|
||||||
#define CIDR0_OFFSET 0xFF0 /* DBGCID0 */
|
#define CIDR0_OFFSET 0xFF0 /* DBGCID0 */
|
||||||
#define CIDR1_OFFSET 0xFF4 /* DBGCID1 */
|
#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)")},
|
{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)")},
|
{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)")},
|
{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)")},
|
{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)")},
|
{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)")},
|
{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)")},
|
{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)")},
|
{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)")},
|
{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;
|
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)
|
static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, int num_entry)
|
||||||
{
|
{
|
||||||
(void) 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 */
|
/* ROM table */
|
||||||
if (cid_class == cidc_romtab) {
|
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 */
|
/* Check SYSMEM bit */
|
||||||
#if defined(ENABLE_DEBUG)
|
|
||||||
uint32_t memtype = adiv5_mem_read32(ap, addr | ADIV5_ROM_MEMTYPE) &
|
uint32_t memtype = adiv5_mem_read32(ap, addr | ADIV5_ROM_MEMTYPE) &
|
||||||
ADIV5_ROM_MEMTYPE_SYSMEM;
|
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_WARN("Fault reading ROM table entry\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_INFO("ROM: Table BASE=0x%" PRIx32 " SYSMEM=0x%" PRIx32
|
DEBUG_INFO("ROM: Table BASE=0x%" PRIx32 " SYSMEM=0x%08" PRIx32
|
||||||
", PIDR 0x%02" PRIx32 "%08" PRIx32 "\n", addr,
|
", designer %3x Partno %3x\n", addr, memtype, designer,
|
||||||
memtype, (uint32_t)(pidr >> 32), (uint32_t)pidr);
|
partno);
|
||||||
#endif
|
#endif
|
||||||
|
if (recursion == 0) {
|
||||||
|
ap->ap_designer = designer;
|
||||||
|
ap->ap_partno = partno;
|
||||||
|
}
|
||||||
for (int i = 0; i < 960; i++) {
|
for (int i = 0; i < 960; i++) {
|
||||||
adiv5_dp_error(ap->dp);
|
adiv5_dp_error(ap->dp);
|
||||||
uint32_t entry = adiv5_mem_read32(ap, addr + i*4);
|
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 */
|
/* Probe recursively */
|
||||||
res |= adiv5_component_probe(
|
adiv5_component_probe(
|
||||||
ap, addr + (entry & ADIV5_ROM_ROMENTRY_OFFSET),
|
ap, addr + (entry & ADIV5_ROM_ROMENTRY_OFFSET),
|
||||||
recursion + 1, i);
|
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) {
|
switch (pidr_pn_bits[i].arch) {
|
||||||
case aa_cortexm:
|
case aa_cortexm:
|
||||||
DEBUG_INFO("%s-> cortexm_probe\n", indent + 1);
|
DEBUG_INFO("%s-> cortexm_probe\n", indent + 1);
|
||||||
cortexm_probe(ap, false);
|
cortexm_probe(ap);
|
||||||
break;
|
break;
|
||||||
case aa_cortexa:
|
case aa_cortexa:
|
||||||
DEBUG_INFO("\n -> cortexa_probe\n");
|
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
|
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);
|
" CSW=%08"PRIx32"\n", apsel, ap->idr, cfg, ap->base, ap->csw);
|
||||||
#endif
|
#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;
|
return ap;
|
||||||
}
|
}
|
||||||
|
|
||||||
void adiv5_dp_init(ADIv5_DP_t *dp)
|
void adiv5_dp_init(ADIv5_DP_t *dp)
|
||||||
{
|
{
|
||||||
volatile bool probed = false;
|
|
||||||
volatile uint32_t ctrlstat = 0;
|
volatile uint32_t ctrlstat = 0;
|
||||||
adiv5_dp_ref(dp);
|
adiv5_dp_ref(dp);
|
||||||
#if PC_HOSTED == 1
|
#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 */
|
/* The rest should only be added after checking ROM table */
|
||||||
probed |= adiv5_component_probe(ap, ap->base, 0, 0);
|
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_dp_unref(dp);
|
adiv5_dp_unref(dp);
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,19 @@
|
|||||||
#define ADIV5_AP_BASE ADIV5_AP_REG(0xF8)
|
#define ADIV5_AP_BASE ADIV5_AP_REG(0xF8)
|
||||||
#define ADIV5_AP_IDR ADIV5_AP_REG(0xFC)
|
#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) */
|
/* AP Control and Status Word (CSW) */
|
||||||
#define ADIV5_AP_CSW_DBGSWENABLE (1u << 31)
|
#define ADIV5_AP_CSW_DBGSWENABLE (1u << 31)
|
||||||
/* Bits 30:24 - Prot, Implementation defined, for Cortex-M3: */
|
/* Bits 30:24 - Prot, Implementation defined, for Cortex-M3: */
|
||||||
@ -181,6 +194,10 @@ struct ADIv5_AP_s {
|
|||||||
uint32_t idr;
|
uint32_t idr;
|
||||||
uint32_t base;
|
uint32_t base;
|
||||||
uint32_t csw;
|
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
|
#if PC_HOSTED == 0
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Black Magic Debug project.
|
* 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 <gareth@blacksphere.co.nz>,
|
* Written by Gareth McMullin <gareth@blacksphere.co.nz>,
|
||||||
* Koen De Vleeschauwer and Uwe Bonne
|
* Koen De Vleeschauwer and Uwe Bonnes
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -35,6 +35,7 @@
|
|||||||
#include "cortexm.h"
|
#include "cortexm.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
|
#include "gdb_packet.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -263,28 +264,7 @@ static void cortexm_priv_free(void *priv)
|
|||||||
free(priv);
|
free(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cortexm_forced_halt(target *t)
|
bool cortexm_probe(ADIv5_AP_t *ap)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
target *t;
|
target *t;
|
||||||
|
|
||||||
@ -294,6 +274,8 @@ bool cortexm_probe(ADIv5_AP_t *ap, bool forced)
|
|||||||
}
|
}
|
||||||
|
|
||||||
adiv5_ap_ref(ap);
|
adiv5_ap_ref(ap);
|
||||||
|
t->t_designer = ap->ap_designer;
|
||||||
|
t->idcode = ap->ap_partno;
|
||||||
struct cortexm_priv *priv = calloc(1, sizeof(*priv));
|
struct cortexm_priv *priv = calloc(1, sizeof(*priv));
|
||||||
if (!priv) { /* calloc failed: heap exhaustion */
|
if (!priv) { /* calloc failed: heap exhaustion */
|
||||||
DEBUG_WARN("calloc: failed in %s\n", __func__);
|
DEBUG_WARN("calloc: failed in %s\n", __func__);
|
||||||
@ -391,40 +373,65 @@ bool cortexm_probe(ADIv5_AP_t *ap, bool forced)
|
|||||||
} else {
|
} else {
|
||||||
target_check_error(t);
|
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) \
|
#define PROBE(x) \
|
||||||
do { if ((x)(t)) {target_halt_resume(t, 0); return true;} else target_check_error(t); } while (0)
|
do { if ((x)(t)) {target_halt_resume(t, 0); return true;} else target_check_error(t); } while (0)
|
||||||
|
|
||||||
|
switch (ap->ap_designer) {
|
||||||
|
case AP_DESIGNER_FREESCALE:
|
||||||
|
PROBE(kinetis_probe);
|
||||||
|
break;
|
||||||
|
case AP_DESIGNER_STM:
|
||||||
PROBE(stm32f1_probe);
|
PROBE(stm32f1_probe);
|
||||||
PROBE(stm32f4_probe);
|
PROBE(stm32f4_probe);
|
||||||
PROBE(stm32h7_probe);
|
PROBE(stm32h7_probe);
|
||||||
PROBE(stm32l0_probe); /* STM32L0xx & STM32L1xx */
|
PROBE(stm32l0_probe);
|
||||||
PROBE(stm32l4_probe);
|
PROBE(stm32l4_probe);
|
||||||
PROBE(lpc11xx_probe);
|
break;
|
||||||
PROBE(lpc15xx_probe);
|
case AP_DESIGNER_CYPRESS:
|
||||||
PROBE(lpc43xx_probe);
|
DEBUG_WARN("Unhandled Cypress device\n");
|
||||||
PROBE(lpc546xx_probe);
|
break;
|
||||||
PROBE(sam3x_probe);
|
case AP_DESIGNER_INFINEON:
|
||||||
PROBE(sam4l_probe);
|
DEBUG_WARN("Unhandled Infineon device\n");
|
||||||
|
break;
|
||||||
|
case AP_DESIGNER_NORDIC:
|
||||||
PROBE(nrf51_probe);
|
PROBE(nrf51_probe);
|
||||||
|
break;
|
||||||
|
case AP_DESIGNER_ATMEL:
|
||||||
|
PROBE(sam4l_probe);
|
||||||
PROBE(samd_probe);
|
PROBE(samd_probe);
|
||||||
PROBE(samx5x_probe);
|
PROBE(samx5x_probe);
|
||||||
PROBE(lmi_probe);
|
break;
|
||||||
PROBE(kinetis_probe);
|
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);
|
PROBE(efm32_probe);
|
||||||
|
break;
|
||||||
|
case AP_DESIGNER_TEXAS:
|
||||||
PROBE(msp432_probe);
|
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(ke04_probe);
|
||||||
PROBE(lpc17xx_probe);
|
PROBE(lpc17xx_probe);
|
||||||
|
}
|
||||||
#undef PROBE
|
#undef PROBE
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,9 +445,6 @@ bool cortexm_attach(target *t)
|
|||||||
target_check_error(t);
|
target_check_error(t);
|
||||||
|
|
||||||
target_halt_request(t);
|
target_halt_request(t);
|
||||||
if (!cortexm_forced_halt(t))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* Request halt on reset */
|
/* Request halt on reset */
|
||||||
target_mem_write32(t, CORTEXM_DEMCR, priv->demcr);
|
target_mem_write32(t, CORTEXM_DEMCR, priv->demcr);
|
||||||
|
|
||||||
@ -474,6 +478,22 @@ bool cortexm_attach(target *t)
|
|||||||
target_mem_write32(t, CORTEXM_FPB_CTRL,
|
target_mem_write32(t, CORTEXM_FPB_CTRL,
|
||||||
CORTEXM_FPB_CTRL_KEY | CORTEXM_FPB_CTRL_ENABLE);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,6 +510,9 @@ void cortexm_detach(target *t)
|
|||||||
for(i = 0; i < priv->hw_watchpoint_max; i++)
|
for(i = 0; i < priv->hw_watchpoint_max; i++)
|
||||||
target_mem_write32(t, CORTEXM_DWT_FUNC(i), 0);
|
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 */
|
/* Disable debug */
|
||||||
target_mem_write32(t, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY);
|
target_mem_write32(t, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY);
|
||||||
/* Add some clock cycles to get the CPU running again.*/
|
/* Add some clock cycles to get the CPU running again.*/
|
||||||
|
@ -171,7 +171,7 @@ extern long cortexm_wait_timeout;
|
|||||||
|
|
||||||
#define CORTEXM_TOPT_INHIBIT_SRST (1 << 2)
|
#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);
|
ADIv5_AP_t *cortexm_ap(target *t);
|
||||||
|
|
||||||
bool cortexm_attach(target *t);
|
bool cortexm_attach(target *t);
|
||||||
|
@ -137,7 +137,7 @@ lpc11xx_probe(target *t)
|
|||||||
target_add_commands(t, lpc11xx_cmd_list, "LPC8N04");
|
target_add_commands(t, lpc11xx_cmd_list, "LPC8N04");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (idcode) {
|
if ((t->t_designer != AP_DESIGNER_SPECULAR) && !idcode) {
|
||||||
DEBUG_INFO("LPC11xx: Unknown IDCODE 0x%08" PRIx32 "\n", idcode);
|
DEBUG_INFO("LPC11xx: Unknown IDCODE 0x%08" PRIx32 "\n", idcode);
|
||||||
}
|
}
|
||||||
idcode = target_mem_read32(t, LPC8XX_DEVICE_ID);
|
idcode = target_mem_read32(t, LPC8XX_DEVICE_ID);
|
||||||
|
@ -132,7 +132,6 @@ bool nrf51_probe(target *t)
|
|||||||
if ((info_part != 0xffffffff) && (info_part != 0) &&
|
if ((info_part != 0xffffffff) && (info_part != 0) &&
|
||||||
((info_part & 0x00ff000) == 0x52000)) {
|
((info_part & 0x00ff000) == 0x52000)) {
|
||||||
uint32_t ram_size = target_mem_read32(t, NRF52_INFO_RAM);
|
uint32_t ram_size = target_mem_read32(t, NRF52_INFO_RAM);
|
||||||
t->idcode = info_part;
|
|
||||||
t->driver = "Nordic nRF52";
|
t->driver = "Nordic nRF52";
|
||||||
t->target_options |= CORTEXM_TOPT_INHIBIT_SRST;
|
t->target_options |= CORTEXM_TOPT_INHIBIT_SRST;
|
||||||
target_add_ram(t, 0x20000000, ram_size * 1024);
|
target_add_ram(t, 0x20000000, ram_size * 1024);
|
||||||
|
@ -170,9 +170,9 @@ static void sam4_add_flash(target *t,
|
|||||||
target_add_flash(t, f);
|
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:
|
case CHIPID_CIDR_NVPSIZ_8K:
|
||||||
return 0x2000;
|
return 0x2000;
|
||||||
case CHIPID_CIDR_NVPSIZ_16K:
|
case CHIPID_CIDR_NVPSIZ_16K:
|
||||||
@ -197,9 +197,9 @@ static size_t sam_flash_size(uint32_t idcode)
|
|||||||
|
|
||||||
bool sam3x_probe(target *t)
|
bool sam3x_probe(target *t)
|
||||||
{
|
{
|
||||||
t->idcode = target_mem_read32(t, SAM3X_CHIPID_CIDR);
|
uint32_t cidr = target_mem_read32(t, SAM3X_CHIPID_CIDR);
|
||||||
size_t size = sam_flash_size(t->idcode);
|
size_t size = sam_flash_size(cidr);
|
||||||
switch (t->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
|
switch (cidr & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
|
||||||
case CHIPID_CIDR_ARCH_SAM3XxC | CHIPID_CIDR_EPROC_CM3:
|
case CHIPID_CIDR_ARCH_SAM3XxC | CHIPID_CIDR_EPROC_CM3:
|
||||||
case CHIPID_CIDR_ARCH_SAM3XxE | CHIPID_CIDR_EPROC_CM3:
|
case CHIPID_CIDR_ARCH_SAM3XxE | CHIPID_CIDR_EPROC_CM3:
|
||||||
case CHIPID_CIDR_ARCH_SAM3XxG | CHIPID_CIDR_EPROC_CM3:
|
case CHIPID_CIDR_ARCH_SAM3XxG | CHIPID_CIDR_EPROC_CM3:
|
||||||
@ -212,9 +212,9 @@ bool sam3x_probe(target *t)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
t->idcode = target_mem_read32(t, SAM34NSU_CHIPID_CIDR);
|
cidr = target_mem_read32(t, SAM34NSU_CHIPID_CIDR);
|
||||||
size = sam_flash_size(t->idcode);
|
size = sam_flash_size(cidr);
|
||||||
switch (t->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
|
switch (cidr & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
|
||||||
case CHIPID_CIDR_ARCH_SAM3NxA | CHIPID_CIDR_EPROC_CM3:
|
case CHIPID_CIDR_ARCH_SAM3NxA | CHIPID_CIDR_EPROC_CM3:
|
||||||
case CHIPID_CIDR_ARCH_SAM3NxB | CHIPID_CIDR_EPROC_CM3:
|
case CHIPID_CIDR_ARCH_SAM3NxB | CHIPID_CIDR_EPROC_CM3:
|
||||||
case CHIPID_CIDR_ARCH_SAM3NxC | 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";
|
t->driver = "Atmel SAM3N/S";
|
||||||
target_add_ram(t, 0x20000000, 0x200000);
|
target_add_ram(t, 0x20000000, 0x200000);
|
||||||
/* These devices only have a single bank */
|
/* 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);
|
sam3_add_flash(t, SAM3N_EEFC_BASE, 0x400000, size);
|
||||||
target_add_commands(t, sam3x_cmd_list, "SAM3N/S");
|
target_add_commands(t, sam3x_cmd_list, "SAM3N/S");
|
||||||
return true;
|
return true;
|
||||||
@ -248,7 +248,7 @@ bool sam3x_probe(target *t)
|
|||||||
case CHIPID_CIDR_ARCH_SAM4SDC | CHIPID_CIDR_EPROC_CM4:
|
case CHIPID_CIDR_ARCH_SAM4SDC | CHIPID_CIDR_EPROC_CM4:
|
||||||
t->driver = "Atmel SAM4S";
|
t->driver = "Atmel SAM4S";
|
||||||
target_add_ram(t, 0x20000000, 0x400000);
|
target_add_ram(t, 0x20000000, 0x400000);
|
||||||
size_t size = sam_flash_size(t->idcode);
|
size_t size = sam_flash_size(cidr);
|
||||||
if (size <= 0x80000) {
|
if (size <= 0x80000) {
|
||||||
/* Smaller devices have a single bank */
|
/* Smaller devices have a single bank */
|
||||||
sam4_add_flash(t, SAM4S_EEFC_BASE(0), 0x400000, size);
|
sam4_add_flash(t, SAM4S_EEFC_BASE(0), 0x400000, size);
|
||||||
|
@ -186,13 +186,13 @@ static void sam4l_add_flash(target *t, uint32_t addr, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return size of RAM */
|
/* Return size of RAM */
|
||||||
static size_t sam_ram_size(uint32_t idcode) {
|
static size_t sam_ram_size(uint32_t cidr) {
|
||||||
return __ram_size[((idcode >> CHIPID_CIDR_SRAMSIZ_SHIFT) & CHIPID_CIDR_SRAMSIZ_MASK)];
|
return __ram_size[((cidr >> CHIPID_CIDR_SRAMSIZ_SHIFT) & CHIPID_CIDR_SRAMSIZ_MASK)];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return size of FLASH */
|
/* Return size of FLASH */
|
||||||
static size_t sam_nvp_size(uint32_t idcode) {
|
static size_t sam_nvp_size(uint32_t cidr) {
|
||||||
return __nvp_size[((idcode >> CHIPID_CIDR_NVPSIZ_SHIFT) & CHIPID_CIDR_NVPSIZ_MASK)];
|
return __nvp_size[((cidr >> CHIPID_CIDR_NVPSIZ_SHIFT) & CHIPID_CIDR_NVPSIZ_MASK)];
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SMAP_BASE 0x400a3000
|
#define SMAP_BASE 0x400a3000
|
||||||
@ -228,14 +228,14 @@ bool sam4l_probe(target *t)
|
|||||||
{
|
{
|
||||||
size_t ram_size, flash_size;
|
size_t ram_size, flash_size;
|
||||||
|
|
||||||
t->idcode = target_mem_read32(t, SAM4L_CHIPID_CIDR);
|
uint32_t cidr = target_mem_read32(t, SAM4L_CHIPID_CIDR);
|
||||||
if (((t->idcode >> CHIPID_CIDR_ARCH_SHIFT) & CHIPID_CIDR_ARCH_MASK) == SAM4L_ARCH) {
|
if (((cidr >> CHIPID_CIDR_ARCH_SHIFT) & CHIPID_CIDR_ARCH_MASK) == SAM4L_ARCH) {
|
||||||
t->driver = "Atmel SAM4L";
|
t->driver = "Atmel SAM4L";
|
||||||
/* this function says we need to do "extra" stuff after reset */
|
/* this function says we need to do "extra" stuff after reset */
|
||||||
t->extended_reset = sam4l_extended_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);
|
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);
|
sam4l_add_flash(t, 0x0, flash_size);
|
||||||
DEBUG_INFO("\nSAM4L: RAM = 0x%x (%dK), FLASH = 0x%x (%dK)\n",
|
DEBUG_INFO("\nSAM4L: RAM = 0x%x (%dK), FLASH = 0x%x (%dK)\n",
|
||||||
(unsigned int) ram_size, (unsigned int) (ram_size / 1024),
|
(unsigned int) ram_size, (unsigned int) (ram_size / 1024),
|
||||||
|
@ -118,9 +118,10 @@ static void stm32f1_add_flash(target *t,
|
|||||||
|
|
||||||
bool stm32f1_probe(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 flash_size;
|
||||||
size_t block_size = 0x400;
|
size_t block_size = 0x400;
|
||||||
t->idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff;
|
|
||||||
switch(t->idcode) {
|
switch(t->idcode) {
|
||||||
case 0x410: /* Medium density */
|
case 0x410: /* Medium density */
|
||||||
case 0x412: /* Low density */
|
case 0x412: /* Low density */
|
||||||
@ -167,10 +168,6 @@ bool stm32f1_probe(target *t)
|
|||||||
stm32f1_add_flash(t, 0x8000000, 0x80000, 0x800);
|
stm32f1_add_flash(t, 0x8000000, 0x80000, 0x800);
|
||||||
target_add_commands(t, stm32f1_cmd_list, "STM32F3");
|
target_add_commands(t, stm32f1_cmd_list, "STM32F3");
|
||||||
return true;
|
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*/
|
case 0x444: /* STM32F03 RM0091 Rev.7, STM32F030x[4|6] RM0360 Rev. 4*/
|
||||||
t->driver = "STM32F03";
|
t->driver = "STM32F03";
|
||||||
flash_size = 0x8000;
|
flash_size = 0x8000;
|
||||||
|
@ -197,28 +197,22 @@ char *stm32f4_get_chip_name(uint32_t idcode)
|
|||||||
|
|
||||||
static void stm32f7_detach(target *t)
|
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);
|
cortexm_detach(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool stm32f4_probe(target *t)
|
bool stm32f4_probe(target *t)
|
||||||
{
|
{
|
||||||
ADIv5_AP_t *ap = cortexm_ap(t);
|
if (t->idcode == ID_STM32F20X) {
|
||||||
uint32_t idcode;
|
|
||||||
|
|
||||||
idcode = (ap->dp->targetid >> 16) & 0xfff;
|
|
||||||
if (!idcode)
|
|
||||||
idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xFFF;
|
|
||||||
|
|
||||||
if (idcode == ID_STM32F20X) {
|
|
||||||
/* F405 revision A have a wrong IDCODE, use ARM_CPUID to make the
|
/* F405 revision A have a wrong IDCODE, use ARM_CPUID to make the
|
||||||
* distinction with F205. Revision is also wrong (0x2000 instead
|
* distinction with F205. Revision is also wrong (0x2000 instead
|
||||||
* of 0x1000). See F40x/F41x errata. */
|
* of 0x1000). See F40x/F41x errata. */
|
||||||
uint32_t cpuid = target_mem_read32(t, ARM_CPUID);
|
uint32_t cpuid = target_mem_read32(t, ARM_CPUID);
|
||||||
if ((cpuid & 0xFFF0) == 0xC240)
|
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_STM32F74X: /* F74x RM0385 Rev.4 */
|
||||||
case ID_STM32F76X: /* F76x F77x RM0410 */
|
case ID_STM32F76X: /* F76x F77x RM0410 */
|
||||||
case ID_STM32F72X: /* F72x F73x RM0431 */
|
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_STM32F412: /* F412 RM0402 Rev.4, 256 kB Ram */
|
||||||
case ID_STM32F401E: /* F401 D/E RM0368 Rev.3 */
|
case ID_STM32F401E: /* F401 D/E RM0368 Rev.3 */
|
||||||
case ID_STM32F413: /* F413 RM0430 Rev.2, 320 kB Ram, 1.5 MB flash. */
|
case ID_STM32F413: /* F413 RM0430 Rev.2, 320 kB Ram, 1.5 MB flash. */
|
||||||
t->idcode = idcode;
|
t->driver = stm32f4_get_chip_name(t->idcode);
|
||||||
t->driver = stm32f4_get_chip_name(idcode);
|
|
||||||
t->attach = stm32f4_attach;
|
t->attach = stm32f4_attach;
|
||||||
target_add_commands(t, stm32f4_cmd_list, t->driver);
|
target_add_commands(t, stm32f4_cmd_list, t->driver);
|
||||||
return true;
|
return true;
|
||||||
@ -306,8 +299,6 @@ static bool stm32f4_attach(target *t)
|
|||||||
bool use_dual_bank = false;
|
bool use_dual_bank = false;
|
||||||
target_mem_map_free(t);
|
target_mem_map_free(t);
|
||||||
if (is_f7) {
|
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, 0x00000000, 0x4000); /* 16 k ITCM Ram */
|
||||||
target_add_ram(t, 0x20000000, 0x20000); /* 128 k DTCM Ram */
|
target_add_ram(t, 0x20000000, 0x20000); /* 128 k DTCM Ram */
|
||||||
target_add_ram(t, 0x20020000, 0x60000); /* 384 k Ram */
|
target_add_ram(t, 0x20020000, 0x60000); /* 384 k Ram */
|
||||||
|
@ -188,11 +188,6 @@ static bool stm32h7_attach(target *t)
|
|||||||
{
|
{
|
||||||
if (!cortexm_attach(t))
|
if (!cortexm_attach(t))
|
||||||
return false;
|
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
|
/* If IWDG runs as HARDWARE watchdog (44.3.4) erase
|
||||||
* will be aborted by the Watchdog and erase fails!
|
* will be aborted by the Watchdog and erase fails!
|
||||||
* Setting IWDG_KR to 0xaaaa does not seem to help!*/
|
* 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)
|
bool stm32h7_probe(target *t)
|
||||||
{
|
{
|
||||||
ADIv5_AP_t *ap = cortexm_ap(t);
|
if (t->idcode == ID_STM32H74x) {
|
||||||
uint32_t idcode = (ap->dp->targetid >> 16) & 0xfff;
|
|
||||||
if (idcode == ID_STM32H74x) {
|
|
||||||
t->idcode = idcode;
|
|
||||||
t->driver = stm32h74_driver_str;
|
t->driver = stm32h74_driver_str;
|
||||||
t->attach = stm32h7_attach;
|
t->attach = stm32h7_attach;
|
||||||
t->detach = stm32h7_detach;
|
t->detach = stm32h7_detach;
|
||||||
target_add_commands(t, stm32h7_cmd_list, stm32h74_driver_str);
|
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -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. */
|
STM32L0xx parts as well as the STM32L1xx's. */
|
||||||
bool stm32l0_probe(target* t)
|
bool stm32l0_probe(target* t)
|
||||||
{
|
{
|
||||||
uint32_t idcode;
|
switch (t->idcode) {
|
||||||
|
|
||||||
idcode = target_mem_read32(t, STM32L1_DBGMCU_IDCODE_PHYS) & 0xfff;
|
|
||||||
switch (idcode) {
|
|
||||||
case 0x416: /* CAT. 1 device */
|
case 0x416: /* CAT. 1 device */
|
||||||
case 0x429: /* CAT. 2 device */
|
case 0x429: /* CAT. 2 device */
|
||||||
case 0x427: /* CAT. 3 device */
|
case 0x427: /* CAT. 3 device */
|
||||||
case 0x436: /* CAT. 4 device */
|
case 0x436: /* CAT. 4 device */
|
||||||
case 0x437: /* CAT. 5 device */
|
case 0x437: /* CAT. 5 device */
|
||||||
t->idcode = idcode;
|
|
||||||
t->driver = "STM32L1x";
|
t->driver = "STM32L1x";
|
||||||
target_add_ram(t, 0x20000000, 0x14000);
|
target_add_ram(t, 0x20000000, 0x14000);
|
||||||
stm32l_add_flash(t, 0x8000000, 0x80000, 0x100);
|
stm32l_add_flash(t, 0x8000000, 0x80000, 0x100);
|
||||||
//stm32l_add_eeprom(t, 0x8080000, 0x4000);
|
//stm32l_add_eeprom(t, 0x8080000, 0x4000);
|
||||||
target_add_commands(t, stm32lx_cmd_list, "STM32L1x");
|
target_add_commands(t, stm32lx_cmd_list, "STM32L1x");
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
idcode = target_mem_read32(t, STM32L0_DBGMCU_IDCODE_PHYS) & 0xfff;
|
|
||||||
switch (idcode) {
|
|
||||||
case 0x457: /* STM32L0xx Cat1 */
|
case 0x457: /* STM32L0xx Cat1 */
|
||||||
case 0x425: /* STM32L0xx Cat2 */
|
case 0x425: /* STM32L0xx Cat2 */
|
||||||
case 0x417: /* STM32L0xx Cat3 */
|
case 0x417: /* STM32L0xx Cat3 */
|
||||||
case 0x447: /* STM32L0xx Cat5 */
|
case 0x447: /* STM32L0xx Cat5 */
|
||||||
t->idcode = idcode;
|
|
||||||
t->driver = "STM32L0x";
|
t->driver = "STM32L0x";
|
||||||
target_add_ram(t, 0x20000000, 0x5000);
|
target_add_ram(t, 0x20000000, 0x5000);
|
||||||
stm32l_add_flash(t, 0x8000000, 0x10000, 0x80);
|
stm32l_add_flash(t, 0x8000000, 0x10000, 0x80);
|
||||||
|
@ -373,18 +373,11 @@ static void stm32l4_detach(target *t)
|
|||||||
|
|
||||||
bool stm32l4_probe(target *t)
|
bool stm32l4_probe(target *t)
|
||||||
{
|
{
|
||||||
uint32_t idcode_reg = STM32L4_DBGMCU_IDCODE_PHYS;
|
struct stm32l4_info const *chip = stm32l4_get_chip_info(t->idcode);
|
||||||
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);
|
|
||||||
|
|
||||||
if( !chip->idcode ) /* Not found */
|
if( !chip->idcode ) /* Not found */
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
t->idcode = idcode;
|
|
||||||
t->driver = chip->designator;
|
t->driver = chip->designator;
|
||||||
t->attach = stm32l4_attach;
|
t->attach = stm32l4_attach;
|
||||||
t->detach = stm32l4_detach;
|
t->detach = stm32l4_detach;
|
||||||
|
@ -502,6 +502,16 @@ const char *target_core_name(target *t)
|
|||||||
return t->core;
|
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 target_mem_read32(target *t, uint32_t addr)
|
||||||
{
|
{
|
||||||
uint32_t ret;
|
uint32_t ret;
|
||||||
|
@ -111,7 +111,8 @@ struct target_s {
|
|||||||
|
|
||||||
/* target-defined options */
|
/* target-defined options */
|
||||||
unsigned target_options;
|
unsigned target_options;
|
||||||
uint32_t idcode;
|
uint16_t t_designer;
|
||||||
|
uint16_t idcode;
|
||||||
uint32_t target_storage;
|
uint32_t target_storage;
|
||||||
|
|
||||||
struct target_ram *ram;
|
struct target_ram *ram;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user