Compare commits

...

6 Commits

Author SHA1 Message Date
dragonmux 0c2e597c23
lpc55: Fixed some of the worst issues with this code 2 years ago
Uwe Bonnes 5647b8dc2a
lpc55: Cleanup in the target support 3 years ago
Uwe Bonnes 57413447a4
lpc55: More fiddling. 3 years ago
Uwe Bonnes 32d3b58a28
lpc55: Activate debug, detect. No memory map, no flash. 3 years ago
Uwe Bonnes 0f91bc30ea
adiv5: Different APs may have the same base. 4 years ago
Uwe Bonnes 320c605eb1
adiv5: Fix the defines for DP bank switching 3 years ago
  1. 1
      src/Makefile
  2. 26
      src/target/adiv5.c
  3. 12
      src/target/adiv5.h
  4. 4
      src/target/adiv5_swdp.c
  5. 7
      src/target/cortexm.c
  6. 152
      src/target/lpc55xx.c
  7. 1
      src/target/target_internal.h

1
src/Makefile

@ -40,6 +40,7 @@ SRC = \
lpc15xx.c \
lpc43xx.c \
lpc546xx.c \
lpc55xx.c \
kinetis.c \
main.c \
morse.c \

26
src/target/adiv5.c

@ -43,6 +43,7 @@
#define ARM_AP_TYPE_AXI 4
#define ARM_AP_TYPE_AHB5 5
#define AUTHSTATUS 0xFB8
/* ROM table CIDR values */
#define CIDR0_OFFSET 0xFF0 /* DBGCID0 */
#define CIDR1_OFFSET 0xFF4 /* DBGCID1 */
@ -626,8 +627,9 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel)
if(!tmpap.idr) /* IDR Invalid */
return NULL;
tmpap.csw = adiv5_ap_read(&tmpap, ADIV5_AP_CSW) &
~(ADIV5_AP_CSW_SIZE_MASK | ADIV5_AP_CSW_ADDRINC_MASK);
tmpap.csw = adiv5_ap_read(&tmpap, ADIV5_AP_CSW);
tmpap.csw &= ~(ADIV5_AP_CSW_SIZE_MASK | ADIV5_AP_CSW_ADDRINC_MASK);
tmpap.csw |= 0x80000000;
if (tmpap.csw & ADIV5_AP_CSW_TRINPROG) {
DEBUG_WARN("AP %d: Transaction in progress. AP is not be usable!\n",
@ -761,8 +763,11 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
}
}
extern void lpc55_ap_prepare(ADIv5_DP_t *dp);
if (((dp->targetid >> 1) & 0x7ff) == AP_DESIGNER_NXP) {
lpc55_ap_prepare(dp);
}
/* Probe for APs on this DP */
uint32_t last_base = 0;
int void_aps = 0;
dp->refcnt++;
for(int i = 0; (i < 256) && (void_aps < 8); i++) {
@ -786,18 +791,6 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
continue;
}
}
if (ap->base == last_base) {
DEBUG_WARN("AP %d: Duplicate base\n", i);
#if PC_HOSTED == 1
if (dp->ap_cleanup)
dp->ap_cleanup(i);
#endif
adiv5_ap_unref(ap);
adiv5_dp_unref(dp);
/* FIXME: Should we expect valid APs behind duplicate ones? */
return;
}
last_base = ap->base;
extern void kinetis_mdm_probe(ADIv5_AP_t *);
kinetis_mdm_probe(ap);
@ -807,6 +800,9 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
extern void efm32_aap_probe(ADIv5_AP_t *);
efm32_aap_probe(ap);
extern void lpc55_dmap_probe(ADIv5_AP_t *);
lpc55_dmap_probe(ap);
/* Halt the device and release from reset if reset is active!*/
if (!ap->apsel && ((ap->idr & 0xf) == ARM_AP_TYPE_AHB))
cortexm_prepare(ap);

12
src/target/adiv5.h

@ -27,11 +27,12 @@
#define ADIV5_DP_REG(x) (x)
#define ADIV5_AP_REG(x) (ADIV5_APnDP | (x))
#define ADIV5_DP_BANK0 0x00
#define ADIV5_DP_BANK1 0x10
#define ADIV5_DP_BANK2 0x20
#define ADIV5_DP_BANK3 0x30
#define ADIV5_DP_BANK4 0x40
/* Arguments to ADIV5_DP_SELECT to switch banks*/
#define ADIV5_DP_BANK0 0x0
#define ADIV5_DP_BANK1 0x1
#define ADIV5_DP_BANK2 0x2
#define ADIV5_DP_BANK3 0x3
#define ADIV5_DP_BANK4 0x4
/* ADIv5 DP Register addresses */
#define ADIV5_DP_IDCODE ADIV5_DP_REG(0x0)
@ -92,6 +93,7 @@
/* 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_NXP 0x015
#define AP_DESIGNER_TEXAS 0x017
#define AP_DESIGNER_ATMEL 0x01f
#define AP_DESIGNER_STM 0x020

4
src/target/adiv5_swdp.c

@ -122,9 +122,9 @@ int adiv5_swdp_scan(uint32_t targetid)
if ((idcode & ADIV5_DP_VERSION_MASK) == ADIV5_DPv2) {
scan_multidrop = true;
/* Read TargetID. Can be done with device in WFI, sleep or reset!*/
adiv5_dp_write(initial_dp, ADIV5_DP_SELECT, 2);
adiv5_dp_write(initial_dp, ADIV5_DP_SELECT, ADIV5_DP_BANK2);
target_id = adiv5_dp_read(initial_dp, ADIV5_DP_CTRLSTAT);
adiv5_dp_write(initial_dp, ADIV5_DP_SELECT, 0);
adiv5_dp_write(initial_dp, ADIV5_DP_SELECT, ADIV5_DP_BANK0);
DEBUG_INFO("TARGETID %08" PRIx32 "\n", target_id);
switch (target_id) {
case 0x01002927: /* RP2040 */

7
src/target/cortexm.c

@ -432,6 +432,13 @@ bool cortexm_probe(ADIv5_AP_t *ap)
case AP_DESIGNER_CYPRESS:
DEBUG_WARN("Unhandled Cypress device\n");
break;
case AP_DESIGNER_NXP:
if ((t->cpuid & CPUID_PARTNO_MASK) == CORTEX_M33) {
PROBE(lpc55xx_probe);
} else {
DEBUG_WARN("Unhandled NXP device\n");
}
break;
case AP_DESIGNER_INFINEON:
DEBUG_WARN("Unhandled Infineon device\n");
break;

152
src/target/lpc55xx.c

@ -0,0 +1,152 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2022 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.
*/
#include "general.h"
#include "target.h"
#include "target_internal.h"
#include "cortexm.h"
#define LPC55_DMAP_IDR 0x002A0000
#define LPC5XXXX_CHIPID 0x40000ff8
#define LPC55_DMAP_BULK_ERASE 0x02
#define LPC55_DMAP_START_DEBUG_SESSION 0x07
static uint32_t lpc55_dmap_cmd(ADIv5_AP_t *ap, uint32_t cmd)
{
uint32_t value;
platform_timeout timeout;
platform_timeout_set(&timeout, 20);
do {
/* Check that mailbox is not busy*/
value = adiv5_ap_read(ap, ADIV5_AP_CSW);
if (platform_timeout_is_expired(&timeout))
break;
} while (value);
platform_timeout_set(&timeout, 20);
if (value)
return value;
adiv5_ap_write(ap, ADIV5_AP_TAR, cmd);
platform_timeout_set(&timeout, 20);
do {
value = adiv5_ap_read(ap, ADIV5_AP_DRW) & 0xffff;
if (platform_timeout_is_expired(&timeout))
break;
} while(value);
if (value) {
DEBUG_WARN("LPC55 cms %x failed\n", cmd);
}
return value;
}
void lpc55_ap_prepare(ADIv5_DP_t *dp)
{
/* Reading targetid again here upsets the LPC55 ans STM32U5!*/
/* UM11126, 51.6.1
* Debug session with uninitialized/invalid flash image or ISP mode
*/
adiv5_dp_abort(dp, ADIV5_DP_ABORT_DAPABORT);
ADIv5_AP_t tmpap;
memset(&tmpap, 0, sizeof(tmpap));
tmpap.dp = dp;
tmpap.apsel = 2;
tmpap.idr = adiv5_ap_read(&tmpap, ADIV5_AP_IDR);
if (tmpap.idr == LPC55_DMAP_IDR) {
/* All fine when AP0 is visible*/
tmpap.apsel = 0;
tmpap.idr = adiv5_ap_read(&tmpap, ADIV5_AP_IDR);
if (!tmpap.idr) {
DEBUG_INFO("LPC55 activation sequence\n");
/* AP0 not visible, activation sequence needed*/
tmpap.apsel = 2;
adiv5_ap_write(&tmpap, ADIV5_AP_CSW, 0x21);
lpc55_dmap_cmd(&tmpap, LPC55_DMAP_START_DEBUG_SESSION);
}
} else {
DEBUG_WARN("LPC55 AP2 not visible %08" PRIx32 "\n", tmpap.idr);
}
}
bool lpc55xx_probe(target *t)
{
ADIv5_AP_t *ap = cortexm_ap(t);
if (ap->apsel == 1)
return false;
uint32_t chipid = target_mem_read32(t, 0x50000ff8);
DEBUG_WARN("Chipid %08" PRIx32 "\n", chipid);
(void)chipid;
target_add_ram(t, 0x20000000, 0x44000);
t->target_options |= CORTEXM_TOPT_INHIBIT_NRST;
switch (t->cpuid & CPUID_PATCH_MASK) {
case 3:
t->driver = "LPC55";
break;
case 4:
t->driver = "LPC551x";
break;
}
return true;
}
static bool lpc55_dmap_mass_erase(target *t)
{
ADIv5_AP_t *ap = t->priv;
if (lpc55_dmap_cmd(ap, LPC55_DMAP_BULK_ERASE))
return false;
return true;
}
bool lpc55_dmap_probe(ADIv5_AP_t *ap)
{
switch(ap->idr) {
case LPC55_DMAP_IDR:
break;
default:
return false;
}
target *t = target_new();
if (!t) {
DEBUG_WARN("nxp_dmap_probe target_new failed\n");
return false;
}
t->mass_erase = lpc55_dmap_mass_erase;
adiv5_ap_ref(ap);
t->priv = ap;
t->priv_free = (void*)adiv5_ap_unref;
t->driver = "LPC55 Debugger Mailbox";
t->regs_size = 4;
return true;
}

1
src/target/target_internal.h

@ -199,6 +199,7 @@ bool lpc15xx_probe(target *t);
bool lpc17xx_probe(target *t);
bool lpc43xx_probe(target *t);
bool lpc546xx_probe(target *t);
bool lpc55xx_probe(target *t);
bool samx7x_probe(target *t);
bool sam3x_probe(target *t);
bool sam4l_probe(target *t);

Loading…
Cancel
Save