Skip to content

Commit 04091e4

Browse files
committed
dap: fix consecutive AP read handling and improve USB pipelining
USB/Ring buffer improvements: - Implement ring buffer pattern matching original debugprobe for proper USB pipelining support (DAP_PACKET_COUNT=2) - Add QueueCommands/ExecuteCommands support for atomic command batching - Add comprehensive USB packet tracing for debugging Debug shell enhancements: - Add 'dap stats' command showing USB, ring buffer, and SWD statistics - Add 'dap trace' command for protocol tracing - Add 'dap dump' command for USB packet trace analysis - Add 'dap reset' command to clear statistics SWD/PIO improvements: - Improve SWD turnaround and data phase configuration - Add dormant wakeup and JTAG-to-SWD sequences for ADIv5.2+ targets - Various PIO diagnostics enhancements
1 parent c04aa4b commit 04091e4

File tree

10 files changed

+2071
-398
lines changed

10 files changed

+2071
-398
lines changed

include/dap.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,23 @@ uint32_t dap_vendor_command(const uint8_t *request, uint8_t *response);
6666
* @return Number of idle cycles
6767
*/
6868
uint8_t dap_get_idle_cycles(void);
69+
70+
/**
71+
* @brief Get configured SWD turnaround period
72+
*
73+
* Returns the turnaround period (1-4 clock cycles) as configured
74+
* by DAP_SWD_Configure command.
75+
*
76+
* @return Turnaround period in clock cycles
77+
*/
78+
uint8_t dap_get_swd_turnaround(void);
79+
80+
/**
81+
* @brief Get configured SWD data phase flag
82+
*
83+
* Returns whether data phase should be generated on WAIT/FAULT,
84+
* as configured by DAP_SWD_Configure command.
85+
*
86+
* @return 1 if data phase should be generated, 0 otherwise
87+
*/
88+
uint8_t dap_get_swd_data_phase(void);

include/pio_swd.h

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -42,73 +42,84 @@
4242

4343
#else
4444
/*
45-
* Pre-assembled PIO instructions (fallback when pioasm not available)
45+
* Pre-assembled PIO instructions for probe.pio (standard version)
46+
*
47+
* This is the basic SWD probe program from the original debugprobe.
48+
* It uses 1-bit optional side-set for SWCLK control only.
49+
* Direction control is via PIO pindirs, not an external OE pin.
50+
*
51+
* Pin layout (consecutive from PROBE_PIN_OFFSET=12):
52+
* - GPIO12: SWCLK - Clock (side-set controlled)
53+
* - GPIO13: SWDI - Data input from target (separate pin)
54+
* - GPIO14: SWDIO - Data output to target
55+
*
56+
* The level shifter has auto-direction sensing - no OE control needed.
4657
*
4758
* .program probe
4859
* .side_set 1 opt
4960
*
5061
* public write_cmd:
51-
* public turnaround_cmd:
62+
* public turnaround_cmd: ; Alias of write (offset 0)
5263
* pull
53-
* write_bitloop:
54-
* out pins, 1 [1] side 0x0
55-
* jmp x-- write_bitloop [1] side 0x1
64+
* write_bitloop: ; offset 1
65+
* out pins, 1 [1] side 0x0 ; Data output on negedge
66+
* jmp x-- write_bitloop [1] side 0x1 ; Captured by target on posedge
5667
*
5768
* .wrap_target
58-
* public get_next_cmd:
59-
* pull side 0x0
60-
* out x, 8
61-
* out pindirs, 1
62-
* out pc, 5
69+
* public get_next_cmd: ; offset 3
70+
* pull side 0x0 ; SWCLK initially low
71+
* out x, 8 ; Get bit count
72+
* out pindirs, 1 ; Set SWDIO direction
73+
* out pc, 5 ; Go to command routine
6374
*
64-
* read_bitloop:
75+
* read_bitloop: ; offset 7
6576
* nop
66-
* public read_cmd:
67-
* in pins, 1 [1] side 0x1
77+
* public read_cmd: ; offset 8
78+
* in pins, 1 [1] side 0x1 ; Data captured on posedge
6879
* jmp x-- read_bitloop side 0x0
6980
* push
70-
* .wrap
81+
* .wrap ; offset 10
7182
*/
7283

7384
static const uint16_t pio_swd_program_instructions[] = {
74-
/* 0: pull - write_cmd, turnaround_cmd */
85+
/* 0: write_cmd/turnaround_cmd - pull */
7586
0x80a0,
76-
/* 1: out pins, 1 [1] side 0x0 - write_bitloop */
77-
0x6101,
78-
/* 2: jmp x-- 1 [1] side 0x1 - continue write loop */
79-
0x1541,
80-
/* 3: pull side 0x0 - get_next_cmd (wrap_target) */
87+
/* 1: out pins, 1 [1] side 0x0 */
88+
0x7101,
89+
/* 2: jmp x-- 1 [1] side 0x1 */
90+
0x1941,
91+
/* 3: get_next_cmd (wrap_target) - pull side 0x0 */
8192
0x90a0,
82-
/* 4: out x, 8 - get bit count */
93+
/* 4: out x, 8 */
8394
0x6028,
84-
/* 5: out pindirs, 1 - set SWDIO direction */
95+
/* 5: out pindirs, 1 */
8596
0x6081,
86-
/* 6: out pc, 5 - jump to command routine */
97+
/* 6: out pc, 5 */
8798
0x60a5,
88-
/* 7: nop - read_bitloop (mov y, y) */
99+
/* 7: read_bitloop - nop */
89100
0xa042,
90-
/* 8: in pins, 1 [1] side 0x1 - read_cmd */
91-
0x5501,
92-
/* 9: jmp x-- 7 side 0x0 - continue read loop */
101+
/* 8: read_cmd - in pins, 1 [1] side 0x1 */
102+
0x5901,
103+
/* 9: jmp x-- 7 side 0x0 */
93104
0x1047,
94-
/* 10: push */
105+
/* 10: push (wrap) */
95106
0x8020,
96107
};
97108

98109
static const pio_program_t pio_swd_program = {
99110
.instructions = pio_swd_program_instructions,
100111
.length = ARRAY_SIZE(pio_swd_program_instructions),
101-
.origin = -1,
112+
.origin = 0, /* MUST be 0 - jmp instructions have hardcoded absolute targets */
102113
.pio_version = 0,
103114
};
104115

105116
#define PIO_SWD_PROGRAM_LENGTH ARRAY_SIZE(pio_swd_program_instructions)
106117
#define PIO_SWD_WRAP_TARGET 3 /* get_next_cmd */
107118
#define PIO_SWD_WRAP 10 /* after push */
108119

109-
/* Entry points (offsets) */
120+
/* Entry points (offsets) - turnaround_cmd = write_cmd (same entry) */
110121
#define PIO_SWD_OFFSET_WRITE_CMD 0
111-
#define PIO_SWD_OFFSET_TURNAROUND_CMD 0
122+
#define PIO_SWD_OFFSET_TURNAROUND_CMD 0 /* Alias of write_cmd */
112123
#define PIO_SWD_OFFSET_GET_NEXT_CMD 3
113124
#define PIO_SWD_OFFSET_READ_CMD 8
114125

include/probe.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,13 @@ void probe_get_pin_info(int *swclk_pin, int *swdio_pin, int *reset_pin);
205205
*/
206206
bool probe_is_pio_enabled(void);
207207

208+
/**
209+
* @brief Enable/disable PIO acceleration (for debugging)
210+
*
211+
* @param enable true to use PIO, false for GPIO bit-bang
212+
*/
213+
void probe_set_pio_enabled(bool enable);
214+
208215
/**
209216
* @brief Get system clock frequency
210217
*

include/probe_config.h

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
/* Debug Probe Hardware Pin Assignments */
2020
#if defined(CONFIG_BOARD_RPI_PICO) || defined(CONFIG_BOARD_RPI_PICO_W)
2121
/* Pico board configuration (DEBUG_ON_PICO mode) */
22+
#define PROBE_PIN_OFFSET 2 /* Base pin for PIO consecutive pins */
2223
#define PROBE_SWCLK_PIN 2
2324
#define PROBE_SWDIO_PIN 3
25+
#define PROBE_SWDI_PIN PROBE_SWDIO_PIN /* Same pin on Pico (no separate input) */
2426
#define PROBE_SWDIR_PIN (-1) /* Direction control (not used on Pico) */
2527
#define PROBE_RESET_PIN 6 /* Target reset */
2628

@@ -44,11 +46,25 @@
4446
#define PROBE_IO_OEN (-1)
4547

4648
#else
47-
/* Debug Probe Hardware configuration */
48-
#define PROBE_SWCLK_PIN 11
49-
#define PROBE_SWDIO_PIN 12
50-
#define PROBE_SWDIR_PIN 13
51-
#define PROBE_RESET_PIN 14
49+
/* Debug Probe Hardware configuration
50+
*
51+
* From original board_debug_probe_config.h - the Debug Probe uses:
52+
* - SWCLK (GPIO12): Clock output
53+
* - SWDI (GPIO13): Data INPUT from target (separate pin via level shifter)
54+
* - SWDIO (GPIO14): Data OUTPUT to target (via level shifter)
55+
*
56+
* The level shifter has auto-direction sensing - no OE or direction control.
57+
* The input and output paths are separate, which is why SWDI != SWDIO.
58+
*
59+
* Pin offset for PIO: 12 (consecutive pins for SWCLK=12, then either SWDI or SWDIO)
60+
* Note: The probe.pio program (not probe_oen.pio) is used since there's no SWDIOEN.
61+
*/
62+
#define PROBE_PIN_OFFSET 12 /* Base pin for PIO consecutive pins */
63+
#define PROBE_SWCLK_PIN 12 /* SWCLK output */
64+
#define PROBE_SWDI_PIN 13 /* SWDI - Data input from target */
65+
#define PROBE_SWDIO_PIN 14 /* SWDIO - Data output to target */
66+
#define PROBE_SWDIR_PIN (-1) /* No direction control */
67+
#define PROBE_RESET_PIN (-1) /* No reset pin on Debug Probe */
5268

5369
/* JTAG pins for Debug Probe (TDI/TDO not available on hardware) */
5470
#define PROBE_TCK_PIN PROBE_SWCLK_PIN /* TCK = SWCLK */
@@ -79,8 +95,8 @@
7995
/* Legacy alias for backward compatibility */
8096
#define PROBE_DAP_LED PROBE_DAP_RUNNING_LED
8197

82-
/* Output enable for level shifters */
83-
#define PROBE_IO_OEN 10
98+
/* No level shifter output enable on Debug Probe - auto-direction sensing */
99+
#define PROBE_IO_OEN (-1)
84100
#endif
85101

86102
/* JTAG availability check */
@@ -91,7 +107,10 @@
91107
/* USB Configuration */
92108
#define CFG_TUD_HID_EP_BUFSIZE 64
93109
#define DAP_PACKET_SIZE 64
94-
#define DAP_PACKET_COUNT 4
110+
/* Packet count for USB buffering.
111+
* Must be at least 2 for ring buffer logic to work (modulo N-1 check).
112+
* Value of 2 matches original debugprobe and enables pyocd pipelining. */
113+
#define DAP_PACKET_COUNT 2
95114

96115
/* UART Configuration */
97116
#ifndef CONFIG_DEBUGPROBE_UART_BAUDRATE

0 commit comments

Comments
 (0)