blob: 5636c0c6bda631ffbd9c228d862702c2ecaa96cf [file] [log] [blame] [edit]
/*
* The MIT License (MIT)
*
* Copyright (c) 2021-2023 Raspberry Pi (Trading) Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
// Every TX FIFO entry is either a command, or up to 32 bits of data.
// Command format:
//
// | 13:9 | 8 | 7:0 |
// | Cmd | Dir | Count |
//
// Count is the number of bits to be transferred by this command, minus 1.
// Dir is the output enable for the SWDIO pin.
// Cmd is the address of the write_cmd, read_cmd or get_next_cmd label.
//
// write_cmd expects a FIFO data entry, but read_cmd does not.
//
// read_cmd pushes data to the FIFO, but write_cmd does not. (The lack of RX
// garbage on writes allows the interface code to return early after pushing a
// write command, as there is no need in general to poll for a command's
// completion as long as all commands are executed in order.)
//
// The SWCLK period is 4 PIO SM execution cycles.
.program probe
.side_set 1 opt
public write_cmd:
public turnaround_cmd: ; Alias of write, used for probe_oen.pio
pull
write_bitloop:
out pins, 1 [1] side 0x0 ; Data is output by host on negedge
jmp x-- write_bitloop [1] side 0x1 ; ...and captured by target on posedge
; Fall through to next command
.wrap_target
public get_next_cmd:
pull side 0x0 ; SWCLK is initially low
out x, 8 ; Get bit count
out pindirs, 1 ; Set SWDIO direction
out pc, 5 ; Go to command routine
read_bitloop:
nop ; Additional delay on taken loop branch
public read_cmd:
in pins, 1 [1] side 0x1 ; Data is captured by host on posedge
jmp x-- read_bitloop side 0x0
push
.wrap ; Wrap to next command
; Implement probe_gpio_init() and probe_sm_init() methods here - set pins, offsets, sidesets etc
% c-sdk {
static inline 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_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);
}
// DAP interface says all pins have to be High-Z when disabled
static inline void probe_gpio_deinit()
{
#if defined(PROBE_PIN_RESET)
gpio_deinit(PROBE_PIN_RESET);
gpio_disable_pulls(PROBE_PIN_RESET);
#endif
gpio_deinit(PROBE_PIN_SWCLK);
gpio_disable_pulls(PROBE_PIN_SWCLK);
gpio_deinit(PROBE_PIN_SWDIO);
gpio_disable_pulls(PROBE_PIN_SWDIO);
}
static inline void probe_sm_init(pio_sm_config* sm_config) {
// Set SWCLK as a sideset pin
sm_config_set_sideset_pins(sm_config, PROBE_PIN_SWCLK);
// 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);
#ifdef PROBE_IO_SWDI
sm_config_set_in_pins(sm_config, PROBE_PIN_SWDI);
#else
sm_config_set_in_pins(sm_config, PROBE_PIN_SWDIO);
#endif
// Set 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, 2, 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);
}
%}