diff --git a/src/Makefile b/src/Makefile index 06813c5..de05365 100644 --- a/src/Makefile +++ b/src/Makefile @@ -48,6 +48,7 @@ SRC = \ nxpke04.c \ platform.c \ remote.c \ + rp.c \ sam3x.c \ sam4l.c \ samd.c \ diff --git a/src/target/adiv5.c b/src/target/adiv5.c index fe3f457..7e11de7 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -3,7 +3,7 @@ * * Copyright (C) 2015 Black Sphere Technologies Ltd. * Written by Gareth McMullin - * Copyright (C) 2018 - 2020 Uwe Bonnes + * Copyright (C) 2018 - 2021 Uwe Bonnes * (bon@elektron.ikp.physik.tu-darmstadt.de) * * This program is free software: you can redistribute it and/or modify @@ -620,6 +620,20 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel) return ap; } +/* No real AP on RP2040. Special setup.*/ +static void rp_rescue_setup(ADIv5_DP_t *dp) +{ + ADIv5_AP_t *ap = malloc(sizeof(*ap)); + if (!ap) { /* malloc failed: heap exhaustion */ + DEBUG_WARN("malloc: failed in %s\n", __func__); + return; + } + ap->dp = dp; + extern void rp_rescue_probe(ADIv5_AP_t *); + rp_rescue_probe(ap); + return; +} + void adiv5_dp_init(ADIv5_DP_t *dp) { #define DPIDR_PARTNO_MASK 0x0ff00000 @@ -630,8 +644,12 @@ void adiv5_dp_init(ADIv5_DP_t *dp) free(dp); return; } - DEBUG_INFO("DPIDR 0x%08" PRIx32 " (v%" PRId32 " %srev%" PRId32 ")\n", - dp->idcode, + if (dp->idcode == 0x10212927) { + rp_rescue_setup(dp); + free(dp); + return; + } + DEBUG_INFO("DPIDR 0x%08" PRIx32 " (v%d %srev%d)\n", dp->idcode, (dp->idcode >> 12) & 0xf, (dp->idcode & 0x10000) ? "MINDP " : "", dp->idcode >> 28); volatile uint32_t ctrlstat = 0; diff --git a/src/target/adiv5.h b/src/target/adiv5.h index 97bf928..1d2a227 100644 --- a/src/target/adiv5.h +++ b/src/target/adiv5.h @@ -88,7 +88,8 @@ #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*/ +/* Known designers seen in SYSROM-PIDR. Ignore Bit 0 from + * the designer bits to get JEDEC Ids with bit 7 ignored.*/ #define AP_DESIGNER_FREESCALE 0x00e #define AP_DESIGNER_TEXAS 0x017 #define AP_DESIGNER_ATMEL 0x01f @@ -102,6 +103,7 @@ #define AP_DESIGNER_CS 0x555 #define AP_DESIGNER_ENERGY_MICRO 0x673 #define AP_DESIGNER_GIGADEVICE 0x751 +#define AP_DESIGNER_RASPBERRY 0x927 /* AP Control and Status Word (CSW) */ #define ADIV5_AP_CSW_DBGSWENABLE (1u << 31) diff --git a/src/target/adiv5_swdp.c b/src/target/adiv5_swdp.c index db0667b..b20ae27 100644 --- a/src/target/adiv5_swdp.c +++ b/src/target/adiv5_swdp.c @@ -163,9 +163,6 @@ int adiv5_swdp_scan(uint32_t targetid) if (initial_dp->dp_low_read(initial_dp, ADIV5_DP_IDCODE, &idcode)) continue; - if (dp_targetid == 0xf1002927) /* Fixme: Handle RP2040 rescue port */ - continue; - DEBUG_WARN("DP %2d IDCODE %08" PRIx32 " TID 0x%08" PRIx32 "\n", i, idcode, dp_targetid); } else { dp_targetid = 0; } diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 5c76eea..9fb89a3 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -437,7 +437,10 @@ bool cortexm_probe(ADIv5_AP_t *ap) "probed device\n", ap->ap_designer, ap->ap_partno); #endif } - if (ap->ap_partno == 0x4c3) { /* Cortex-M3 ROM */ + if (ap->ap_partno == 0x4c0) { /* Cortex-M0+ ROM */ + if ((ap->dp->targetid & 0xfff) == AP_DESIGNER_RASPBERRY) + PROBE(rp_probe); + } else if (ap->ap_partno == 0x4c3) { /* Cortex-M3 ROM */ PROBE(stm32f1_probe); /* Care for STM32F1 clones */ PROBE(lpc15xx_probe); /* Thanks to JojoS for testing */ } else if (ap->ap_partno == 0x471) { /* Cortex-M0 ROM */ diff --git a/src/target/rp.c b/src/target/rp.c new file mode 100644 index 0000000..0787c64 --- /dev/null +++ b/src/target/rp.c @@ -0,0 +1,84 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2021 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* This file implements Raspberry Pico (RP2040) target specific functions + * for detecting the device, providing the XML memory map but not yet + * Flash memory programming. + */ + +#include "general.h" +#include "target.h" +#include "target_internal.h" +#include "cortexm.h" + +bool rp_probe(target *t) +{ + t->driver = "Raspberry RP2040"; + target_add_ram(t, 0x20000000, 0x40000); + return true; +} + + +static bool rp_rescue_reset(target *t, int argc, const char **argv); + +const struct command_s rp_rescue_cmd_list[] = { + {"rescue_reset", (cmd_handler)rp_rescue_reset, "Hard reset to bootrom and halt"}, + {NULL, NULL, NULL} +}; + +void rp_rescue_probe(ADIv5_AP_t *ap) +{ + target *t = target_new(); + if (!t) { + return; + } + + adiv5_ap_ref(ap); + t->priv = ap; + t->priv_free = (void*)adiv5_ap_unref; + t->driver = "Raspberry RP2040 Rescue"; + + target_add_commands(t, rp_rescue_cmd_list, t->driver); +} + +static bool rp_rescue_reset(target *t, int argc, const char **argv) +{ + (void)argc; + (void)argv; + ADIv5_AP_t *ap = (ADIv5_AP_t *)t->priv; + ap->dp->low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_DP_CTRLSTAT, + ADIV5_DP_CTRLSTAT_CDBGPWRUPREQ); + ap->dp->low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_DP_CTRLSTAT, 0); + return true; +} diff --git a/src/target/target.c b/src/target/target.c index 2f70a14..eb43f37 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -54,7 +54,6 @@ target *target_new(void) t->attach = (void*)nop_function; t->detach = (void*)nop_function; - t->check_error = (void*)nop_function; t->mem_read = (void*)nop_function; t->mem_write = (void*)nop_function; t->reg_read = (void*)nop_function; @@ -348,7 +347,13 @@ void target_detach(target *t) #endif } -bool target_check_error(target *t) { return t->check_error(t); } +bool target_check_error(target *t) { + if (t) + return t->check_error(t); + else + return false; +} + bool target_attached(target *t) { return t->attached; } /* Memory access functions */ diff --git a/src/target/target_internal.h b/src/target/target_internal.h index ebd9d62..ebc791f 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -192,4 +192,5 @@ bool kinetis_probe(target *t); bool efm32_probe(target *t); bool msp432_probe(target *t); bool ke04_probe(target *t); +bool rp_probe(target *t); #endif