From ee129219bd537597fd59f6995cc703ca9c852144 Mon Sep 17 00:00:00 2001 From: cnlohr <lohr85@gmail.com> Date: Sun, 19 Feb 2023 01:17:08 -0800 Subject: [PATCH] Add ability to read-back data. --- minichlink/minichlink.c | 112 +++++++++++++++++++++++++++++++++++- minichlink/test.bat | 2 +- minichlink/wch_dump_flash.c | 54 +++++++++++++++++ minichlink/wch_link_base.h | 4 ++ 4 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 minichlink/wch_dump_flash.c diff --git a/minichlink/minichlink.c b/minichlink/minichlink.c index 346ea99..cce5149 100644 --- a/minichlink/minichlink.c +++ b/minichlink/minichlink.c @@ -1,4 +1,5 @@ #include <stdio.h> +#include <stdlib.h> #include "wch_link_base.h" @@ -36,6 +37,8 @@ const uint8_t * bootloader = (const uint8_t*) "\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"; +static int64_t SimpleReadNumberInt( const char * number, int64_t defaultNumber ); + int bootloader_len = 512; int main( int argc, char ** argv ) @@ -107,8 +110,84 @@ keep_going: 4, "\x81\x06\x01\x01" ); break; */ - case 'w': + case 'o': + { + int i; + int transferred; + if( argchar[2] != 0 ) goto help; + iarg++; + argchar = 0; // Stop advancing + if( iarg + 2 >= argc ) goto help; + uint64_t offset = SimpleReadNumberInt( argv[iarg++], -1 ); + uint64_t amount = SimpleReadNumberInt( argv[iarg++], -1 ); + if( offset > 0xffffffff || amount > 0xffffffff ) + { + fprintf( stderr, "Error: memory value request out of range.\n" ); + return -9; + } + + // Round up amount. + amount = ( amount + 3 ) & 0xfffffffc; + FILE * f = fopen( argv[iarg], "wb" ); + if( !f ) + { + fprintf( stderr, "Error: can't open write file \"%s\"\n", argv[iarg] ); + return -9; + } + uint32_t * readbuff = malloc( amount ); + int readbuffplace = 0; + wch_link_command( devh, "\x81\x06\x01\x01", 4, 0, 0, 0 ); + + // Flush out any pending data. + libusb_bulk_transfer( devh, 0x82, rbuff, 1024, &transferred, 1 ); + + // 3/8 = Read Memory + // First 4 bytes are big-endian location. + // Next 4 bytes are big-endian amount. + uint8_t readop[11] = { 0x81, 0x03, 0x08, }; + + readop[3] = (offset>>24)&0xff; + readop[4] = (offset>>16)&0xff; + readop[5] = (offset>>8)&0xff; + readop[6] = (offset>>0)&0xff; + + readop[7] = (amount>>24)&0xff; + readop[8] = (amount>>16)&0xff; + readop[9] = (amount>>8)&0xff; + readop[10] = (amount>>0)&0xff; + + wch_link_command( devh, readop, 11, 0, 0, 0 ); + + // Perform operation + wch_link_command( devh, "\x81\x02\x01\x0c", 4, 0, 0, 0 ); + + uint32_t remain = amount; + while( remain ) + { + transferred = 0; + WCHCHECK( libusb_bulk_transfer( devh, 0x82, rbuff, 1024, &transferred, WCHTIMEOUT ) ); + memcpy( ((uint8_t*)readbuff) + readbuffplace, rbuff, transferred ); + readbuffplace += transferred; + remain -= transferred; + } + + // Flip internal endian. Must be done separately in case something was unaligned when + // reading. + for( i = 0; i < readbuffplace/4; i++ ) { + uint32_t r = readbuff[i]; + readbuff[i] = (r>>24) | ((r & 0xff0000) >> 8) | ((r & 0xff00)<<8) | (( r & 0xff )<<24); + } + + fwrite( readbuff, readbuffplace, 1, f ); + + free( readbuff ); + + fclose( f ); + break; + } + case 'w': + { if( argchar[2] != 0 ) goto help; iarg++; argchar = 0; // Stop advancing @@ -207,5 +286,36 @@ help: // fprintf( stderr, " -P Enable Read Protection (UNTESTED)\n" ); // fprintf( stderr, " -p Disable Read Protection (UNTESTED)\n" ); fprintf( stderr, " -w [binary image to write]\n" ); + fprintf( stderr, " -o [memory address, decimal or 0x, try 0x08000000] [size, decimal or 0x, try 16384] [output binary image]\n" ); return -1; } + + +#if defined(WINDOWS) || defined(WIN32) || defined(_WIN32) +#define strtoll _strtoi64 +#endif + +static int64_t SimpleReadNumberInt( const char * number, int64_t defaultNumber ) +{ + if( !number || !number[0] ) return defaultNumber; + int radix = 10; + if( number[0] == '0' ) + { + char nc = number[1]; + number+=2; + if( nc == 0 ) return 0; + else if( nc == 'x' ) radix = 16; + else if( nc == 'b' ) radix = 2; + else { number--; radix = 8; } + } + char * endptr; + uint64_t ret = strtoll( number, &endptr, radix ); + if( endptr == number ) + { + return defaultNumber; + } + else + { + return ret; + } +} diff --git a/minichlink/test.bat b/minichlink/test.bat index 912a017..6761071 100644 --- a/minichlink/test.bat +++ b/minichlink/test.bat @@ -4,7 +4,7 @@ tcc wch_erase.c libusb-1.0.dll tcc wch_reset.c libusb-1.0.dll tcc wch_write_simple.c libusb-1.0.dll tcc minichlink.c libusb-1.0.dll - +tcc wch_dump_flash.c libusb-1.0.dll rem wch_erase.exe rem wch_write_simple.exe ..\barebones\barebones.bin rem wch_reset.exe diff --git a/minichlink/wch_dump_flash.c b/minichlink/wch_dump_flash.c new file mode 100644 index 0000000..43857b2 --- /dev/null +++ b/minichlink/wch_dump_flash.c @@ -0,0 +1,54 @@ +#include <stdio.h> +#include "wch_link_base.h" + +// TODO Make me actually query data! + +int main() +{ + int i; + int transferred; + int status; + char rbuff[1024]; + libusb_device_handle * devh = wch_link_base_setup(); + + wch_link_command( devh, "\x81\x06\x01\x01", 4, 0, 0, 0 ); + + // Flush out any pending data. + libusb_bulk_transfer( devh, 0x82, rbuff, 1024, &transferred, 1 ); + + // 3/8 = Read Memory + // First 4 bytes are big-endian location. + // Next 4 bytes are big-endian amount. + uint8_t readop[11] = { 0x81, 0x03, 0x08, }; + uint32_t readptr = 0x08000000; + uint32_t amount = 16384; + + readop[3] = (readptr>>24)&0xff; + readop[4] = (readptr>>16)&0xff; + readop[5] = (readptr>>8)&0xff; + readop[6] = (readptr>>0)&0xff; + + readop[7] = (amount>>24)&0xff; + readop[8] = (amount>>16)&0xff; + readop[9] = (amount>>8)&0xff; + readop[10] = (amount>>0)&0xff; + + wch_link_command( devh, readop, 11, 0, 0, 0 ); + + // Perform operation + wch_link_command( devh, "\x81\x02\x01\x0c", 4, 0, 0, 0 ); + + printf( "WARNING ENDIAN WILL BE REVERSED\n" ); + + uint32_t remain = amount; + while( remain ) + { + WCHCHECK( libusb_bulk_transfer( devh, 0x82, rbuff, 1024, &transferred, WCHTIMEOUT ) ); + for( i = 0; i < transferred; i++ ) + printf( "%08x", (uint8_t)rbuff[i] ); + printf( "\n" ); + remain -= transferred; + } + + wch_link_command( devh, "\x81\x0d\x01\xff", 4, 0, 0, 0 ); +} diff --git a/minichlink/wch_link_base.h b/minichlink/wch_link_base.h index ee41455..62f57ec 100644 --- a/minichlink/wch_link_base.h +++ b/minichlink/wch_link_base.h @@ -99,8 +99,12 @@ static inline libusb_device_handle * wch_link_base_setup() // 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" + // TODO: What in the world is this? It doesn't appear to be needed. wch_link_command( devh, "\x81\x0c\x02\x09\x01", 5, 0, 0, 0 ); //Reply is: 820c0101 + + // This puts the processor on hold to allow the debugger to run. 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) if( transferred != 20 ) { -- GitLab