From 09f0badae0b6a8419035f9ab859d147835b38f4b Mon Sep 17 00:00:00 2001
From: cnlohr <lohr85@gmail.com>
Date: Mon, 13 Mar 2023 03:38:26 -0400
Subject: [PATCH] My esp32s2 is a signal generator now I guess. Add ability to
 use vendor commands with programmers.

---
 attic/external_crystal_run_from_ram_turbo.c |  56 ++++++++++++++++
 ch32v003fun/ch32v003fun.c                   |   1 +
 examples/blink/blink.bin                    | Bin 520 -> 544 bytes
 examples/blink/blink.c                      |  14 ++--
 minichlink/minichlink.c                     |  22 +++++--
 minichlink/minichlink.h                     |   5 ++
 minichlink/pgm-esp32s2-ch32xx.c             |  69 +++++++++++++++++++-
 7 files changed, 158 insertions(+), 9 deletions(-)
 create mode 100644 attic/external_crystal_run_from_ram_turbo.c

diff --git a/attic/external_crystal_run_from_ram_turbo.c b/attic/external_crystal_run_from_ram_turbo.c
new file mode 100644
index 0000000..cd2a0bb
--- /dev/null
+++ b/attic/external_crystal_run_from_ram_turbo.c
@@ -0,0 +1,56 @@
+// Could be defined here, or in the processor defines.
+#define SYSTEM_CORE_CLOCK 24000000
+
+#include "ch32v003fun.h"
+#include <stdio.h>
+
+#define APB_CLOCK SYSTEM_CORE_CLOCK
+
+uint32_t count;
+
+void RamFunction() __attribute__((naked));
+void RamFunction()
+{
+	asm volatile("\n\
+		li a0, 1 | (1<<4)\n\
+		li a1, (1<<16) | (1<<(16+4))\n\
+		la a2, 0x40011410\n\
+1:\n\
+		c.sw a0, 0(a2)\n\
+		c.sw a1, 0(a2)\n\
+		c.sw a0, 0(a2)\n\
+		c.sw a1, 0(a2)\n\
+		c.sw a0, 0(a2)\n\
+		c.sw a1, 0(a2)\n\
+		c.sw a0, 0(a2)\n\
+		c.sw a1, 0(a2)\n\
+		j 1b" );
+}
+
+uint8_t rambuffer[128];
+
+int main()
+{
+	EXTEN->EXTEN_CTR = EXTEN_LDO_TRIM; // Boost LDO.
+	SystemInitHSEPLL( RCC_HSEBYP );
+	// When running from RAM appears to go up to about 96MHz.
+
+	// Enable GPIOD.
+	RCC->APB2PCENR |= RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOC;
+
+	// GPIO D0 Push-Pull, 10MHz Output
+	GPIOD->CFGLR &= ~(0xf<<(4*0));
+	GPIOD->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*0);
+
+	// GPIO D0 Push-Pull, 10MHz Output
+	GPIOD->CFGLR &= ~(0xf<<(4*4));
+	GPIOD->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*4);
+
+	// GPIO D0 Push-Pull, 10MHz Output
+	GPIOC->CFGLR &= ~(0xf<<(4*4));
+	GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*4);
+
+memcpy( rambuffer, RamFunction, 128 );
+	void (*fn)() = (void*) rambuffer;
+	fn();
+}
diff --git a/ch32v003fun/ch32v003fun.c b/ch32v003fun/ch32v003fun.c
index e40153e..a97d1f8 100644
--- a/ch32v003fun/ch32v003fun.c
+++ b/ch32v003fun/ch32v003fun.c
@@ -840,6 +840,7 @@ void SystemInitHSEPLL( int HSEBYP )
 	RCC->CTLR  = RCC_HSION | RCC_HSEON | RCC_PLLON | HSEBYP;       // Enable HSE and keep HSI+PLL on.
 	while(!(RCC->CTLR&RCC_HSERDY));
 	RCC->CFGR0 = RCC_SW_HSE | RCC_HPRE_DIV1;                       // HCLK = SYSCLK = APB1 and use HSE for System Clock.
+	FLASH->ACTLR = FLASH_ACTLR_LATENCY_1;                          // 1 Cycle Latency
 	RCC->CTLR  = RCC_HSEON | HSEBYP;                               // Turn off PLL and HSI.
 	RCC->CFGR0 = RCC_SW_HSE | RCC_HPRE_DIV1 | RCC_PLLSRC_HSE_Mul2; // Use PLL with HSE.
 	RCC->CTLR  = RCC_HSEON | RCC_PLLON | HSEBYP;                   // Turn PLL Back on..
diff --git a/examples/blink/blink.bin b/examples/blink/blink.bin
index f5244807298493f49c777f4e01a93a19666c80c3..b3a46101b449bc35e39918f5f26d29ececf14ff7 100755
GIT binary patch
delta 367
zcmeBRS-`@V&#*v}0SKlsg78E^`Fbb^CJ3V;3SbJUM}y4Y{+;2$4d=?)Hx8RWXA@%(
zW@k5>xGAgNF>N~wgMx56JM)b5+r=3jn3uCVIL=mH@Ept%P8VkYv748%JD9V7{9h~n
zvrl=!buj-Tm^H<@w139o8P0(~(p-em!PQ+^<B0>SyTl1yb8~h<29TM`E1o+XOqV&K
zXy3e?g`t&QdBGQki~I9|j+)NS$e=K}F)?j&7o(Kj(kI5LR~d>0LJh=Ofo@`5`gn4y
yV}mdo14DAeRt9B-qYT2Vt_+WTw*C`lWl)+9R5Q6X^`ST$P%YcD2a_K$ssR8Iz+<ui

delta 343
zcmZ3$(!s))&!8Z|00ec6AUsh}z8=bf3BqWI0+>ST(IE4;e`k1b!?|+yjl<^QY(fme
z?Cd`#Zpy0P&i3*DUoqiycBUEUw~I46FfV6!*v`VB;5b`(!E-QAI9;3p#xCuLu@0t%
zg4svi%|#d;lr_FM=-O{*7i0jjSnZpavoN%>D=+xMaCCb<(DLbw3<{GQAEpa8GBOCW
zGH?_Nuo_HeGhir|p5WFX&dLB3RDEWgdX=GAAk+ZJR{-*#PCmydCDfoW9mt*B`t*@F
O8&H@n?a}04jA{TiI8zn?

diff --git a/examples/blink/blink.c b/examples/blink/blink.c
index 408b02f..81a2760 100644
--- a/examples/blink/blink.c
+++ b/examples/blink/blink.c
@@ -13,7 +13,7 @@ int main()
 	SystemInit48HSI();
 
 	// Enable GPIOD.
-	RCC->APB2PCENR |= RCC_APB2Periph_GPIOD;
+	RCC->APB2PCENR |= RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOC;
 
 	// GPIO D0 Push-Pull, 10MHz Output
 	GPIOD->CFGLR &= ~(0xf<<(4*0));
@@ -23,12 +23,18 @@ int main()
 	GPIOD->CFGLR &= ~(0xf<<(4*4));
 	GPIOD->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*4);
 
+	// GPIO D0 Push-Pull, 10MHz Output
+	GPIOC->CFGLR &= ~(0xf<<(4*4));
+	GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*4);
+
 	while(1)
 	{
-		GPIOD->BSHR = 1 | (1<<4);	 // Turn on GPIOD0
-		Delay_Ms( 200 );
+		GPIOD->BSHR = 1 | (1<<4);	 // Turn on GPIOD0&D4
+		GPIOC->BSHR = 1;	         // Turn on GPIOC0
+		Delay_Ms( 250 );
 		GPIOD->BSHR = (1<<16) | (1<<(16+4)); // Turn off GPIOD0
-		Delay_Ms( 200 );
+		GPIOC->BSHR = (1<<16);       // Turn off GPIOC0
+		Delay_Ms( 250 );
 		count++;
 	}
 }
diff --git a/minichlink/minichlink.c b/minichlink/minichlink.c
index b4cb47a..5f6b094 100644
--- a/minichlink/minichlink.c
+++ b/minichlink/minichlink.c
@@ -11,7 +11,6 @@
 #include "minichlink.h"
 #include "../ch32v003fun/ch32v003fun.h"
 
-static int64_t SimpleReadNumberInt( const char * number, int64_t defaultNumber );
 static int64_t StringToMemoryAddress( const char * number );
 static void StaticUpdatePROGBUFRegs( void * dev );
 static int InternalUnlockBootloader( void * dev );
@@ -41,9 +40,11 @@ int main( int argc, char ** argv )
 	int status;
 	int must_be_end = 0;
 
-	int doing_unblock = (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'u' );
+	int skip_startup = 
+		(argc > 1 && argv[1][0] == '-' && argv[1][1] == 'u' ) |
+		(argc > 1 && argv[1][0] == '-' && argv[1][1] == 'X' );
 
-	if( !doing_unblock && MCF.SetupInterface )
+	if( !skip_startup && MCF.SetupInterface )
 	{
 		if( MCF.SetupInterface( dev ) < 0 )
 		{
@@ -178,6 +179,19 @@ keep_going:
 					goto unimplemented;
 				break;
 			}
+			case 'X':
+			{
+				iarg++;
+				if( iarg >= argc )
+				{
+					fprintf( stderr, "Vendor command requires an actual command\n" );
+					goto unimplemented;
+				}
+				if( MCF.VendorCommand )
+					if( MCF.VendorCommand( dev, argv[iarg++] ) )
+						goto unimplemented;
+				break;
+			}
 			case 'r':
 			{
 				if( MCF.HaltMode ) MCF.HaltMode( dev, 0 );
@@ -409,7 +423,7 @@ unimplemented:
 
 static int StaticUnlockFlash( void * dev, struct InternalState * iss );
 
-static int64_t SimpleReadNumberInt( const char * number, int64_t defaultNumber )
+int64_t SimpleReadNumberInt( const char * number, int64_t defaultNumber )
 {
 	if( !number || !number[0] ) return defaultNumber;
 	int radix = 10;
diff --git a/minichlink/minichlink.h b/minichlink/minichlink.h
index d10f1ff..100e127 100644
--- a/minichlink/minichlink.h
+++ b/minichlink/minichlink.h
@@ -54,6 +54,8 @@ struct MiniChlinkFunctions
 
 	int (*PerformSongAndDance)( void * dev );
 
+	int (*VendorCommand)( void * dev, const char * command );
+
 	// Do Not override these.  they are cursed.
 	int (*WriteHalfWord)( void * dev, uint32_t address_to_write, uint32_t data );
 	int (*ReadHalfWord)( void * dev, uint32_t address_to_read, uint32_t * data );
@@ -116,5 +118,8 @@ void * TryInit_ESP32S2CHFUN();
 // Returns 0 if ok, populated, 1 if not populated.
 int SetupAutomaticHighLevelFunctions( void * dev );
 
+// Useful for converting numbers like 0x, etc.
+int64_t SimpleReadNumberInt( const char * number, int64_t defaultNumber );
+
 #endif
 
diff --git a/minichlink/pgm-esp32s2-ch32xx.c b/minichlink/pgm-esp32s2-ch32xx.c
index 6f7b7fa..77e2f03 100644
--- a/minichlink/pgm-esp32s2-ch32xx.c
+++ b/minichlink/pgm-esp32s2-ch32xx.c
@@ -255,6 +255,73 @@ int ESPVoidHighLevelState( void * dev )
 	return 0;
 }
 
+int ESPVendorCommand( void * dev, const char * cmd )
+{
+	char command[10] = { 0 };
+	char tbuf[10] = { 0 };
+	int fields[10];
+	char c;
+	int i = 0;
+	int f = 0;
+	while( (c = *cmd++) )
+	{
+		if( c == ':' ) break;
+		if( c == '\0' ) break;
+		if( i + 1 >= sizeof( command )) break;
+		command[i++] = c;
+		command[i] = 0;
+	}
+	i = 0;
+	f = 0;
+	while( 1 )
+	{
+		c = *cmd++;
+		if( c == ':' || c == '\0' )
+		{
+			fields[f++] = SimpleReadNumberInt( tbuf,  0 );
+			puts( tbuf );
+			if( f == 10 ) break; 
+			tbuf[0] = 0;
+			i = 0;
+			if( c == '\0' ) break;
+			continue;
+		}
+		if( i + 1 >= sizeof( tbuf )) break;
+		tbuf[i++] = c;
+		tbuf[i] = 0;
+	}
+	printf( "Got Vendor Command \"%s\"\n", command );
+	ESPFlushLLCommands( dev );
+	if( strcasecmp( command, "ECLK" ) == 0 )
+	{
+		printf( "Setting up external clock on pin.\n" );
+		if( f < 5 )
+		{
+			fprintf( stderr, "Error: Need fields :use_apll:sdm0:sdm1:sdm2:odiv try 1:0:0:8:3 for 24MHz\n" );
+			fprintf( stderr, "Definition:\n\
+	use_apll = Configures APLL = 480 / 4 = 120\n\
+	40 * (SDM2 + SDM1/(2^8) + SDM0/(2^16) + 4) / ( 2 * (ODIV+2) );\n\
+	Datasheet recommends that numerator is between 300 and 500MHz.\n ");
+			return -9;
+		}
+		Write2LE( dev, 0x0cfe );
+		Write1( dev, fields[0] ); 
+		Write1( dev, fields[1] ); 
+		Write1( dev, fields[2] ); 
+		Write1( dev, fields[3] ); 
+		Write1( dev, fields[4] ); 
+		Write1( dev, 0 ); 
+		Write1( dev, 0 ); 
+		Write1( dev, 0 ); 
+	ESPFlushLLCommands( dev );
+	}
+	else
+	{
+		fprintf( stderr, "Error: Unknown vendor command %s\n", command );
+	}
+	return 0;
+}
+
 void * TryInit_ESP32S2CHFUN()
 {
 	#define VID 0x303a
@@ -287,7 +354,7 @@ void * TryInit_ESP32S2CHFUN()
 	MCF.PerformSongAndDance = ESPPerformSongAndDance;
 
 	MCF.BlockWrite64 = ESPBlockWrite64;
-
+	MCF.VendorCommand = ESPVendorCommand;
 	// Reset internal programmer state.
 	Write2LE( eps, 0x0afe );
 
-- 
GitLab