Skip to content

Commit

Permalink
Fix on windows + Allow bypass mode for ch32v006
Browse files Browse the repository at this point in the history
  • Loading branch information
cnlohr committed Mar 2, 2025
1 parent eb474e0 commit ae515dc
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 55 deletions.
3 changes: 3 additions & 0 deletions ch32fun/ch32fun.mk
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Default prefix for Windows
ifeq ($(OS),Windows_NT)
PREFIX?=riscv64-unknown-elf
ifeq ($(shell which $(PREFIX)),)
PREFIX:=riscv-none-elf
endif
# Check if riscv64-unknown-elf-gcc exists
else ifneq ($(shell which riscv64-unknown-elf-gcc),)
PREFIX?=riscv64-unknown-elf
Expand Down
4 changes: 2 additions & 2 deletions minichlink/minichlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ int main( int argc, char ** argv )
}
case 'w':
{
struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal);
//struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal);
if( argchar[2] != 0 ) goto help;
iarg++;
argchar = 0; // Stop advancing
Expand Down Expand Up @@ -2274,7 +2274,7 @@ static int DefaultHaltMode( void * dev, int mode )
// Returns 0 if no text waiting.
// maxlen MUST be at least 8 characters. We null terminate.
int DefaultPollTerminal( void * dev, uint8_t * buffer, int maxlen, uint32_t leaveflagA, int leaveflagB )
{
{
struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal);
int r;
uint32_t rr;
Expand Down
Binary file modified minichlink/minichlink.exe
Binary file not shown.
137 changes: 84 additions & 53 deletions minichlink/pgm-wch-linke.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,12 @@ static void printChipInfo(enum RiscVChip chip) {

static int checkChip(enum RiscVChip chip) {
switch(chip) {
case CHIP_UNKNOWN:
case CHIP_CH32V002:
case CHIP_CH32V004:
case CHIP_CH32V003:
case CHIP_CH32V006:
case CHIP_CH32V005:
case CHIP_CH32X03x:
return 0; // Use direct mode
case CHIP_CH32V10x:
Expand Down Expand Up @@ -365,21 +370,29 @@ static int LESetupInterface( void * d )
// 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

int unknown_chip_fallback = 0;

// This puts the processor on hold to allow the debugger to run.
int already_tried_reset = 0;
int is_already_connected = 0;
do
{
// Read DMSTATUS - in case we are a ch32x035, or other chip that does not respond to \x81\x0d\x01\x02.
wch_link_command( dev, "\x81\x08\x06\x05\x11\x00\x00\x00\x00\x01", 11, (int*)&transferred, rbuff, 1024 ); // Reply: Ignored, 820d050900300500
if( transferred == 9 && rbuff[8] != 0x02 && rbuff[8] != 0x03 && rbuff[8] != 0x00 )

// There's a couple situations where the older firmware on the official programmer freaks out.
// We don't want to inconvenience our users, so just try to work through it by falling back to the minichlink functions.
// Part connected. But the programmer doesn't know what it is.
if( transferred == 9 && ( ( rbuff[4] == 0x00 ) ||
( rbuff[8] != 0x02 && rbuff[8] != 0x03 && rbuff[8] != 0x00 ) ) )
{
// Already connected.
if( is_already_connected )
{
printf( "Already Connected\n" );
// Still need to read in the data so we can select the correct chip.
wch_link_command( dev, "\x81\x0d\x01\x02", 4, (int*)&transferred, rbuff, 1024 ); // ?? this seems to work?
unknown_chip_fallback = 1;
break;
}
is_already_connected = 1;
Expand All @@ -394,8 +407,11 @@ static int LESetupInterface( void * d )
fprintf(stderr, "link error, nothing connected to linker (%d = [%02x %02x %02x %02x]). Trying to put processor in hold and retrying.\n", transferred, rbuff[0], rbuff[1], rbuff[2], rbuff[3]);

// Give up if too long
if( already_tried_reset > 10 )
return -1;
if( already_tried_reset > 5 )
{
unknown_chip_fallback = 1;
break;
}

wch_link_multicommands( (libusb_device_handle *)dev, 1, 4, "\x81\x0d\x01\x13" ); // Try forcing reset line low.
wch_link_command( (libusb_device_handle *)dev, "\x81\x0d\x01\xff", 4, 0, 0, 0); //Exit programming
Expand Down Expand Up @@ -428,6 +444,12 @@ static int LESetupInterface( void * d )
return -1;
}

if( unknown_chip_fallback )
{
printf( "Unknown chip fallback\n" );
chip = CHIP_UNKNOWN;
}

printChipInfo(chip);

iss->target_chip_type = chip;
Expand Down Expand Up @@ -463,69 +485,78 @@ static int LESetupInterface( void * d )
// 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)

retry_ID:
wch_link_command( dev, "\x81\x11\x01\x05", 4, (int*)&transferred, rbuff, 1024 ); // Reply: Chip ID + Other data (see below)

if( rbuff[0] == 0x00 )
if( unknown_chip_fallback )
{
if( timeout++ < 10 ) goto retry_ID;
fprintf( stderr, "Failed to get chip ID\n" );
return -4;
// This is a little cursed. If we're in fallback mode, none of the other chip-specific operations will work
// the processor will be in a very cursed mode. We can't trust it.
MCF.HaltMode( d, HALT_MODE_REBOOT );
}

if( transferred != 20 )
else
{
fprintf( stderr, "Error: could not get part status\n" );
return -1;
}
int flash_size = (rbuff[2]<<8) | rbuff[3];
fprintf( stderr, "Flash Storage: %d kB\n", 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] );
retry_ID:
wch_link_command( dev, "\x81\x11\x01\x05", 4, (int*)&transferred, rbuff, 1024 ); // Reply: Chip ID + Other data (see below)

// Quirk, was fixed in LinkE version 2.12.
if( iss->target_chip_type == CHIP_CH32V10x && flash_size == 62 )
{
fprintf( stderr, "While the debugger reports this as a CH32V10x, it's probably a CH32X03x\n" );
chip = iss->target_chip_type = CHIP_CH32X03x;
}
if( rbuff[0] == 0x00 )
{
if( timeout++ < 10 ) goto retry_ID;
fprintf( stderr, "Failed to get chip ID\n" );
return -4;
}

if( iss->target_chip_type == CHIP_CH32X03x )
{
iss->sector_size = 256;
}
if( transferred != 20 )
{
fprintf( stderr, "Error: could not get part status\n" );
return -1;
}
int flash_size = (rbuff[2]<<8) | rbuff[3];
fprintf( stderr, "Flash Storage: %d kB\n", 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] );

// Quirk, was fixed in LinkE version 2.12.
if( iss->target_chip_type == CHIP_CH32V10x && flash_size == 62 )
{
fprintf( stderr, "While the debugger reports this as a CH32V10x, it's probably a CH32X03x\n" );
chip = iss->target_chip_type = CHIP_CH32X03x;
}

int result = checkChip(chip);
if( result == 1 ) // Using blob write
{
fprintf( stderr, "Using binary blob write for operation.\n" );
MCF.WriteBinaryBlob = LEWriteBinaryBlob;
if( iss->target_chip_type == CHIP_CH32X03x )
{
iss->sector_size = 256;
}

iss->sector_size = 256;
int result = checkChip(chip);
if( result == 1 ) // Using blob write
{
fprintf( stderr, "Using binary blob write for operation.\n" );
MCF.WriteBinaryBlob = LEWriteBinaryBlob;

wch_link_command( dev, "\x81\x0d\x01\x03", 4, (int*)&transferred, rbuff, 1024 ); // Reply: Ignored, 820d050900300500
iss->sector_size = 256;

} else if( result < 0 ) {
fprintf( stderr, "Chip type not supported. Aborting...\n" );
return -1;
}
wch_link_command( dev, "\x81\x0d\x01\x03", 4, (int*)&transferred, rbuff, 1024 ); // Reply: Ignored, 820d050900300500

} else if( result < 0 ) {
fprintf( stderr, "Chip type not supported. Aborting...\n" );
return -1;
}

// 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");
}
// 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;
}

iss->flash_size = flash_size*1024;
if(rbuff[3] == 0x01) {
fprintf(stderr, "Read protection: enabled\n");
} else {
fprintf(stderr, "Read protection: disabled\n");
}

iss->flash_size = flash_size*1024;
}

return 0;
}
Expand Down

0 comments on commit ae515dc

Please sign in to comment.