diff --git a/examples/debugprintfdemo/debugprintfdemo.c b/examples/debugprintfdemo/debugprintfdemo.c index 27ea9245ca67e6997d46bf89588c66c378faf05b..f5a801d6ae39a298e64ce9485eb7b4cd74df5f6a 100644 --- a/examples/debugprintfdemo/debugprintfdemo.c +++ b/examples/debugprintfdemo/debugprintfdemo.c @@ -31,6 +31,6 @@ int main() //Delay_Ms( 50 ); GPIOD->BSHR = (1<<16) | ( 1<<(4+16) ); // Turn off GPIOD0 //Delay_Ms( 50 ); - printf( "%d\n", count++ ); + printf( "+%d\n", count++ ); } } diff --git a/minichlink/minichlink.c b/minichlink/minichlink.c index ea25796fa1d1745485c34de02bad24ba716aab8d..8ecc3b1d8f1909ff3f2924bc3f7f1ad5343e0bc2 100644 --- a/minichlink/minichlink.c +++ b/minichlink/minichlink.c @@ -13,6 +13,8 @@ static int64_t SimpleReadNumberInt( const char * number, int64_t defaultNumber ); static int64_t StringToMemoryAddress( const char * number ); +static void StaticUpdatePROGBUFRegs( void * dev ); + void TestFunction(void * v ); struct MiniChlinkFunctions MCF; @@ -38,7 +40,9 @@ int main( int argc, char ** argv ) int status; int must_be_end = 0; - if( MCF.SetupInterface ) + int doing_unblock = (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'u' ); + + if( !doing_unblock && MCF.SetupInterface ) { if( MCF.SetupInterface( dev ) < 0 ) { @@ -488,7 +492,7 @@ int DefaultSetupInterface( void * dev ) MCF.WriteReg32( dev, DMCFGR, 0x5aa50000 | (1<<10) ); // CFGR (1<<10 == Allow output from slave) 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. + // Read back chip status. This is really basic. uint32_t reg = 0; int r = MCF.ReadReg32( dev, DMSTATUS, ® ); if( r >= 0 ) @@ -510,6 +514,18 @@ int DefaultSetupInterface( void * dev ) return 0; } +static void StaticUpdatePROGBUFRegs( void * dev ) +{ + MCF.WriteReg32( dev, DMDATA0, 0xe00000f4 ); // DATA0's location in memory. + MCF.WriteReg32( dev, DMCOMMAND, 0x0023100a ); // Copy data to x10 + MCF.WriteReg32( dev, DMDATA0, 0xe00000f8 ); // DATA1's location in memory. + MCF.WriteReg32( dev, DMCOMMAND, 0x0023100b ); // Copy data to x11 + 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 +} + static int DefaultWriteWord( void * dev, uint32_t address_to_write, uint32_t data ) { struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal); @@ -539,14 +555,7 @@ static int DefaultWriteWord( void * dev, uint32_t address_to_write, uint32_t dat if( iss->statetag != STTAG( "RDSQ" ) ) { - MCF.WriteReg32( dev, DMDATA0, 0xe00000f4 ); // DATA0's location in memory. - MCF.WriteReg32( dev, DMCOMMAND, 0x0023100a ); // Copy data to x10 - MCF.WriteReg32( dev, DMDATA0, 0xe00000f8 ); // DATA1's location in memory. - MCF.WriteReg32( dev, DMCOMMAND, 0x0023100b ); // Copy data to x11 - 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 + StaticUpdatePROGBUFRegs( dev ); } } @@ -594,7 +603,9 @@ static int DefaultWriteWord( void * dev, uint32_t address_to_write, uint32_t dat MCF.WriteReg32( dev, DMDATA0, data ); if( is_flash ) { - MCF.DelayUS( dev, 100 ); + // XXX TODO: This likely can be a very short delay. + // XXX POSSIBLE OPTIMIZATION REINVESTIGATE. + ret |= MCF.WaitForDoneOp( dev ); } else { @@ -621,6 +632,24 @@ int DefaultWriteBinaryBlob( void * dev, uint32_t address_to_write, uint32_t blob if( blob_size == 0 ) return 0; if( (address_to_write & 0xff000000) == 0x08000000 || (address_to_write & 0xff000000) == 0x00000000 ) + is_flash = 1; + + if( is_flash && MCF.BlockWrite64 && ( address_to_write & 0x3f ) == 0 ) + { + int i; + for( i = 0; i < blob_size; i+= 64 ) + { + int r = MCF.BlockWrite64( dev, address_to_write + i, blob + i ); + if( r ) + { + fprintf( stderr, "Error writing block at memory %08x\n", address_to_write ); + return r; + } + } + return 0; + } + + if( is_flash ) { // Need to unlock flash. // Flash reg base = 0x40022000, @@ -638,7 +667,7 @@ int DefaultWriteBinaryBlob( void * dev, uint32_t address_to_write, uint32_t blob printf( "Erasing TO %08x %08x\n", address_to_write, blob_size ); MCF.Erase( dev, address_to_write, blob_size, 0 ); } - + printf( "Done\n" ); MCF.FlushLLCommands( dev ); MCF.DelayUS( dev, 100 ); // Why do we need this? @@ -651,8 +680,8 @@ int DefaultWriteBinaryBlob( void * dev, uint32_t address_to_write, uint32_t blob if( is_flash ) { group = (wp & 0xffffffc0); - MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_PAGE_PG ); // THIS IS REQUIRED. - MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_BUF_RST | CR_PAGE_PG ); + MCF.WriteWord( dev, 0x40022010, CR_PAGE_PG ); // THIS IS REQUIRED, (intptr_t)&FLASH->CTLR = 0x40022010 + MCF.WriteWord( dev, 0x40022010, CR_BUF_RST | CR_PAGE_PG ); // (intptr_t)&FLASH->CTLR = 0x40022010 int j; for( j = 0; j < 16; j++ ) @@ -669,8 +698,8 @@ int DefaultWriteBinaryBlob( void * dev, uint32_t address_to_write, uint32_t blob MCF.WriteWord( dev, wp, data ); wp += 4; } - MCF.WriteWord( dev, (intptr_t)&FLASH->ADDR, group ); - MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_PAGE_PG|CR_STRT_Set ); + MCF.WriteWord( dev, 0x40022014, group ); //0x40022014 -> FLASH->ADDR + MCF.WriteWord( dev, 0x40022010, CR_PAGE_PG|CR_STRT_Set ); // 0x40022010 -> FLASH->CTLR if( MCF.WaitForFlash ) MCF.WaitForFlash( dev ); } else @@ -681,7 +710,6 @@ int DefaultWriteBinaryBlob( void * dev, uint32_t address_to_write, uint32_t blob data = ((uint32_t*)blob)[index/4]; else if( (int32_t)(blob_size - index) > 0 ) memcpy( &data, &blob[index], blob_size - index ); - printf( "WRITING %08x => %08x\n", data, wp ); MCF.WriteWord( dev, wp, data ); wp += 4; } @@ -719,15 +747,7 @@ static int DefaultReadWord( void * dev, uint32_t address_to_read, uint32_t * dat if( iss->statetag != STTAG( "WRSQ" ) ) { - MCF.WriteReg32( dev, DMDATA0, 0xe00000f4 ); // DATA0's location in memory. - MCF.WriteReg32( dev, DMCOMMAND, 0x0023100a ); // Copy data to x10 - MCF.WriteReg32( dev, DMDATA0, 0xe00000f8 ); // DATA1's location in memory. - MCF.WriteReg32( dev, DMCOMMAND, 0x0023100b ); // Copy data to x11 - 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" ); + StaticUpdatePROGBUFRegs( dev ); } MCF.WriteReg32( dev, DMABSTRACTAUTO, 1 ); // Enable Autoexec. } @@ -749,18 +769,18 @@ static int DefaultReadWord( void * dev, uint32_t address_to_read, uint32_t * dat static int StaticUnlockFlash( void * dev, struct InternalState * iss ) { uint32_t rw; - MCF.ReadWord( dev, (intptr_t)&FLASH->CTLR, &rw ); + MCF.ReadWord( dev, 0x40022010, &rw ); // FLASH->CTLR = 0x40022010 if( rw & 0x8080 ) { - MCF.WriteWord( dev, (intptr_t)&FLASH->KEYR, 0x45670123 ); - MCF.WriteWord( dev, (intptr_t)&FLASH->KEYR, 0xCDEF89AB ); - MCF.WriteWord( dev, (intptr_t)&FLASH->OBKEYR, 0x45670123 ); - MCF.WriteWord( dev, (intptr_t)&FLASH->OBKEYR, 0xCDEF89AB ); - MCF.WriteWord( dev, (intptr_t)&FLASH->MODEKEYR, 0x45670123 ); - MCF.WriteWord( dev, (intptr_t)&FLASH->MODEKEYR, 0xCDEF89AB ); + MCF.WriteWord( dev, 0x40022004, 0x45670123 ); // FLASH->KEYR = 0x40022004 + MCF.WriteWord( dev, 0x40022004, 0xCDEF89AB ); + MCF.WriteWord( dev, 0x40022008, 0x45670123 ); // OBKEYR = 0x40022008 + MCF.WriteWord( dev, 0x40022008, 0xCDEF89AB ); + MCF.WriteWord( dev, 0x40022024, 0x45670123 ); // MODEKEYR = 0x40022024 + MCF.WriteWord( dev, 0x40022024, 0xCDEF89AB ); - MCF.ReadWord( dev, (intptr_t)&FLASH->CTLR, &rw ); + MCF.ReadWord( dev, 0x40022010, &rw ); // FLASH->CTLR = 0x40022010 if( rw & 0x8080 ) { fprintf( stderr, "Error: Flash is not unlocked (CTLR = %08x)\n", rw ); @@ -914,6 +934,44 @@ int DefaultPollTerminal( void * dev, uint8_t * buffer, int maxlen ) return 0; } } + +int DefaultUnbrick( void * dev ) +{ + printf( "Entering Unbrick Mode\n" ); + MCF.Control3v3( dev, 0 ); + MCF.DelayUS( dev, 65535 ); + MCF.FlushLLCommands( dev ); + MCF.Control3v3( dev, 1 ); + MCF.FlushLLCommands( dev ); + printf( "Connection starting\n" ); + int timeout = 0; + int max_timeout = 500; + uint32_t ds = 0; + for( timeout = 0; timeout < max_timeout; timeout++ ) + { + if( MCF.PerformSongAndDance ) + { + MCF.PerformSongAndDance( dev ); + } + MCF.DelayUS( dev, 10 ); + 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.ReadReg32( dev, DMSTATUS, &ds ); + MCF.FlushLLCommands( dev ); + if( ds != 0xffffffff && ds != 0x00000000 ) break; + } + if( timeout == max_timeout ) + { + printf( "Timed out trying to unbrick\n" ); + return -5; + } + printf( "Timeout: %d DMSTATUS: %08x\n", timeout, ds ); + MCF.Erase( dev, 0, 0, 1); + MCF.FlushLLCommands( dev ); + return -5; +} + int DefaultPrintChipInfo( void * dev ) { uint32_t reg; @@ -971,6 +1029,8 @@ int SetupAutomaticHighLevelFunctions( void * dev ) MCF.WaitForDoneOp = DefaultWaitForDoneOp; if( !MCF.PrintChipInfo ) MCF.PrintChipInfo = DefaultPrintChipInfo; + if( !MCF.Unbrick ) + MCF.Unbrick = DefaultUnbrick; struct InternalState * iss = malloc( sizeof( struct InternalState ) ); iss->statetag = 0; diff --git a/minichlink/minichlink.h b/minichlink/minichlink.h index 0b4957c77e751fca250156eb52594e9bdfc2f8eb..de5302a76dd9847e9ea4c7a8d4b823f4668069a0 100644 --- a/minichlink/minichlink.h +++ b/minichlink/minichlink.h @@ -39,7 +39,9 @@ struct MiniChlinkFunctions int (*PrintChipInfo)( void * dev ); - // TODO: What about 64-byte block-writes? + // Geared for flash, but could be anything. + int (*BlockWrite64)( void * dev, uint32_t address_to_write, uint8_t * data ); + // TODO: What about 64-byte block-reads? // TODO: What about byte read/write? // TODO: What about half read/write? @@ -48,6 +50,8 @@ struct MiniChlinkFunctions // Returns negative if error. // Returns 0 if no text waiting. int (*PollTerminal)( void * dev, uint8_t * buffer, int maxlen ); + + int (*PerformSongAndDance)( void * dev ); }; /** If you are writing a driver, the minimal number of functions you can implement are: diff --git a/minichlink/pgm-esp32s2-ch32xx.c b/minichlink/pgm-esp32s2-ch32xx.c index 21d5c9348239870d7189204a9cae938fecc0acb9..05252b623836e998b4a5137defcfd94b0d45780b 100644 --- a/minichlink/pgm-esp32s2-ch32xx.c +++ b/minichlink/pgm-esp32s2-ch32xx.c @@ -53,6 +53,9 @@ static inline void Write1( struct ESP32ProgrammerStruct * e, uint8_t val ) static int ESPWriteReg32( void * dev, uint8_t reg_7_bit, uint32_t value ) { struct ESP32ProgrammerStruct * eps = (struct ESP32ProgrammerStruct *)dev; +// printf( "WriteReg: %02x -> %08x\n", reg_7_bit, value ); + + if( SRemain( eps ) < 5 ) ESPFlushLLCommands( eps ); Write1( eps, (reg_7_bit<<1) | 1 ); @@ -64,11 +67,12 @@ int ESPReadReg32( void * dev, uint8_t reg_7_bit, uint32_t * commandresp ) { struct ESP32ProgrammerStruct * eps = (struct ESP32ProgrammerStruct *)dev; ESPFlushLLCommands( eps ); - Write1( eps, (reg_7_bit<<1) | 0 ); ESPFlushLLCommands( eps ); +// printf( "ReadReg: %02x -> %d\n", reg_7_bit,eps->replylen ); + if( eps->replylen < 6 ) { return -9; @@ -106,6 +110,17 @@ int ESPFlushLLCommands( void * dev ) retry: eps->reply[0] = 0xad; // Key report ID r = hid_get_feature_report( eps->hd, eps->reply, sizeof( eps->reply ) ); +/* + int i; + printf( "RESP: %d\n",eps->reply[0] ); + + for( i = 0; i < eps->reply[0]; i++ ) + { + printf( "%02x ", eps->reply[i+1] ); + if( (i % 16) == 15 ) printf( "\n" ); + } + printf( "\n" );*/ + if( eps->reply[0] == 0xff ) goto retry; //printf( ">:::%d: %02x %02x %02x %02x %02x %02x\n", eps->replylen, eps->reply[0], eps->reply[1], eps->reply[2], eps->reply[3], eps->reply[4], eps->reply[5] ); if( r < 0 ) @@ -113,8 +128,7 @@ retry: fprintf( stderr, "Error: Got error %d when sending hid feature report.\n", r ); return r; } - - eps->replylen = r; + eps->replylen = eps->reply[0] + 1; // Include the header byte. return r; } @@ -133,6 +147,44 @@ int ESPControl3v3( void * dev, int bOn ) return 0; } + +int ESPReadWord( void * dev, uint32_t address_to_read, uint32_t * data ) +{ + struct ESP32ProgrammerStruct * eps = (struct ESP32ProgrammerStruct *)dev; +//printf( "READ: %08x\n", address_to_read ); + if( SRemain( eps ) < 6 ) + ESPFlushLLCommands( eps ); + + Write2LE( eps, 0x09fe ); + Write4LE( eps, address_to_read ); + ESPFlushLLCommands( eps ); + +// printf( "Got: %d\n", eps->replylen ); + if( eps->replylen < 5 ) + { + return -9; + } + int tail = eps->replylen-5; + memcpy( data, eps->reply + tail + 1, 4 ); +// printf( "Read Mem: %08x => %08x\n", address_to_read, *data ); + return eps->reply[tail]; +} + +int ESPWriteWord( void * dev, uint32_t address_to_write, uint32_t data ) +{ + struct ESP32ProgrammerStruct * eps = (struct ESP32ProgrammerStruct *)dev; + +//printf( "WRITE: %08x\n", address_to_write ); + + if( SRemain( eps ) < 10 ) + ESPFlushLLCommands( eps ); + + Write2LE( eps, 0x08fe ); + Write4LE( eps, address_to_write ); + Write4LE( eps, data ); + return 0; +} + static int ESPDelayUS( void * dev, int microseconds ) { struct ESP32ProgrammerStruct * eps = (struct ESP32ProgrammerStruct *)dev; @@ -145,6 +197,25 @@ static int ESPDelayUS( void * dev, int microseconds ) } +static int ESPWaitForFlash( void * dev ) +{ + struct ESP32ProgrammerStruct * eps = (struct ESP32ProgrammerStruct *)dev; + if( SRemain( eps ) < 2 ) + ESPFlushLLCommands( eps ); + Write2LE( eps, 0x06fe ); + return 0; +} + +static int ESPWaitForDoneOp( void * dev ) +{ + struct ESP32ProgrammerStruct * eps = (struct ESP32ProgrammerStruct *)dev; + if( SRemain( eps ) < 2 ) + ESPFlushLLCommands( dev ); + Write2LE( eps, 0x07fe ); + return 0; +} + + int ESPExit( void * dev ) { struct ESP32ProgrammerStruct * eps = (struct ESP32ProgrammerStruct *)dev; @@ -153,6 +224,30 @@ int ESPExit( void * dev ) return 0; } +int ESPBlockWrite64( void * dev, uint32_t address_to_write, uint8_t * data ) +{ + struct ESP32ProgrammerStruct * eps = (struct ESP32ProgrammerStruct *)dev; + ESPFlushLLCommands( dev ); + Write2LE( eps, 0x0bfe ); + Write4LE( eps, address_to_write ); + int i; + for( i = 0; i < 64; i++ ) Write1( eps, data[i] ); + do + { + ESPFlushLLCommands( dev ); + } while( eps->replylen < 2 ); + return eps->reply[1]; +} + +int ESPPerformSongAndDance( void * dev ) +{ + struct ESP32ProgrammerStruct * eps = (struct ESP32ProgrammerStruct *)dev; + Write2LE( eps, 0x01fe ); + ESPFlushLLCommands( dev ); + return 0; +} + + void * TryInit_ESP32S2CHFUN() { #define VID 0x303a @@ -174,6 +269,20 @@ void * TryInit_ESP32S2CHFUN() MCF.Control3v3 = ESPControl3v3; MCF.Exit = ESPExit; + // These are optional. Disabling these is a good mechanismto make sure the core functions still work. + MCF.WriteWord = ESPWriteWord; + MCF.ReadWord = ESPReadWord; + + MCF.WaitForFlash = ESPWaitForFlash; + MCF.WaitForDoneOp = ESPWaitForDoneOp; + + MCF.PerformSongAndDance = ESPPerformSongAndDance; + + MCF.BlockWrite64 = ESPBlockWrite64; + + // Reset internal programmer state. + Write2LE( eps, 0x0afe ); + return eps; }