Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/wch link support #2061

Draft
wants to merge 17 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ option(
'apollo3',
'at32f4',
'ch32',
'ch32v',
'ch579',
'efm',
'gd32',
Expand Down Expand Up @@ -148,3 +149,8 @@ option(
value: false,
description: 'Enable firmware-side protocol acceleration of RISC-V Debug'
)
option(
'rvswd_support',
type: 'boolean',
value: false
)
101 changes: 84 additions & 17 deletions src/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,19 @@
#include "usb.h"
#endif

typedef struct scan_command {
bool (*scan)(void);
const char *name;
} scan_command_s;

static bool cmd_version(target_s *target, int argc, const char **argv);
static bool cmd_help(target_s *target, int argc, const char **argv);

static bool cmd_jtag_scan(target_s *target, int argc, const char **argv);
static bool cmd_swd_scan(target_s *target, int argc, const char **argv);
#if defined(CONFIG_RVSWD) && defined(PLATFORM_HAS_RVSWD)
static bool cmd_rvswd_scan(target_s *target, int argc, const char **argv);
#endif
static bool cmd_auto_scan(target_s *target, int argc, const char **argv);
static bool cmd_frequency(target_s *target, int argc, const char **argv);
static bool cmd_targets(target_s *target, int argc, const char **argv);
Expand Down Expand Up @@ -94,6 +102,9 @@ const command_s cmd_list[] = {
{"jtag_scan", cmd_jtag_scan, "Scan JTAG chain for devices"},
{"swd_scan", cmd_swd_scan, "Scan SWD interface for devices: [TARGET_ID]"},
{"swdp_scan", cmd_swd_scan, "Deprecated: use swd_scan instead"},
#if defined(CONFIG_RVSWD) && defined(PLATFORM_HAS_RVSWD)
{"rvswd_scan", cmd_rvswd_scan, "Scan RVSWD for devices"},
#endif
{"auto_scan", cmd_auto_scan, "Automatically scan all chain types for devices"},
{"frequency", cmd_frequency, "set minimum high and low times: [FREQ]"},
{"targets", cmd_targets, "Display list of available targets"},
Expand Down Expand Up @@ -287,9 +298,9 @@ bool cmd_swd_scan(target_s *target, int argc, const char **argv)
bool scan_result = false;
TRY (EXCEPTION_ALL) {
#if CONFIG_BMDA == 1
scan_result = bmda_swd_scan(targetid);
scan_result = bmda_swd_scan_targetid(targetid);
#else
scan_result = adiv5_swd_scan(targetid);
scan_result = adiv5_swd_scan_targetid(targetid);
#endif
}
CATCH () {
Expand All @@ -316,35 +327,26 @@ bool cmd_swd_scan(target_s *target, int argc, const char **argv)
return true;
}

bool cmd_auto_scan(target_s *target, int argc, const char **argv)
#if defined(CONFIG_RVSWD) && defined(PLATFORM_HAS_RVSWD)
bool cmd_rvswd_scan(target_s *target, int argc, const char **argv)
{
(void)target;
(void)argc;
(void)argv;

gdb_outf("Target voltage: %s\n", platform_target_voltage());
if (platform_target_voltage())
gdb_outf("Target voltage: %s\n", platform_target_voltage());

if (connect_assert_nrst)
platform_nrst_set_val(true); /* will be deasserted after attach */

bool scan_result = false;
TRY (EXCEPTION_ALL) {
#if CONFIG_BMDA == 1
scan_result = bmda_jtag_scan();
scan_result = bmda_rvswd_scan();
#else
scan_result = jtag_scan();
scan_result = false;
#endif
if (!scan_result) {
gdb_out("JTAG scan found no devices, trying SWD!\n");

#if CONFIG_BMDA == 1
scan_result = bmda_swd_scan(0);
#else
scan_result = adiv5_swd_scan(0);
#endif
if (!scan_result)
gdb_out("SWD scan found no devices.\n");
}
}
CATCH () {
case EXCEPTION_TIMEOUT:
Expand All @@ -357,6 +359,71 @@ bool cmd_auto_scan(target_s *target, int argc, const char **argv)
break;
}

if (!scan_result) {
platform_target_clk_output_enable(false);
perigoso marked this conversation as resolved.
Show resolved Hide resolved
platform_nrst_set_val(false);
gdb_out("RVSWD scan failed!\n");
return false;
}

cmd_targets(NULL, 0, NULL);
platform_target_clk_output_enable(false);
morse(NULL, false);
return true;
}
#endif

bool cmd_auto_scan(target_s *target, int argc, const char **argv)
{
(void)target;
(void)argc;
(void)argv;

gdb_outf("Target voltage: %s\n", platform_target_voltage());

if (connect_assert_nrst)
platform_nrst_set_val(true); /* will be deasserted after attach */

static const scan_command_s scan_commands[] =
#if CONFIG_BMDA == 1
/* clang-format off */
{
{bmda_jtag_scan, "JTAG"},
{bmda_swd_scan, "SWD"},
#if defined(CONFIG_RVSWD) && defined(PLATFORM_HAS_RVSWD)
{bmda_rvswd_scan, "RVSWD"},
#endif
};
#else
{
{jtag_scan, "JTAG"},
{adiv5_swd_scan, "SWD"},
};
/* clang-format on */
#endif

bool scan_result = false;
for (size_t i = 0; i < ARRAY_LENGTH(scan_commands); i++) {
TRY (EXCEPTION_ALL) {
scan_result = scan_commands[i].scan();
}
CATCH () {
case EXCEPTION_TIMEOUT:
gdb_outf("Timeout during %s scan. Is target stuck in WFI?\n", scan_commands[i].name);
break;
case EXCEPTION_ERROR:
gdb_outf("%s exception: %s\n", scan_commands[i].name, exception_frame.msg);
break;
default:
break;
}

if (scan_result)
break;

gdb_outf("%s scan found no devices.\n", scan_commands[i].name);
}

if (!scan_result) {
platform_target_clk_output_enable(false);
platform_nrst_set_val(false);
Expand Down
11 changes: 9 additions & 2 deletions src/include/target.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include <stdint.h>
#include <sys/types.h>

#include "platform.h"

#if defined(_MSC_VER)
#include <basetsd.h>
typedef SSIZE_T ssize_t;
Expand All @@ -43,10 +45,15 @@ typedef target_addr32_t target_addr_t;
typedef struct target_controller target_controller_s;

#if CONFIG_BMDA == 1
bool bmda_swd_scan(uint32_t targetid);
bool bmda_swd_scan(void);
bool bmda_swd_scan_targetid(uint32_t targetid);
bool bmda_jtag_scan(void);
#if defined(CONFIG_RVSWD) && defined(PLATFORM_HAS_RVSWD)
bool bmda_rvswd_scan(void);
#endif
#endif
bool adiv5_swd_scan(uint32_t targetid);
bool adiv5_swd_scan(void);
bool adiv5_swd_scan_targetid(uint32_t targetid);
bool jtag_scan(void);

size_t target_foreach(void (*callback)(size_t index, target_s *target, void *context), void *context);
Expand Down
8 changes: 8 additions & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ if rtt_support
endif
endif

# RVSWD support handling
rvswd_support = get_option('rvswd_support')
if rvswd_support
libbmd_core_args += ['-DCONFIG_RVSWD=1']
bmd_core_args += ['-DCONFIG_RVSWD=1']
endif

# Advertise QStartNoAckMode
advertise_noackmode = get_option('advertise_noackmode')
if advertise_noackmode
Expand Down Expand Up @@ -117,6 +124,7 @@ summary(
{
'Debug output': debug_output,
'RTT support': rtt_support,
'RVSWD support': rvswd_support,
'Advertise QStartNoAckMode': advertise_noackmode,
},
bool_yn: true,
Expand Down
3 changes: 2 additions & 1 deletion src/platforms/hosted/bmp_libusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ static const debugger_device_s debugger_devices[] = {
{VENDOR_ID_STLINK, PRODUCT_ID_STLINKV3, PROBE_TYPE_STLINK_V2, NULL, "ST-Link v3"},
{VENDOR_ID_STLINK, PRODUCT_ID_STLINKV3E, PROBE_TYPE_STLINK_V2, NULL, "ST-Link v3E"},
{VENDOR_ID_SEGGER, PRODUCT_ID_ANY, PROBE_TYPE_JLINK, NULL, "Segger J-Link"},
{VENDOR_ID_WCH, PRODUCT_ID_WCHLINK_RV, PROBE_TYPE_WCHLINK, NULL, "WCH-Link"},
{VENDOR_ID_FTDI, PRODUCT_ID_FTDI_FT2232, PROBE_TYPE_FTDI, NULL, "FTDI FT2232"},
{VENDOR_ID_FTDI, PRODUCT_ID_FTDI_FT4232, PROBE_TYPE_FTDI, NULL, "FTDI FT4232"},
{VENDOR_ID_FTDI, PRODUCT_ID_FTDI_FT232, PROBE_TYPE_FTDI, NULL, "FTDI FT232"},
Expand Down Expand Up @@ -118,7 +119,7 @@ const debugger_device_s *get_debugger_device_from_vid_pid(const uint16_t probe_v
void bmp_ident(bmda_probe_s *info)
{
DEBUG_INFO("Black Magic Debug App " FIRMWARE_VERSION "\n for Black Magic Probe, ST-Link v2 and v3, CMSIS-DAP, "
"J-Link and FTDI (MPSSE)\n");
"J-Link, FTDI (MPSSE) and WCH-Link\n");
if (info && info->vid && info->pid) {
DEBUG_INFO("Using %04x:%04x %s %s\n %s %s\n", info->vid, info->pid,
(info->serial[0]) ? info->serial : NO_SERIAL_NUMBER, info->manufacturer, info->product, info->version);
Expand Down
4 changes: 2 additions & 2 deletions src/platforms/hosted/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,11 +461,11 @@ bool scan_for_targets(const bmda_cli_options_s *const opt)
if (opt->opt_scanmode == BMP_SCAN_JTAG)
return bmda_jtag_scan();
if (opt->opt_scanmode == BMP_SCAN_SWD)
return bmda_swd_scan(opt->opt_targetid);
return bmda_swd_scan_targetid(opt->opt_targetid);
if (bmda_jtag_scan())
return true;
DEBUG_WARN("JTAG scan found no devices, trying SWD.\n");
if (bmda_swd_scan(opt->opt_targetid))
if (bmda_swd_scan_targetid(opt->opt_targetid))
return true;
DEBUG_ERROR("SWD scan failed!\n");
return false;
Expand Down
3 changes: 3 additions & 0 deletions src/platforms/hosted/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ bmda_sources = files(
'jlink.c',
'jlink_jtag.c',
'jlink_swd.c',
'wchlink.c',
'wchlink_rvswd.c',
'wchlink_riscv_dtm.c',
)
subdir('remote')

Expand Down
33 changes: 31 additions & 2 deletions src/platforms/hosted/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include "stlinkv2.h"
#include "ftdi_bmp.h"
#include "jlink.h"
#include "wchlink.h"
#include "cmsis_dap.h"
#endif

Expand Down Expand Up @@ -163,6 +164,11 @@ void platform_init(int argc, char **argv)
if (!jlink_init())
exit(1);
break;

case PROBE_TYPE_WCHLINK:
if (!wchlink_init())
exit(-1);
break;
#endif

#ifdef ENABLE_GPIOD
Expand Down Expand Up @@ -190,7 +196,12 @@ void platform_init(int argc, char **argv)
}
}

bool bmda_swd_scan(const uint32_t targetid)
bool bmda_swd_scan(void)
{
return bmda_swd_scan_targetid(0);
}

bool bmda_swd_scan_targetid(const uint32_t targetid)
{
bmda_probe_info.is_jtag = false;
platform_max_frequency_set(max_frequency);
Expand All @@ -203,7 +214,7 @@ bool bmda_swd_scan(const uint32_t targetid)
#ifdef ENABLE_GPIOD
case PROBE_TYPE_GPIOD:
#endif
return adiv5_swd_scan(targetid);
return adiv5_swd_scan_targetid(targetid);

#if HOSTED_BMP_ONLY == 0
case PROBE_TYPE_STLINK_V2:
Expand Down Expand Up @@ -309,6 +320,21 @@ bool bmda_jtag_init(void)
}
}

bool bmda_rvswd_scan()
{
bmda_probe_info.is_jtag = false;

switch (bmda_probe_info.type) {
#if HOSTED_BMP_ONLY == 0
case PROBE_TYPE_WCHLINK:
return wchlink_rvswd_scan();
#endif

default:
return false;
}
}

void bmda_adiv5_dp_init(adiv5_debug_port_s *const dp)
{
switch (bmda_probe_info.type) {
Expand Down Expand Up @@ -411,6 +437,9 @@ char *bmda_adaptor_ident(void)
case PROBE_TYPE_JLINK:
return "J-Link";

case PROBE_TYPE_WCHLINK:
return "WCH-Link";

case PROBE_TYPE_GPIOD:
return "GPIOD";

Expand Down
7 changes: 7 additions & 0 deletions src/platforms/hosted/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ void platform_buffer_flush(void);
do { \
} while (0)
#define PLATFORM_HAS_POWER_SWITCH
#define PLATFORM_HAS_RVSWD

#define PRODUCT_ID_ANY 0xffffU

Expand Down Expand Up @@ -77,13 +78,19 @@ void platform_buffer_flush(void);
#define VENDOR_ID_ORBCODE 0x1209U
#define PRODUCT_ID_ORBTRACE 0x3443U

#define VENDOR_ID_WCH 0x1a86U
#define PRODUCT_ID_WCHLINK_RV 0x8010U /* WCH-Link and WCH-LinkE in mode RV */
#define PRODUCT_ID_WCHLINK_DAP 0x8011U /* WCH-Link in mode DAP */
#define PRODUCT_ID_WCHLINKE_DAP 0x8012U /* WCH-LinkE in mode DAP */

typedef enum probe_type {
PROBE_TYPE_NONE = 0,
PROBE_TYPE_BMP,
PROBE_TYPE_STLINK_V2,
PROBE_TYPE_FTDI,
PROBE_TYPE_CMSIS_DAP,
PROBE_TYPE_JLINK,
PROBE_TYPE_WCHLINK,
PROBE_TYPE_GPIOD,
} probe_type_e;

Expand Down
Loading
Loading