From 0ff8b5530b2042f777a79b7fef314cbd0e50d794 Mon Sep 17 00:00:00 2001 From: newbrain Date: Thu, 11 Feb 2021 22:40:51 +0100 Subject: [PATCH] Hardware target reset support --- src/picoprobe_config.h | 3 +++ src/probe.c | 32 +++++++++++++++++++++++--------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/picoprobe_config.h b/src/picoprobe_config.h index 23ad28c..87be47b 100644 --- a/src/picoprobe_config.h +++ b/src/picoprobe_config.h @@ -52,6 +52,9 @@ #define PROBE_PIN_SWCLK PROBE_PIN_OFFSET + 0 // 2 #define PROBE_PIN_SWDIO PROBE_PIN_OFFSET + 1 // 3 +// Target reset config +#define PROBE_PIN_RESET 6 + // UART config #define PICOPROBE_UART_TX 4 #define PICOPROBE_UART_RX 5 diff --git a/src/probe.c b/src/probe.c index c23ce7e..3396796 100644 --- a/src/probe.c +++ b/src/probe.c @@ -68,11 +68,12 @@ struct _probe { static struct _probe probe; enum PROBE_CMDS { - PROBE_INVALID = 0, // Invalid command - PROBE_WRITE_BITS = 1, // Host wants us to write bits - PROBE_READ_BITS = 2, // Host wants us to read bits - PROBE_SET_FREQ = 3, // Set TCK - PROBE_RESET = 4, // Reset all state + PROBE_INVALID = 0, // Invalid command + PROBE_WRITE_BITS = 1, // Host wants us to write bits + PROBE_READ_BITS = 2, // Host wants us to read bits + PROBE_SET_FREQ = 3, // Set TCK + PROBE_RESET = 4, // Reset all state + PROBE_TARGET_RESET = 5, // Reset target }; struct __attribute__((__packed__)) probe_cmd_hdr { @@ -93,6 +94,12 @@ void probe_set_swclk_freq(uint freq_khz) { pio_sm_set_clkdiv_int_frac(pio0, PROBE_SM, divider, 0); } +static inline void probe_assert_reset(bool state) +{ + /* Change the direction to out to drive pin to 0 or to in to emulate open drain */ + gpio_set_dir(PROBE_PIN_RESET, state); +} + static inline void probe_write_bits(uint bit_count, uint8_t data_byte) { DEBUG_PINS_SET(probe_timing, DBG_PIN_WRITE); pio_sm_put_blocking(pio0, PROBE_SM, bit_count - 1); @@ -137,11 +144,16 @@ void probe_init() { // Make sure SWDIO has a pullup on it. Idle state is high gpio_pull_up(PROBE_PIN_SWDIO); + // 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); + uint offset = pio_add_program(pio0, &probe_program); probe.offset = offset; pio_sm_config sm_config = probe_program_get_default_config(offset); - + // Set SWCLK as a sideset pin sm_config_set_sideset_pins(&sm_config, PROBE_PIN_SWCLK); @@ -225,7 +237,7 @@ void probe_prepare_read_header(struct probe_cmd_hdr *hdr) { void probe_handle_pkt(void) { uint8_t *pkt = &probe.rx_buf[0] + sizeof(struct probe_pkt_hdr); uint remaining = probe.rx_len - sizeof(struct probe_pkt_hdr); - + DEBUG_PINS_SET(probe_timing, DBG_PIN_PKT); picoprobe_debug("Processing packet of length %d\n", probe.rx_len); @@ -236,7 +248,7 @@ void probe_handle_pkt(void) { uint data_bytes = DIV_ROUND_UP(hdr->bits, 8); pkt += sizeof(struct probe_cmd_hdr); remaining -= sizeof(struct probe_cmd_hdr); - + if (hdr->cmd == PROBE_WRITE_BITS) { uint8_t *data = pkt; probe_handle_write(data, hdr->bits); @@ -251,6 +263,8 @@ void probe_handle_pkt(void) { // TODO: Is there anything to do after a reset? // tx len and rx len should already be 0 ; + } else if (hdr->cmd == PROBE_TARGET_RESET) { + probe_assert_reset(hdr->bits); } } probe.rx_len = 0; @@ -275,7 +289,7 @@ void probe_task(void) { return; } probe.rx_len += count; - } + } if (probe.rx_len >= sizeof(struct probe_pkt_hdr)) { struct probe_pkt_hdr *pkt_hdr = (struct probe_pkt_hdr*)&probe.rx_buf[0];