From 4af0bf6ed57745508d86ab9ad2af5e052d0c617f Mon Sep 17 00:00:00 2001 From: ZhiYuanNJ <78026992+ZhiyuanYuanNJ@users.noreply.github.com> Date: Thu, 29 Feb 2024 03:44:49 +0800 Subject: [PATCH] update CH347 (#424) --- src/ch347jtag.cpp | 175 +++++++++++++++++++++++----------------------- src/ch347jtag.hpp | 3 +- src/jtag.cpp | 2 +- 3 files changed, 89 insertions(+), 91 deletions(-) diff --git a/src/ch347jtag.cpp b/src/ch347jtag.cpp index ca2ce53c2e..10e15ca758 100644 --- a/src/ch347jtag.cpp +++ b/src/ch347jtag.cpp @@ -22,7 +22,12 @@ using namespace std; #define CH347JTAG_VID 0x1a86 -#define CH347JTAG_PID 0x55dd +#define CH347T_JTAG_PID 0x55dd //ch347T +#define CH347F_JTAG_PID 0x55de //ch347F + +#define KHZ(n) (uint32_t)((n)*UINT32_C(1000)) +#define MHZ(n) (uint32_t)((n)*UINT32_C(1000000)) +#define GHZ(n) (uint32_t)((n)*UINT32_C(1000000000)) #define CH347JTAG_INTF 2 #define CH347JTAG_WRITE_EP 0x06 @@ -51,17 +56,17 @@ static void LIBUSB_CALL sync_cb(struct libusb_transfer *transfer) { // defer should only be used with rlen == 0 -int CH347Jtag::usb_xfer(unsigned wlen, unsigned rlen, unsigned *ract, bool defer) { +int CH347Jtag::usb_xfer(unsigned wlen, unsigned rlen, unsigned *ract, bool defer) +{ + int actual_length = 0; if (_verbose) { fprintf(stderr, "usb_xfer: deferred: %ld\n", obuf - _obuf); } - if (defer && !rlen && obuf - _obuf + wlen < MAX_BUFFER - 12) { + if (defer && !rlen && obuf - _obuf + wlen < (MAX_BUFFER - 12)) { obuf += wlen; return 0; } - // write out whole buffer - if (obuf - _obuf > MAX_BUFFER) { throw runtime_error("buffer overflow"); } @@ -84,66 +89,39 @@ int CH347Jtag::usb_xfer(unsigned wlen, unsigned rlen, unsigned *ract, bool defer fprintf(stderr, "}\n\n"); } - int wcomplete = 0, rcomplete = 0; - libusb_fill_bulk_transfer(wtrans, dev_handle, CH347JTAG_WRITE_EP, obuf, - wlen, sync_cb, &wcomplete, CH347JTAG_TIMEOUT); - int r = libusb_submit_transfer(wtrans); - if (r < 0) - return r; - if (rlen) { - rcomplete = 0; - libusb_fill_bulk_transfer(rtrans, dev_handle, CH347JTAG_READ_EP, ibuf, - rlen, sync_cb, &rcomplete, CH347JTAG_TIMEOUT); - r = libusb_submit_transfer(rtrans); - if (r < 0) + int r = 0; + if (wlen) { + if ((r = libusb_bulk_transfer(dev_handle, CH347JTAG_WRITE_EP, obuf, wlen, &actual_length, CH347JTAG_TIMEOUT)) < 0 ) { return r; - } else { - rcomplete = 1; - } - while (!wcomplete) { - r = libusb_handle_events_completed(usb_ctx, &wcomplete); - if (r < 0) { - if (r != LIBUSB_ERROR_INTERRUPTED) { - libusb_cancel_transfer(wtrans); - if (rlen) libusb_cancel_transfer(rtrans); - } - continue; - } - if (!wtrans->dev_handle) { - wtrans->status = LIBUSB_TRANSFER_NO_DEVICE; - wcomplete = 1; } } - while (!rcomplete) { - r = libusb_handle_events_completed(usb_ctx, &rcomplete); - if (r < 0) { - if (r != LIBUSB_ERROR_INTERRUPTED) - libusb_cancel_transfer(rtrans); - continue; - } - if (!rtrans->dev_handle) { - rtrans->status = LIBUSB_TRANSFER_NO_DEVICE; - rcomplete = 1; + if (_verbose) { + fprintf(stderr, "obuf[%d] = {", wlen); + for (unsigned i = 0; i < wlen; ++i) { + fprintf(stderr, "%02x ", obuf[i]); } + fprintf(stderr, "}\n\n"); } - if (wtrans->status != LIBUSB_TRANSFER_COMPLETED) { - return LIBUSB_ERROR_IO; - } - if (rlen) { - if (rtrans->status != LIBUSB_TRANSFER_COMPLETED) { - return LIBUSB_ERROR_IO; - } - if ((int)rlen > rtrans->actual_length) { - throw runtime_error("input buffer underflow"); - } - if (ract) *ract = rtrans->actual_length; - if (_verbose) { - fprintf(stderr, "ibuf[%d] = {", rtrans->actual_length); - for (int i = 0; i < rtrans->actual_length; ++i) { - fprintf(stderr, "%02x ", ibuf[i]); + obuf = _obuf; + int rlen_total = 0; + uint8_t *pibuf = ibuf; + if (rlen){ + while (rlen) { + if ((r = libusb_bulk_transfer(dev_handle, CH347JTAG_READ_EP, pibuf, rlen, &actual_length, CH347JTAG_TIMEOUT)) < 0 ) { + return r; + } + if (_verbose) { + fprintf(stderr, "ibuf[%d] = {", actual_length); + for (int i = rlen_total; i < rlen_total + actual_length; ++i) { + fprintf(stderr, "%02x ", ibuf[i]); + } + fprintf(stderr, "}\n\n"); } - fprintf(stderr, "}\n\n"); + rlen -= actual_length; + pibuf += actual_length; + rlen_total += actual_length; } + *ract = rlen_total; } return 0; } @@ -164,10 +142,13 @@ int CH347Jtag::setClk(const uint8_t &factor) { return 0; } -CH347Jtag::CH347Jtag(uint32_t clkHZ, int8_t verbose): +CH347Jtag::CH347Jtag(uint32_t clkHZ, int8_t verbose, int vid, int pid, uint8_t bus_addr, uint8_t dev_addr): _verbose(verbose>1), dev_handle(NULL), usb_ctx(NULL), obuf(_obuf) { + libusb_device** devs; int actual_length = 0; + int i = 0; + ssize_t cnt; struct libusb_device_descriptor desc; struct libusb_device *dev; int rv; @@ -175,8 +156,19 @@ CH347Jtag::CH347Jtag(uint32_t clkHZ, int8_t verbose): printError("libusb init failed"); goto err_exit; } - dev_handle = libusb_open_device_with_vid_pid(usb_ctx, CH347JTAG_VID, - CH347JTAG_PID); + cnt = libusb_get_device_list(NULL, &devs); + if (cnt < 0) goto err_exit; + while ((dev = devs[i++]) != NULL) { + if (libusb_get_device_descriptor(dev, &desc) < 0) + continue; + if (desc.idVendor != vid || desc.idProduct != pid) + continue; + if (bus_addr != 0 && dev_addr != 0 && (libusb_get_bus_number(dev) != bus_addr || libusb_get_device_address(dev) != dev_addr)) + continue; + libusb_open(dev, &dev_handle); + break; + } + libusb_free_device_list(devs, 1); if (!dev_handle) { printError("fails to open device"); goto usb_exit; @@ -193,8 +185,11 @@ CH347Jtag::CH347Jtag(uint32_t clkHZ, int8_t verbose): goto usb_exit; } - if (desc.bcdDevice < 0x241) { + if (desc.bcdDevice < 0x241 && pid == CH347T_JTAG_PID) { + _is_largerPack = false; printWarn("Old version of the chip, JTAG might not work"); + }else{ + _is_largerPack = true; } if (libusb_set_auto_detach_kernel_driver(dev_handle, true)) { @@ -243,27 +238,28 @@ CH347Jtag::~CH347Jtag() int CH347Jtag::_setClkFreq(uint32_t clkHZ) { -#if 1 - unsigned i = 0, sl = 60000000 >> 5; - for (; i < 6; ++i, sl <<= 1) { - if (clkHZ < sl) - break; - } -#else - int i = 6; - unsigned sl = 60000000; - for (; i > 1; --i, sl >>= 1) { - if (clkHZ > sl) - break; - } -#endif - _clkHZ = sl; - if (setClk(i)) { + int setClk_index = 0; + uint32_t speed_clock_larger_pack[8] = { + KHZ(468.75), KHZ(937.5), MHZ(1.875), MHZ(3.75), + MHZ(7.5), MHZ(15), MHZ(30), MHZ(60) + }; + uint32_t speed_clock_standard_pack[6] = { + MHZ(1.875), MHZ(3.75), + MHZ(7.5), MHZ(15), MHZ(30), MHZ(60) + }; + uint32_t *ptr = _is_largerPack ? speed_clock_larger_pack : speed_clock_standard_pack; + int size = (_is_largerPack?sizeof(speed_clock_larger_pack):sizeof(speed_clock_standard_pack)) / sizeof(uint32_t); + for (int i = 0; i < size; ++i) { + if (clkHZ > ptr[i] && clkHZ <= ptr[i+1]){ + setClk_index = i + 1; + } + } + if (setClk(setClk_index)) { printError("failed to set clock rate"); return 0; } char mess[256]; - snprintf(mess, 256, "JTAG TCK frequency set to %.3f MHz\n\n", _clkHZ/1e6); + snprintf(mess, 256, "JTAG TCK frequency set to %.3f MHz\n\n", (double)ptr[setClk_index] / MHZ(1)); printInfo(mess); return _clkHZ; } @@ -271,9 +267,10 @@ int CH347Jtag::_setClkFreq(uint32_t clkHZ) int CH347Jtag::writeTMS(const uint8_t *tms, uint32_t len, bool flush_buffer, __attribute__((unused)) const uint8_t tdi) { - if (get_obuf_length() < (int)(len * 2 + 4)) { // check if there is enough room left - flush(); - } + // if (get_obuf_length() < (int)(len * 2 + 4)) { // check if there is enough room left + // flush(); + // } + flush(); uint8_t *ptr = obuf; for (uint32_t i = 0; i < len; ++i) { if (ptr == obuf) { @@ -424,12 +421,12 @@ int CH347Jtag::writeTDI(const uint8_t *tx, uint8_t *rx, uint32_t len, bool end) cerr << "writeTDI: invalid read data: " << endl; return -EXIT_FAILURE; } - for (unsigned i = 0; i < size / 8; ++i) { - uint8_t b = 0; - uint8_t *xb = &ibuf[3 + i * 8]; - for (unsigned j = 0; j < 8; ++j) - b |= (xb[j] & 1) << j; - *rptr++ = b; + for (unsigned i = 0; i < size; ++i) { + if (ibuf[3 + i] == 0x01) { + *rptr |= (0x01 << i); + }else{ + *rptr &= ~(0x01 << i); + } } return EXIT_SUCCESS; -} +} \ No newline at end of file diff --git a/src/ch347jtag.hpp b/src/ch347jtag.hpp index db61d99f59..41a1df355b 100644 --- a/src/ch347jtag.hpp +++ b/src/ch347jtag.hpp @@ -12,7 +12,7 @@ constexpr unsigned MAX_BUFFER = 512; class CH347Jtag : public JtagInterface { public: - CH347Jtag(uint32_t clkHZ, int8_t verbose); + CH347Jtag(uint32_t clkHZ, int8_t verbose, int vid, int pid, uint8_t bus_addr, uint8_t dev_addr); virtual ~CH347Jtag(); int setClkFreq(uint32_t clkHZ) override { return _setClkFreq(clkHZ); }; @@ -32,6 +32,7 @@ class CH347Jtag : public JtagInterface { private: bool _verbose; + bool _is_largerPack; int setClk(const uint8_t &factor); libusb_device_handle *dev_handle; diff --git a/src/jtag.cpp b/src/jtag.cpp index 5eece8624b..9991f1aee5 100644 --- a/src/jtag.cpp +++ b/src/jtag.cpp @@ -103,7 +103,7 @@ Jtag::Jtag(const cable_t &cable, const jtag_pins_conf_t *pin_conf, _jtag = new CH552_jtag(cable, dev, serial, clkHZ, verbose); break; case MODE_CH347: - _jtag = new CH347Jtag(clkHZ, verbose); + _jtag = new CH347Jtag(clkHZ, verbose, cable.vid, cable.pid, cable.bus_addr, cable.device_addr); break; case MODE_DIRTYJTAG: _jtag = new DirtyJtag(clkHZ, verbose);