blob: ad2dbb5c27b52acdfce38a5b896897c67c7669cf [file] [log] [blame]
; Output-enable active-low variant of the SWD probe
.program probe
.side_set 2 opt
; SWDIO_OEN is pin 0, SWCLK pin 1, SWDIO (out) pin 2, SWDI (in) pin 3.
; Pin 0 and 1 are sideset pins
public out_negedge:
set pindirs, 0x1 side 0x0 ; OE_N 0, data high, clock 0
public out_idle:
pull ; pull nbits - 1
mov x, osr
pull ; pull data
public out_negedge_bitloop:
out pins, 1 side 0x0
jmp x-- out_negedge_bitloop side 0x2 ; OE_N 0, clock high
set pins, 1 side 0x0 ; drive data high (idle bus state)
push ; Push to rx fifo just so processor knows when done
jmp out_negedge ; Wait for next transaction
public in_posedge:
set pindirs, 0x0 side 0x1 ; OE_N 1, data high, clock 0
public in_idle:
pull
mov x, osr
in_posedge_bitloop:
in pins, 1 side 0x1 ; OE_N 1, clock 0
jmp x-- in_posedge_bitloop side 0x3 ; OE_N 1, clock 1
push
jmp in_posedge
; Implement probe_gpio_init() and probe_sm_init() methods here - set pins, offsets, sidesets etc
% c-sdk {
void probe_gpio_init()
{
#if defined(PROBE_PIN_RESET)
// Target reset pin: pull up, input to emulate open drain pin
gpio_pull_up(PROBE_PIN_RESET);
// gpio_init will leave the pin cleared and set as input
gpio_init(PROBE_PIN_RESET);
#endif
// Funcsel pins
pio_gpio_init(pio0, PROBE_PIN_SWDIOEN);
pio_gpio_init(pio0, PROBE_PIN_SWCLK);
pio_gpio_init(pio0, PROBE_PIN_SWDIO);
// Make sure SWDIO has a pullup on it. Idle state is high
gpio_pull_up(PROBE_PIN_SWDIO);
gpio_pull_up(PROBE_PIN_SWDIOEN);
}
void probe_sm_init(pio_sm_config* sm_config) {
// Set SWDIOEN and SWCLK as sideset pins
sm_config_set_sideset_pins(&sm_config, PROBE_PIN_SWDIOEN);
// Set SWDIO offset
sm_config_set_out_pins(sm_config, PROBE_PIN_SWDIO, 1);
sm_config_set_set_pins(sm_config, PROBE_PIN_SWDIO, 1);
sm_config_set_in_pins(sm_config, PROBE_PIN_SWDI);
// Set SWDIOEN, SWD and SWDIO pins as output to start. This will be set in the sm
pio_sm_set_consecutive_pindirs(pio0, PROBE_SM, PROBE_PIN_OFFSET, 3, true);
// shift output right, autopull off, autopull threshold
sm_config_set_out_shift(sm_config, true, false, 0);
// shift input right as swd data is lsb first, autopush off
sm_config_set_in_shift(sm_config, true, false, 0);
}
%}