From 0688830e2c36ec9c2d84e1530a9ff205f32c1bcb Mon Sep 17 00:00:00 2001 From: cnlohr <lohr85@gmail.com> Date: Sun, 12 Mar 2023 07:40:36 -0400 Subject: [PATCH] Use compressed instructions and significantly reduce cost of switching between reads/writes. --- ch32v003fun/ch32v003fun.h | 2 +- minichlink/Makefile | 2 +- minichlink/minichlink.c | 389 +++++++++++++++----------------- minichlink/minichlink.h | 9 +- minichlink/pgm-esp32s2-ch32xx.c | 6 +- minichlink/pgm-wch-linke.c | 17 +- 6 files changed, 205 insertions(+), 220 deletions(-) diff --git a/ch32v003fun/ch32v003fun.h b/ch32v003fun/ch32v003fun.h index f256100..9f25a84 100644 --- a/ch32v003fun/ch32v003fun.h +++ b/ch32v003fun/ch32v003fun.h @@ -2473,7 +2473,7 @@ extern "C" { /* ch32v00x_adc.c ------------------------------------------------------------*/ -/* + /* ADC DISCNUM mask */ #define CTLR1_DISCNUM_Reset ((uint32_t)0xFFFF1FFF) diff --git a/minichlink/Makefile b/minichlink/Makefile index c1f081e..26a4024 100644 --- a/minichlink/Makefile +++ b/minichlink/Makefile @@ -2,7 +2,7 @@ TOOLS:=minichlink all : $(TOOLS) -CFLAGS:=-O0 -g3 +CFLAGS:=-O0 -g3 -Wall LDFLAGS:=-lpthread -lusb-1.0 -ludev minichlink : minichlink.c pgm-wch-linke.c pgm-esp32s2-ch32xx.c diff --git a/minichlink/minichlink.c b/minichlink/minichlink.c index 568d12b..57dfe80 100644 --- a/minichlink/minichlink.c +++ b/minichlink/minichlink.c @@ -3,6 +3,8 @@ // Freely licensable under the MIT/x11, NewBSD Licenses, or // public domain where applicable. +// TODO: Can we make a unified DMPROG for reading + writing? + #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -11,7 +13,6 @@ static int64_t SimpleReadNumberInt( const char * number, int64_t defaultNumber ); static int64_t StringToMemoryAddress( const char * number ); - void TestFunction(void * v ); struct MiniChlinkFunctions MCF; @@ -36,7 +37,6 @@ int main( int argc, char ** argv ) int status; int must_be_end = 0; - uint8_t rbuff[1024]; if( MCF.SetupInterface ) { @@ -104,7 +104,7 @@ keep_going: else goto unimplemented; break; - case 'b': + case 'b': //reBoot if( !MCF.HaltMode || MCF.HaltMode( dev, 1 ) ) goto unimplemented; break; @@ -113,21 +113,25 @@ keep_going: goto unimplemented; break; case 'E': //Erase whole chip. + if( MCF.HaltMode ) MCF.HaltMode( dev, 0 ); if( !MCF.Erase || MCF.Erase( dev, 0, 0, 1 ) ) goto unimplemented; break; case 'h': if( !MCF.HaltMode || MCF.HaltMode( dev, 0 ) ) + goto unimplemented; break; // disable NRST pin (turn it into a GPIO) case 'd': // see "RSTMODE" in datasheet + if( MCF.HaltMode ) MCF.HaltMode( dev, 0 ); if( MCF.ConfigureNRSTAsGPIO ) MCF.ConfigureNRSTAsGPIO( dev, 0 ); else goto unimplemented; break; case 'D': // see "RSTMODE" in datasheet + if( MCF.HaltMode ) MCF.HaltMode( dev, 0 ); if( MCF.ConfigureNRSTAsGPIO ) MCF.ConfigureNRSTAsGPIO( dev, 1 ); else @@ -152,34 +156,18 @@ keep_going: } } while( 1 ); } - // 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" ); + { + if( MCF.PrintChipInfo ) + MCF.PrintChipInfo( dev ); + else + goto unimplemented; break; - */ + } case 'r': { - int i; - int transferred; + if( MCF.HaltMode ) MCF.HaltMode( dev, 0 ); + if( argchar[2] != 0 ) { fprintf( stderr, "Error: can't have char after paramter field\n" ); @@ -218,7 +206,6 @@ keep_going: return -9; } uint8_t * readbuff = malloc( amount ); - int readbuffplace = 0; if( MCF.ReadBinaryBlob ) { @@ -257,20 +244,22 @@ keep_going: } case 'w': { + if( MCF.HaltMode ) MCF.HaltMode( dev, 0 ); + if( argchar[2] != 0 ) goto help; iarg++; argchar = 0; // Stop advancing if( iarg + 1 >= argc ) goto help; + // Write binary. - int i; int len = 0; - char * image = 0; + uint8_t * image = 0; const char * fname = argv[iarg++]; if( fname[0] == '-' ) { len = strlen( fname + 1 ); - image = strdup( fname + 1 ); + image = (uint8_t*)strdup( fname + 1 ); status = 1; } else if( fname[0] == '+' ) @@ -321,7 +310,6 @@ keep_going: fclose( f ); } - uint64_t offset = StringToMemoryAddress( argv[iarg] ); if( offset > 0xffffffff ) { @@ -339,6 +327,7 @@ keep_going: exit( -9 ); } + if( MCF.WriteBinaryBlob ) { if( MCF.WriteBinaryBlob( dev, offset, len, image ) ) @@ -404,8 +393,6 @@ unimplemented: #endif static int StaticUnlockFlash( void * dev, struct InternalState * iss ); -static int StaticWaitForFlash( void * dev ); -static int StaticEnterResetMode( void * dev, struct InternalState * iss, int halt ); static int64_t SimpleReadNumberInt( const char * number, int64_t defaultNumber ) { @@ -453,7 +440,7 @@ static int64_t StringToMemoryAddress( const char * number ) return SimpleReadNumberInt( number, -1 ); } -static int StaticWaitForFlash( void * dev ) +static int DefaultWaitForFlash( void * dev ) { uint32_t rw, timeout = 0; do @@ -472,30 +459,23 @@ static int StaticWaitForFlash( void * dev ) return 0; } -static int StaticEnterResetMode( void * dev, struct InternalState * iss, int mode ) +static int DefaultWaitForDoneOp( void * dev ) { - switch ( mode ) + int r; + uint32_t rrv; + do { - case 0: - MCF.WriteReg32( dev, DMCONTROL, 0x80000001 ); // Make the debug module work properly. - MCF.WriteReg32( dev, DMCONTROL, 0x80000001 ); // Initiate a halt request. - MCF.WriteReg32( dev, DMCONTROL, 0x00000001 ); // Clear Halt Request. - MCF.FlushLLCommands( dev ); - break; - case 1: - MCF.WriteReg32( dev, DMCONTROL, 0x80000001 ); // Make the debug module work properly. - MCF.WriteReg32( dev, DMCONTROL, 0x80000001 ); // Initiate a halt request. - MCF.WriteReg32( dev, DMCONTROL, 0x80000003 ); // Reboot. - MCF.WriteReg32( dev, DMCONTROL, 0x40000001 ); // resumereq - MCF.FlushLLCommands( dev ); - printf( "Reboot\n" ); - break; - case 2: - MCF.WriteReg32( dev, DMCONTROL, 0x40000001 ); // resumereq - MCF.FlushLLCommands( dev ); - break; + r = MCF.ReadReg32( dev, DMABSTRACTCS, &rrv ); + if( r ) return r; } - iss->processor_in_mode = mode; + while( rrv & (1<<12) ); + if( (rrv >> 8 ) & 7 ) + { + fprintf( stderr, "Fault writing memory (DMABSTRACTS = %08x)\n", rrv ); + MCF.WriteReg32( dev, DMABSTRACTCS, 0x00000700 ); + return -9; + } + return 0; } int DefaultSetupInterface( void * dev ) @@ -509,7 +489,7 @@ int DefaultSetupInterface( void * dev ) MCF.WriteReg32( dev, DMCFGR, 0x5aa50000 | (1<<10) ); // Bug in silicon? If coming out of cold boot, and we don't do our little "song and dance" this has to be called. // Read back chip status. This is really baskc. - uint32_t reg; + uint32_t reg = 0; int r = MCF.ReadReg32( dev, DMSTATUS, ® ); if( r >= 0 ) { @@ -526,41 +506,14 @@ int DefaultSetupInterface( void * dev ) return r; } - if( MCF.ReadWord( dev, 0x1FFFF800, ® ) ) goto fail; - printf( "USER/RDPR: %08x\n", reg ); -/* if( MCF.ReadWord( dev, 0x1FFFF804, ® ) ) goto fail; - printf( "NDATA: %08x\n", reg ); - if( MCF.ReadWord( dev, 0x1FFFF808, ® ) ) goto fail; - printf( "WRPR01: %08x\n", reg ); - if( MCF.ReadWord( dev, 0x1FFFF80c, ® ) ) goto fail; - printf( "WRPR23: %08x\n", reg );*/ - if( MCF.ReadWord( dev, 0x1FFFF7E0, ® ) ) goto fail; - printf( "Flash Size: %d kB\n", (reg&0xffff) ); - if( MCF.ReadWord( dev, 0x1FFFF7E8, ® ) ) goto fail; - printf( "R32_ESIG_UNIID1: %08x\n", reg ); - if( MCF.ReadWord( dev, 0x1FFFF7EC, ® ) ) goto fail; - printf( "R32_ESIG_UNIID2: %08x\n", reg ); - if( MCF.ReadWord( dev, 0x1FFFF7F0, ® ) ) goto fail; - printf( "R32_ESIG_UNIID3: %08x\n", reg ); - - iss->statetag = STTAG( "HALT" ); + iss->statetag = STTAG( "STRT" ); return 0; -fail: - fprintf( stderr, "Error: Failed to get chip details\n" ); - return -11; } static int DefaultWriteWord( void * dev, uint32_t address_to_write, uint32_t data ) { struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal); - uint32_t rrv; - int r; - int first = 0; - - if( iss->processor_in_mode ) - { - StaticEnterResetMode( dev, iss, 0 ); - } + int ret = 0; int is_flash = 0; if( ( address_to_write & 0xff000000 ) == 0x08000000 || ( address_to_write & 0x1FFFF800 ) == 0x1FFFF000 ) @@ -571,55 +524,64 @@ static int DefaultWriteWord( void * dev, uint32_t address_to_write, uint32_t dat if( iss->statetag != STTAG( "WRSQ" ) || is_flash != iss->lastwriteflags ) { - MCF.WriteReg32( dev, DMABSTRACTAUTO, 0x00000000 ); // Disable Autoexec. - - // Different address, so we don't need to re-write all the program regs. - MCF.WriteReg32( dev, DMPROGBUF0, 0x00032283 ); // lw x5,0(x6) - MCF.WriteReg32( dev, DMPROGBUF1, 0x0072a023 ); // sw x7,0(x5) - MCF.WriteReg32( dev, DMPROGBUF2, 0x00428293 ); // addi x5, x5, 4 - MCF.WriteReg32( dev, DMPROGBUF3, 0x00532023 ); // sw x5,0(x6) - if( is_flash ) + int did_disable_req = 0; + if( iss->statetag != STTAG( "WRSQ" ) ) { - // After writing to memory, also hit up page load flag. - MCF.WriteReg32( dev, DMPROGBUF4, 0x00942023 ); // sw x9,0(x8) - MCF.WriteReg32( dev, DMPROGBUF5, 0x00100073 ); // ebreak - - MCF.WriteReg32( dev, DMDATA0, (intptr_t)&FLASH->CTLR ); - MCF.WriteReg32( dev, DMCOMMAND, 0x00231008 ); // Copy data to x8 - MCF.WriteReg32( dev, DMDATA0, CR_PAGE_PG|CR_BUF_LOAD); - MCF.WriteReg32( dev, DMCOMMAND, 0x00231009 ); // Copy data to x9 + MCF.WriteReg32( dev, DMABSTRACTAUTO, 0x00000000 ); // Disable Autoexec. + did_disable_req = 1; + // Different address, so we don't need to re-write all the program regs. + // c.lw x9,0(x10) // Get the address to write to. + // c.sw x8,0(x9) // Write to the address. + MCF.WriteReg32( dev, DMPROGBUF0, 0xc0804104 ); + // c.addi x9, 4 + // c.sw x9,0(x10) + MCF.WriteReg32( dev, DMPROGBUF1, 0xc1040491 ); + + if( iss->statetag != STTAG( "RDSQ" ) ) + { + MCF.WriteReg32( dev, DMDATA0, 0xe00000f4 ); // DATA0's location in memory. + MCF.WriteReg32( dev, DMCOMMAND, 0x0023100b ); // Copy data to x11 + MCF.WriteReg32( dev, DMDATA0, 0xe00000f8 ); // DATA1's location in memory. + MCF.WriteReg32( dev, DMCOMMAND, 0x0023100a ); // Copy data to x10 + MCF.WriteReg32( dev, DMDATA0, 0x40022010 ); //FLASH->CTLR + MCF.WriteReg32( dev, DMCOMMAND, 0x0023100c ); // Copy data to x12 + MCF.WriteReg32( dev, DMDATA0, CR_PAGE_PG|CR_BUF_LOAD); + MCF.WriteReg32( dev, DMCOMMAND, 0x0023100d ); // Copy data to x13 + } } - else + + if( iss->lastwriteflags != is_flash || iss->statetag != STTAG( "WRSQ" ) ) { - MCF.WriteReg32( dev, DMPROGBUF4, 0x00100073 ); // ebreak + // If we are doing flash, we have to ack, otherwise we don't want to ack. + if( is_flash ) + { + // After writing to memory, also hit up page load flag. + // c.sw x13,0(x12) // Acknowledge the page write. + // c.ebreak + MCF.WriteReg32( dev, DMPROGBUF2, 0x9002c214 ); + } + else + { + MCF.WriteReg32( dev, DMPROGBUF2, 0x00019002 ); // c.ebreak + } } + MCF.WriteReg32( dev, DMDATA1, address_to_write ); + MCF.WriteReg32( dev, DMDATA0, data ); - MCF.WriteReg32( dev, DMDATA0, 0xe00000f8); // Address of DATA1. - MCF.WriteReg32( dev, DMCOMMAND, 0x00231006 ); // Location of DATA1 to x6 - + if( did_disable_req ) + { + MCF.WriteReg32( dev, DMCOMMAND, 0x00271008 ); // Copy data to x8, and execute program. + MCF.WriteReg32( dev, DMABSTRACTAUTO, 1 ); // Enable Autoexec. + } iss->lastwriteflags = is_flash; - MCF.WriteReg32( dev, DMDATA1, address_to_write ); iss->statetag = STTAG( "WRSQ" ); iss->currentstateval = address_to_write; - MCF.WriteReg32( dev, DMDATA0, data ); - MCF.WriteReg32( dev, DMCOMMAND, 0x00271007 ); // Copy data to x7, and execute program. - MCF.WriteReg32( dev, DMABSTRACTAUTO, 1 ); // Enable Autoexec. - - do - { - r = MCF.ReadReg32( dev, DMABSTRACTCS, &rrv ); - if( r ) return r; - } - while( rrv & (1<<12) ); - if( (rrv >> 8 ) & 7 ) - { - fprintf( stderr, "Fault writing memory (DMABSTRACTS = %08x)\n", rrv ); - MCF.WriteReg32( dev, DMABSTRACTCS, 0x00000700 ); - } + if( is_flash ) + ret |= MCF.WaitForDoneOp( dev ); } else { @@ -636,18 +598,7 @@ static int DefaultWriteWord( void * dev, uint32_t address_to_write, uint32_t dat } else { - do - { - r = MCF.ReadReg32( dev, DMABSTRACTCS, &rrv ); - if( r ) return r; - } - while( rrv & (1<<12) ); - if( (rrv >> 8 ) & 7 ) - { - fprintf( stderr, "Fault writing memory (DMABSTRACTS = %08x)\n", rrv ); - rrv &= 0xfffff8ff; - MCF.WriteReg32( dev, DMABSTRACTCS, rrv ); - } + ret |= MCF.WaitForDoneOp( dev ); } } @@ -657,22 +608,18 @@ static int DefaultWriteWord( void * dev, uint32_t address_to_write, uint32_t dat return 0; } + int DefaultWriteBinaryBlob( void * dev, uint32_t address_to_write, uint32_t blob_size, uint8_t * blob ) { + // NOTE IF YOU FIX SOMETHING IN THIS FUNCTION PLEASE ALSO UPDATE THE PROGRAMMERS. + // this is only fallback functionality for really realy basic programmers. + uint32_t rw; - int timeout = 0; struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal); int is_flash = 0; - uint32_t lastgroup = -1; if( blob_size == 0 ) return 0; - if( iss->processor_in_mode ) - { - StaticEnterResetMode( dev, iss, 0 ); - } - - if( (address_to_write & 0xff000000) == 0x08000000 || (address_to_write & 0xff000000) == 0x00000000 ) { // Need to unlock flash. @@ -698,7 +645,6 @@ int DefaultWriteBinaryBlob( void * dev, uint32_t address_to_write, uint32_t blob uint32_t wp = address_to_write; uint32_t ew = wp + blob_size; int group = -1; - lastgroup = -1; while( wp < ew ) { @@ -725,9 +671,7 @@ int DefaultWriteBinaryBlob( void * dev, uint32_t address_to_write, uint32_t blob } MCF.WriteWord( dev, (intptr_t)&FLASH->ADDR, group ); MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_PAGE_PG|CR_STRT_Set ); - StaticWaitForFlash( dev ); - - lastgroup = group; + if( MCF.WaitForFlash ) MCF.WaitForFlash( dev ); } else { @@ -745,7 +689,7 @@ int DefaultWriteBinaryBlob( void * dev, uint32_t address_to_write, uint32_t blob if( is_flash ) { - if( StaticWaitForFlash( dev ) ) goto timedout; + if( MCF.WaitForFlash && MCF.WaitForFlash( dev ) ) goto timedout; } return 0; timedout: @@ -756,53 +700,45 @@ timedout: static int DefaultReadWord( void * dev, uint32_t address_to_read, uint32_t * data ) { struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal); - uint32_t rrv = 0; - int r; - int first = 0; - - if( iss->processor_in_mode ) - { - StaticEnterResetMode( dev, iss, 0 ); - } if( iss->statetag != STTAG( "RDSQ" ) || address_to_read != iss->currentstateval ) { - MCF.WriteReg32( dev, DMABSTRACTAUTO, 0 ); // Disable Autoexec. - MCF.WriteReg32( dev, DMPROGBUF0, 0x0002a303 ); // lw x6,0(x5) - MCF.WriteReg32( dev, DMPROGBUF1, 0x00428293 ); // addi x5, x5, 4 - MCF.WriteReg32( dev, DMPROGBUF2, 0x0065a023 ); // sw x6,0(x11) // Write back to DATA0 - MCF.WriteReg32( dev, DMPROGBUF3, 0x00100073 ); // ebreak - - MCF.WriteReg32( dev, DMDATA0, address_to_read ); - MCF.WriteReg32( dev, DMCOMMAND, 0x00231005 ); // Copy data to x5 + if( iss->statetag != STTAG( "RDSQ" ) ) + { + MCF.WriteReg32( dev, DMABSTRACTAUTO, 0 ); // Disable Autoexec. - MCF.WriteReg32( dev, DMDATA0, 0xe00000f4 ); // DATA0's location in memory. - MCF.WriteReg32( dev, DMCOMMAND, 0x0023100b ); // Copy data to x11 + // c.lw x8,0(x10) // Pull the address from DATA1 + // c.lw x9,0(x8) // Read the data at that location. + MCF.WriteReg32( dev, DMPROGBUF0, 0x40044100 ); + // c.addi x8, 4 + // c.sw x9, 0(x11) // Write back to DATA0 + MCF.WriteReg32( dev, DMPROGBUF1, 0xc1840411 ); + // c.sw x8, 0(x10) // Write addy to DATA1 + // c.ebreak + MCF.WriteReg32( dev, DMPROGBUF2, 0x9002c100 ); + + if( iss->statetag != STTAG( "WRSQ" ) ) + { + MCF.WriteReg32( dev, DMDATA0, 0xe00000f4 ); // DATA0's location in memory. + MCF.WriteReg32( dev, DMCOMMAND, 0x0023100b ); // Copy data to x11 + MCF.WriteReg32( dev, DMDATA0, 0xe00000f8 ); // DATA1's location in memory. + MCF.WriteReg32( dev, DMCOMMAND, 0x0023100a ); // Copy data to x10 + MCF.WriteReg32( dev, DMDATA0, 0x40022010 ); //FLASH->CTLR + MCF.WriteReg32( dev, DMCOMMAND, 0x0023100c ); // Copy data to x12 + MCF.WriteReg32( dev, DMDATA0, CR_PAGE_PG|CR_BUF_LOAD); + MCF.WriteReg32( dev, DMCOMMAND, 0x0023100d ); // Copy data to x13 + printf( "REGS CONNED B\n" ); + } + MCF.WriteReg32( dev, DMABSTRACTAUTO, 1 ); // Enable Autoexec. + } + MCF.WriteReg32( dev, DMDATA1, address_to_read ); MCF.WriteReg32( dev, DMCOMMAND, 0x00241000 ); // Only execute. - MCF.WriteReg32( dev, DMABSTRACTAUTO, 1 ); // Enable Autoexec. - do - { - r = MCF.ReadReg32( dev, DMABSTRACTCS, &rrv ); - if( r ) return r; - } - while( rrv & (1<<12) ); - first = 1; iss->statetag = STTAG( "RDSQ" ); iss->currentstateval = address_to_read; - do - { - r = MCF.ReadReg32( dev, DMABSTRACTCS, &rrv ); - if( r ) return r; - } - while( rrv & (1<<12) ); - - if( (rrv >> 8 ) & 7 ) - { - fprintf( stderr, "Fault reading memory (DMABSTRACTS = %08x)\n", rrv ); - } + MCF.WaitForDoneOp( dev ); } iss->currentstateval += 4; @@ -839,12 +775,6 @@ int DefaultErase( void * dev, uint32_t address, uint32_t length, int type ) { struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal); uint32_t rw; - uint32_t timeout = 0; - - if( iss->processor_in_mode ) - { - StaticEnterResetMode( dev, iss, 0 ); - } if( !iss->flash_unlocked ) { @@ -860,7 +790,7 @@ int DefaultErase( void * dev, uint32_t address, uint32_t length, int type ) MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, 0 ); MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, FLASH_CTLR_MER ); MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_STRT_Set|FLASH_CTLR_MER ); - if( StaticWaitForFlash( dev ) ) return -11; + if( MCF.WaitForFlash && MCF.WaitForFlash( dev ) ) return -11; MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, 0 ); } else @@ -880,24 +810,15 @@ int DefaultErase( void * dev, uint32_t address, uint32_t length, int type ) // Step 6: Set the STAT bit of FLASH_CTLR register to '1' to initiate a fast page erase (64 bytes) action. MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_STRT_Set|CR_PAGE_ER ); - if( StaticWaitForFlash( dev ) ) return -99; + if( MCF.WaitForFlash && MCF.WaitForFlash( dev ) ) return -99; chunk_to_erase+=64; } } return 0; -timedout: - return -6; } int DefaultReadBinaryBlob( void * dev, uint32_t address_to_read_from, uint32_t read_size, uint8_t * blob ) { - struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal); - - if( iss->processor_in_mode ) - { - StaticEnterResetMode( dev, iss, 0 ); - } - uint32_t rpos = address_to_read_from; uint32_t rend = address_to_read_from + read_size; while( rpos < rend ) @@ -911,13 +832,34 @@ int DefaultReadBinaryBlob( void * dev, uint32_t address_to_read_from, uint32_t r blob += 4; rpos += 4; } + return 0; } static int DefaultHaltMode( void * dev, int mode ) { struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal); - StaticEnterResetMode( dev, iss, mode ); + switch ( mode ) + { + case 0: + MCF.WriteReg32( dev, DMCONTROL, 0x80000001 ); // Make the debug module work properly. + MCF.WriteReg32( dev, DMCONTROL, 0x80000001 ); // Initiate a halt request. + MCF.WriteReg32( dev, DMCONTROL, 0x00000001 ); // Clear Halt Request. + MCF.FlushLLCommands( dev ); + break; + case 1: + MCF.WriteReg32( dev, DMCONTROL, 0x80000001 ); // Make the debug module work properly. + MCF.WriteReg32( dev, DMCONTROL, 0x80000001 ); // Initiate a halt request. + MCF.WriteReg32( dev, DMCONTROL, 0x80000003 ); // Reboot. + MCF.WriteReg32( dev, DMCONTROL, 0x40000001 ); // resumereq + MCF.FlushLLCommands( dev ); + break; + case 2: + MCF.WriteReg32( dev, DMCONTROL, 0x40000001 ); // resumereq + MCF.FlushLLCommands( dev ); + break; + } + iss->processor_in_mode = mode; return 0; } @@ -942,13 +884,14 @@ int DefaultPollTerminal( void * dev, uint8_t * buffer, int maxlen ) { int ret = 0; int num_printf_chars = (rr & 0x3f)-4; // Actaully can't be more than 32. + if( num_printf_chars > 0 && num_printf_chars <= 7) { if( num_printf_chars > 3 ) { uint32_t r2; r = MCF.ReadReg32( dev, DMDATA1, &r2 ); - memcpy( buffer+4, &r2, num_printf_chars - 3 ); + memcpy( buffer+3, &r2, num_printf_chars - 3 ); } int firstrem = num_printf_chars; if( firstrem > 3 ) firstrem = 3; @@ -964,6 +907,32 @@ int DefaultPollTerminal( void * dev, uint8_t * buffer, int maxlen ) return 0; } } +int DefaultPrintChipInfo( void * dev ) +{ + uint32_t reg; + MCF.HaltMode( dev, 0 ); + + if( MCF.ReadWord( dev, 0x1FFFF800, ® ) ) goto fail; + printf( "USER/RDPR: %08x\n", reg ); +/* if( MCF.ReadWord( dev, 0x1FFFF804, ® ) ) goto fail; + printf( "NDATA: %08x\n", reg ); + if( MCF.ReadWord( dev, 0x1FFFF808, ® ) ) goto fail; + printf( "WRPR01: %08x\n", reg ); + if( MCF.ReadWord( dev, 0x1FFFF80c, ® ) ) goto fail; + printf( "WRPR23: %08x\n", reg );*/ + if( MCF.ReadWord( dev, 0x1FFFF7E0, ® ) ) goto fail; + printf( "Flash Size: %d kB\n", (reg&0xffff) ); + if( MCF.ReadWord( dev, 0x1FFFF7E8, ® ) ) goto fail; + printf( "R32_ESIG_UNIID1: %08x\n", reg ); + if( MCF.ReadWord( dev, 0x1FFFF7EC, ® ) ) goto fail; + printf( "R32_ESIG_UNIID2: %08x\n", reg ); + if( MCF.ReadWord( dev, 0x1FFFF7F0, ® ) ) goto fail; + printf( "R32_ESIG_UNIID3: %08x\n", reg ); + return 0; +fail: + fprintf( stderr, "Error: Failed to get chip details\n" ); + return -11; +} int SetupAutomaticHighLevelFunctions( void * dev ) { @@ -989,24 +958,26 @@ int SetupAutomaticHighLevelFunctions( void * dev ) MCF.HaltMode = DefaultHaltMode; if( !MCF.PollTerminal ) MCF.PollTerminal = DefaultPollTerminal; - + if( !MCF.WaitForFlash ) + MCF.WaitForFlash = DefaultWaitForFlash; + if( !MCF.WaitForDoneOp ) + MCF.WaitForDoneOp = DefaultWaitForDoneOp; + if( !MCF.PrintChipInfo ) + MCF.PrintChipInfo = DefaultPrintChipInfo; struct InternalState * iss = malloc( sizeof( struct InternalState ) ); iss->statetag = 0; iss->currentstateval = 0; ((struct ProgrammerStructBase*)dev)->internal = iss; + return 0; } - - void TestFunction(void * dev ) { - struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal); - uint32_t rv; int r; MCF.WriteReg32( dev, DMCONTROL, 0x80000001 ); // Make the debug module work properly. diff --git a/minichlink/minichlink.h b/minichlink/minichlink.h index bd329fd..0b4957c 100644 --- a/minichlink/minichlink.h +++ b/minichlink/minichlink.h @@ -34,6 +34,11 @@ struct MiniChlinkFunctions int (*WriteWord)( void * dev, uint32_t address_to_write, uint32_t data ); // Flags = 1 for "doing a fast FLASH write." int (*ReadWord)( void * dev, uint32_t address_to_read, uint32_t * data ); + int (*WaitForFlash)( void * dev ); + int (*WaitForDoneOp)( void * dev ); + + int (*PrintChipInfo)( void * dev ); + // TODO: What about 64-byte block-writes? // TODO: What about 64-byte block-reads? // TODO: What about byte read/write? @@ -54,9 +59,11 @@ struct MiniChlinkFunctions // Convert a 4-character string to an int. #define STTAG( x ) (*((uint32_t*)(x))) +struct InternalState; + struct ProgrammerStructBase { - void * internal; + struct InternalState * internal; // You can put other things here. }; diff --git a/minichlink/pgm-esp32s2-ch32xx.c b/minichlink/pgm-esp32s2-ch32xx.c index 9021f37..21d5c93 100644 --- a/minichlink/pgm-esp32s2-ch32xx.c +++ b/minichlink/pgm-esp32s2-ch32xx.c @@ -57,6 +57,7 @@ static int ESPWriteReg32( void * dev, uint8_t reg_7_bit, uint32_t value ) Write1( eps, (reg_7_bit<<1) | 1 ); Write4LE( eps, value ); + return 0; } int ESPReadReg32( void * dev, uint8_t reg_7_bit, uint32_t * commandresp ) @@ -66,7 +67,7 @@ int ESPReadReg32( void * dev, uint8_t reg_7_bit, uint32_t * commandresp ) Write1( eps, (reg_7_bit<<1) | 0 ); - int len = ESPFlushLLCommands( eps ); + ESPFlushLLCommands( eps ); if( eps->replylen < 6 ) { @@ -129,6 +130,7 @@ int ESPControl3v3( void * dev, int bOn ) Write2LE( eps, 0x03fe ); else Write2LE( eps, 0x02fe ); + return 0; } static int ESPDelayUS( void * dev, int microseconds ) @@ -139,6 +141,7 @@ static int ESPDelayUS( void * dev, int microseconds ) Write2LE( eps, 0x04fe ); Write4LE( eps, microseconds ); + return 0; } @@ -147,6 +150,7 @@ int ESPExit( void * dev ) struct ESP32ProgrammerStruct * eps = (struct ESP32ProgrammerStruct *)dev; hid_close( eps->hd ); free( eps ); + return 0; } void * TryInit_ESP32S2CHFUN() diff --git a/minichlink/pgm-wch-linke.c b/minichlink/pgm-wch-linke.c index c0342e7..5fa2ade 100644 --- a/minichlink/pgm-wch-linke.c +++ b/minichlink/pgm-wch-linke.c @@ -16,7 +16,7 @@ struct LinkEProgrammerStruct }; #define WCHTIMEOUT 5000 -#define WCHCHECK(x) if( status = x ) { fprintf( stderr, "Bad USB Operation on " __FILE__ ":%d (%d)\n", __LINE__, status ); exit( status ); } +#define WCHCHECK(x) if( (status = x) ) { fprintf( stderr, "Bad USB Operation on " __FILE__ ":%d (%d)\n", __LINE__, status ); exit( status ); } const uint8_t * bootloader = (const uint8_t*) "\x21\x11\x22\xca\x26\xc8\x93\x77\x15\x00\x99\xcf\xb7\x06\x67\x45" \ @@ -54,14 +54,15 @@ const uint8_t * bootloader = (const uint8_t*) int bootloader_len = 512; -void wch_link_command( libusb_device_handle * devh, const uint8_t * command, int commandlen, int * transferred, uint8_t * reply, int replymax ) +void wch_link_command( libusb_device_handle * devh, const void * command_v, int commandlen, int * transferred, uint8_t * reply, int replymax ) { + uint8_t * command = (uint8_t*)command_v; uint8_t buffer[1024]; int got_to_recv = 0; int status; int transferred_local; if( !transferred ) transferred = &transferred_local; - status = libusb_bulk_transfer( devh, 0x01, (char*)command, commandlen, transferred, WCHTIMEOUT ); + status = libusb_bulk_transfer( devh, 0x01, command, commandlen, transferred, WCHTIMEOUT ); if( status ) goto sendfail; got_to_recv = 1; @@ -70,7 +71,7 @@ void wch_link_command( libusb_device_handle * devh, const uint8_t * command, int reply = buffer; replymax = sizeof( buffer ); } - status = libusb_bulk_transfer( devh, 0x81, (char*)reply, replymax, transferred, WCHTIMEOUT ); + status = libusb_bulk_transfer( devh, 0x81, reply, replymax, transferred, WCHTIMEOUT ); if( status ) goto sendfail; return; sendfail: @@ -111,7 +112,6 @@ static inline libusb_device_handle * wch_link_base_setup( int inhibit_startup ) libusb_device *found = NULL; ssize_t cnt = libusb_get_device_list(ctx, &list); ssize_t i = 0; - int err = 0; for (i = 0; i < cnt; i++) { libusb_device *device = list[i]; struct libusb_device_descriptor desc; @@ -148,7 +148,7 @@ static int LESetupInterface( void * d ) uint32_t transferred = 0; // Place part into reset. - wch_link_command( dev, "\x81\x0d\x01\x01", 4, &transferred, rbuff, 1024 ); // Reply is: "\x82\x0d\x04\x02\x08\x02\x00" + wch_link_command( dev, "\x81\x0d\x01\x01", 4, (int*)&transferred, rbuff, 1024 ); // Reply is: "\x82\x0d\x04\x02\x08\x02\x00" // 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 @@ -156,7 +156,7 @@ static int LESetupInterface( void * d ) // This puts the processor on hold to allow the debugger to run. wch_link_command( dev, "\x81\x0d\x01\x02", 4, 0, 0, 0 ); // Reply: Ignored, 820d050900300500 - wch_link_command( dev, "\x81\x11\x01\x09", 4, &transferred, rbuff, 1024 ); // Reply: Chip ID + Other data (see below) + wch_link_command( dev, "\x81\x11\x01\x09", 4, (int*)&transferred, rbuff, 1024 ); // Reply: Chip ID + Other data (see below) if( transferred != 20 ) { fprintf( stderr, "Error: could not get part status\n" ); @@ -197,6 +197,7 @@ static int LEUnbrick( void * dev ) printf( "Sending unbrick\n" ); wch_link_command( (libusb_device_handle *)dev, "\x81\x0d\x01\x0f\x09", 5, 0, 0, 0 ); printf( "Done unbrick\n" ); + return 0; } static int LEHaltMode( void * d, int mode ) @@ -232,6 +233,7 @@ static int LEConfigureNRSTAsGPIO( void * d, int one_if_yes_gpio ) { wch_link_multicommands( (libusb_device_handle *)dev, 2, 11, "\x81\x06\x08\x02\xf7\xff\xff\xff\xff\xff\xff", 4, "\x81\x0b\x01\x01" ); } + return 0; } static int LEReadBinaryBlob( void * d, uint32_t offset, uint32_t amount, uint8_t * readbuff ) @@ -359,6 +361,7 @@ int LEExit( void * d ) libusb_device_handle * dev = ((struct LinkEProgrammerStruct*)d)->devh; wch_link_command( (libusb_device_handle *)dev, "\x81\x0d\x01\xff", 4, 0, 0, 0); + return 0; } void * TryInit_WCHLinkE() -- GitLab