diff --git a/src/command.c b/src/command.c index 7cea3ded04c..c1b84191cf1 100644 --- a/src/command.c +++ b/src/command.c @@ -340,7 +340,7 @@ bool cmd_rvswd_scan(target_s *target, int argc, const char **argv) #if CONFIG_BMDA == 1 scan_result = bmda_rvswd_scan(); #else - scan_result = false; + scan_result = rvswd_scan(); #endif } CATCH () { @@ -400,7 +400,7 @@ bool cmd_auto_scan(target_s *target, int argc, const char **argv) #if CONFIG_BMDA == 1 scan_result = bmda_rvswd_scan(); #else - scan_result = false; + scan_result = rvswd_scan(); #endif if (!scan_result) gdb_out("RVSWD scan found no devices.\n"); diff --git a/src/include/rvswd.h b/src/include/rvswd.h new file mode 100644 index 00000000000..79235ec4106 --- /dev/null +++ b/src/include/rvswd.h @@ -0,0 +1,44 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2011 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef INCLUDE_RVSWD_H +#define INCLUDE_RVSWD_H + +#include +#include +#include + +/* Functions interface talking RVSWD */ +typedef struct rvswd_proc { + /* Perform a clock_cycles read */ + uint32_t (*seq_in)(size_t clock_cycles); + /* Perform a clock_cycles read + parity */ + bool (*seq_in_parity)(uint32_t *ret, size_t clock_cycles); + /* Perform a clock_cycles write with the provided data */ + void (*seq_out)(uint32_t tms_states, size_t clock_cycles); + /* Perform a clock_cycles write + parity with the provided data */ + void (*seq_out_parity)(uint32_t tms_states, size_t clock_cycles); +} rvswd_proc_s; + +extern rvswd_proc_s rvswd_proc; + +void rvswd_init(void); + +#endif /* INCLUDE_RVSWD_H */ diff --git a/src/include/target.h b/src/include/target.h index 80783b68fe0..3ed2f84b7d6 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -49,6 +49,9 @@ bool bmda_rvswd_scan(void); #endif bool adiv5_swd_scan(uint32_t targetid); bool jtag_scan(void); +#ifdef PLATFORM_HAS_RVSWD +bool rvswd_scan(void); +#endif size_t target_foreach(void (*callback)(size_t index, target_s *target, void *context), void *context); void target_list_free(void); diff --git a/src/platforms/common/meson.build b/src/platforms/common/meson.build index 4c2ce75a98b..ced755b32ea 100644 --- a/src/platforms/common/meson.build +++ b/src/platforms/common/meson.build @@ -34,6 +34,7 @@ platform_common_sources = files( 'aux_serial.c', 'jtagtap.c', 'swdptap.c', + 'rvswd.c', 'usb.c', 'usb_dfu_stub.c', 'usb_serial.c', diff --git a/src/platforms/common/rvswd.c b/src/platforms/common/rvswd.c new file mode 100644 index 00000000000..ae7e931238d --- /dev/null +++ b/src/platforms/common/rvswd.c @@ -0,0 +1,197 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2011 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* This file implements the SW-DP interface. */ + +#include "general.h" +#include "platform.h" +#include "timing.h" +#include "rvswd.h" +#include "maths_utils.h" + +// FIXME: reusing the SWD macros for now +#if !defined(SWDIO_IN_PORT) +#define SWDIO_IN_PORT SWDIO_PORT +#endif +#if !defined(SWDIO_IN_PIN) +#define SWDIO_IN_PIN SWDIO_PIN +#endif + +// typedef enum swdio_status_e { +// SWDIO_STATUS_FLOAT = 0, +// SWDIO_STATUS_DRIVE +// } swdio_status_t; + +rvswd_proc_s rvswd_proc; + +// static void swdptap_turnaround(swdio_status_t dir) __attribute__((optimize(3))); +// static uint32_t swdptap_seq_in(size_t clock_cycles) __attribute__((optimize(3))); +// static bool swdptap_seq_in_parity(uint32_t *ret, size_t clock_cycles) __attribute__((optimize(3))); +// static void swdptap_seq_out(uint32_t tms_states, size_t clock_cycles) __attribute__((optimize(3))); +// static void swdptap_seq_out_parity(uint32_t tms_states, size_t clock_cycles) __attribute__((optimize(3))); + +void rvswd_init(void) +{ + // rvswd_proc.seq_in = swdptap_seq_in; + // rvswd_proc.seq_in_parity = swdptap_seq_in_parity; + // rvswd_proc.seq_out = swdptap_seq_out; + // rvswd_proc.seq_out_parity = swdptap_seq_out_parity; +} + +// static void swdptap_turnaround(const swdio_status_t dir) +// { +// static swdio_status_t olddir = SWDIO_STATUS_FLOAT; +// /* Don't turnaround if direction not changing */ +// if (dir == olddir) +// return; +// olddir = dir; + +// #ifdef DEBUG_SWD_BITS +// DEBUG_INFO("%s", dir ? "\n-> " : "\n<- "); +// #endif + +// if (dir == SWDIO_STATUS_FLOAT) { +// SWDIO_MODE_FLOAT(); +// } else +// gpio_clear(SWCLK_PORT, SWCLK_PIN); + +// for (volatile uint32_t counter = target_clk_divider + 1; counter > 0; --counter) +// continue; + +// gpio_set(SWCLK_PORT, SWCLK_PIN); +// for (volatile uint32_t counter = target_clk_divider + 1; counter > 0; --counter) +// continue; + +// if (dir == SWDIO_STATUS_DRIVE) { +// gpio_clear(SWCLK_PORT, SWCLK_PIN); +// SWDIO_MODE_DRIVE(); +// } +// } + +// static uint32_t swdptap_seq_in_clk_delay(size_t clock_cycles) __attribute__((optimize(3))); + +// static uint32_t swdptap_seq_in_clk_delay(const size_t clock_cycles) +// { +// uint32_t value = 0; +// for (size_t cycle = 0; cycle < clock_cycles; ++cycle) { +// gpio_clear(SWCLK_PORT, SWCLK_PIN); +// value |= gpio_get(SWDIO_IN_PORT, SWDIO_IN_PIN) ? 1U << cycle : 0U; +// for (volatile uint32_t counter = target_clk_divider; counter > 0; --counter) +// continue; +// gpio_set(SWCLK_PORT, SWCLK_PIN); +// for (volatile uint32_t counter = target_clk_divider; counter > 0; --counter) +// continue; +// } +// gpio_clear(SWCLK_PORT, SWCLK_PIN); +// return value; +// } + +// static uint32_t swdptap_seq_in_no_delay(size_t clock_cycles) __attribute__((optimize(3))); + +// static uint32_t swdptap_seq_in_no_delay(const size_t clock_cycles) +// { +// uint32_t value = 0; +// for (size_t cycle = 0; cycle < clock_cycles; ++cycle) { +// gpio_clear(SWCLK_PORT, SWCLK_PIN); +// value |= gpio_get(SWDIO_IN_PORT, SWDIO_IN_PIN) ? 1U << cycle : 0U; +// gpio_set(SWCLK_PORT, SWCLK_PIN); +// __asm__("nop"); +// } +// gpio_clear(SWCLK_PORT, SWCLK_PIN); +// return value; +// } + +// static uint32_t swdptap_seq_in(size_t clock_cycles) +// { +// swdptap_turnaround(SWDIO_STATUS_FLOAT); +// if (target_clk_divider != UINT32_MAX) +// return swdptap_seq_in_clk_delay(clock_cycles); +// else // NOLINT(readability-else-after-return) +// return swdptap_seq_in_no_delay(clock_cycles); +// } + +// static bool swdptap_seq_in_parity(uint32_t *ret, size_t clock_cycles) +// { +// const uint32_t result = swdptap_seq_in(clock_cycles); +// for (volatile uint32_t counter = target_clk_divider + 1; counter > 0; --counter) +// continue; + +// const bool parity = calculate_odd_parity(result); +// const bool bit = gpio_get(SWDIO_IN_PORT, SWDIO_IN_PIN); + +// gpio_set(SWCLK_PORT, SWCLK_PIN); +// for (volatile uint32_t counter = target_clk_divider + 1; counter > 0; --counter) +// continue; + +// *ret = result; +// /* Terminate the read cycle now */ +// swdptap_turnaround(SWDIO_STATUS_DRIVE); +// return parity != bit; +// } + +// static void swdptap_seq_out_clk_delay(uint32_t tms_states, size_t clock_cycles) __attribute__((optimize(3))); + +// static void swdptap_seq_out_clk_delay(const uint32_t tms_states, const size_t clock_cycles) +// { +// for (size_t cycle = 0; cycle < clock_cycles; ++cycle) { +// gpio_clear(SWCLK_PORT, SWCLK_PIN); +// gpio_set_val(SWDIO_PORT, SWDIO_PIN, tms_states & (1 << cycle)); +// for (volatile uint32_t counter = target_clk_divider; counter > 0; --counter) +// continue; +// gpio_set(SWCLK_PORT, SWCLK_PIN); +// for (volatile uint32_t counter = target_clk_divider; counter > 0; --counter) +// continue; +// } +// gpio_clear(SWCLK_PORT, SWCLK_PIN); +// } + +// static void swdptap_seq_out_no_delay(uint32_t tms_states, size_t clock_cycles) __attribute__((optimize(3))); + +// static void swdptap_seq_out_no_delay(const uint32_t tms_states, const size_t clock_cycles) +// { +// for (size_t cycle = 0; cycle < clock_cycles; ++cycle) { +// gpio_clear(SWCLK_PORT, SWCLK_PIN); +// gpio_set_val(SWDIO_PORT, SWDIO_PIN, tms_states & (1 << cycle)); +// gpio_set(SWCLK_PORT, SWCLK_PIN); +// } +// gpio_clear(SWCLK_PORT, SWCLK_PIN); +// } + +// static void swdptap_seq_out(const uint32_t tms_states, const size_t clock_cycles) +// { +// swdptap_turnaround(SWDIO_STATUS_DRIVE); +// if (target_clk_divider != UINT32_MAX) +// swdptap_seq_out_clk_delay(tms_states, clock_cycles); +// else +// swdptap_seq_out_no_delay(tms_states, clock_cycles); +// } + +// static void swdptap_seq_out_parity(const uint32_t tms_states, const size_t clock_cycles) +// { +// const bool parity = calculate_odd_parity(tms_states); +// swdptap_seq_out(tms_states, clock_cycles); +// gpio_set_val(SWDIO_PORT, SWDIO_PIN, parity); +// for (volatile uint32_t counter = target_clk_divider + 1; counter > 0; --counter) +// continue; +// gpio_set(SWCLK_PORT, SWCLK_PIN); +// for (volatile uint32_t counter = target_clk_divider + 1; counter > 0; --counter) +// continue; +// gpio_clear(SWCLK_PORT, SWCLK_PIN); +// } diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index 041fbd362a3..d6111fe3451 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -31,6 +31,7 @@ #include "platform.h" #include "jtagtap.h" #include "swd.h" +#include "rvswd.h" #include "target.h" #include "target_internal.h" #include "adiv5.h" @@ -64,6 +65,7 @@ bmda_probe_s bmda_probe_info; #ifndef ENABLE_GPIOD jtag_proc_s jtag_proc; swd_proc_s swd_proc; +rvswd_proc_s rvswd_proc; #endif static uint32_t max_frequency = 4000000U; diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index e2c393c7a33..abc7e99cc14 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -29,6 +29,7 @@ #define PLATFORM_HAS_TRACESWO #define PLATFORM_HAS_POWER_SWITCH +#define PLATFORM_HAS_RVSWD #if ENABLE_DEBUG == 1 #define PLATFORM_HAS_DEBUG diff --git a/src/target/meson.build b/src/target/meson.build index 4bf388d4755..5766bf9e1d3 100644 --- a/src/target/meson.build +++ b/src/target/meson.build @@ -42,6 +42,7 @@ target_common_sources = files( 'gdb_reg.c', 'jtag_devs.c', 'jtag_scan.c', + 'rvswd_scan.c', 'semihosting.c', 'sfdp.c', 'spi.c', diff --git a/src/target/rvswd_scan.c b/src/target/rvswd_scan.c new file mode 100644 index 00000000000..6fe49a13fe6 --- /dev/null +++ b/src/target/rvswd_scan.c @@ -0,0 +1,269 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2023 1BitSquared + * Written by Rafael Silva + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* This file implements RVSWD protocol support. TODO */ + +#include "general.h" +// #include "jtagtap.h" +#include "rvswd_scan.h" + +// #include "target.h" +// #include "adiv5.h" +// #include "jtag_devs.h" +// #include "gdb_packet.h" + +/* + * This scans the RVSWD interface for any possible device chain attached. + * It acomplishes this by performing these basic steps: + * + * 1. Perform a SWD -> JTAG transition just in case any ARM devices were in SWD mode + * 2. Reset the TAPs of any attached device (this ensures they're all in ID code mode) + * 3. Read out the ID code register chain, shifting in all 1's, until we read an + * all-1's ID back (indicating the end of the chain) + * 4. Read out the active instruction register chain, shifting in all 1's, + * and applying quirks as required to calculate how long each IR is + * 5. Switch back to the DR chain and read out all the devices again now they are in + * BYPASS mode as a way to validate we have the chain length right + * + * Once this process is complete, all devices should be accounted for, the + * device structures all set up with suitable pre- and post-scan values for both the + * IR and DR chains, and all devices should be in BYPASS ready for additional probing + * and inspection. Finally, we loop through seeing if we understand any of the + * ID codes seen and dispatching to suitable handlers if we do. + */ +bool rvswd_scan(void) +{ + /* Free the device list if any, and clean state ready */ + target_list_free(); + +#if CONFIG_BMDA == 0 + rvswd_init(); +#endif + + // platform_target_clk_output_enable(false); + + return false; +} + +// static bool jtag_read_idcodes(void) +// { +// /* Reset the chain ready and transition to Shift-DR */ +// jtag_proc.jtagtap_reset(); +// DEBUG_INFO("Change state to Shift-DR\n"); +// jtagtap_shift_dr(); + +// DEBUG_INFO("Scanning out ID codes\n"); +// size_t device = 0; +// /* Try scanning to one ID past the end of the chain */ +// for (; device <= JTAG_MAX_DEVS; ++device) { +// /* Try to read out 32 bits, while shifting in 1's */ +// uint32_t idcode = 0; +// jtag_proc.jtagtap_tdi_tdo_seq((uint8_t *)&idcode, false, ones, 32); +// /* If the IDCode read is all 1's, we've reached the end */ +// if (idcode == 0xffffffffU) +// break; +// /* Check if the max supported chain length is exceeded */ +// if (device == JTAG_MAX_DEVS) { +// DEBUG_ERROR("jtag_scan: Maximum chain length exceeded\n"); +// jtag_dev_count = 0; +// return false; +// } +// /* We got a valid device, add it to the set */ +// jtag_devs[device].jd_idcode = idcode; +// } + +// /* Well, it worked, so clean up and do housekeeping */ +// DEBUG_INFO("Return to Run-Test/Idle\n"); +// jtag_proc.jtagtap_next(true, true); +// jtagtap_return_idle(1); +// jtag_dev_count = device; +// return true; +// } + +// static void jtag_display_idcodes(void) +// { +// #if ENABLE_DEBUG == 1 +// for (size_t device = 0; device < jtag_dev_count; ++device) { +// const char *description = "Unknown"; +// for (size_t idx = 0; dev_descr[idx].idcode; ++idx) { +// if ((jtag_devs[device].jd_idcode & dev_descr[idx].idmask) == dev_descr[idx].idcode) { +// if (dev_descr[idx].descr) +// description = dev_descr[idx].descr; +// break; +// } +// } +// DEBUG_INFO("ID code 0x%08" PRIx32 ": %s\n", jtag_devs[device].jd_idcode, description); +// } +// #endif +// } + +// static jtag_ir_quirks_s jtag_device_get_quirks(const uint32_t idcode) +// { +// for (size_t idx = 0; dev_descr[idx].idcode; ++idx) { +// if ((idcode & dev_descr[idx].idmask) == dev_descr[idx].idcode) +// return dev_descr[idx].ir_quirks; +// } +// return (jtag_ir_quirks_s){0}; +// } + +// static bool jtag_read_irs(void) +// { +// /* Transition to Shift-IR */ +// DEBUG_INFO("Change state to Shift-IR\n"); +// jtagtap_shift_ir(); + +// DEBUG_INFO("Scanning out IRs\n"); +// /* Start with no prescan and the first device */ +// size_t prescan = 0U; +// size_t device = 0U; +// uint8_t ir_len = 0U; +// /* Grab the first device's quirks, if any */ +// jtag_ir_quirks_s ir_quirks = jtag_device_get_quirks(jtag_devs[0].jd_idcode); + +// /* Try scanning out the IR for the device */ +// while (ir_len <= JTAG_MAX_IR_LEN) { +// /* Read the next IR bit */ +// const bool next_bit = jtag_proc.jtagtap_next(false, true); +// /* If we have quirks, validate the bit against the expected IR */ +// if (ir_quirks.ir_length && ((ir_quirks.ir_value >> ir_len) & 1U) != next_bit) { +// DEBUG_ERROR("jtag_scan: IR does not match the expected value, bailing out\n"); +// jtag_dev_count = 0; +// return false; +// } +// /* IEEE 1149.1 requires the first bit to be a 1, but not all devices conform (see #1130 on GH) */ +// if (ir_len == 0 && !next_bit) +// DEBUG_WARN("jtag_scan: Sanity check failed: IR[0] shifted out as 0\n"); + +// /* The bit validated ok, so increment the counter */ +// ++ir_len; + +// /* +// * If we do not have quirks in play, this was a 1 bit and we're not reading the first bit of the +// * current IR, or if we've now read sufficient bits for the quirk, we've begun the next device +// */ +// if ((!ir_quirks.ir_length && next_bit && ir_len > 1U) || ir_len == ir_quirks.ir_length) { +// /* If we're not in quirks mode and the IR length is now 2 (2 1-bits in a row read), we're actually done */ +// if (!ir_quirks.ir_length && ir_len == 2U) +// break; + +// /* +// * If we're reading using quirks, we'll read exactly the right number of bits, +// * if not then we overrun by 1 for the device. Calculate the adjustment. +// */ +// const uint8_t overrun = ir_quirks.ir_length ? 0U : 1U; +// const uint8_t device_ir = ir_len - overrun; + +// /* Set up the IR fields for the device and set up for the next */ +// jtag_devs[device].ir_len = device_ir; +// jtag_devs[device].ir_prescan = prescan; +// jtag_devs[device].current_ir = UINT32_MAX; +// prescan += device_ir; +// ++device; +// ir_len = overrun; +// /* Grab the device quirks for this new device, if any */ +// ir_quirks = jtag_device_get_quirks(jtag_devs[device].jd_idcode); +// } +// } + +// /* Sanity check that we didn't get an over-long IR */ +// if (ir_len > JTAG_MAX_IR_LEN) { +// DEBUG_ERROR("jtag_scan: Maximum IR length exceeded\n"); +// jtag_dev_count = 0; +// return 0; +// } +// return true; +// } + +// static bool jtag_sanity_check(void) +// { +// /* Transition to Shift-DR */ +// DEBUG_INFO("Change state to Shift-DR\n"); +// jtagtap_shift_dr(); +// /* Count devices on chain */ +// size_t device = 0; +// for (; device <= jtag_dev_count; ++device) { +// if (jtag_proc.jtagtap_next(false, true)) +// break; +// /* Configure the DR pre/post scan values */ +// jtag_devs[device].dr_prescan = device; +// jtag_devs[device].dr_postscan = jtag_dev_count - device - 1U; +// } + +// /* If the device count gleaned above does not match the device count, error out */ +// if (device != jtag_dev_count) { +// DEBUG_ERROR("jtag_scan: Sanity check failed: BYPASS dev count doesn't match IR scan\n"); +// jtag_dev_count = 0; +// return false; +// } + +// /* Everything's accounted for, so clean up */ +// DEBUG_INFO("Return to Run-Test/Idle\n"); +// jtag_proc.jtagtap_next(true, true); +// jtagtap_return_idle(1); +// /* Return if there are any devices on the scan chain */ +// return jtag_dev_count; +// } + +// void jtag_dev_write_ir(const uint8_t dev_index, const uint32_t ir) +// { +// jtag_dev_s *device = &jtag_devs[dev_index]; +// /* If the request would duplicate work already done, do nothing */ +// if (ir == device->current_ir) +// return; + +// /* Set all the other devices IR's to being in bypass */ +// for (size_t device_index = 0; device_index < jtag_dev_count; device_index++) +// jtag_devs[device_index].current_ir = UINT32_MAX; +// device->current_ir = ir; + +// /* Do the work to make the scanchain match the jtag_devs state */ +// jtagtap_shift_ir(); +// jtag_proc.jtagtap_tdi_seq(false, ones, device->ir_prescan); +// jtag_proc.jtagtap_tdi_seq(!device->ir_postscan, (const uint8_t *)&ir, device->ir_len); +// jtag_proc.jtagtap_tdi_seq(true, ones, device->ir_postscan); +// jtagtap_return_idle(1); +// } + +// void jtag_dev_shift_dr(const uint8_t dev_index, uint8_t *data_out, const uint8_t *data_in, const size_t clock_cycles) +// { +// jtag_dev_s *device = &jtag_devs[dev_index]; +// jtagtap_shift_dr(); +// jtag_proc.jtagtap_tdi_seq(false, ones, device->dr_prescan); +// if (data_out) +// jtag_proc.jtagtap_tdi_tdo_seq( +// (uint8_t *)data_out, !device->dr_postscan, (const uint8_t *)data_in, clock_cycles); +// else +// jtag_proc.jtagtap_tdi_seq(!device->dr_postscan, (const uint8_t *)data_in, clock_cycles); +// jtag_proc.jtagtap_tdi_seq(true, ones, device->dr_postscan); +// jtagtap_return_idle(1); +// } diff --git a/src/target/rvswd_scan.h b/src/target/rvswd_scan.h new file mode 100644 index 00000000000..81ca84ee09a --- /dev/null +++ b/src/target/rvswd_scan.h @@ -0,0 +1,64 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2023 1BitSquared + * Written by Rafael Silva + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TARGET_RVSWD_SCAN_H +#define TARGET_RVSWD_SCAN_H + +// #include +#include "rvswd.h" + +// #define JTAG_MAX_DEVS 32U +// #define JTAG_MAX_IR_LEN 32U /* NOTE: This is not long enough for all Xilinx devices */ + +// typedef struct jtag_dev { +// uint32_t jd_idcode; +// uint32_t current_ir; + +// /* The DR prescan doubles as the device index */ +// uint8_t dr_prescan; +// uint8_t dr_postscan; + +// uint8_t ir_len; +// uint8_t ir_prescan; +// uint8_t ir_postscan; +// } jtag_dev_s; + +// extern jtag_dev_s jtag_devs[JTAG_MAX_DEVS]; +// extern uint32_t jtag_dev_count; +// extern const uint8_t ones[8]; + +// void jtag_dev_write_ir(uint8_t jd_index, uint32_t ir); +// void jtag_dev_shift_dr(uint8_t jd_index, uint8_t *dout, const uint8_t *din, size_t ticks); +// void jtag_add_device(uint32_t dev_index, const jtag_dev_s *jtag_dev); + +#endif /* TARGET_RVSWD_SCAN_H */