xdebug

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 437a6da3a57cc05d3964a0f1571e22d74424f56a
parent 050b143acadd580ca8491c5cc14e0813dbfe0e4c
Author: Brian Swetland <swetland@frotz.net>
Date:   Tue, 28 Feb 2023 15:04:38 -0800

transport: complete swd attach sequence

This now handles SWJ-DPs in JTAG mode, DPv2s in Dormant State,
and supports DPv2 MultiDrop Target Selection.

Tested against SAMD21(CM0+), NRF52840(CM4), EFR32BG22(CM33),
RP2040(2xCM0+ Multidrop), LPC4370(2xCM4+CM0), and STM32F103(CM3)

Diffstat:
Msrc/transport.c | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Msrc/transport.h | 3++-
Msrc/xdebug.c | 42+++++++++++++++++++++++++++++++++---------
3 files changed, 91 insertions(+), 24 deletions(-)

diff --git a/src/transport.c b/src/transport.c @@ -319,20 +319,62 @@ int dc_ap_wr(DC* dc, unsigned apaddr, uint32_t val) { return dc_q_exec(dc); } -int dc_attach(DC* dc) { - uint8_t io[23] = { DAP_SWD_Sequence, 3, - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 64 1s - 0x10, 0x9E, 0xE7, // JTAG to SWD magic sequence - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, // 60 1s, 4 0s - }; - if (dap_cmd(dc, io, 23, io, 2) < 0) { - return -1; - } - if (io[1] != 0) { - ERROR("dc_attach() failure 0x%02x\n", io[1]); - return -1; - } - return 0; +// SWD Attach Sequence: +// 1. Send >50 1s and then the JTAG to SWD escape code +// (in case this is a JTAG-SWD DAP in JTAG mode) +// 2. Send >8 1s and then the Selection Alert Sequence +// and then the SWD Activation Code +// (in case this is a SWD v2 DAP in Dormant State) +// 3. Send >50 1s and then 4 0s -- the Line Reset Sequence +// 4. If multidrop, issue a write to DP.TARGETSEL, but +// ignore the ACK response +// 5. Issue a read from DP.IDR + +static uint8_t attach_cmd[54] = { + DAP_SWD_Sequence, 5, + + // [--- 64 1s ----------------------------------] + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // [JTAG2SWD] [- 16 1s ] [--------------------- + 0x00, 0x9E, 0xE7, 0xFF, 0xFF, 0x92, 0xF3, 0x09, 0x62, + // ----- Selection Alert Sequence --------------- + 0x00, 0x95, 0x2D, 0x85, 0x86, 0xE9, 0xAF, 0xDD, 0xE3, + // ---------------------] [Act Code] [--------- + 0x00, 0xA2, 0x0E, 0xBC, 0x19, 0xA0, 0xF1, 0xFF, 0xFF, + // ----- Line Reset Sequence -------] + 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, + + // WR DP TARGETSEL + 0x08, 0x99, + // 5 bits idle + 0x85, + // WR VALUE:32, PARTY:1, ZEROs:7 + 0x28, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +int dc_attach(DC* dc, unsigned flags, uint32_t tgt, uint32_t* idcode) { + uint8_t rsp[3]; + + if (flags & DC_MULTIDROP) { + // Copy and patch the attach sequence to include + // the DP.TARGETSEL write and insert the target + // id and parity + uint8_t cmd[54]; + memcpy(cmd, attach_cmd, 54); + cmd[1] = 8; + memcpy(cmd + 49, &tgt, sizeof(tgt)); + cmd[53] = __builtin_parity(tgt); + dap_cmd(dc, cmd, 54, rsp, 3); + } else { + // use the common part of the attach sequence, as-is + dap_cmd(dc, attach_cmd, 45, rsp, 2); + } + + // Issue a bare DP.IDR read, as required after a line reset + // or line reset + target select + dc_q_init(dc); + dc_q_raw_rd(dc, XFER_DP | XFER_RD | XFER_00, idcode); + return dc_q_exec(dc); } static usb_handle* usb_connect(void) { diff --git a/src/transport.h b/src/transport.h @@ -33,5 +33,6 @@ int dc_ap_wr(dctx_t* dc, unsigned apaddr, uint32_t val); int dc_create(dctx_t** dc); // attempt to attach to the debug target -int dc_attach(dctx_t* dc); +int dc_attach(dctx_t* dc, unsigned flags, uint32_t tgt, uint32_t* idcode); +#define DC_MULTIDROP 1 diff --git a/src/xdebug.c b/src/xdebug.c @@ -11,26 +11,50 @@ #include "transport.h" int main(int argc, char **argv) { - uint32_t n; + uint32_t n = 0; dctx_t* dc; if (dc_create(&dc) < 0) { return -1; } - dc_attach(dc); - - n = 0; - dc_dp_rd(dc, DP_DPIDR, &n); + dc_attach(dc, 0, 0, &n); printf("IDCODE %08x\n", n); - dc_dp_rd(dc, DP_CS, &n); - printf("CTRL/STAT %08x\n", n); + // If this is a RP2040, we need to connect in multidrop + // mode before doing anything else. + if (n == 0x0bc12477) { + dc_dp_rd(dc, DP_TARGETID, &n); + if (n == 0x01002927) { // RP2040 + dc_attach(dc, DC_MULTIDROP, 0x01002927, &n); + } + } + // power up system & debug + dc_dp_rd(dc, DP_CS, &n); + printf("CTRL/STAT %08x\n", n); dc_dp_wr(dc, DP_CS, DP_CS_CDBGPWRUPREQ | DP_CS_CSYSPWRUPREQ); - dc_dp_rd(dc, DP_CS, &n); - printf("CTRL/STAT %08x\n", n); + printf("CTRL/STAT %08x\n", n); + + // dump some info + dc_dp_rd(dc, DP_DPIDR, &n); + printf("DP.DPIDR %08x\n", n); + dc_dp_rd(dc, DP_TARGETID, &n); + printf("DP.TARGETID %08x\n", n); + dc_dp_rd(dc, DP_DLPIDR, &n); + printf("DP.DLPIDR %08x\n", n); + dc_ap_rd(dc, MAP_IDR, &n); + printf("MAP.IDR %08x\n", n); + dc_ap_rd(dc, MAP_CSW, &n); + printf("MAP.CSW %08x\n", n); + dc_ap_rd(dc, MAP_CFG, &n); + printf("MAP.CFG %08x\n", n); + dc_ap_rd(dc, MAP_CFG1, &n); + printf("MAP.CFG1 %08x\n", n); + dc_ap_rd(dc, MAP_BASE, &n); + printf("MAP.BASE %08x\n", n); + return 0; }