Skip to content

Commit fbc4116

Browse files
committed
probe: split pioasm and setup code into variant files, and add OEN variant
1 parent 364adfe commit fbc4116

File tree

6 files changed

+133
-38
lines changed

6 files changed

+133
-38
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ target_include_directories(picoprobe PRIVATE
3636
target_compile_options(picoprobe PRIVATE -Wall)
3737

3838
pico_generate_pio_header(picoprobe ${CMAKE_CURRENT_LIST_DIR}/src/probe.pio)
39+
pico_generate_pio_header(picoprobe ${CMAKE_CURRENT_LIST_DIR}/src/probe_oen.pio)
3940

4041
target_include_directories(picoprobe PRIVATE src)
4142

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,9 @@ Picoprobe allows a Pico / RP2040 to be used as USB -> SWD and UART bridge. This
33

44
# Documentation
55
Picoprobe documentation can be found in the [Pico Getting Started Guide](https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf). See "Appendix A: Using Picoprobe".
6+
7+
# TODO
8+
- TinyUSB's vendor interface is FIFO-based and not packet-based. Using raw tx/rx callbacks is preferable as this stops DAP command batches from being concatenated, which confused openOCD.
9+
- Instead of polling, move the DAP thread to an asynchronously started/stopped one-shot operation to reduce CPU wakeups
10+
- AutoBaud selection, as PIO is a capable frequency counter
11+
- Possibly include RTT support

src/probe.c

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -111,49 +111,13 @@ void probe_write_mode(void) {
111111
while(pio_sm_get_pc(pio0, PROBE_SM) != probe.offset + probe_offset_out_idle);
112112
}
113113

114-
void probe_gpio_init()
115-
{
116-
#if defined(PROBE_PIN_RESET)
117-
// Target reset pin: pull up, input to emulate open drain pin
118-
gpio_pull_up(PROBE_PIN_RESET);
119-
// gpio_init will leave the pin cleared and set as input
120-
gpio_init(PROBE_PIN_RESET);
121-
#endif
122-
// Funcsel pins
123-
pio_gpio_init(pio0, PROBE_PIN_SWCLK);
124-
pio_gpio_init(pio0, PROBE_PIN_SWDIO);
125-
// Make sure SWDIO has a pullup on it. Idle state is high
126-
gpio_pull_up(PROBE_PIN_SWDIO);
127-
}
128-
129114
void probe_init() {
130115
if (!probe.initted) {
131116
uint offset = pio_add_program(pio0, &probe_program);
132117
probe.offset = offset;
133118

134119
pio_sm_config sm_config = probe_program_get_default_config(offset);
135-
136-
// Set SWCLK as a sideset pin
137-
sm_config_set_sideset_pins(&sm_config, PROBE_PIN_SWCLK);
138-
139-
// Set SWDIO offset
140-
sm_config_set_out_pins(&sm_config, PROBE_PIN_SWDIO, 1);
141-
sm_config_set_set_pins(&sm_config, PROBE_PIN_SWDIO, 1);
142-
#ifdef PROBE_PIN_SWDI
143-
sm_config_set_in_pins(&sm_config, PROBE_PIN_SWDI);
144-
#else
145-
sm_config_set_in_pins(&sm_config, PROBE_PIN_SWDIO);
146-
#endif
147-
148-
// Set SWD and SWDIO pins as output to start. This will be set in the sm
149-
pio_sm_set_consecutive_pindirs(pio0, PROBE_SM, PROBE_PIN_OFFSET, 2, true);
150-
151-
// shift output right, autopull off, autopull threshold
152-
sm_config_set_out_shift(&sm_config, true, false, 0);
153-
// shift input right as swd data is lsb first, autopush off
154-
sm_config_set_in_shift(&sm_config, true, false, 0);
155-
156-
// Init SM with config
120+
probe_sm_init(&sm_config);
157121
pio_sm_init(pio0, PROBE_SM, offset, &sm_config);
158122

159123
// Set up divisor

src/probe.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,21 @@
2626
#ifndef PROBE_H_
2727
#define PROBE_H_
2828

29+
#if defined(PROBE_IO_RAW) || defined(PROBE_IO_SWDI)
30+
#include "probe.pio.h"
31+
#endif
32+
33+
#if defined(PROBE_IO_OEN)
34+
#include "probe_oen.pio.h"
35+
#endif
36+
2937
void probe_set_swclk_freq(uint freq_khz);
3038
void probe_write_bits(uint bit_count, uint32_t data_byte);
3139
uint32_t probe_read_bits(uint bit_count);
3240

3341
void probe_read_mode(void);
3442
void probe_write_mode(void);
3543

36-
void probe_gpio_init(void);
3744
void probe_init(void);
3845
void probe_deinit(void);
3946

src/probe.pio

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,47 @@ in_posedge_bitloop:
4949
jmp x-- in_posedge_bitloop side 0x0 ;
5050
push ; Push to rx fifo when done
5151
jmp in_posedge ; Jump back to start
52+
53+
; Implement probe_gpio_init() and probe_sm_init() methods here - set pins, offsets, sidesets etc
54+
% c-sdk {
55+
56+
static inline void probe_gpio_init()
57+
{
58+
#if defined(PROBE_PIN_RESET)
59+
// Target reset pin: pull up, input to emulate open drain pin
60+
gpio_pull_up(PROBE_PIN_RESET);
61+
// gpio_init will leave the pin cleared and set as input
62+
gpio_init(PROBE_PIN_RESET);
63+
#endif
64+
// Funcsel pins
65+
pio_gpio_init(pio0, PROBE_PIN_SWCLK);
66+
pio_gpio_init(pio0, PROBE_PIN_SWDIO);
67+
// Make sure SWDIO has a pullup on it. Idle state is high
68+
gpio_pull_up(PROBE_PIN_SWDIO);
69+
}
70+
71+
static inline void probe_sm_init(pio_sm_config* sm_config) {
72+
73+
// Set SWCLK as a sideset pin
74+
sm_config_set_sideset_pins(sm_config, PROBE_PIN_SWCLK);
75+
76+
// Set SWDIO offset
77+
sm_config_set_out_pins(sm_config, PROBE_PIN_SWDIO, 1);
78+
sm_config_set_set_pins(sm_config, PROBE_PIN_SWDIO, 1);
79+
#ifdef PROBE_IO_SWDI
80+
sm_config_set_in_pins(sm_config, PROBE_PIN_SWDI);
81+
#else
82+
sm_config_set_in_pins(sm_config, PROBE_PIN_SWDIO);
83+
#endif
84+
85+
86+
// Set SWD and SWDIO pins as output to start. This will be set in the sm
87+
pio_sm_set_consecutive_pindirs(pio0, PROBE_SM, PROBE_PIN_OFFSET, 2, true);
88+
89+
// shift output right, autopull off, autopull threshold
90+
sm_config_set_out_shift(sm_config, true, false, 0);
91+
// shift input right as swd data is lsb first, autopush off
92+
sm_config_set_in_shift(sm_config, true, false, 0);
93+
}
94+
95+
%}

src/probe_oen.pio

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
; Output-enable active-low variant of the SWD probe
2+
3+
.program probe
4+
.side_set 2 opt
5+
6+
; SWDIO_OEN is pin 0, SWCLK pin 1, SWDIO (out) pin 2, SWDI (in) pin 3.
7+
; Pin 0 and 1 are sideset pins
8+
public out_negedge:
9+
set pindirs, 0x1 side 0x0 ; OE_N 0, data high, clock 0
10+
public out_idle:
11+
pull ; pull nbits - 1
12+
mov x, osr
13+
pull ; pull data
14+
public out_negedge_bitloop:
15+
out pins, 1 side 0x0
16+
jmp x-- out_negedge_bitloop side 0x2 ; OE_N 0, clock high
17+
set pins, 1 side 0x0 ; drive data high (idle bus state)
18+
push ; Push to rx fifo just so processor knows when done
19+
jmp out_negedge ; Wait for next transaction
20+
21+
public in_posedge:
22+
set pindirs, 0x0 side 0x1 ; OE_N 1, data high, clock 0
23+
public in_idle:
24+
pull
25+
mov x, osr
26+
in_posedge_bitloop:
27+
in pins, 1 side 0x1 ; OE_N 1, clock 0
28+
jmp x-- in_posedge_bitloop side 0x3 ; OE_N 1, clock 1
29+
push
30+
jmp in_posedge
31+
32+
33+
; Implement probe_gpio_init() and probe_sm_init() methods here - set pins, offsets, sidesets etc
34+
% c-sdk {
35+
36+
void probe_gpio_init()
37+
{
38+
#if defined(PROBE_PIN_RESET)
39+
// Target reset pin: pull up, input to emulate open drain pin
40+
gpio_pull_up(PROBE_PIN_RESET);
41+
// gpio_init will leave the pin cleared and set as input
42+
gpio_init(PROBE_PIN_RESET);
43+
#endif
44+
// Funcsel pins
45+
pio_gpio_init(pio0, PROBE_PIN_SWDIOEN);
46+
pio_gpio_init(pio0, PROBE_PIN_SWCLK);
47+
pio_gpio_init(pio0, PROBE_PIN_SWDIO);
48+
49+
// Make sure SWDIO has a pullup on it. Idle state is high
50+
gpio_pull_up(PROBE_PIN_SWDIO);
51+
gpio_pull_up(PROBE_PIN_SWDIOEN);
52+
}
53+
54+
void probe_sm_init(pio_sm_config* sm_config) {
55+
56+
// Set SWDIOEN and SWCLK as sideset pins
57+
sm_config_set_sideset_pins(&sm_config, PROBE_PIN_SWDIOEN);
58+
59+
// Set SWDIO offset
60+
sm_config_set_out_pins(sm_config, PROBE_PIN_SWDIO, 1);
61+
sm_config_set_set_pins(sm_config, PROBE_PIN_SWDIO, 1);
62+
sm_config_set_in_pins(sm_config, PROBE_PIN_SWDI);
63+
64+
// Set SWDIOEN, SWD and SWDIO pins as output to start. This will be set in the sm
65+
pio_sm_set_consecutive_pindirs(pio0, PROBE_SM, PROBE_PIN_OFFSET, 3, true);
66+
67+
// shift output right, autopull off, autopull threshold
68+
sm_config_set_out_shift(sm_config, true, false, 0);
69+
// shift input right as swd data is lsb first, autopush off
70+
sm_config_set_in_shift(sm_config, true, false, 0);
71+
}
72+
73+
%}

0 commit comments

Comments
 (0)