From 184fdfd1b30410db59b50b427ce5c7b817ae4c88 Mon Sep 17 00:00:00 2001 From: cnlohr <lohr85@gmail.com> Date: Wed, 21 Jun 2023 00:49:41 -0400 Subject: [PATCH] Integrate most changes from Alexander M, bmx and Pokey. --- minichlink/minichlink.c | 32 +++++---- minichlink/minichlink.h | 1 + minichlink/pgm-wch-linke.c | 134 +++++++++++++++++++++++-------------- 3 files changed, 99 insertions(+), 68 deletions(-) diff --git a/minichlink/minichlink.c b/minichlink/minichlink.c index 83c4de7..c73558d 100644 --- a/minichlink/minichlink.c +++ b/minichlink/minichlink.c @@ -18,11 +18,6 @@ void Sleep(uint32_t dwMilliseconds); #include <unistd.h> #endif - -#if defined(WINDOWS) || defined(WIN32) || defined(_WIN32) - #define usleep(x) Sleep((x)/1000); -#endif - static int64_t StringToMemoryAddress( const char * number ) __attribute__((used)); static void StaticUpdatePROGBUFRegs( void * dev ) __attribute__((used)); int DefaultReadBinaryBlob( void * dev, uint32_t address_to_read_from, uint32_t read_size, uint8_t * blob ); @@ -59,6 +54,14 @@ void * MiniCHLinkInitAsDLL( struct MiniChlinkFunctions ** MCFO, const init_hints return 0; } + struct InternalState * iss = calloc( 1, sizeof( struct InternalState ) ); + ((struct ProgrammerStructBase*)dev)->internal = iss; + iss->ram_base = 0x20000000; + iss->ram_size = 2048; + iss->sector_size = 64; + iss->flash_size = 16384; + iss->target_chip_type = 0; + SetupAutomaticHighLevelFunctions( dev ); if( MCFO ) @@ -468,6 +471,7 @@ keep_going: } case 'w': { + struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal); if( argchar[2] != 0 ) goto help; iarg++; argchar = 0; // Stop advancing @@ -684,7 +688,7 @@ static int DefaultWaitForFlash( void * dev ) rw = 0; MCF.ReadWord( dev, (intptr_t)&FLASH->STATR, &rw ); // FLASH_STATR => 0x4002200C if( timeout++ > 100 ) return -1; - } while(rw & 1); // BSY flag. + } while(rw & 2); // BSY flag for 003, or WRBSY for other processors. if( rw & FLASH_STATR_WRPRTERR ) { @@ -1715,10 +1719,7 @@ int DefaultUnbrick( void * dev ) // After more experimentation, it appaers to work best by not clearing the halt request. MCF.FlushLLCommands( dev ); - if( MCF.DelayUS ) - MCF.DelayUS( dev, 20000 ); - else - usleep(20000); + MCF.DelayUS( dev, 20000 ); if( timeout == max_timeout ) { @@ -1778,7 +1779,11 @@ int DefaultVoidHighLevelState( void * dev ) int DefaultDelayUS( void * dev, int us ) { +#if defined(WINDOWS) || defined(WIN32) || defined(_WIN32) + Sleep( (us+9999) / 1000 ); +#else usleep( us ); +#endif return 0; } @@ -1839,13 +1844,6 @@ int SetupAutomaticHighLevelFunctions( void * dev ) if( !MCF.DelayUS ) MCF.DelayUS = DefaultDelayUS; - struct InternalState * iss = calloc( 1, sizeof( struct InternalState ) ); - iss->ram_base = 0x20000000; - iss->ram_size = 2048; - iss->sector_size = 64; - iss->flash_size = 16384; - - ((struct ProgrammerStructBase*)dev)->internal = iss; return 0; } diff --git a/minichlink/minichlink.h b/minichlink/minichlink.h index 50f859c..dfdb244 100644 --- a/minichlink/minichlink.h +++ b/minichlink/minichlink.h @@ -116,6 +116,7 @@ struct InternalState uint32_t ram_size; int sector_size; int flash_size; + int target_chip_type; // 0 for unknown (or 003), otherwise a part number. uint8_t flash_sector_status[MAX_FLASH_SECTORS]; // 0 means unerased/unknown. 1 means erased. }; diff --git a/minichlink/pgm-wch-linke.c b/minichlink/pgm-wch-linke.c index 2a3e516..61f98d6 100644 --- a/minichlink/pgm-wch-linke.c +++ b/minichlink/pgm-wch-linke.c @@ -18,8 +18,8 @@ struct LinkEProgrammerStruct // For non-ch32v003 chips. //static int LEReadBinaryBlob( void * d, uint32_t offset, uint32_t amount, uint8_t * readbuff ); -//static int InternalLinkEHaltMode( void * d, int mode ); -//static int LEWriteBinaryBlob( void * d, uint32_t address_to_write, uint32_t len, uint8_t * blob ); +static int InternalLinkEHaltMode( void * d, int mode ); +static int LEWriteBinaryBlob( void * d, uint32_t address_to_write, uint32_t len, uint8_t * blob ); #define WCHTIMEOUT 5000 #define WCHCHECK(x) if( (status = x) ) { fprintf( stderr, "Bad USB Operation on " __FILE__ ":%d (%d)\n", __LINE__, status ); exit( status ); } @@ -191,6 +191,8 @@ int LEFlushLLCommands( void * dev ) static int LESetupInterface( void * d ) { libusb_device_handle * dev = ((struct LinkEProgrammerStruct*)d)->devh; + struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal); + uint8_t rbuff[1024]; uint32_t transferred = 0; @@ -223,6 +225,10 @@ static int LESetupInterface( void * d ) // TODO: What in the world is this? It doesn't appear to be needed. wch_link_command( dev, "\x81\x0c\x02\x09\x01", 5, 0, 0, 0 ); //Reply is: 820c0101 + // Note from further debugging: + // My capture differs in this case: \x05 instead of \x09 -> But does not seem to be needed + //wch_link_command( dev, "\x81\x0c\x02\x05\x01", 5, 0, 0, 0 ); //Reply is: 820c0101 + // This puts the processor on hold to allow the debugger to run. wch_link_command( dev, "\x81\x0d\x01\x02", 4, (int*)&transferred, rbuff, 1024 ); // Reply: Ignored, 820d050900300500 if (rbuff[0] == 0x81 && rbuff[1] == 0x55 && rbuff[2] == 0x01 && rbuff[3] == 0x01) @@ -230,8 +236,18 @@ static int LESetupInterface( void * d ) fprintf(stderr, "link error, nothing connected to linker\n"); return -1; } - uint32_t target_chip_type = ( rbuff[4] << 4) + (rbuff[5] >> 4); - fprintf(stderr, "Chip Type: %03x\n", target_chip_type); + + uint32_t target_chip_type = ( rbuff[4] << 4) + (rbuff[5] >> 4); + fprintf(stderr, "Chip Type: %03x\n", target_chip_type); + if( target_chip_type == 0x307 || target_chip_type == 0x203 ) + { + fprintf( stderr, "CH32V307 or CH32V203 Detected. Allowing old-flash-mode for operation.\n" ); + MCF.WriteBinaryBlob = LEWriteBinaryBlob; + + iss->sector_size = 256; + + wch_link_command( dev, "\x81\x0d\x01\x03", 4, (int*)&transferred, rbuff, 1024 ); // Reply: Ignored, 820d050900300500 + } // For some reason, if we don't do this sometimes the programmer starts in a hosey mode. MCF.WriteReg32( d, DMCONTROL, 0x80000001 ); // Make the debug module work properly. @@ -254,7 +270,10 @@ static int LESetupInterface( void * d ) } // This puts the processor on hold to allow the debugger to run. - wch_link_command( dev, "\x81\x11\x01\x09", 4, (int*)&transferred, rbuff, 1024 ); // Reply: Chip ID + Other data (see below) + // Recommended to switch to 05 from 09 by Alexander M + // wch_link_command( dev, "\x81\x11\x01\x09", 4, (int*)&transferred, rbuff, 1024 ); // Reply: Chip ID + Other data (see below) + wch_link_command( dev, "\x81\x11\x01\x05", 4, (int*)&transferred, rbuff, 1024 ); // Reply: Chip ID + Other data (see below) + if( transferred != 20 ) { fprintf( stderr, "Error: could not get part status\n" ); @@ -264,7 +283,24 @@ static int LESetupInterface( void * d ) 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] ); - + + // Check for read protection + wch_link_command( dev, "\x81\x06\x01\x01", 4, (int*)&transferred, rbuff, 1024 ); + if(transferred != 4) { + fprintf(stderr, "Error: could not get read protection status\n"); + return -1; + } + + if(rbuff[3] == 0x01) { + fprintf(stderr, "Read protection: enabled\n"); + } else { + fprintf(stderr, "Read protection: disabled\n"); + } + + + iss->flash_size = (rbuff[2]<<8) | rbuff[3]; + iss->target_chip_type = target_chip_type; + return 0; } @@ -365,49 +401,47 @@ void * TryInit_WCHLinkE() }; -#if 0 +#if 1 // In case you are using a non-CH32V003 board. - 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" \ +"\x93\x77\x15\x00\x41\x11\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\x95\xc7\xb7\x27\x02\x40\x98\x4b" \ +"\xad\x66\x37\x38\x00\x40\x13\x67\x47\x00\x98\xcb\x98\x4b\x93\x86" \ +"\xa6\xaa\x13\x67\x07\x04\x98\xcb\xd8\x47\x05\x8b\x61\xeb\x98\x4b" \ +"\x6d\x9b\x98\xcb\x93\x77\x45\x00\xa9\xcb\x93\x07\xf6\x0f\xa1\x83" \ +"\x2e\xc0\x2d\x68\x81\x76\x3e\xc4\xb7\x08\x02\x00\xb7\x27\x02\x40" \ +"\x37\x33\x00\x40\x13\x08\xa8\xaa\xfd\x16\x98\x4b\x33\x67\x17\x01" \ +"\x98\xcb\x02\x47\xd8\xcb\x98\x4b\x13\x67\x07\x04\x98\xcb\xd8\x47" \ +"\x05\x8b\x41\xeb\x98\x4b\x75\x8f\x98\xcb\x02\x47\x13\x07\x07\x10" \ +"\x3a\xc0\x22\x47\x7d\x17\x3a\xc4\x69\xfb\x93\x77\x85\x00\xd5\xcb" \ +"\x93\x07\xf6\x0f\x2e\xc0\xa1\x83\x3e\xc4\x37\x27\x02\x40\x1c\x4b" \ +"\xc1\x66\x41\x68\xd5\x8f\x1c\xcb\xb7\x16\x00\x20\xb7\x27\x02\x40" \ +"\x93\x08\x00\x04\x37\x03\x20\x00\x98\x4b\x33\x67\x07\x01\x98\xcb" \ +"\xd8\x47\x05\x8b\x75\xff\x02\x47\x3a\xc2\x46\xc6\x32\x47\x0d\xef" \ +"\x98\x4b\x33\x67\x67\x00\x98\xcb\xd8\x47\x05\x8b\x75\xff\xd8\x47" \ +"\x41\x8b\x39\xc3\xd8\x47\xc1\x76\xfd\x16\x13\x67\x07\x01\xd8\xc7" \ +"\x98\x4b\x21\x45\x75\x8f\x98\xcb\x41\x01\x02\x90\x23\x20\xd8\x00" \ +"\x25\xb7\x23\x20\x03\x01\xa5\xb7\x12\x47\x13\x8e\x46\x00\x94\x42" \ +"\x14\xc3\x12\x47\x11\x07\x3a\xc2\x32\x47\x7d\x17\x3a\xc6\xd8\x47" \ +"\x09\x8b\x75\xff\xf2\x86\x5d\xb7\x02\x47\x13\x07\x07\x10\x3a\xc0" \ +"\x22\x47\x7d\x17\x3a\xc4\x49\xf3\x98\x4b\xc1\x76\xfd\x16\x75\x8f" \ +"\x98\xcb\x41\x89\x15\xc9\x2e\xc0\x0d\x06\x02\xc4\x09\x82\x32\xc6" \ +"\xb7\x17\x00\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\xbd\xbf\x41\x45\xad\xbf" \ +"\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\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\xff\xff\xff\xff"; int bootloader_len = 512; #endif -#if 0 static int InternalLinkEHaltMode( void * d, int mode ) { libusb_device_handle * dev = ((struct LinkEProgrammerStruct*)d)->devh; @@ -432,7 +466,6 @@ static int InternalLinkEHaltMode( void * d, int mode ) } return 0; } -#endif #if 0 static int LEReadBinaryBlob( void * d, uint32_t offset, uint32_t amount, uint8_t * readbuff ) @@ -494,10 +527,10 @@ static int LEReadBinaryBlob( void * d, uint32_t offset, uint32_t amount, uint8_t } #endif -#if 0 static int LEWriteBinaryBlob( void * d, uint32_t address_to_write, uint32_t len, uint8_t * blob ) { libusb_device_handle * dev = ((struct LinkEProgrammerStruct*)d)->devh; + struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal); InternalLinkEHaltMode( d, 0 ); @@ -506,7 +539,7 @@ static int LEWriteBinaryBlob( void * d, uint32_t address_to_write, uint32_t len, uint8_t rbuff[1024]; int transferred; - int padlen = ((len-1) & (~0x3f)) + 0x40; + int padlen = ((len-1) & (~(iss->sector_size-1)) + iss->sector_size; wch_link_command( (libusb_device_handle *)dev, "\x81\x06\x01\x01", 4, 0, 0, 0 ); wch_link_command( (libusb_device_handle *)dev, "\x81\x06\x01\x01", 4, 0, 0, 0 ); // Not sure why but it seems to work better when we request twice. @@ -521,9 +554,9 @@ static int LEWriteBinaryBlob( void * d, uint32_t address_to_write, uint32_t len, wch_link_command( (libusb_device_handle *)dev, "\x81\x02\x01\x05", 4, 0, 0, 0 ); int pplace = 0; - for( pplace = 0; pplace < bootloader_len; pplace += 64 ) + for( pplace = 0; pplace < bootloader_len; pplace += iss->sector_size ) { - WCHCHECK( libusb_bulk_transfer( (libusb_device_handle *)dev, 0x02, (uint8_t*)(bootloader+pplace), 64, &transferred, WCHTIMEOUT ) ); + WCHCHECK( libusb_bulk_transfer( (libusb_device_handle *)dev, 0x02, (uint8_t*)(bootloader+pplace), iss->sector_size, &transferred, WCHTIMEOUT ) ); } for( i = 0; i < 10; i++ ) @@ -542,24 +575,23 @@ static int LEWriteBinaryBlob( void * d, uint32_t address_to_write, uint32_t len, wch_link_command( (libusb_device_handle *)dev, "\x81\x02\x01\x02", 4, 0, 0, 0 ); - for( pplace = 0; pplace < padlen; pplace += 64 ) + for( pplace = 0; pplace < padlen; pplace += iss->sector_size ) { - if( pplace + 64 > len ) + if( pplace + iss->sector_size > len ) { - uint8_t paddeddata[64]; - int gap = pplace + 64 - len; + uint8_t paddeddata[iss->sector_size]; + int gap = pplace + iss->sector_size - len; int okcopy = len - pplace; memcpy( paddeddata, blob + pplace, okcopy ); memset( paddeddata + okcopy, 0xff, gap ); - WCHCHECK( libusb_bulk_transfer( (libusb_device_handle *)dev, 0x02, paddeddata, 64, &transferred, WCHTIMEOUT ) ); + WCHCHECK( libusb_bulk_transfer( (libusb_device_handle *)dev, 0x02, paddeddata, iss->sector_size, &transferred, WCHTIMEOUT ) ); } else { - WCHCHECK( libusb_bulk_transfer( (libusb_device_handle *)dev, 0x02, blob+pplace, 64, &transferred, WCHTIMEOUT ) ); + WCHCHECK( libusb_bulk_transfer( (libusb_device_handle *)dev, 0x02, blob+pplace, iss->sector_size, &transferred, WCHTIMEOUT ) ); } } return 0; } -#endif -- GitLab