diff --git a/ch32v003fun/ch32v003fun.c b/ch32v003fun/ch32v003fun.c
index 1af064c48f35bd434572b90fddd595101164be4f..18ce488f90546ec317a470f20032a03dd1b70ae2 100644
--- a/ch32v003fun/ch32v003fun.c
+++ b/ch32v003fun/ch32v003fun.c
@@ -795,7 +795,7 @@ void handle_reset()
 	while( tempout != tempend )
 		*(tempout++) = *(tempin++); 
 
-	__set_MEPC( (uint32_t)main );
+	asm volatile("csrw mepc, %0" : : "r"(main));
 
 	// set mepc to be main as the root app.
 	asm volatile( "mret\n" );
@@ -844,4 +844,12 @@ int _write(int fd, const char *buf, int size)
 	return size;
 }
 
-
+void DelaySysTick( uint32_t n )
+{
+    SysTick->SR &= ~(1 << 0);
+    SysTick->CMP = n;
+    SysTick->CNT = 0; 
+    SysTick->CTLR |=(1 << 0);
+    while(!(SysTick->SR & (1 << 0)));
+    SysTick->CTLR &= ~(1 << 0);
+}
diff --git a/ch32v003fun/ch32v003fun.h b/ch32v003fun/ch32v003fun.h
index 33242f6183e7bd90fbf0c4b0f7ff4e099d0d6364..92ca4daeb4bb96b0b6dcffa2a28fdbf432b1b995 100644
--- a/ch32v003fun/ch32v003fun.h
+++ b/ch32v003fun/ch32v003fun.h
@@ -4819,21 +4819,11 @@ extern "C" {
 #define DELAY_US_TIME (SYSTEM_CORE_CLOCK / 8000000)
 #define DELAY_MS_TIME (SYSTEM_CORE_CLOCK / 8000)
 
-static void DelaySysTick( uint32_t n )
-{
-    SysTick->SR &= ~(1 << 0);
-    SysTick->CMP = n;
-    SysTick->CNT = 0; 
-    SysTick->CTLR |=(1 << 0);
-    while(!(SysTick->SR & (1 << 0)));
-    SysTick->CTLR &= ~(1 << 0);
-}
+void DelaySysTick( uint32_t n );
 
 #define Delay_Us(n) DelaySysTick( n * DELAY_US_TIME )
 #define Delay_Ms(n) DelaySysTick( n * DELAY_MS_TIME )
 
-
-
 // Tricky: We need to make sure main and SystemInit() are preserved.
 int main() __attribute__((used));
 void SystemInit(void) __attribute__((used));
diff --git a/ch32v003fun/ch32v003fun.ld b/ch32v003fun/ch32v003fun.ld
new file mode 100644
index 0000000000000000000000000000000000000000..d3d27288f1530e420dafd11ea17d1c93401890c9
--- /dev/null
+++ b/ch32v003fun/ch32v003fun.ld
@@ -0,0 +1,159 @@
+ENTRY( InterruptVector )
+
+__stack_size = 256;
+
+PROVIDE( _stack_size = __stack_size );
+
+MEMORY
+{
+	FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 16K
+	RAM (xrw)  : ORIGIN = 0x20000000, LENGTH = 2K
+}
+
+SECTIONS
+{
+    .init :
+    { 
+      _sinit = .;
+      . = ALIGN(4);
+      KEEP(*(SORT_NONE(.init)))
+      . = ALIGN(4);
+      _einit = .;
+    } >FLASH AT>FLASH
+
+    .text :
+    {
+      . = ALIGN(4);
+      *(.text)
+      *(.text.*)
+      *(.rodata)
+      *(.rodata*)
+      *(.gnu.linkonce.t.*)
+      . = ALIGN(4);
+    } >FLASH AT>FLASH 
+
+    .fini :
+    {
+      KEEP(*(SORT_NONE(.fini)))
+      . = ALIGN(4);
+    } >FLASH AT>FLASH
+
+    PROVIDE( _etext = . );
+    PROVIDE( _eitcm = . );  
+
+    .preinit_array :
+    {
+      PROVIDE_HIDDEN (__preinit_array_start = .);
+      KEEP (*(.preinit_array))
+      PROVIDE_HIDDEN (__preinit_array_end = .);
+    } >FLASH AT>FLASH 
+  
+    .init_array :
+    {
+      PROVIDE_HIDDEN (__init_array_start = .);
+      KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+      KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+      PROVIDE_HIDDEN (__init_array_end = .);
+    } >FLASH AT>FLASH 
+  
+    .fini_array :
+    {
+      PROVIDE_HIDDEN (__fini_array_start = .);
+      KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+      KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+      PROVIDE_HIDDEN (__fini_array_end = .);
+    } >FLASH AT>FLASH 
+  
+    .ctors :
+    {
+      /* gcc uses crtbegin.o to find the start of
+         the constructors, so we make sure it is
+         first.  Because this is a wildcard, it
+         doesn't matter if the user does not
+         actually link against crtbegin.o; the
+         linker won't look for a file to match a
+         wildcard.  The wildcard also means that it
+         doesn't matter which directory crtbegin.o
+         is in.  */
+      KEEP (*crtbegin.o(.ctors))
+      KEEP (*crtbegin?.o(.ctors))
+      /* We don't want to include the .ctor section from
+         the crtend.o file until after the sorted ctors.
+         The .ctor section from the crtend file contains the
+         end of ctors marker and it must be last */
+      KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+      KEEP (*(SORT(.ctors.*)))
+      KEEP (*(.ctors))
+    } >FLASH AT>FLASH 
+  
+    .dtors :
+    {
+      KEEP (*crtbegin.o(.dtors))
+      KEEP (*crtbegin?.o(.dtors))
+      KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+      KEEP (*(SORT(.dtors.*)))
+      KEEP (*(.dtors))
+    } >FLASH AT>FLASH 
+
+    .dalign :
+    {
+      . = ALIGN(4);
+      PROVIDE(_data_vma = .);
+    } >RAM AT>FLASH  
+
+    .dlalign :
+    {
+      . = ALIGN(4); 
+      PROVIDE(_data_lma = .);
+    } >FLASH AT>FLASH
+
+    .data :
+    {
+      . = ALIGN(4);
+      *(.gnu.linkonce.r.*)
+      *(.data .data.*)
+      *(.gnu.linkonce.d.*)
+      . = ALIGN(8);
+      PROVIDE( __global_pointer$ = . + 0x800 );
+      *(.sdata .sdata.*)
+      *(.sdata2*)
+      *(.gnu.linkonce.s.*)
+      . = ALIGN(8);
+      *(.srodata.cst16)
+      *(.srodata.cst8)
+      *(.srodata.cst4)
+      *(.srodata.cst2)
+      *(.srodata .srodata.*)
+      . = ALIGN(4);
+      PROVIDE( _edata = .);
+    } >RAM AT>FLASH
+
+    .bss :
+    {
+      . = ALIGN(4);
+      PROVIDE( _sbss = .);
+      *(.sbss*)
+      *(.gnu.linkonce.sb.*)
+      *(.bss*)
+      *(.gnu.linkonce.b.*)    
+      *(COMMON*)
+      . = ALIGN(4);
+      PROVIDE( _ebss = .);
+    } >RAM AT>FLASH
+
+    PROVIDE( _end = _ebss);
+	PROVIDE( end = . );
+
+	.stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :
+	{
+	    PROVIDE( _heap_end = . );
+	    . = ALIGN(4);
+	    PROVIDE(_susrstack = . );
+	    . = . + __stack_size;
+	    PROVIDE( _eusrstack = .);
+	} >RAM 
+	
+}
+
+
+
diff --git a/examples/blink/Makefile b/examples/blink/Makefile
index d15d989a4124e5c201ee3bb74ab6e8914ce9eb49..0a4310763ff6d7bf7217bf4c8605f652274616fd 100644
--- a/examples/blink/Makefile
+++ b/examples/blink/Makefile
@@ -11,7 +11,7 @@ EVT:=../../ch32v003evt
 MINICHLINK:=../../minichlink
 
 ifeq ($(OS),Windows_NT)
-# On Windows, all the major GCC installs are missing the eg
+# On Windows, all the major RISC-V GCC installs are missing the -ec libgcc.
 LIB_GCC=../../misc/libgcc.a
 else
 LIB_GCC=-lgcc
@@ -29,7 +29,7 @@ CFLAGS:= \
 	-nostdlib \
 	-I.
 
-LDFLAGS:=-T $(EVT)/ch32v003.ld -Wl,--gc-sections
+LDFLAGS:=-T $(CH32V003FUN)/ch32v003fun.ld -Wl,--gc-sections
 
 SYSTEM_C:=$(CH32V003FUN)/ch32v003fun.c
 
diff --git a/examples/blink/blink.bin b/examples/blink/blink.bin
index c211941e46da7c4c56961e2b686a0183d307c903..e22d2b54b66c603299ca02592e7849815ac9ac9e 100644
Binary files a/examples/blink/blink.bin and b/examples/blink/blink.bin differ
diff --git a/examples/blink/blink.c b/examples/blink/blink.c
index 12d2f242b82c8a8b54c80fccd72dfa54aae5e37b..9b99747755972c996826b2746e9da96746a4f782 100644
--- a/examples/blink/blink.c
+++ b/examples/blink/blink.c
@@ -6,6 +6,8 @@
 
 #define APB_CLOCK SYSTEM_CORE_CLOCK
 
+uint32_t count;
+
 int main()
 {
 	SystemInit48HSI();
@@ -26,5 +28,6 @@ int main()
 		Delay_Ms( 100 );
 		GPIOD->BSHR = (1<<(16+0)) | (1<<(16+4)); // Turn off GPIOD0
 		Delay_Ms( 100 );
+		count++;
 	}
 }
diff --git a/minichlink/minichlink.c b/minichlink/minichlink.c
index 60b31e9a2e796b197d1ffcd2c49379c60b07df65..f1aee9c8f51f2a84b9cc2ff997dfbb692c07d834 100644
--- a/minichlink/minichlink.c
+++ b/minichlink/minichlink.c
@@ -9,7 +9,7 @@
 #include "minichlink.h"
 
 static int64_t SimpleReadNumberInt( const char * number, int64_t defaultNumber );
-
+void TestFunction(void * v );
 struct MiniChlinkFunctions MCF;
 
 int main( int argc, char ** argv )
@@ -28,6 +28,8 @@ int main( int argc, char ** argv )
 		fprintf( stderr, "Error: Could not initialize any supported programmers\n" );
 		return -32;
 	}
+	
+	SetupAutomaticHighLevelFunctions();
 
 	int status;
 	int must_be_end = 0;
@@ -42,6 +44,8 @@ int main( int argc, char ** argv )
 		}
 	}
 
+	//TestFunction( dev );
+
 	int iarg = 1;
 	const char * lastcommand = 0;
 	for( ; iarg < argc; iarg++ )
@@ -314,21 +318,21 @@ static int64_t SimpleReadNumberInt( const char * number, int64_t defaultNumber )
 }
 
 
-int ESPSetupInterface( void * dev )
+int DefaultSetupInterface( void * dev )
 {
 	struct ESP32ProgrammerStruct * eps = (struct ESP32ProgrammerStruct *)dev;
 
 	if( MCF.Control3v3 ) MCF.Control3v3( dev, 1 );
 	if( MCF.DelayUS ) MCF.DelayUS( dev, 16000 );
-	MCF.WriteReg32( dev, 0x7e, 0x5aa50000 | (1<<10) ); // Shadow Config Reg
-	MCF.WriteReg32( dev, 0x7d, 0x5aa50000 | (1<<10) ); // CFGR (1<<10 == Allow output from slave)
-	MCF.WriteReg32( dev, 0x7d, 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.
-	MCF.WriteReg32( dev, 0x10, 0x80000001 ); // Make the debug module work properly.
-	MCF.WriteReg32( dev, 0x10, 0x80000001 ); // Initiate a halt request.
+	MCF.WriteReg32( dev, SHDWCFGR, 0x5aa50000 | (1<<10) ); // Shadow Config Reg
+	MCF.WriteReg32( dev, CFGR, 0x5aa50000 | (1<<10) ); // CFGR (1<<10 == Allow output from slave)
+	MCF.WriteReg32( dev, CFGR, 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.
+	MCF.WriteReg32( dev, DMCONTROL, 0x80000001 ); // Make the debug module work properly.
+	MCF.WriteReg32( dev, DMCONTROL, 0x80000001 ); // Initiate a halt request.
 
 	// Read back chip ID.
 	uint32_t reg;
-	int r = MCF.ReadReg32( dev, 0x11, &reg );
+	int r = MCF.ReadReg32( dev, DMSTATUS, &reg );
 	if( r >= 0 )
 	{
 		// Valid R.
@@ -346,6 +350,97 @@ int ESPSetupInterface( void * dev )
 	}
 }
 
+static int WriteWord( void * dev, uint32_t address_to_write, uint32_t data )
+{
+	int r;
+	MCF.WriteReg32( dev, DMPROGBUF0, 0x0072a023 ); // sw x7,0(x5)
+	MCF.WriteReg32( dev, DMPROGBUF0, 0x00100073 ); // ebreak
+	MCF.WriteReg32( dev, DMDATA0, address_to_write );
+	MCF.WriteReg32( dev, DMCOMMAND, 0x00231005 ); // Copy data to x5
+	uint32_t rrv;
+	do
+	{
+		r = MCF.ReadReg32( dev, DMABSTRACTCS, &rrv );
+		if( r ) return r;
+	}
+	while( rrv & (1<<12) );
+	
+	MCF.WriteReg32( dev, DMDATA0, data );
+	MCF.WriteReg32( dev, DMCOMMAND, 0x00271007 ); // Copy data to x7, and execute program.
+	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 );
+	}
+	return 0;
+}
+
+int DefaultWriteBinaryBlob( void * dev, uint32_t address_to_write, uint32_t blob_size, uint8_t * blob )
+{
+	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.
+}
+
+static int ReadWord( void * dev, uint32_t address_to_read, uint32_t * data )
+{
+	int r;
+	MCF.WriteReg32( dev, DMPROGBUF0, 0x0002a303 ); // lw x6,0(x5)
+	MCF.WriteReg32( dev, DMPROGBUF0, 0x00100073 ); // ebreak
+	MCF.WriteReg32( dev, DMDATA0, address_to_read );
+	MCF.WriteReg32( dev, DMCOMMAND, 0x00271005 ); // Copy data to x5
+	uint32_t rrv;
+	do
+	{
+		r = MCF.ReadReg32( dev, DMABSTRACTCS, &rrv );
+		if( r ) return r;
+	}
+	while( rrv & (1<<12) );
+	printf( "RRV: %08x\n", rrv );
+	MCF.WriteReg32( dev, DMCOMMAND, 0x00221006 ); // Copy x7 to data0
+	do
+	{
+		r = MCF.ReadReg32( dev, DMABSTRACTCS, &rrv );
+		if( r ) return r;
+	}
+	while( rrv & (1<<12) );
+	printf( "RRV: %08x\n", rrv );
+	if( (rrv >> 8 ) & 7 )
+	{
+		fprintf( stderr, "Fault writing memory (DMABSTRACTS = %08x)\n", rrv );
+	}
+	
+	return MCF.ReadReg32( dev, DMDATA0, data );
+}
+
+int DefaultReadBinaryBlob( void * dev, uint32_t address_to_read_from, uint32_t read_size, uint8_t * blob )
+{
+	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.
+	
+	
+}
+
+void TestFunction(void * dev )
+{
+	uint32_t rv;
+	int r;
+	
+	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.
+
+	r = ReadWord( dev, 0x08000004, &rv );
+	printf( "%d %08x\n", r, rv );
+}
+
+
 
 int SetupAutomaticHighLevelFunctions()
 {
@@ -354,5 +449,13 @@ int SetupAutomaticHighLevelFunctions()
 
 	// Else, TODO: Build the high level functions from low level functions.
 	// If a high-level function alrady exists, don't override.
+	
+	if( !MCF.SetupInterface )
+		MCF.SetupInterface = DefaultSetupInterface;
+	if( !MCF.WriteBinaryBlob )
+		MCF.WriteBinaryBlob = DefaultWriteBinaryBlob;
+	if( !MCF.ReadBinaryBlob )
+		MCF.ReadBinaryBlob = DefaultReadBinaryBlob;
+
 }
 
diff --git a/minichlink/minichlink.exe b/minichlink/minichlink.exe
index c03479bd4cb8ca2901becc1164a234389be3f8be..5c187f5e3995cdace9814183aecea6eedf6fc83d 100644
Binary files a/minichlink/minichlink.exe and b/minichlink/minichlink.exe differ
diff --git a/minichlink/minichlink.h b/minichlink/minichlink.h
index 22b4f9b32f3e64e720d1e194087dc6f2ec8d11bd..730409c059a232492dcdda79fb34f0834ad87a3d 100644
--- a/minichlink/minichlink.h
+++ b/minichlink/minichlink.h
@@ -30,6 +30,28 @@ struct MiniChlinkFunctions
 	int (*ReadBinaryBlob)( void * dev, uint32_t address_to_read_from, uint32_t read_size, uint8_t * blob );
 };
 
+
+#define DMDATA0        0x04
+#define DMDATA1        0x05
+#define DMCONTROL      0x10
+#define DMSTATUS       0x11
+#define DMHARTINFO     0x12
+#define DMABSTRACTCS   0x16
+#define DMCOMMAND      0x17
+#define DMABSTRACTAUTO 0x18
+#define DMPROGBUF0     0x20
+#define DMPROGBUF1     0x21
+#define DMPROGBUF2     0x22
+#define DMPROGBUF3     0x23
+#define DMPROGBUF4     0x24
+#define DMPROGBUF5     0x25
+#define DMPROGBUF6     0x26
+#define DMPROGBUF7     0x27
+
+#define CPBR       0x7C
+#define CFGR       0x7D
+#define SHDWCFGR   0x7E
+
 extern struct MiniChlinkFunctions MCF;
 
 // Returns 'dev' on success, else 0.
diff --git a/minichlink/pgm-esp32s2-ch32xx.c b/minichlink/pgm-esp32s2-ch32xx.c
index deb89c7a9875107ba342392ead0d8933f553eaf3..c51dcbb5a855c91021026475fa2df5ffe572596e 100644
--- a/minichlink/pgm-esp32s2-ch32xx.c
+++ b/minichlink/pgm-esp32s2-ch32xx.c
@@ -64,6 +64,7 @@ int ESPReadReg32( void * dev, uint8_t reg_7_bit, uint32_t * commandresp )
 	Write1( eps, (reg_7_bit<<1) | 0 );
 
 	int len = ESPFlushLLCommands( eps );
+
 	if( eps->replylen < 5 )
 	{
 		return -9;
@@ -86,7 +87,7 @@ int ESPFlushLLCommands( void * dev )
 	}
 	eps->commandbuffer[0] = 0xad; // Key report ID
 	eps->commandbuffer[eps->commandplace] = 0xff;
-	int r = hid_send_feature_report( eps->hd, eps->commandbuffer, eps->commandplace );
+	int r = hid_send_feature_report( eps->hd, eps->commandbuffer, 255 );
 	eps->commandplace = 1;
 	if( r < 0 )
 	{
@@ -96,6 +97,7 @@ int ESPFlushLLCommands( void * dev )
 
 	eps->reply[0] = 0xad; // Key report ID
 	r = hid_get_feature_report( eps->hd, eps->reply, sizeof( eps->reply ) );
+printf( "RRLEN: %d\n", r );
 	if( r < 0 )
 	{
 		fprintf( stderr, "Error: Got error %d when sending hid feature report.\n", r );