From f7fcdb54eddabf2d9e39b96fcd30905694115ba8 Mon Sep 17 00:00:00 2001
From: cnlohr <lohr85@gmail.com>
Date: Mon, 6 Mar 2023 08:50:15 -0800
Subject: [PATCH] Enough testing for tonight.  the CH-LinkE Still works, and
 I'm closing in on an ESP32 programmer.

---
 ch32v003fun/ch32v003fun.c       |  12 ++-
 ch32v003fun/ch32v003fun.h       |  12 +--
 ch32v003fun/ch32v003fun.ld      | 159 ++++++++++++++++++++++++++++++++
 examples/blink/Makefile         |   4 +-
 examples/blink/blink.bin        | Bin 524 -> 536 bytes
 examples/blink/blink.c          |   3 +
 minichlink/minichlink.c         | 119 ++++++++++++++++++++++--
 minichlink/minichlink.exe       | Bin 28672 -> 30208 bytes
 minichlink/minichlink.h         |  22 +++++
 minichlink/pgm-esp32s2-ch32xx.c |   4 +-
 10 files changed, 311 insertions(+), 24 deletions(-)
 create mode 100644 ch32v003fun/ch32v003fun.ld

diff --git a/ch32v003fun/ch32v003fun.c b/ch32v003fun/ch32v003fun.c
index 1af064c..18ce488 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 33242f6..92ca4da 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 0000000..d3d2728
--- /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 d15d989..0a43107 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
GIT binary patch
delta 245
zcmeBSnZd%B&)^`z00crzAUsh}z8=bf3BqWI0+>ST(IE4;e`k1b!?|+yjl<^Z6W8c4
zsU4VjBZ6f+3xmRB14cR7qwc~iEDka!CYo<&7i5q*VQSyJoQ0v4U3tM5hNF`c8KoH0
vC)Y4ai$0tD$cUkMLXg3Bb_NCJrR)sN%N-jgZ(x*R%d}@!Z%~|kiO~uGzX~cY

delta 231
zcmbQi(!;`+&)^`=00eAIAUsh}z8=bf3BqWI0+>ST(IE4;e`k1b!?|+yjl<^Z6W8cW
zycIFoj8RTln1#jRsJqOGmFC;o1sP;cbeg}NT*xTJm@&DBQCjl(<VQvf#S?-IwzD%R
eFfV0i0MX6M*%>D9VU%Huv}aa7pfLF!qZI%EuO!R>

diff --git a/examples/blink/blink.c b/examples/blink/blink.c
index 12d2f24..9b99747 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 60b31e9..f1aee9c 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
GIT binary patch
delta 9297
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

delta 7996
zcmcgx2~d<*w*LPsElUtlWU*0b_I(lA7iDW`5KvG-AV3tiahWJGNvwd4vPh?8Mm_ps
zsZpaZ8ja&K!z96p3+R}{BpNlD7ftdeW@eH!(L_xM!RXj??m{>HCskAL)vI*X<vaJB
z@0`1x|K9umwA_+gZpfRT8&f7p(j+YSbFJNSB$~YY+?J1`9gnw3(nNwv7$>`tCIag#
zvqvv%mL!wB#ZNsxx^dA{jcD~MrG8k-V5jVpxXlyARaB2<4wezWOiAjEUbS$3<9tbK
zqLDXavBR<gzLDcgItnF8XV4DmT8E^uZNaEF#mq!iYwu&at}!R;B&opgPJ!WUk>N^_
z;Ukkb+WHq#mQVao90yBa6;WsYtpqs{lyey+5vfxd=_J~EZkWyH{vKzPkS-atcXUQo
z0K7-kF%C~iQkMCB+N&-W>v3zWT4k*267U+ewfs!6rMb6j6&-&GZT+o|l4R80VMCol
zJJ=;WjKy~f3~%9pUsw9ADc))~nG_X+ubtZWn9>?TqnaJCS)=MeBfO^yl$)X1&Wo(z
zl{`3U=OqWhMpclvc?}y;zX}`f&ve2+@7goRZ`MGkDlqY_k#?EdySV)|H1Oq_h^{)L
zc1Wy;aq{jp@VLs80E-~6gx{+)auHlo1<AoMpwf^r%;5cH!-%FOoP_>Oqgm6J8fc%%
ziw*Gf=t!TlG#B{7&w5lbf5!^p{OIXHi>wrll2VGc{xA#-zqU`6ePE$|u6!L1+voZ;
z6<7k#sa6DDS^$qYWG9C+{W+acwkDewbu+a0+&7zbMh<N0*bHjv`hB5;c837Bt5u4i
zJvw;ZL9ITjV*!q10G?p&M_DXY4%~J~iE+e7#wN#NDW6Y3r849s9aK2#g1^c~im{!B
z<Q+BL;2PRXq51E8IPbW|<LOG;E88JO<wJ>6_=GU-v(M_|n-80u!aQ!}VTQKvroF81
z72$gF;2oz7{b4j2v;)}q2)8E6*ABD}$z$7CMyH`d454|RVpc-X)-#BYoCsV;ompe+
zhonqN8vEN+I;lfAwKRmWi}r&*7X|Y|6u~}5R?iRCU~aTwqpAsxJ(3)gv(hrNZS3i7
z5Hax)8>~=7s?~zKb0C?gg*4}z`kTvX>vS`kpv?BmXu|bkOW7ZWdzr~2*D~7I$`xS=
z+DzZ)SO~|JgwN1s`oKy!O$qvuyIn73bXyreX=5)XY_$>&Dce{_39GGy?MgxoCCsuC
zQaY53bjpaaGJc~ZcvFH)4*WPqt^Y9_<*)IN$bpSY@^wmh*Ggzo5_%}%B`e{8lJG1g
zJYywX8bNSohr|<<@vCh3%tbwaE|qmw_W2QPMvg~Y52lg1Kb9un<YB6@>xL!!9w?p6
zS;FbUxdSa@Ws;i(8(a(JSh(mK<m|MRr3ohEoh9(lHITf$1Omqe$wpW`E?8bj|B{R)
z&^IB7cyPGA7`_}ANUkh~G2`R(QPcVK8H)#a^5^4`YI6#@A%o?9e=_!&=VLTV{b6(n
zUr)14f1=X!I@<6A>PMb*;oMxE;d9;kTeO0`oxGU(4f$j0dvMJJu0e$g73}1o+l(1P
zCq~Psp<?3evJ<$ebLERLPo3blH-pB}y6TJ$1%|ir#5Q%oKDB#@epuhy8)~(U6I!tu
zkPI;UcoLHizE>B?qafS6P6pWT?O(PQFB^i?oQ^FRRJEwV4p&fMkE;DBl)9LL?Rctm
zix0gulyJ8v>zUiC`mH{m5H-m@G?1}yhg1#D8g7H~9XLOQ^W!K#<{848xW|ap<+zQ@
z*)%j8RQDIKCI%Kzmt5|0$>Ori#-)k7oZ>F8QWr2|ul88@fj0a^&ewDPQ>=*|ne}R^
z#pSPfLE@7|2XY5DRP0q2cS&U~4csNp;<CfW<p_5f#a$lErvr)PF2v$eX5+GuyPTiT
z#(o-Id_u1>2AwBo8?F!MZsgn+8XjtV>_ZP&_;27v%Q}K<DQpA<oS)6QQ$@40OSR16
z(qiMXmAgE`UF=vB{XYBUE3nDen`|$J!@lvPt{6V`^-P_{E?{)GAJ0=h3Kb&R%JAXR
zv4;yybQ;H@jnz9<F2xY586<;=5bBpL6IkvyM}7r*{pPz@C(>i`fw8^OdNw@^iT-oR
z-2~|K^MwEOPbCMr_=Ep!lFdZT_xOb2nCKOVW^h;g(uc$6Bwfhy&>B!pj>WSGKLjix
z!PW3sV2d0Np9L-;YpXyTltzlGU_($TxmyW;37R1{fnRWvd=e^y6J>YU99&Kg&Vw5v
zQ($6<2i_86L*hsrS8PXx3`bFMx&j&bayx{EE^|MCXC`htmM50>!vzk7u99B>udqzl
z4{*!T8MT|mbo~aFhWR>V#4zO@IPU5VN5aCQ961Xw_`M@GhVP;njcPTP22B66HQe3x
zO<@vYdmt$M65itm!tawA*>E=^i5#5`;gK40KMQMaP!}0MQn}^?*PKA(cV+N#q?)Yb
z8mFiv(pm;NQNeOOEQ`{R)H2u<RU=P@uc9*L{SXlyAa}sb=wx|2bVe6AJ`zqBamZ8;
zA4P|e=IQXf&JDa`lI3ks8lxt@T+tE}CC9+Am_4qS@pgh!aYOWZ3p^S-LtPw7gWNJ|
zZ&`1RNtj8dCg_Wuj2F~TW0S}?A>cJ74;!zWa!9@e_HotfhG4o!k8r{|%?))r>&EZm
z?vlVFn3U{G?9-U$)v3kuM6io5!qqN~_i}$fK$6xEeU5t~f1^U*^i;;&5}$zWmd3lm
z*9rFIehO0##?O)e05cLgNnZgA>&o?xi3Z}tH7k-C^DWe*=@{o+64Pu<0<troY23MH
zR&u>u27gRWliT1<vL}gE!QDJJIG$z)niNkQVsc6{Ztts8>b)f2;lqnQV3y-36K<tM
zh3uM)gXVYPyabkrd~#_PZbTb9i27$jW@=W1aqf_A{aFVYJq%itk+8dKFUwu6NoT|?
z9)5q^342n5BK|&!$F`iXFXGFj%?Wz}8F;Vl2lys6E2(qHY{siEyXfNkAf~uvs#nIS
zRmLcQ^=Y-T3*1QSv~T|>z5+b7V+p$<Jtw>pBVxjcHz||5_lWVw((ot$hJ-Ga$5gnT
zK1ogh=ZsW54)Zg@<sN9rNM5MVqCFlS)@n7&koSK?CxfaUZRlG-Z}A3I4X=%Vz-kq|
zmVvtq+DdutAodPxvw7`VZmY@acA2(_$j6{DvrP_zdzk_F;7`s9iqTBL%YZ%h5*u+w
zxxmni(r4IjcKEiN*u`nMZ<Vk*t2E(7X0_<>gTc)+==7{bZPKF7*gj<OHBIuMHv(|U
zzDd@`uxxY5Ng(lDoQL9_Xr|qt6GL9+;ukp+BHwi5i;GwN4Y>E%ENeH~_+_tD#!21{
z!MQ%3i<GQJWSN#gb?#!%V5RK`JSR+F!L{5(&v8oI5o&u5g0zX_O}L5Kv|Ix#wN+$a
z6zlOP+Eh}`#fZFWax;=?cjcv$=ehV*-VBn*#lrkhG9ePK<WC^?BH)?)7_U$8jYen4
z4NUH#pHZk3i!<35!8iva;LH3Oq><OkB4CRy09NXp$uzE+L^VdTFPt?wr68NGZ$Y8F
zy!%XngG_!5<sB?sRCr?y+XLC&g;zDn^f-Pep--f-7}NH`iTkMI_tR?J=xhdCj7)2C
zZv^9vsd7N~8T?B~2y4K;IDwoBreb$#v71bG1~K*85`VHY0G=y}B#-&QJ0<CbY9~c6
z4m;TNA`sV+_u^`xq8A&HY3)THl+LUo9f7Q!-kB?7w_yg04dx+km^K4wL0b=45AYtW
zLtoJp@?HS*KQL>*yc_aL<L&-yG+Hi~_`vQ`&G<z~!(+obWdm@j)JxOkuLyq?4|{9R
zoMCj?%))mukd1FOy%AWaJJ&MMamsKhHsRL5-m;nGvLEZ{sM&M$S82YCyvJOiiY`^w
zZT8f^&ufEsS?waP9r~8l-sH7;-?3UBuf4!)=XkARfZ0y*+C{pr8C0+F+UL|Z-k^G!
zSKr|qOKSv}X2)tLVy{PRs<_8XrtNrU@iB{6pAL;;>Yhdh?!)4seFbXf1k0~N+ni=O
z6Uf{(Ngtry8nq2CW0EPED5B2BgU4pQec<Ta(86Z!YhAuiaLz5=xo~2=CF8@D0se$c
zYqti#r##E)EN#}P-FM*}tSHw8e26|e<Ctp<+^<uh9~`^159lMTF{;#I@Ikr8bsOhx
z=e+;$1-lA=lK3)&Rz$nRq0(6FYH+}Nb+j)mtO#-arw<GJkb%3|2X<BX>-Qcvn=hQh
z?n;t5Xb?}!UlO12(ennMz&_E2|F8I}@c(z%AqHqcy;7m9i@@uIei%m!{r?v8gx@p~
zFLm0m;@_Z$a2Uqu$<Wt$>kn0bwR1>~q1Oya>MpPQErHwf6CrqkKkgBdbnVIR!UfT)
zk|H+ER3l08n49!7eR>P4vOm=u@MHWsN&52$T~(_jeS*3NBXsIENt&SF;^(2CPBR>T
zMFPtO)(TuAaFxI(1-1z66u4R74uN|Gz9jIE0#6BigQH%0PbjVn{JX$g0>2mdP@p{y
zk^Wo-`U#8{m?SV$;0%G>OOlp~`jZTCKHG(2i@<#XUl!Oa@QT1s1%55?p1`p<&-6D*
zV2HptfjWVlB}q$Yov!CPVc0G3jKB{C-WNFR7>0{Sf0+VH1TGQSA#j^O&X%N~TWXe1
zztCF$+*0#={$<ws=a!ncFa08GjqC7}r7rk?TWdJDd?O^Tcy#othF|@<adG$WR{Wmm
zH?>QWjP24d9kg7-l+d7VDVFp2#j8I=lH4;TX$N8!UhCK5_okxh_!5~RNtdv6O~X?Y
zZC|3zcPjqx4?pEB#uwUqh_7I&!y|kb#(DuuH<nXa-oWxPmT%jo2+6TSl7g_LW2wZl
z0LyYLYq4y=0$5(ca;BsEi^tUj9$VeAwZTsR6mF8V7_l6|4VB8TAU?0*@=?T(g#0<8
zmp|7BAZ`}&F2uzFT)!HzJDAI-5$Tv{%sGg3>{LF0Naq7(y)=LVoe*j$LZlNw<!{AA
zP&phYgiZjJmm$)Lq4H`(I#E=v5feq_UX<y?QP~bBnoc&A+YsquQ28?A*bK}{T2W{4
zRiN^9l<8_vc?Tk0B`Q}S(iNn#1~Em*xrnEP{1)Q2EY8`Bn481pnTQvKd<`)tm+MRP
zC^U;oC*lb$H~bm#rjQ2__vUf^5yX&uF2^D67V;s)J@_9r+PTAs75J%($_o(H#as?T
zye{N_Anqu^U6GOwpzs|QDnCT*#&3UAK8;v2i_7#QXcB(#ruuBe(kd=Lig;AWuOUJ;
i*Y81euH~{f;)htSVY!K=zK+WhHuXj$zIt!2%>Ng!7vTK>

diff --git a/minichlink/minichlink.h b/minichlink/minichlink.h
index 22b4f9b..730409c 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 deb89c7..c51dcbb 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 );
-- 
GitLab