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 0000000000000000000000000000000000000000..cd2a0bbc47cc7b48969b54d6b6cc430dfeab7fd6 --- /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 e40153eefe7a2f1cb00b5f35a9dc43ae8b84d0ab..a97d1f8dab719d2c4caeb81e870a42645c2b3de6 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 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 408b02f49809ac1de1ce03d4bb50e1317a9cb972..81a2760f328c43977bb161c7b43715d15f696d6b 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 b4cb47a24f5298637caebeda62c0acc2470398d6..5f6b09428db3726254a4cc5473ce177eca07f01a 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 d10f1ffb20722357851caa5e8dbd5209b3932d94..100e1270d11d652b69505a4514271dd1a7cc578b 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 6f7b7fa041cc4fa3d58af3cb09033108784e2659..77e2f03a3e65b272ed42590f1660054522d5efc7 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 );