Compare commits

...

9 Commits

Author SHA1 Message Date
Antonio Borneo
443139db00 jtag: keep the list of drivers in alphabetic order
The introduction of the driver ch347 breaks the order.
Fix it.

Change-Id: I868fd3ec0b6694fb4bb7b28db0083ab1a9409b1c
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/9089
Reviewed-by: Matthias Jentsch <info@easydevkits.com>
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-by: ZhiYuanNJ <871238103@qq.com>
Tested-by: jenkins
2025-08-24 05:05:05 +00:00
Tomas Vanek
1879145bff drivers/ch347: limit SWD packet size by processing time
CH347 chip firmware probably does not service USB poll/requests
from the host during processing of SWD packet. If the processing
takes longer than approx 8 ms, USB host disconnects the adapter
from the bus as if it were dead.

To avoid disconnect, compute approximate processing time
of SWD transactions and flush the queue if the total time
gets over the limit (use 7 ms to keep some safety margin).

Allow ch347_swd_send_idle() to split the requested delay
to more partial sequences. It prevents USB disconnect at beginning
of target examine, when memaccess 255 clk is used.
Also memaccess > 255 clk is now possible.

Set the maximal divisor to fit the longest ADI sequence
into 7 ms processing time.

Tested on a linux x64 PC and RPi 5.

Change-Id: Ibdcff4de52e3eb4d86ed83af81a1c64f1f9b5d24
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/8746
Tested-by: jenkins
Reviewed-by: ZhiYuanNJ <871238103@qq.com>
2025-08-24 05:04:50 +00:00
Tomas Vanek
b4a1976886 drivers/ch347: fix SWD log messages
Remove annoying and not too informative error message `ack != SWD_ACK_OK`.
Fix copy&paste error in message `SWD Read data parity mismatch` logged
in case of a write returning bad ack.
Raise log level of read/write descriptive message to DEBUG when reg
read/writes returns bad ack.

Change-Id: Ic3433ae8bd02472756adf269658bfba0ba34dc26
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/8747
Reviewed-by: ZhiYuanNJ <871238103@qq.com>
Tested-by: jenkins
2025-08-24 05:04:30 +00:00
Tomas Vanek
fe50eceaff drivers/ch347: don't loose swd_read/write_reg errors
SWD read_reg() and write_reg() methods are declared with
void return. Save the error code to ch347_swd_context.queued_retval
(will be returned later by SWD run method) instead of ignoring it.

Change-Id: Ib95a1bc3398712ac2f8520c79d281633d75f0335
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/8745
Reviewed-by: ZhiYuanNJ <871238103@qq.com>
Tested-by: jenkins
2025-08-24 05:04:14 +00:00
Tomas Vanek
0c575ced95 drivers/ch347: fix conditional sending of idle clock cycles
ch347_swd_run_queue() fulfilled ADI requirement for idle cycles
after the last transaction just if there was room in the buffer.
A lazy programmer avoided this way the danger of recurrent call.

Introduce ch347_swd_run_queue_inner() without sending idle cycles.
They are useless when flushing the queue to get room for the next
transaction.

ch347_swd_run_queue() now can make room for idle cycles
in the queue without recursion.

While on it remove two useless debug logs showing ap_delay_clk
value and prevent the overflow of ap_delay_clk forcing it to be <= 255.

Change-Id: Ia7b7f0d373ff463e2f0742bdd068c3833c57f340
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/8744
Reviewed-by: ZhiYuanNJ <871238103@qq.com>
Tested-by: jenkins
2025-08-24 05:03:55 +00:00
Tomas Vanek
87f7828679 drivers/ch347: add SWD speed settings
SWD has completely different speed setting than JTAG.
There is no official chip documentation. The trial and error
method on SWD init USB packet discovered a byte parameter used
as a divisor from 1 MHz maximal clock.

Prevent setting too low clocks as it may trigger USB disconnects.

CH347T/F versions 5.44/1.1 add 5 MHz SWD speed at divisor/index 0.

CH347F related parts co-authored by ZhiYuanNJ <871238103@qq.com>

Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Change-Id: I5a990a43dcd7a6d73c71b795283a9fbdff489bf4
Reviewed-on: https://review.openocd.org/c/openocd/+/8743
Reviewed-by: ZhiYuanNJ <871238103@qq.com>
Tested-by: jenkins
2025-08-24 05:03:34 +00:00
Tomas Vanek
c7aaaac809 drivers/ch347: detailed packet logging
Split USB data packet logs by CH347 protocol commands

Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Change-Id: I0f61529755f007ab13f42643676199790c5be2d4
Reviewed-on: https://review.openocd.org/c/openocd/+/8742
Reviewed-by: ZhiYuanNJ <871238103@qq.com>
Tested-by: jenkins
2025-08-24 05:03:20 +00:00
Tomas Vanek
99cb670bec drivers/ch347, doc: warn about CH347T problems
Also suggest a possible solution if available.

CH347F related parts co-authored by ZhiYuanNJ <871238103@qq.com>

Change-Id: Id6557909fcb56a1e95e16277c1cd7df6769cf4dd
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/8741
Reviewed-by: ZhiYuanNJ <871238103@qq.com>
Tested-by: jenkins
2025-08-24 05:03:02 +00:00
EasyDevKits
7d0e125896 jtag/drivers: Add support for CH347-based JTAG adapters
This adds general support for JTAG adapters based on the WCH CH347T and
CH347F chips.

The CH347T must be configured in mode 3 to provide both UART and JTAG
interfaces. The CH347F exposes UART and JTAG directly. Similar to FTDI
FT2232-based devices, the CH347T/F can be used for simultaneous UART and
JTAG communication.

The ch347 driver code is based on:
  https://github.com/WCHSoftGroup/ch347

Bug fixes and adjustments were made to align the code with OpenOCD style
and ensure compatibility. The driver was integrated into the OpenOCD
build system.

The USB packet format was identified using public GitHub sources and
documented here:
  https://www.easydevkits.com/wch-ch347-jtag-interface/

Change-Id: I5fca9dd015111e4410fea029611fdeedbb228fdb
Signed-off-by: EasyDevKits <info@easydevkits.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/7937
Tested-by: jenkins
Reviewed-by: ZhiYuanNJ <871238103@qq.com>
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
2025-08-24 05:02:38 +00:00
8 changed files with 2682 additions and 0 deletions

View File

@@ -129,6 +129,7 @@ m4_define([ADAPTER_OPT], [m4_translit(ADAPTER_ARG($1), [_], [-])])
m4_define([USB1_ADAPTERS],
[[[ftdi], [MPSSE mode of FTDI based devices], [FTDI]],
[[ch347], [Mode 3 of CH347 based devices], [CH347]],
[[stlink], [ST-Link Programmer], [HLADAPTER_STLINK]],
[[ti_icdi], [TI ICDI JTAG Programmer], [HLADAPTER_ICDI]],
[[ulink], [Keil ULINK JTAG Programmer], [ULINK]],
@@ -724,6 +725,7 @@ AM_CONDITIONAL([INTERNAL_JIMTCL], [test "x$use_internal_jimtcl" = "xyes"])
AM_CONDITIONAL([HAVE_JIMTCL_PKG_CONFIG], [test "x$have_jimtcl_pkg_config" = "xyes"])
AM_CONDITIONAL([INTERNAL_LIBJAYLINK], [test "x$use_internal_libjaylink" = "xyes"])
AM_CONDITIONAL([USE_GCOV], [test "x$enable_gcov" = "xyes"])
# Look for environ alternatives. Possibility #1: is environ in unistd.h or stdlib.h?

View File

@@ -220,6 +220,11 @@ ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="06ad", MODE="660", GROUP="plugdev",
# USBprog with OpenOCD firmware
ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="660", GROUP="plugdev", TAG+="uaccess"
# WCH CH347T chip in mode 3
ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55dd", MODE="660", GROUP="plugdev", TAG+="uaccess"
# WCH CH347F chip
ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55de", MODE="660", GROUP="plugdev", TAG+="uaccess"
# TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board
ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="660", GROUP="plugdev", TAG+="uaccess"

View File

@@ -633,6 +633,10 @@ This is deprecated from Linux v5.3; prefer using @b{linuxgpiod}.
@item @b{esp_usb_jtag}
@* A JTAG driver to communicate with builtin debug modules of Espressif ESP32-C3 and ESP32-S3 chips using OpenOCD.
@item @b{ch347}
@* A JTAG driver that works with the WCH CH347F and CH347T chips.
When using the CH347T, it must be configured to operate in mode 3 (UART + JTAG).
@end itemize
@node About Jim Tcl
@@ -2554,6 +2558,67 @@ and a specific set of GPIOs is used.
@c chooses among list of bit configs ... only one option
@end deffn
@deffn {Interface Driver} {ch347}
Driver for WCH CH347F and CH347T chips.
When using the CH347T, it must be configured to operate in mode 3 (UART + JTAG).
@b{WARNING:} WCH CH347T chips have rather poor performance
with respect to the USB HS connection. Upgrade firmware to the latest version!
@itemize @bullet
@item Chip version 2.41:
@itemize @minus
@item JTAG timing is very weird, some clock pulses are
much shorter then the requested clock frequency.
@item SWD is not implemented.
@end itemize
@item Chip version 4.41:
@itemize @minus
@item SWD clock is limited to 1 MHz maximum.
@item SWD reading AP reg CH347 erroneously drives
SWDIO to H for 392 ns after the last ACK bit. Some devices get so upset
that send wrong data with parity error. A resistor in the SWDIO circuit
mitigates the problem.
@item A long SWD operation causes that USB host disconnects the adapter.
@end itemize
@item Chip version 5.44:
@itemize @minus
@item Maximal SWD clock speed is 5 MHz
@item A long SWD operation causes that USB host disconnects the adapter.
@end itemize
@end itemize
This driver has these driver-specific command:
@deffn {Config Command} {ch347 vid_pid} [vid pid]+
The vendor ID and product ID of the CH347F or CH347T device in mode 3. If not specified
the driver will use vendor ID 0x1a86 and product ID 0x55dd.
Currently, up to four [@var{vid}, @var{pid}] pairs may be given, e.g.
@example
ch347 vid_pid 0x1a86 0x55dd 0x1a86 0x55de
@end example
@end deffn
@deffn {Config Command} {ch347 device_desc} description
If specified connect to a device which exactly has this product description
string. If not specified the first found device with the correct vendor
and product ID will be connected.
@example
ch347 device_desc "EasyDevKit"
@end example
@end deffn
@deffn {Config Command} {ch347 activity_led} [n]gpio_number
If specified the drive let an activity LED blink during JTAG operations.
The number is the GPIO number of the CH347T chip. If prefixed with "n",
then this GPIO should be low active. The example configures GPIO4 as
low active activity LED. For the CH347T chip only GPIO3 (Pin11 / SCL),
GPIO4 (Pin15 / ACT), GPIO5 (Pin9 / TRST) and GPIO6 (Pin2 / CTS1) are possible.
@example
ch347 activity_led n4
@end example
@end deffn
@end deffn
@deffn {Interface Driver} {cmsis-dap}
ARM CMSIS-DAP compliant based adapter v1 (USB HID based)
or v2 (USB bulk).

View File

@@ -0,0 +1,146 @@
# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
# Link: https://www.easydevkits.com
# PCB: ESP32-WROVER-E WCH JTAG DevKit v0.1
# Chip: CH347T in mode 3 (UART+JTAG mode)
# Product id of 0x55dd is only valid if the chip is started in mode 3
# These are the other product ids: mode 0 = 0x55da, mode 1 = 0x55db, mode 2 = 0x55dc
# The similar chip CH347F has no modes and always product id 0x55de
Bus 001 Device 013: ID 1a86:55dd QinHeng Electronics EasyDevKit
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x1a86 QinHeng Electronics
idProduct 0x55dd
bcdDevice 4.41
iManufacturer 1 EasyDevKits
iProduct 2 EasyDevKit
iSerial 3 ACBACJGAAB
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x0062
bNumInterfaces 3
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 500mA
Interface Association:
bLength 8
bDescriptorType 11
bFirstInterface 0
bInterfaceCount 2
bFunctionClass 2 Communications
bFunctionSubClass 2 Abstract (modem)
bFunctionProtocol 1 AT-commands (v.25ter)
iFunction 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 2 Communications
bInterfaceSubClass 2 Abstract (modem)
bInterfaceProtocol 1 AT-commands (v.25ter)
iInterface 0
CDC Header:
bcdCDC 1.10
CDC Call Management:
bmCapabilities 0x00
bDataInterface 1
CDC ACM:
bmCapabilities 0x02
line coding and serial state
CDC Union:
bMasterInterface 0
bSlaveInterface 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 10 CDC Data
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x04 EP 4 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x84 EP 4 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x06 EP 6 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x86 EP 6 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Device Qualifier (for other device speed):
bLength 10
bDescriptorType 6
bcdUSB 2.00
bDeviceClass 255 Vendor Specific Class
bDeviceSubClass 0
bDeviceProtocol 255
bMaxPacketSize0 64
bNumConfigurations 1
Device Status: 0x0000
(Bus Powered)

View File

@@ -208,6 +208,9 @@ endif
if AM335XGPIO
DRIVERFILES += %D%/am335xgpio.c
endif
if CH347
DRIVERFILES += %D%/ch347.c
endif
DRIVERHEADERS = \
%D%/bitbang.h \

2457
src/jtag/drivers/ch347.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -379,6 +379,7 @@ extern struct adapter_driver armjtagew_adapter_driver;
extern struct adapter_driver at91rm9200_adapter_driver;
extern struct adapter_driver bcm2835gpio_adapter_driver;
extern struct adapter_driver buspirate_adapter_driver;
extern struct adapter_driver ch347_adapter_driver;
extern struct adapter_driver cmsis_dap_adapter_driver;
extern struct adapter_driver dmem_dap_adapter_driver;
extern struct adapter_driver dummy_adapter_driver;

View File

@@ -59,6 +59,9 @@ struct adapter_driver *adapter_drivers[] = {
#if BUILD_BUS_PIRATE == 1
&buspirate_adapter_driver,
#endif
#if BUILD_CH347 == 1
&ch347_adapter_driver,
#endif
#if BUILD_CMSIS_DAP_USB == 1 || BUILD_CMSIS_DAP_HID == 1
&cmsis_dap_adapter_driver,
#endif