From f35b0f4db418eb3a351e3d116c4aee83a0c38d3f Mon Sep 17 00:00:00 2001 From: cnlohr <lohr85@gmail.com> Date: Sat, 18 Feb 2023 22:59:41 -0500 Subject: [PATCH] Fully works on Linux. One click "make" and it also reflashes. --- barebones/Makefile | 8 +- barebones/barebones.c | 4 +- minichlink/Makefile | 24 +++++ minichlink/minichlink.c | 192 ++++++++++++++++++++++++++++++++++ minichlink/wch_link_base.h | 34 ++++-- minichlink/wch_power.c | 52 --------- minichlink/wch_reset.c | 17 ++- minichlink/wch_write_simple.c | 35 ++++--- 8 files changed, 276 insertions(+), 90 deletions(-) create mode 100644 minichlink/Makefile create mode 100644 minichlink/minichlink.c delete mode 100644 minichlink/wch_power.c diff --git a/barebones/Makefile b/barebones/Makefile index dbab071..3f68c64 100644 --- a/barebones/Makefile +++ b/barebones/Makefile @@ -25,14 +25,16 @@ SYSTEM_C:=$(EVT)/startup_ch32v00x.S $(EVT)/embedlibc.c $(TARGET).elf : barebones.c $(SYSTEM_C) $(PREFIX)-gcc -o $@ $^ $(CFLAGS) $(LDFLAGS) -$(TARGET).hex : $(TARGET).elf +$(TARGET).bin : $(TARGET).elf $(PREFIX)-size $^ $(PREFIX)-objdump -S $^ > $(TARGET).lst $(PREFIX)-objdump -t $^ > $(TARGET).map $(PREFIX)-objcopy -O binary $< $(TARGET).bin - $(PREFIX)-objcopy -O ihex $< $@ + $(PREFIX)-objcopy -O ihex $< $(TARGET).hex -flash : $(TARGET).hex +flash : $(TARGET).bin + make -C ../minichlink all + ../minichlink/minichlink -w $< -r clean : rm -rf $(TARGET).elf $(TARGET).bin $(TARGET).hex $(TARGET).lst $(TARGET).map $(TARGET).hex diff --git a/barebones/barebones.c b/barebones/barebones.c index 3ae0efa..f731594 100644 --- a/barebones/barebones.c +++ b/barebones/barebones.c @@ -78,8 +78,8 @@ int main() { GPIOD->BSHR = 1; // Turn on GPIOD0 puts( "Hello" ); - Delay_Ms( 100 ); + Delay_Ms( 50 ); GPIOD->BSHR = 1<<16; // Turn off GPIOD0 - Delay_Ms( 100 ); + Delay_Ms( 50 ); } } diff --git a/minichlink/Makefile b/minichlink/Makefile new file mode 100644 index 0000000..bdc97bc --- /dev/null +++ b/minichlink/Makefile @@ -0,0 +1,24 @@ +TOOLS:=wch_erase wch_reset wch_write_simple minichlink + +all : $(TOOLS) + +CFLAGS:=-O1 -g +LDFLAGS:=-lpthread -lusb-1.0 + +wch_erase : wch_erase.c + gcc -o $@ $^ $(LDFLAGS) $(CFLAGS) +wch_reset : wch_reset.c + gcc -o $@ $^ $(LDFLAGS) $(CFLAGS) +wch_write_simple : wch_write_simple.c + gcc -o $@ $^ $(LDFLAGS) $(CFLAGS) +minichlink : minichlink.c + gcc -o $@ $^ $(LDFLAGS) $(CFLAGS) + +install_udev_rules : + echo "SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"1a86\", ATTRS{idProduct}==\"8010\", GROUP=\"plugdev\", MODE=\"0666\"" > /etc/udev/rules.d/99-qch-LinkE.rules + +clean : + rm -rf $(TOOLS) + + + diff --git a/minichlink/minichlink.c b/minichlink/minichlink.c new file mode 100644 index 0000000..7a2dc21 --- /dev/null +++ b/minichlink/minichlink.c @@ -0,0 +1,192 @@ +#include <stdio.h> +#include "wch_link_base.h" + + +const uint8_t * bootloader = (const uint8_t*) +"\x21\x11\x22\xca\x26\xc8\x93\x77\x15\x00\x99\xcf\xb7\x06\x67\x45" \ +"\xb7\x27\x02\x40\x93\x86\x36\x12\x37\x97\xef\xcd\xd4\xc3\x13\x07" \ +"\xb7\x9a\xd8\xc3\xd4\xd3\xd8\xd3\x93\x77\x25\x00\x9d\xc7\xb7\x27" \ +"\x02\x40\x98\x4b\xad\x66\x37\x33\x00\x40\x13\x67\x47\x00\x98\xcb" \ +"\x98\x4b\x93\x86\xa6\xaa\x13\x67\x07\x04\x98\xcb\xd8\x47\x05\x8b" \ +"\x63\x16\x07\x10\x98\x4b\x6d\x9b\x98\xcb\x93\x77\x45\x00\xa9\xcb" \ +"\x93\x07\xf6\x03\x99\x83\x2e\xc0\x2d\x63\x81\x76\x3e\xc4\xb7\x32" \ +"\x00\x40\xb7\x27\x02\x40\x13\x03\xa3\xaa\xfd\x16\x98\x4b\xb7\x03" \ +"\x02\x00\x33\x67\x77\x00\x98\xcb\x02\x47\xd8\xcb\x98\x4b\x13\x67" \ +"\x07\x04\x98\xcb\xd8\x47\x05\x8b\x69\xe7\x98\x4b\x75\x8f\x98\xcb" \ +"\x02\x47\x13\x07\x07\x04\x3a\xc0\x22\x47\x7d\x17\x3a\xc4\x79\xf7" \ +"\x93\x77\x85\x00\xf1\xcf\x93\x07\xf6\x03\x2e\xc0\x99\x83\x37\x27" \ +"\x02\x40\x3e\xc4\x1c\x4b\xc1\x66\x2d\x63\xd5\x8f\x1c\xcb\x37\x07" \ +"\x00\x20\x13\x07\x07\x20\xb7\x27\x02\x40\xb7\x03\x08\x00\xb7\x32" \ +"\x00\x40\x13\x03\xa3\xaa\x94\x4b\xb3\xe6\x76\x00\x94\xcb\xd4\x47" \ +"\x85\x8a\xf5\xfe\x82\x46\xba\x84\x37\x04\x04\x00\x36\xc2\xc1\x46" \ +"\x36\xc6\x92\x46\x84\x40\x11\x07\x84\xc2\x94\x4b\xc1\x8e\x94\xcb" \ +"\xd4\x47\x85\x8a\xb1\xea\x92\x46\xba\x84\x91\x06\x36\xc2\xb2\x46" \ +"\xfd\x16\x36\xc6\xf9\xfe\x82\x46\xd4\xcb\x94\x4b\x93\xe6\x06\x04" \ +"\x94\xcb\xd4\x47\x85\x8a\x85\xee\xd4\x47\xc1\x8a\x85\xce\xd8\x47" \ +"\xb7\x06\xf3\xff\xfd\x16\x13\x67\x07\x01\xd8\xc7\x98\x4b\x21\x45" \ +"\x75\x8f\x98\xcb\x52\x44\xc2\x44\x61\x01\x02\x90\x23\x20\xd3\x00" \ +"\xf5\xb5\x23\xa0\x62\x00\x3d\xb7\x23\xa0\x62\x00\x55\xb7\x23\xa0" \ +"\x62\x00\xc1\xb7\x82\x46\x93\x86\x06\x04\x36\xc0\xa2\x46\xfd\x16" \ +"\x36\xc4\xb5\xf2\x98\x4b\xb7\x06\xf3\xff\xfd\x16\x75\x8f\x98\xcb" \ +"\x41\x89\x05\xcd\x2e\xc0\x0d\x06\x02\xc4\x09\x82\xb7\x07\x00\x20" \ +"\x32\xc6\x93\x87\x07\x20\x98\x43\x13\x86\x47\x00\xa2\x47\x82\x46" \ +"\x8a\x07\xb6\x97\x9c\x43\x63\x1c\xf7\x00\xa2\x47\x85\x07\x3e\xc4" \ +"\xa2\x46\x32\x47\xb2\x87\xe3\xe0\xe6\xfe\x01\x45\x61\xb7\x41\x45" \ +"\x51\xb7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" \ +"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" \ +"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"; + +int bootloader_len = 512; + +int main( int argc, char ** argv ) +{ + int status; + uint8_t rbuff[1024]; + + libusb_device_handle * devh = wch_link_base_setup(); + + int iarg; + for( iarg = 1; iarg < argc; iarg++ ) + { + char * argchar = argv[iarg]; + if( argchar[0] != '-' ) goto help; +keep_going: + switch( argchar[1] ) + { + default: goto help; + case '3': wch_link_command( devh, "\x81\x0d\x01\x09", 4, 0, 0, 0 ); break; + case '5': wch_link_command( devh, "\x81\x0d\x01\x0b", 4, 0, 0, 0 ); break; + case 't': wch_link_command( devh, "\x81\x0d\x01\x0a", 4, 0, 0, 0 ); break; + case 'f': wch_link_command( devh, "\x81\x0d\x01\x0c", 4, 0, 0, 0 ); break; + case 'r': + // This is clearly not the "best" method to exit reset. I don't know why this combination works. + wch_link_multicommands( devh, 3, 4, "\x81\x0b\x01\x01", 4, "\x81\x0d\x01\x02", 4, "\x81\x0d\x01\xff" ); + break; + case 'R': + // Part one "immediately" places the part into reset. Part 2 says when we're done, leave part in reset. + wch_link_multicommands( devh, 2, 4, "\x81\x0d\x01\x02", 4, "\x81\x0d\x01\x01" ); + break; + + // PROTECTION UNTESTED! + /* + case 'p': + wch_link_multicommands( devh, 8, + 11, "\x81\x06\x08\x02\xf7\xff\xff\xff\xff\xff\xff", + 4, "\x81\x0b\x01\x01", + 4, "\x81\x0d\x01\xff", + 4, "\x81\x0d\x01\x01", + 5, "\x81\x0c\x02\x09\x01", + 4, "\x81\x0d\x01\x02", + 4, "\x81\x06\x01\x01", + 4, "\x81\x0d\x01\xff" ); + break; + case 'P': + wch_link_multicommands( devh, 7, + 11, "\x81\x06\x08\x03\xf7\xff\xff\xff\xff\xff\xff", + 4, "\x81\x0b\x01\x01", + 4, "\x81\x0d\x01\xff", + 4, "\x81\x0d\x01\x01", + 5, "\x81\x0c\x02\x09\x01", + 4, "\x81\x0d\x01\x02", + 4, "\x81\x06\x01\x01" ); + break; + */ + case 'w': + { + if( argchar[2] != 0 ) goto help; + iarg++; + argchar = 0; // Stop advancing + if( iarg >= argc ) goto help; + + // Write binary. + int i; + FILE * f = fopen( argv[iarg], "rb" ); + fseek( f, 0, SEEK_END ); + int len = ftell( f ); + fseek( f, 0, SEEK_SET ); + int padlen = ((len-1) & (~0x3f)) + 0x40; + char * image = malloc( padlen ); + memset( image, 0xff, padlen ); + status = fread( image, len, 1, f ); + fclose( f ); + + if( status != 1 ) + { + fprintf( stderr, "Error: File I/O Fault.\n" ); + exit( -10 ); + } + if( len > 16384 ) + { + fprintf( stderr, "Error: Image for CH32V003 too large (%d)\n", len ); + exit( -9 ); + } + + int transferred; + wch_link_command( devh, "\x81\x06\x01\x01", 4, 0, 0, 0 ); + wch_link_command( devh, "\x81\x06\x01\x01", 4, 0, 0, 0 ); // Not sure why but it seems to work better when we request twice. + + // This contains the write data quantity, in bytes. (The last 2 octets) + // Then it just rollllls on in. + char rksbuff[11] = { 0x81, 0x01, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + rksbuff[9] = len >> 8; + rksbuff[10] = len & 0xff; + wch_link_command( devh, rksbuff, 11, 0, 0, 0 ); + + wch_link_command( devh, "\x81\x02\x01\x05", 4, 0, 0, 0 ); + + int pplace = 0; + for( pplace = 0; pplace < bootloader_len; pplace += 64 ) + { + WCHCHECK( libusb_bulk_transfer( devh, 0x02, (uint8_t*)(bootloader+pplace), 64, &transferred, WCHTIMEOUT ) ); + } + + for( i = 0; i < 10; i++ ) + { + wch_link_command( devh, "\x81\x02\x01\x07", 4, &transferred, rbuff, 1024 ); + if( transferred == 4 && rbuff[0] == 0x82 && rbuff[1] == 0x02 && rbuff[2] == 0x01 && rbuff[3] == 0x07 ) + { + break; + } + } + if( i == 10 ) + { + fprintf( stderr, "Error, confusing respones to 02/01/07\n" ); + exit( -109 ); + } + + wch_link_command( devh, "\x81\x02\x01\x02", 4, 0, 0, 0 ); + + for( pplace = 0; pplace < padlen; pplace += 64 ) + { + WCHCHECK( libusb_bulk_transfer( devh, 0x02,image+pplace, 64, &transferred, WCHTIMEOUT ) ); + } + + // Waiting or something on 2.46.2??????? I don't know why the main system does this. + // WCHCHECK( libusb_bulk_transfer( devh, 0x82, rbuff, 1024, &transferred, 2000 ) ); // Ignore respone. + free( image ); + break; + } + + } + if( argchar && argchar[2] != 0 ) { argchar++; goto keep_going; } + } + + wch_link_command( devh, "\x81\x0d\x01\xff", 4, 0, 0, 0); + + return 0; + +help: + fprintf( stderr, "Usage: minichlink [args]\n" ); + fprintf( stderr, " single-letter args may be combined, i.e. -3r\n" ); + fprintf( stderr, " multi-part args cannot.\n" ); + fprintf( stderr, " -3 Enable 3.3V\n" ); + fprintf( stderr, " -5 Enable 5V\n" ); + fprintf( stderr, " -t Disable 3.3V\n" ); + fprintf( stderr, " -f Disable 5V\n" ); + fprintf( stderr, " -r Release from reest\n" ); + fprintf( stderr, " -R Place into Reset\n" ); +// fprintf( stderr, " -P Enable Read Protection (UNTESTED)\n" ); +// fprintf( stderr, " -p Disable Read Protection (UNTESTED)\n" ); + fprintf( stderr, " -w [binary image to write]\n" ); + return -1; +} diff --git a/minichlink/wch_link_base.h b/minichlink/wch_link_base.h index 515d952..ee41455 100644 --- a/minichlink/wch_link_base.h +++ b/minichlink/wch_link_base.h @@ -3,6 +3,9 @@ #ifndef _WCH_LINK_BASE_H #define _WCH_LINK_BASE_H +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> #include "libusb.h" #define WCHTIMEOUT 5000 @@ -38,6 +41,19 @@ sendfail: exit( status ); } +static void wch_link_multicommands( libusb_device_handle * devh, int nrcommands, ... ) +{ + int i; + va_list argp; + va_start(argp, nrcommands); + for( i = 0; i < nrcommands; i++ ) + { + int clen = va_arg(argp, int); + wch_link_command( devh, va_arg(argp, char *), clen, 0, 0, 0 ); + } + va_end( argp ); +} + static inline libusb_device_handle * wch_link_base_setup() { libusb_context * ctx = 0; @@ -47,8 +63,6 @@ static inline libusb_device_handle * wch_link_base_setup() fprintf( stderr, "Error: libusb_init_context() returned %d\n", status ); exit( status ); } - printf( "OK %d %p\n", status, ctx ); - //libusb_set_debug(ctx, 0); libusb_device **list; libusb_device *found = NULL; @@ -68,8 +82,6 @@ static inline libusb_device_handle * wch_link_base_setup() exit( -9 ); } - //USB\VID_1A86&PID_8010&MI_00\6&3AA7447&0&0000 - //USB\VID_1A86&PID_8010&MI_00 libusb_device_handle * devh; status = libusb_open( found, &devh ); if( status ) @@ -84,7 +96,9 @@ static inline libusb_device_handle * wch_link_base_setup() int transferred; libusb_bulk_transfer( devh, 0x81, rbuff, 1024, &transferred, 1 ); // Clear out any pending transfers. Don't wait though. - wch_link_command( devh, "\x81\x0d\x01\x01", 4, 0, 0, 0 ); // Reply is: "\x82\x0d\x04\x02\x08\x02\x00" + // Place part into reset. + wch_link_command( devh, "\x81\x0d\x01\x01", 4, &transferred, rbuff, 1024 ); // Reply is: "\x82\x0d\x04\x02\x08\x02\x00" + wch_link_command( devh, "\x81\x0c\x02\x09\x01", 5, 0, 0, 0 ); //Reply is: 820c0101 wch_link_command( devh, "\x81\x0d\x01\x02", 4, 0, 0, 0 ); // Reply: Ignored, 820d050900300500 wch_link_command( devh, "\x81\x11\x01\x09", 4, &transferred, rbuff, 1024 ); // Reply: Chip ID + Other data (see below) @@ -93,8 +107,14 @@ static inline libusb_device_handle * wch_link_base_setup() fprintf( stderr, "Error: could not get part status\n" ); exit( -99 ); } - fprintf( stderr, "Part Type: 0x%02x%02x\n", rbuff[1], rbuff[2] ); - fprintf( stderr, "Part UUID: %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", rbuff[3], rbuff[4], rbuff[5], rbuff[6], rbuff[7], rbuff[8], rbuff[9], rbuff[10] ); + fprintf( stderr, "Part Type (A): 0x%02x%02x\n", rbuff[2], rbuff[3] ); // Is this Flash size? + fprintf( stderr, "Part UUID : %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", rbuff[4], rbuff[5], rbuff[6], rbuff[7], rbuff[8], rbuff[9], rbuff[10], rbuff[11] ); + fprintf( stderr, "PFlags : %02x-%02x-%02x-%02x\n", rbuff[12], rbuff[13], rbuff[14], rbuff[15] ); + fprintf( stderr, "Part Type (B): %02x-%02x-%02x-%02x\n", rbuff[16], rbuff[17], rbuff[18], rbuff[19] ); + + //for( i = 0; i < transferred; i++ ) + // printf( "%02x ", rbuff[i] ); + //printf( "\n" ); return devh; } diff --git a/minichlink/wch_power.c b/minichlink/wch_power.c deleted file mode 100644 index 5cc3d9e..0000000 --- a/minichlink/wch_power.c +++ /dev/null @@ -1,52 +0,0 @@ -#include <stdio.h> -#include "wch_link_base.h" - -int main() -{ - // Note this is for CH32V003, MCU UID 20-9e-ab-cd-88-b3-bc-84 - -return 0; - - libusb_device_handle * devh = wch_link_base_setup(); - int transferred; - int status; -"\x81\x0d\x01\x01" -"\x81\x0c\x02\x09\x01" - -// Disable 3.3: -"\x81\x0d\x01\x0a" -// Enable 3.3: -"\x81\x0d\x01\x09" -// Disable 5v: -"\x81\x0d\x01\x0c" -// Enable 5v: -"\x81\x0d\x01\x0b" - -// Or so the software says... In reality it doesn't follow those rules. - -// also for disabling read protection: -"\x81\x0c\x02\x09\x01" -"\x81\x0d\x01\x02" -"\x81\x06\x08\x02\xf7\xff\xff\xff\xff\xff\xff" -"\x81\x0b\x01\x01" -"\x81\x0d\x01\xff" -"\x81\x0d\x01\x01" -"\x81\x0c\x02\x09\x01" -"\x81\x0d\x01\x02" -"\x81\x06\x01\x01" -"\x81\x0d\x01\xff" - -// to enable read protection -"\x81\x0d\x01\x01" -"\x81\x0c\x02\x09\x01" -"\x81\x0d\x01\x02" -"\x81\x06\x08\x03\xf7\xff\xff\xff\xff\xff\xff" -"\x81\x0b\x01\x01" -"\x81\x0d\x01\xff" -"\x81\x0d\x01\x01" -"\x81\x0c\x02\x09\x01" -"\x81\x0d\x01\x02" -"\x81\x06\x01\x01" -"\x81\x0d\x01\xff" - -} diff --git a/minichlink/wch_reset.c b/minichlink/wch_reset.c index 0a3ee17..be2d389 100644 --- a/minichlink/wch_reset.c +++ b/minichlink/wch_reset.c @@ -3,16 +3,13 @@ // TESTED -// Note - should probably do reads between the writes. - int main() { libusb_device_handle * devh = wch_link_base_setup(); - int transferred; - uint8_t rbuff[1024]; - int status; - WCHCHECK( libusb_bulk_transfer( devh, 0x01, "\x81\x0b\x01\x01", 4, &transferred, WCHTIMEOUT) ); - WCHCHECK( libusb_bulk_transfer( devh, 0x81, rbuff, 1024, &transferred, 500 ) ); - WCHCHECK( libusb_bulk_transfer( devh, 0x01, "\x81\x0d\x01\xff", 4, &transferred, WCHTIMEOUT) ); - WCHCHECK( libusb_bulk_transfer( devh, 0x81, rbuff, 1024, &transferred, 500 ) ); -} \ No newline at end of file + + // Issue reset + wch_link_command( devh, "\x81\x0b\x01\x01", 4, 0, 0, 0 ); + + // Close out. + wch_link_command( devh, "\x81\x0d\x01\xff", 4, 0, 0, 0 ); +} diff --git a/minichlink/wch_write_simple.c b/minichlink/wch_write_simple.c index 1b09756..de31488 100644 --- a/minichlink/wch_write_simple.c +++ b/minichlink/wch_write_simple.c @@ -1,10 +1,10 @@ #include <stdio.h> #include "wch_link_base.h" -// UNTESTED +// tested // Having some difficulty with the base. -const char * bootloader = +const uint8_t * bootloader = (const uint8_t*) "\x21\x11\x22\xca\x26\xc8\x93\x77\x15\x00\x99\xcf\xb7\x06\x67\x45" \ "\xb7\x27\x02\x40\x93\x86\x36\x12\x37\x97\xef\xcd\xd4\xc3\x13\x07" \ "\xb7\x9a\xd8\xc3\xd4\xd3\xd8\xd3\x93\x77\x25\x00\x9d\xc7\xb7\x27" \ @@ -44,6 +44,7 @@ int bootloader_len = 512; int main( int argc, char ** argv ) { int i; + int status; uint8_t rbuff[1024]; if( argc != 2 ) @@ -58,9 +59,14 @@ int main( int argc, char ** argv ) int padlen = ((len-1) & (~0x3f)) + 0x40; char * image = malloc( padlen ); memset( image, 0xff, padlen ); - fread( image, len, 1, f ); + status = fread( image, len, 1, f ); fclose( f ); + if( status != 1 ) + { + fprintf( stderr, "Error: File I/O Fault.\n" ); + return -10; + } if( len > 16384 ) { fprintf( stderr, "Error: Image for CH32V003 too large\n" ); @@ -69,7 +75,6 @@ int main( int argc, char ** argv ) libusb_device_handle * devh = wch_link_base_setup(); int transferred; - int status; wch_link_command( devh, "\x81\x06\x01\x01", 4, 0, 0, 0 ); wch_link_command( devh, "\x81\x06\x01\x01", 4, 0, 0, 0 ); // Not sure why but it seems to work better when we request twice. @@ -85,7 +90,7 @@ int main( int argc, char ** argv ) int pplace = 0; for( pplace = 0; pplace < bootloader_len; pplace += 64 ) { - WCHCHECK( libusb_bulk_transfer( devh, 0x02, bootloader+pplace, 64, &transferred, WCHTIMEOUT ) ); + WCHCHECK( libusb_bulk_transfer( devh, 0x02, (uint8_t*)(bootloader+pplace), 64, &transferred, WCHTIMEOUT ) ); } for( i = 0; i < 10; i++ ) @@ -102,21 +107,19 @@ int main( int argc, char ** argv ) exit( -109 ); } - WCHCHECK( libusb_bulk_transfer( devh, 0x01, "\x81\x02\x01\x02", 4, &transferred, WCHTIMEOUT) ); // checkme. - WCHCHECK( libusb_bulk_transfer( devh, 0x81, rbuff, 1024, &transferred, 2000 ) ); // Ignore respone. - + wch_link_command( devh, "\x81\x02\x01\x02", 4, 0, 0, 0 ); for( pplace = 0; pplace < padlen; pplace += 64 ) { WCHCHECK( libusb_bulk_transfer( devh, 0x02,image+pplace, 64, &transferred, WCHTIMEOUT ) ); } - // Waiting or something on 2.46.2??????? - WCHCHECK( libusb_bulk_transfer( devh, 0x82, rbuff, 1024, &transferred, 2000 ) ); // Ignore respone. - - WCHCHECK( libusb_bulk_transfer( devh, 0x01, "\x81\x0d\x01\xff", 4, &transferred, WCHTIMEOUT) ); // checkme. - WCHCHECK( libusb_bulk_transfer( devh, 0x81, rbuff, 1024, &transferred, 2000 ) ); // Ignore respone. - - //211122ca26c89377150099cfb7066745b7270240938636123797efcdd4c31307b79ad8c3d4d3d8d3937725009dc7b7270240984bad66373300401367470098cb984b9386a6aa1367070498cbd847058b63160710984b6d9b98cb93774500a9cb9307f60399832ec02d6381763ec4b7320040b72702401303a3aafd16984bb703 -// WCHCHECK( libusb_bulk_transfer( devh, 0x01, "\x81\x02\x01\x05", 4, &transferred, WCHTIMEOUT) ); + // Waiting or something on 2.46.2??????? I don't know why the main system does this. +// WCHCHECK( libusb_bulk_transfer( devh, 0x82, rbuff, 1024, &transferred, 2000 ) ); // Ignore respone. + + // Issue reset (this is optional) + wch_link_command( devh, "\x81\x0b\x01\x01", 4, 0, 0, 0 ); + + // Closeout + wch_link_command( devh, "\x81\x0d\x01\xff", 4, 0, 0, 0); } -- GitLab