diff --git a/README.md b/README.md
index 919c412af670736420539a135f0283d5715f8715..51c03f60b718f318c1e792401286ce0c3bc53c4c 100644
--- a/README.md
+++ b/README.md
@@ -43,3 +43,12 @@ I wrote some libusb copies of some of the basic functionality from WCH-Link, so
 Currently, it ignores all the respone codes, except when querying the chip.  But it's rather surprising how featured I could get in about 5 hours.
 
 Anyone who wants to write a good/nice utility should probably look at the code in this folder.
+
+###
+ Footnots/links
+
+ * https://raw.githubusercontent.com/openwch/ch32v003/main/RISC-V%20QingKeV2%20Microprocessor%20Debug%20Manual.pdf Debugging Manual
+ * http://www.wch-ic.com/downloads/QingKeV2_Processor_Manual_PDF.html Processor Manual
+ * http://www.wch-ic.com/downloads/CH32V003RM_PDF.html Technical Reference Manual
+ * http://www.wch-ic.com/downloads/CH32V003DS0_PDF.html Datasheet
+
diff --git a/attic/dont_use_wch_printf.c b/attic/dont_use_wch_printf.c
new file mode 100644
index 0000000000000000000000000000000000000000..8c53e6c05dac2e8b43fdc5c53f0b1786b8c894ab
--- /dev/null
+++ b/attic/dont_use_wch_printf.c
@@ -0,0 +1,84 @@
+#include <stdio.h>
+#include "wch_link_base.h"
+
+// TESTED
+
+int main()
+{
+	libusb_device_handle * devh = wch_link_base_setup(1);
+
+	// Place part into reset.
+	wch_link_command( devh, "\x81\x0d\x01\x01", 4, 0, 0, 0 );	// 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\x02", 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\x0d\x01\x02", 4, 0, 0, 0 );
+
+	// Issue reset
+//	wch_link_command( devh, "\x81\x0b\x01\x01", 4, 0, 0, 0 );
+	// Why does db[1] = 6 appear to be some sort of query?
+	// Also 0x0b appears to be a query.  But it wrecks up the chip.
+	// db[1] = 0xd DOES WRITE TO 0xe0000000.  But is it predictable?
+	// db[1] = 8 => get some sort of status back.  This is VERY INTERESTING
+	// db[11]=Get chip status.  Only works in reboot mode.
+	// DO NOT 0x0f!
+
+	// when in pause mode
+	// d 0 2 => Go into reset mode,and do more stuff.
+	// d 0 10 => Force chip into mode but no preamble.
+	//    Found one: 0x0d 0x00 0x03 will write something into the data reg when in debug mode.
+	// Will write other data into the debug register.
+
+	// 0x81, 0x00 = ??? No ops.
+	// 0x81, 0x01 = ??? No ops.
+	// 0x81, 0x01 = ??? No ops.
+	// 0x81, 0x02 = Lots of ops, if in debug mode, wacks chip.  If regular, no bug.
+	// 0x81, 0x03 = ??? No ops.
+	// 0x81, 0x04 = ??? No ops.
+	// 0x81, 0x05 = ??? No ops.
+	// 0x81, 0x06 = Lots of ops ,no clarity.
+	// 0x81, 0x07 = ??? No ops.
+	// 0x81, 0x08 = Lots of ops.
+	//   In debug mode: 82 08 06 00 00 00 00 00 00
+	//   In run mode:   82 08 06 7f ff ff ff ff 03 
+	// 0x81, 0x09 = ??? No ops.
+	// 0x81, 0x0a = ??? No ops
+	// 0x81, 0x0b = Lots of chatter but no go.
+	// 0x81, 0x0c = ??? No ops
+	// 0x81, 0x0d, 0x00, 0x01  --> Halts in such a way d,1,ff does't unhalt.
+	// 0x81, 0x0d, 0x01, 0x01  --> Halts in such a way d,1,ff does't unhalt.
+	// 0x81, 0x0d, 0x01, 0x02  --> Normal Halt.
+	// 0x81, 0x0d, 0x00, 0x03  --> If in debug mode, will write cdef89ab into f4 (data0)
+	// 0x81, 0x0e = ??? No ops
+	// 0x81, 0x10 = ??? No ops
+	// 0x81, 0x11, 0, 0: ==> 20: 82 0d 04 02 08 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+	//      or sometimes ==> 20: 82 0d 04 02 08 02 00 00 88 b3 bc 48 ff ff ff ff 00 30 05 00 
+	//  Point is 0x11 actually comms with the device in non-reset mode. 
+	// 0x81, 0x12 = ??? No ops
+	// 0x81, 0x13 = ??? No ops
+	// 0x81, 0x14 = ??? No ops
+	// 0x81, 0x15 = ??? No ops
+
+	unsigned char databuff[11] = { 0x81, 0x08, 0x08, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	unsigned char rbuff[1024];
+	int i, j;
+//	for( i = 0; i < 20; i++ )
+//	for( j = 0; j < 20; j++ )
+	{
+		databuff[2] = i;
+		databuff[3] = j;
+		int transferred;
+		wch_link_command( devh, databuff, 11, &transferred, rbuff, 1024 );
+		int k;
+		printf( "%d, %d: %d: ", i, j, transferred );
+		for( k = 0; k < transferred; k++ ) printf( "%02x ", rbuff[k] );
+		printf( "\n" );
+		usleep(10000);
+	}
+
+	// Close out.
+	wch_link_command( devh, "\x81\x0d\x01\xff", 4, 0, 0, 0 );
+}
diff --git a/ch32v003evt/ch32v003.ld b/ch32v003evt/ch32v003.ld
index d25e60d0f91560c55b073fbd6d724cd75c5e615d..d3d27288f1530e420dafd11ea17d1c93401890c9 100644
--- a/ch32v003evt/ch32v003.ld
+++ b/ch32v003evt/ch32v003.ld
@@ -1,4 +1,4 @@
-ENTRY( _start )
+ENTRY( InterruptVector )
 
 __stack_size = 256;
 
diff --git a/ch32v003evt/ch32v00x_conf.h b/ch32v003evt/ch32v00x_conf.h
index 01e713230dcf913be285e77a7779acd3f49fa12b..217af40d57d30349d14b4ba0be8e2d7fcd6b10c2 100644
--- a/ch32v003evt/ch32v00x_conf.h
+++ b/ch32v003evt/ch32v00x_conf.h
@@ -31,7 +31,20 @@ extern "C" {
 int main() __attribute__((used));
 void SystemInit(void) __attribute__((used));
 
-	
+// Useful functions
+void SystemInit48HSI( void );
+
+#define UART_BAUD_RATE 115200
+#define OVER8DIV 4
+#define INTEGER_DIVIDER (((25 * (APB_CLOCK)) / ((OVER8DIV) * (UART_BAUD_RATE))))
+#define FRACTIONAL_DIVIDER ((INTEGER_DIVIDER)%100)
+#define UART_BRR ((((INTEGER_DIVIDER) / 100) << 4) | (((((FRACTIONAL_DIVIDER) * ((OVER8DIV)*2)) + 50)/100)&7))
+// Put an output debug UART on Pin D5.
+// You can write to this with printf(...) or puts(...)
+// Call with SetupUART( UART_BRR )
+void SetupUART( int uartBRR );
+
+
 /* ch32v00x_gpio.c -----------------------------------------------------------*/
 /* MASK */
 #define LSB_MASK                  ((uint16_t)0xFFFF)
diff --git a/ch32v003evt/core_riscv.h b/ch32v003evt/core_riscv.h
index 2f533c30b3761c30aa915df956874d7592f77c7c..2e4382d0b8651e0246c2a7eb5619e8809fc9e51e 100644
--- a/ch32v003evt/core_riscv.h
+++ b/ch32v003evt/core_riscv.h
@@ -511,7 +511,7 @@ static inline uint32_t __get_MEPC(void)
  *
  * @return  mepc value
  */
-void __set_MEPC(uint32_t value)
+static inline void __set_MEPC(uint32_t value)
 {
     __ASM volatile("csrw mepc, %0" : : "r"(value));
 }
@@ -532,7 +532,7 @@ static inline uint32_t __get_MCAUSE(void)
 }
 
 /*********************************************************************
- * @fn      __set_MEPC
+ * @fn      __set_MCAUSE
  *
  * @brief   Set the Machine Cause Register
  *
diff --git a/ch32v003evt/startup_ch32v003.c b/ch32v003evt/startup_ch32v003.c
index 8e486b8dd6c0e40eaf45b5025942d42cfab0fb87..c52564a2609669df550c496950e6d4c421e8f04b 100644
--- a/ch32v003evt/startup_ch32v003.c
+++ b/ch32v003evt/startup_ch32v003.c
@@ -5,12 +5,13 @@
 */
 
 #include <stdint.h>
+#include <ch32v00x.h>
 
 int main() __attribute__((used));
 void SystemInit( void ) __attribute__((used));
 
-void InterruptVector() __attribute__((naked)) __attribute((section(".init"))) __attribute__((used));
-void handle_reset() __attribute__((naked)) __attribute((section(".text.handle_reset"))) __attribute__((used));
+void InterruptVector()         __attribute__((naked)) __attribute((section(".init"))) __attribute__((used));
+void handle_reset()            __attribute__((naked)) __attribute((section(".text.handle_reset"))) __attribute__((used));
 void DefaultIRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute__((naked)) __attribute__((used));
 
 extern uint32_t * _sbss;
@@ -27,6 +28,8 @@ void DefaultIRQHandler( void )
 	asm volatile( "1: j 1b" );
 }
 
+// This makes it so that all of the interrupt handlers just alias to
+// DefaultIRQHandler unless they are individually overridden.
 void NMI_Handler( void )                 __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
 void HardFault_Handler( void )           __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
 void SysTick_Handler( void )             __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
@@ -60,10 +63,10 @@ void InterruptVector()
 	asm volatile( "\n\
 	.align  2\n\
 	.option   norvc;\n\
-	j	   handle_reset\n\
+	j handle_reset\n\
 	.word   0\n\
-	.word   NMI_Handler				  /* NMI Handler */		\n\
-	.word   HardFault_Handler			/* Hard Fault Handler */ \n\
+	.word   NMI_Handler               /* NMI Handler */                    \n\
+	.word   HardFault_Handler         /* Hard Fault Handler */             \n\
 	.word   0\n\
 	.word   0\n\
 	.word   0\n\
@@ -72,34 +75,34 @@ void InterruptVector()
 	.word   0\n\
 	.word   0\n\
 	.word   0\n\
-	.word   SysTick_Handler			 /* SysTick Handler */	 \n\
+	.word   SysTick_Handler           /* SysTick Handler */                \n\
 	.word   0\n\
-	.word   SW_Handler				  /* SW Handler */		  \n\
+	.word   SW_Handler                /* SW Handler */                     \n\
 	.word   0\n\
-	/* External Interrupts */									 \n\
-	.word   WWDG_IRQHandler		 	/* Window Watchdog */				\n\
-	.word   PVD_IRQHandler		  	/* PVD through EXTI Line detect */   \n\
-	.word   FLASH_IRQHandler			/* Flash */						  \n\
-	.word   RCC_IRQHandler		  	/* RCC */							\n\
-	.word   EXTI7_0_IRQHandler	   	/* EXTI Line 7..0 */				 \n\
-	.word   AWU_IRQHandler			  /* AWU */							\n\
-	.word   DMA1_Channel1_IRQHandler   	/* DMA1 Channel 1 */				 \n\
-	.word   DMA1_Channel2_IRQHandler   	/* DMA1 Channel 2 */				 \n\
-	.word   DMA1_Channel3_IRQHandler   	/* DMA1 Channel 3 */				 \n\
-	.word   DMA1_Channel4_IRQHandler   	/* DMA1 Channel 4 */				 \n\
-	.word   DMA1_Channel5_IRQHandler   	/* DMA1 Channel 5 */				 \n\
-	.word   DMA1_Channel6_IRQHandler   	/* DMA1 Channel 6 */				 \n\
-	.word   DMA1_Channel7_IRQHandler   	/* DMA1 Channel 7 */				 \n\
-	.word   ADC1_IRQHandler		  	/* ADC1 */						   \n\
-	.word   I2C1_EV_IRQHandler		 	/* I2C1 Event */					 \n\
-	.word   I2C1_ER_IRQHandler		 	/* I2C1 Error */					 \n\
-	.word   USART1_IRQHandler		  	/* USART1 */						 \n\
-	.word   SPI1_IRQHandler				/* SPI1 */						   \n\
-	.word   TIM1_BRK_IRQHandler			/* TIM1 Break */					 \n\
-	.word   TIM1_UP_IRQHandler		 	/* TIM1 Update */					\n\
-	.word   TIM1_TRG_COM_IRQHandler		/* TIM1 Trigger and Commutation */   \n\
-	.word   TIM1_CC_IRQHandler		 	/* TIM1 Capture Compare */		   \n\
-	.word   TIM2_IRQHandler				/* TIM2 */						   \n" );
+	/* External Interrupts */                                              \n\
+	.word   WWDG_IRQHandler           /* Window Watchdog */                \n\
+	.word   PVD_IRQHandler            /* PVD through EXTI Line detect */   \n\
+	.word   FLASH_IRQHandler          /* Flash */                          \n\
+	.word   RCC_IRQHandler            /* RCC */                            \n\
+	.word   EXTI7_0_IRQHandler        /* EXTI Line 7..0 */                 \n\
+	.word   AWU_IRQHandler            /* AWU */                            \n\
+	.word   DMA1_Channel1_IRQHandler  /* DMA1 Channel 1 */                 \n\
+	.word   DMA1_Channel2_IRQHandler  /* DMA1 Channel 2 */                 \n\
+	.word   DMA1_Channel3_IRQHandler  /* DMA1 Channel 3 */                 \n\
+	.word   DMA1_Channel4_IRQHandler  /* DMA1 Channel 4 */                 \n\
+	.word   DMA1_Channel5_IRQHandler  /* DMA1 Channel 5 */                 \n\
+	.word   DMA1_Channel6_IRQHandler  /* DMA1 Channel 6 */                 \n\
+	.word   DMA1_Channel7_IRQHandler  /* DMA1 Channel 7 */                 \n\
+	.word   ADC1_IRQHandler           /* ADC1 */                           \n\
+	.word   I2C1_EV_IRQHandler        /* I2C1 Event */                     \n\
+	.word   I2C1_ER_IRQHandler        /* I2C1 Error */                     \n\
+	.word   USART1_IRQHandler         /* USART1 */                         \n\
+	.word   SPI1_IRQHandler           /* SPI1 */                           \n\
+	.word   TIM1_BRK_IRQHandler       /* TIM1 Break */                     \n\
+	.word   TIM1_UP_IRQHandler        /* TIM1 Update */                    \n\
+	.word   TIM1_TRG_COM_IRQHandler   /* TIM1 Trigger and Commutation */   \n\
+	.word   TIM1_CC_IRQHandler        /* TIM1 Capture Compare */           \n\
+	.word   TIM2_IRQHandler           /* TIM2 */                           \n");
 }
 
 
@@ -112,9 +115,7 @@ void handle_reset()
 	la gp, __global_pointer$\n\
 .option pop\n\
 	la sp, _eusrstack\n"
-
-	// Setup the interrupt vector.
-
+	// Setup the interrupt vector, processor status and INTSYSCR.
 "	li t0, 0x80\n\
 	csrw mstatus, t0\n\
 	li t0, 0x3\n\
@@ -122,32 +123,71 @@ void handle_reset()
 	la t0, InterruptVector\n\
 	ori t0, t0, 3\n\
 	csrw mtvec, t0\n"
+ );
+
+	// Careful: Use registers to prevent overwriting of self-data.
+	// This clears out BSS.
+	register uint32_t * tempout = _sbss;
+	register uint32_t * tempend = _ebss;
+	while( tempout < tempend )
+		*(tempout++) = 0;
 
-	// Clear BSS
-	// Has to be in assembly otherwise it will overwrite the stack.
-    "la t0, _sbss\n\
-    la t1, _ebss\n\
-    bgeu t0, t1, 2f\n\
-1:\n\
-    sw zero, (t0)\n\
-    addi t0, t0, 4\n\
-    bltu t0, t1, 1b\n\
-2:" );
+	// Once we get here, it should be safe to execute regular C code.
 
 	// Load data section from flash to RAM 
-	uint32_t * tempin = _data_lma;
-	uint32_t * tempout = _data_vma;
-	while( tempout != _edata )
+	register uint32_t * tempin = _data_lma;
+	tempout = _data_vma;
+	tempend = _edata;
+	while( tempout != tempend )
 		*(tempout++) = *(tempin++); 
 
-	SystemInit();
+	__set_MEPC( (uint32_t)main );
+
+	// set mepc to be main as the root app.
+	asm volatile( "mret\n" );
+}
+
+void SystemInit48HSI( void )
+{
+	// Values lifted from the EVT.  There is little to no documentation on what this does.
+	RCC->CTLR  = RCC_HSION | RCC_PLLON; 				// Use HSI, but enable PLL.
+	RCC->CFGR0 = RCC_HPRE_DIV1 | RCC_PLLSRC_HSI_Mul2;	// PLLCLK = HSI * 2 = 48 MHz; HCLK = SYSCLK = APB1
+	FLASH->ACTLR = FLASH_ACTLR_LATENCY_1;				// 1 Cycle Latency
+	RCC->INTR  = 0x009F0000;                            // Clear PLL, CSSC, HSE, HSI and LSI ready flags.
+
+	// From SetSysClockTo_48MHZ_HSI
+	while((RCC->CTLR & RCC_PLLRDY) == 0);														// Wait till PLL is ready
+	RCC->CFGR0 = ( RCC->CFGR0 & ((uint32_t)~(RCC_SW))) | (uint32_t)RCC_SW_PLL;					// Select PLL as system clock source
+	while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08);									// Wait till PLL is used as system clock source
+}
 
-	// set mepc to be main as the root interrupt.
-asm volatile( "\n\
-	la t0, main\n\
-	csrw mepc, t0\n\
-	mret\n" );
+void SetupUART( int uartBRR )
+{
+	// Enable GPIOD and UART.
+	RCC->APB2PCENR |= RCC_APB2Periph_GPIOD | RCC_APB2Periph_USART1;
+
+	// Push-Pull, 10MHz Output, GPIO D5, with AutoFunction
+	GPIOD->CFGLR &= ~(0xf<<(4*5));
+	GPIOD->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF)<<(4*5);
+	
+	// 115200, 8n1.  Note if you don't specify a mode, UART remains off even when UE_Set.
+	USART1->CTLR1 = USART_WordLength_8b | USART_Parity_No | USART_Mode_Tx;
+	USART1->CTLR2 = USART_StopBits_1;
+	USART1->CTLR3 = USART_HardwareFlowControl_None;
+
+	USART1->BRR = uartBRR;
+	USART1->CTLR1 |= CTLR1_UE_Set;
 }
 
 
+// For debug writing to the UART.
+int _write(int fd, char *buf, int size)
+{
+	for(int i = 0; i < size; i++){
+	    while( !(USART1->STATR & USART_FLAG_TC));
+	    USART1->DATAR = *buf++;
+	}
+	return size;
+}
+
 
diff --git a/examples/blink/blink.c b/examples/blink/blink.c
index b17372a6d6694539a626c20f5f74d2c2a4e7be14..e99ce3f3e8bf5141451be8caf9249266c6c8267a 100644
--- a/examples/blink/blink.c
+++ b/examples/blink/blink.c
@@ -6,29 +6,10 @@
 
 #define APB_CLOCK SYSTEM_CORE_CLOCK
 
-void SystemInit(void)
-{
-	// Values lifted from the EVT.  There is little to no documentation on what this does.
-	RCC->CTLR |= (uint32_t)0x00000001;
-	RCC->CFGR0 &= (uint32_t)0xFCFF0000;
-	RCC->CTLR &= (uint32_t)0xFEF6FFFF;
-	RCC->CTLR &= (uint32_t)0xFFFBFFFF;
-	RCC->CFGR0 &= (uint32_t)0xFFFEFFFF;
-	RCC->INTR = 0x009F0000;
-
-	// From SetSysClockTo_48MHZ_HSI
-	// This is some dark stuff.  But, I copy-pasted it and it seems towork.
-	FLASH->ACTLR = (FLASH->ACTLR & ((uint32_t)~FLASH_ACTLR_LATENCY)) | FLASH_ACTLR_LATENCY_1; 	// Flash 0 wait state
-	RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; 														// HCLK = SYSCLK = APB1
-	RCC->CFGR0 = ( RCC->CFGR0 & ((uint32_t)~(RCC_PLLSRC)) ) | (uint32_t)(RCC_PLLSRC_HSI_Mul2); 	// PLL configuration: PLLCLK = HSI * 2 = 48 MHz
-	RCC->CTLR |= RCC_PLLON; 																	// Enable PLL
-	while((RCC->CTLR & RCC_PLLRDY) == 0);														// Wait till PLL is ready
-	RCC->CFGR0 = ( RCC->CFGR0 & ((uint32_t)~(RCC_SW))) | (uint32_t)RCC_SW_PLL;					// Select PLL as system clock source
-	while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08);									// Wait till PLL is used as system clock source
-}
-
 int main()
 {
+	SystemInit48HSI();
+
 	// Enable GPIOD.
 	RCC->APB2PCENR |= RCC_APB2Periph_GPIOD;
 
diff --git a/examples/fulldemo/fulldemo.c b/examples/fulldemo/fulldemo.c
index 534e97793a13d1153754865ad41aab018be16fef..340da898fbe9fae936d9966bc72d90ca98a5dc51 100644
--- a/examples/fulldemo/fulldemo.c
+++ b/examples/fulldemo/fulldemo.c
@@ -4,66 +4,16 @@
 
 // Could be defined here, or in the processor defines.
 #define SYSTEM_CORE_CLOCK 48000000
+#define APB_CLOCK SYSTEM_CORE_CLOCK
 
 #include "ch32v00x.h"
 #include <stdio.h>
 
-#define APB_CLOCK SYSTEM_CORE_CLOCK
-
-// For debug writing to the UART.
-int _write(int fd, char *buf, int size)
-{
-    for(int i = 0; i < size; i++){
-        while( !(USART1->STATR & USART_FLAG_TC));
-        USART1->DATAR = *buf++;
-    }
-    return size;
-}
-
-void SystemInit(void)
-{
-	// Values lifted from the EVT.  There is little to no documentation on what this does.
-	RCC->CTLR |= (uint32_t)0x00000001;
-	RCC->CFGR0 &= (uint32_t)0xFCFF0000;
-	RCC->CTLR &= (uint32_t)0xFEF6FFFF;
-	RCC->CTLR &= (uint32_t)0xFFFBFFFF;
-	RCC->CFGR0 &= (uint32_t)0xFFFEFFFF;
-	RCC->INTR = 0x009F0000;
-
-	// From SetSysClockTo_48MHZ_HSI
-	// This is some dark stuff.  But, I copy-pasted it and it seems towork.
-	FLASH->ACTLR = (FLASH->ACTLR & ((uint32_t)~FLASH_ACTLR_LATENCY)) | FLASH_ACTLR_LATENCY_1; 	// Flash 0 wait state
-	RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; 														// HCLK = SYSCLK = APB1
-	RCC->CFGR0 = ( RCC->CFGR0 & ((uint32_t)~(RCC_PLLSRC)) ) | (uint32_t)(RCC_PLLSRC_HSI_Mul2); 	// PLL configuration: PLLCLK = HSI * 2 = 48 MHz
-	RCC->CTLR |= RCC_PLLON; 																	// Enable PLL
-	while((RCC->CTLR & RCC_PLLRDY) == 0);														// Wait till PLL is ready
-	RCC->CFGR0 = ( RCC->CFGR0 & ((uint32_t)~(RCC_SW))) | (uint32_t)RCC_SW_PLL;					// Select PLL as system clock source
-	while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08);									// Wait till PLL is used as system clock source
-
-	// Once clock is up and running, we can enable the UART for other debugging.
-
-	// Enable GPIOD and UART.
-	RCC->APB2PCENR |= RCC_APB2Periph_GPIOD | RCC_APB2Periph_USART1;
-
-	// Push-Pull, 10MHz Output, GPIO D5, with AutoFunction
-	GPIOD->CFGLR &= ~(0xf<<(4*5));
-	GPIOD->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF)<<(4*5);
-	
-	// 115200, 8n1.  Note if you don't specify a mode, UART remains off even when UE_Set.
-	USART1->CTLR1 = USART_WordLength_8b | USART_Parity_No | USART_Mode_Tx;
-	USART1->CTLR2 = USART_StopBits_1;
-	USART1->CTLR3 = USART_HardwareFlowControl_None;
-
-	#define UART_BAUD_RATE 115200
-	#define OVER8DIV 4
-	#define INTEGER_DIVIDER (((25 * (APB_CLOCK)) / (OVER8DIV * (UART_BAUD_RATE))))
-	#define FRACTIONAL_DIVIDER ((INTEGER_DIVIDER)%100)
-	USART1->BRR = ((INTEGER_DIVIDER / 100) << 4) | ((((FRACTIONAL_DIVIDER * (OVER8DIV*2)) + 50)/100)&7);
-	USART1->CTLR1 |= CTLR1_UE_Set;
-}
-
 int main()
 {
+	SystemInit48HSI();
+	SetupUART( UART_BRR );
+
 	// Enable GPIOD.
 	RCC->APB2PCENR |= RCC_APB2Periph_GPIOD;
 
diff --git a/examples/sandbox/sandbox.c b/examples/sandbox/sandbox.c
index d60f918eb2387c057ca9136b5c8fa60ce1d383c1..05365be064812c3b7366d21e686c4742e3f78b5d 100644
--- a/examples/sandbox/sandbox.c
+++ b/examples/sandbox/sandbox.c
@@ -1,68 +1,18 @@
 // Could be defined here, or in the processor defines.
 #define SYSTEM_CORE_CLOCK 48000000
+#define APB_CLOCK SYSTEM_CORE_CLOCK
 
 #include "ch32v00x.h"
 #include <stdio.h>
 #include <string.h>
 
-#define APB_CLOCK SYSTEM_CORE_CLOCK
-
 // Working on WS2812 driving.
 
-// For debug writing to the UART.
-int _write(int fd, char *buf, int size)
-{
-    for(int i = 0; i < size; i++){
-        while( !(USART1->STATR & USART_FLAG_TC));
-        USART1->DATAR = *buf++;
-    }
-    return size;
-}
-
-
-void SystemInit(void)
-{
-	// Values lifted from the EVT.  There is little to no documentation on what this does.
-	RCC->CTLR |= (uint32_t)0x00000001;
-	RCC->CFGR0 &= (uint32_t)0xFCFF0000;
-	RCC->CTLR &= (uint32_t)0xFEF6FFFF;
-	RCC->CTLR &= (uint32_t)0xFFFBFFFF;
-	RCC->CFGR0 &= (uint32_t)0xFFFEFFFF;
-	RCC->INTR = 0x009F0000;
-
-	// From SetSysClockTo_48MHZ_HSI
-	// This is some dark stuff.  But, I copy-pasted it and it seems towork.
-	FLASH->ACTLR = (FLASH->ACTLR & ((uint32_t)~FLASH_ACTLR_LATENCY)) | FLASH_ACTLR_LATENCY_1; 	// Flash 0 wait state
-	RCC->CFGR0 = ( RCC->CFGR0 & ((uint32_t)~(RCC_PLLSRC)) ) | (uint32_t)(RCC_PLLSRC_HSI_Mul2); 	// PLL configuration: PLLCLK = HSI * 2 = 48 MHz
-	RCC->CTLR |= RCC_PLLON; 																	// Enable PLL
-	while((RCC->CTLR & RCC_PLLRDY) == 0);														// Wait till PLL is ready
-	RCC->CFGR0 = ( RCC->CFGR0 & ((uint32_t)~(RCC_SW))) | (uint32_t)RCC_SW_PLL;					// Select PLL as system clock source
-	while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08);									// Wait till PLL is used as system clock source
-
-	// Once clock is up and running, we can enable the UART for other debugging.
-
-	// Enable GPIOD and UART.
-	RCC->APB2PCENR |= RCC_APB2Periph_GPIOD | RCC_APB2Periph_USART1;
-
-	// Push-Pull, 10MHz Output, GPIO D5, with AutoFunction
-	GPIOD->CFGLR &= ~(0xf<<(4*5));
-	GPIOD->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF)<<(4*5);
-	
-	// 115200, 8n1.  Note if you don't specify a mode, UART remains off even when UE_Set.
-	USART1->CTLR1 = USART_WordLength_8b | USART_Parity_No | USART_Mode_Tx;
-	USART1->CTLR2 = USART_StopBits_1;
-	USART1->CTLR3 = USART_HardwareFlowControl_None;
-
-	#define UART_BAUD_RATE 115200
-	#define OVER8DIV 4
-	#define INTEGER_DIVIDER (((25 * (APB_CLOCK)) / (OVER8DIV * (UART_BAUD_RATE))))
-	#define FRACTIONAL_DIVIDER ((INTEGER_DIVIDER)%100)
-	USART1->BRR = ((INTEGER_DIVIDER / 100) << 4) | ((((FRACTIONAL_DIVIDER * (OVER8DIV*2)) + 50)/100)&7);
-	USART1->CTLR1 |= CTLR1_UE_Set;
-}
-
 int main()
 {
+	SystemInit48HSI();
+	SetupUART( UART_BRR );
+
 	int k;
 
 	// Enable GPIOD (for debugging)
@@ -72,11 +22,29 @@ int main()
 	GPIOD->BSHR = 1; // Turn on GPIOD0
 	GPIOD->BSHR = 1<<16; // Turn off GPIOD0
 
-	printf( "CFG: %08x\n", SPI1->CTLR1 );
+
+		//DCSR
+		asm volatile("\n\
+			li t0, 0x4\n\
+			csrw 0x7B0, t0\n\
+		");
 
 	while(1)
 	{
-		Delay_Ms( 100 );
+		Delay_Ms( 2 );
+	    *(uint32_t*)(0xe0000100) = 2;  //Hopefully enable debug (dmcontrol .0) --> Doesn't work.
+
+		uint32_t val = *(uint32_t*)0xe00000f4;
+		*(uint32_t*)0xe00000f4 = 0xaabbccdd;
+
+		printf( "0xe00000f4: %08x %08x\n", val, __get_dscratch0() );
+
+		// Write to dscratch0
+		asm volatile("\n\
+			li t0, 0xa8b8c8d8\n\
+			csrw 0x7B2, t0\n\
+			csrw 0x7B3, t0\n\
+		");
 	}
 }
 
diff --git a/examples/ws2812demo/ws2812b_dma_spi_led_driver.h b/examples/ws2812demo/ws2812b_dma_spi_led_driver.h
index 8d1826403fcea9feb8688265bbe2053df6d2f2f8..d47d8a0090217cac540fe680878284d0bfe60ad4 100644
--- a/examples/ws2812demo/ws2812b_dma_spi_led_driver.h
+++ b/examples/ws2812demo/ws2812b_dma_spi_led_driver.h
@@ -2,6 +2,8 @@
    I may write another version of this to use DMA to timer ports, but, the SPI port can be used
    to generate outputs very efficiently. So, for now, SPI Port.  Additionally, it uses FAR less
    internal bus resources than to do the same thing with timers.
+   
+   For the CH32V003 this means output will be on PORTC Pin 6
 
    Copyright 2023 <>< Charles Lohr, under the MIT-x11 or NewBSD License, you choose!
 
diff --git a/examples/ws2812demo/ws2812bdemo.c b/examples/ws2812demo/ws2812bdemo.c
index a2d21acb220bd76e096d919c22f8213e3898b5a7..9f2d407e895ec50f13beafbd7a0d588269c8bb6b 100644
--- a/examples/ws2812demo/ws2812bdemo.c
+++ b/examples/ws2812demo/ws2812bdemo.c
@@ -1,5 +1,6 @@
 // Could be defined here, or in the processor defines.
 #define SYSTEM_CORE_CLOCK 48000000
+#define APB_CLOCK SYSTEM_CORE_CLOCK
 
 #include "ch32v00x.h"
 #include <stdio.h>
@@ -9,62 +10,8 @@
 
 #include "ws2812b_dma_spi_led_driver.h"
 
-#define APB_CLOCK SYSTEM_CORE_CLOCK
-
 #include "color_utilities.h"
 
-// For debug writing to the UART.
-int _write(int fd, char *buf, int size)
-{
-    for(int i = 0; i < size; i++){
-        while( !(USART1->STATR & USART_FLAG_TC));
-        USART1->DATAR = *buf++;
-    }
-    return size;
-}
-
-
-void SystemInit(void)
-{
-	// Values lifted from the EVT.  There is little to no documentation on what this does.
-	RCC->CTLR |= (uint32_t)0x00000001;
-	RCC->CFGR0 &= (uint32_t)0xFCFF0000;
-	RCC->CTLR &= (uint32_t)0xFEF6FFFF;
-	RCC->CTLR &= (uint32_t)0xFFFBFFFF;
-	RCC->CFGR0 &= (uint32_t)0xFFFEFFFF;
-	RCC->INTR = 0x009F0000;
-
-	// From SetSysClockTo_48MHZ_HSI
-	// This is some dark stuff.  But, I copy-pasted it and it seems towork.
-	FLASH->ACTLR = (FLASH->ACTLR & ((uint32_t)~FLASH_ACTLR_LATENCY)) | FLASH_ACTLR_LATENCY_1; 	// Flash 0 wait state
-	RCC->CFGR0 = ( RCC->CFGR0 & ((uint32_t)~(RCC_PLLSRC)) ) | (uint32_t)(RCC_PLLSRC_HSI_Mul2); 	// PLL configuration: PLLCLK = HSI * 2 = 48 MHz
-	RCC->CTLR |= RCC_PLLON; 																	// Enable PLL
-	while((RCC->CTLR & RCC_PLLRDY) == 0);														// Wait till PLL is ready
-	RCC->CFGR0 = ( RCC->CFGR0 & ((uint32_t)~(RCC_SW))) | (uint32_t)RCC_SW_PLL;					// Select PLL as system clock source
-	while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08);									// Wait till PLL is used as system clock source
-
-	// Once clock is up and running, we can enable the UART for other debugging.
-
-	// Enable GPIOD and UART.
-	RCC->APB2PCENR |= RCC_APB2Periph_GPIOD | RCC_APB2Periph_USART1;
-
-	// Push-Pull, 10MHz Output, GPIO D5, with AutoFunction
-	GPIOD->CFGLR &= ~(0xf<<(4*5));
-	GPIOD->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF)<<(4*5);
-	
-	// 115200, 8n1.  Note if you don't specify a mode, UART remains off even when UE_Set.
-	USART1->CTLR1 = USART_WordLength_8b | USART_Parity_No | USART_Mode_Tx;
-	USART1->CTLR2 = USART_StopBits_1;
-	USART1->CTLR3 = USART_HardwareFlowControl_None;
-
-	#define UART_BAUD_RATE 115200
-	#define OVER8DIV 4
-	#define INTEGER_DIVIDER (((25 * (APB_CLOCK)) / (OVER8DIV * (UART_BAUD_RATE))))
-	#define FRACTIONAL_DIVIDER ((INTEGER_DIVIDER)%100)
-	USART1->BRR = ((INTEGER_DIVIDER / 100) << 4) | ((((FRACTIONAL_DIVIDER * (OVER8DIV*2)) + 50)/100)&7);
-	USART1->CTLR1 |= CTLR1_UE_Set;
-}
-
 #define NR_LEDS 191
 
 uint16_t phases[NR_LEDS];
@@ -87,16 +34,16 @@ uint32_t WS2812BLEDCallback( int ledno )
 int main()
 {
 	int k;
+	SystemInit48HSI();
 
 	// Enable GPIOD (for debugging)
 	RCC->APB2PCENR |= RCC_APB2Periph_GPIOD;
 	GPIOD->CFGLR &= ~(0xf<<(4*0));
 	GPIOD->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*0);
 
+	GPIOD->BSHR = 1;	 // Turn on GPIOD0
 	WS2812BDMAInit( );
 
-	printf( "CFG: %08x\n", SPI1->CTLR1 );
-
 	frameno = 0;
 
 	for( k = 0; k < NR_LEDS; k++ ) phases[k] = k<<8;
@@ -106,8 +53,11 @@ int main()
 
 	while(1)
 	{
+	
+		GPIOD->BSHR = 1;	 // Turn on GPIOD0
 		// Wait for LEDs to totally finish.
 		Delay_Ms( 12 );
+		GPIOD->BSHR = 1<<16; // Turn it off
 
 		while( WS2812BLEDInUse );
 
diff --git a/minichlink/Makefile b/minichlink/Makefile
index bdc97bc760d8e1d5d020f7a5d86632d88a97a296..5706a90ef536e4f396db4b089916757a2145103f 100644
--- a/minichlink/Makefile
+++ b/minichlink/Makefile
@@ -1,4 +1,4 @@
-TOOLS:=wch_erase wch_reset wch_write_simple minichlink
+TOOLS:=wch_erase wch_reset wch_write_simple wch_printf minichlink
 
 all : $(TOOLS)
 
@@ -9,6 +9,8 @@ wch_erase : wch_erase.c
 	gcc -o $@ $^ $(LDFLAGS) $(CFLAGS)
 wch_reset : wch_reset.c
 	gcc -o $@ $^ $(LDFLAGS) $(CFLAGS)
+wch_printf : wch_printf.c
+	gcc -o $@ $^ $(LDFLAGS) $(CFLAGS)
 wch_write_simple : wch_write_simple.c
 	gcc -o $@ $^ $(LDFLAGS) $(CFLAGS)
 minichlink : minichlink.c
@@ -16,6 +18,7 @@ minichlink : minichlink.c
 
 install_udev_rules :
 	echo "SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"1a86\", ATTRS{idProduct}==\"8010\", GROUP=\"plugdev\", MODE=\"0666\"" > /etc/udev/rules.d/99-qch-LinkE.rules
+	service udev restart
 
 clean :
 	rm -rf $(TOOLS)
diff --git a/minichlink/minichlink.c b/minichlink/minichlink.c
index 3298d5d8dd6922c62ebc45bc5c6bd2a03075b0c4..5c3699fb80a656be926cc33208e462b68c6a414b 100644
--- a/minichlink/minichlink.c
+++ b/minichlink/minichlink.c
@@ -47,7 +47,7 @@ int main( int argc, char ** argv )
 	int must_be_end = 0;
 	uint8_t rbuff[1024];
 
-	libusb_device_handle * devh = wch_link_base_setup();
+	libusb_device_handle * devh = wch_link_base_setup(0);
 
 	int iarg;
 	for( iarg = 1; iarg < argc; iarg++ )
diff --git a/minichlink/wch_dump_flash.c b/minichlink/wch_dump_flash.c
index 43857b29175034fb263ac5f09758a4fc548e537c..5105e09399ef15581f916d891c2945e3a937528b 100644
--- a/minichlink/wch_dump_flash.c
+++ b/minichlink/wch_dump_flash.c
@@ -9,7 +9,7 @@ int main()
 	int transferred;
 	int status;
 	char rbuff[1024];
-	libusb_device_handle * devh = wch_link_base_setup();
+	libusb_device_handle * devh = wch_link_base_setup(0);
 
 	wch_link_command( devh, "\x81\x06\x01\x01", 4, 0, 0, 0 );
 
diff --git a/minichlink/wch_erase.c b/minichlink/wch_erase.c
index 96452041c447f22e7429972772025f9b83fc484b..27722897319cc141b88bbaf0f8a321f1334dfd78 100644
--- a/minichlink/wch_erase.c
+++ b/minichlink/wch_erase.c
@@ -6,7 +6,7 @@
 int main()
 {
 	uint8_t rbuff[1024];
-	libusb_device_handle * devh = wch_link_base_setup();
+	libusb_device_handle * devh = wch_link_base_setup(0);
 	int transferred;
 	int status;
 	WCHCHECK( libusb_bulk_transfer( devh, 0x01, "\x81\x02\x01\x01", 4, &transferred, WCHTIMEOUT) );
diff --git a/minichlink/wch_link_base.h b/minichlink/wch_link_base.h
index 38a7161df5e967d65d69288ca3b00150f7b720c0..517924eab8f134eae7ad4579aaa001feaf8d245b 100644
--- a/minichlink/wch_link_base.h
+++ b/minichlink/wch_link_base.h
@@ -54,7 +54,7 @@ static void wch_link_multicommands( libusb_device_handle * devh, int nrcommands,
 	va_end( argp );
 }
 
-static inline libusb_device_handle * wch_link_base_setup()
+static inline libusb_device_handle * wch_link_base_setup( int inhibit_startup )
 {
 	libusb_context * ctx = 0;
 	int status;
@@ -96,26 +96,29 @@ static inline libusb_device_handle * wch_link_base_setup()
 	int transferred;
 	libusb_bulk_transfer( devh, 0x81, rbuff, 1024, &transferred, 1 ); // Clear out any pending transfers.  Don't wait though.
 
-	// 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
+	if( !inhibit_startup )
+	{
+		// 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"
 
-	// 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
+		// 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
 
-	wch_link_command( devh, "\x81\x11\x01\x09", 4, &transferred, rbuff, 1024 ); // Reply: Chip ID + Other data (see below)
-	if( transferred != 20 )
-	{
-		fprintf( stderr, "Error: could not get part status\n" );
-		exit( -99 );
-	}
-	fprintf( stderr, "Part Type (A): 0x%02x%02x (This is the capacity code, in KB)\n", rbuff[2], rbuff[3] );  // Is this Flash size?
-	fprintf( stderr, "Part UUID    : %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", rbuff[4], rbuff[5], rbuff[6], rbuff[7], rbuff[8], rbuff[9], rbuff[10], rbuff[11] );
-	fprintf( stderr, "PFlags       : %02x-%02x-%02x-%02x\n", rbuff[12], rbuff[13], rbuff[14], rbuff[15] );
-	fprintf( stderr, "Part Type (B): %02x-%02x-%02x-%02x\n", rbuff[16], rbuff[17], rbuff[18], rbuff[19] );
+		// 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 )
+		{
+			fprintf( stderr, "Error: could not get part status\n" );
+			exit( -99 );
+		}
+		fprintf( stderr, "Part Type (A): 0x%02x%02x (This is the capacity code, in KB)\n", rbuff[2], rbuff[3] );  // Is this Flash size?
+		fprintf( stderr, "Part UUID    : %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", rbuff[4], rbuff[5], rbuff[6], rbuff[7], rbuff[8], rbuff[9], rbuff[10], rbuff[11] );
+		fprintf( stderr, "PFlags       : %02x-%02x-%02x-%02x\n", rbuff[12], rbuff[13], rbuff[14], rbuff[15] );
+		fprintf( stderr, "Part Type (B): %02x-%02x-%02x-%02x\n", rbuff[16], rbuff[17], rbuff[18], rbuff[19] );
+	}
 	//for( i = 0; i < transferred; i++ )
 	//	printf( "%02x ", rbuff[i] );
 	//printf( "\n" );
diff --git a/minichlink/wch_printf.c b/minichlink/wch_printf.c
new file mode 100644
index 0000000000000000000000000000000000000000..1d78ee8befd5eb0d9ea5deb226dabfee5615beec
--- /dev/null
+++ b/minichlink/wch_printf.c
@@ -0,0 +1,35 @@
+#include <stdio.h>
+#include "wch_link_base.h"
+
+// TESTED
+
+int main()
+{
+	libusb_device_handle * devh = wch_link_base_setup();
+
+	// Issue reset
+//	wch_link_command( devh, "\x81\x0b\x01\x01", 4, 0, 0, 0 );
+	// Why does db[1] = 6 appear to be some sort of query?
+	// Also 0x0b appears to be a query.  But it wrecks up the chip.
+	// db[1] = 0xd DOES WRITE TO 0xe0000000.  But is it predictable?
+	// DO NOT 0x0f!
+	unsigned char databuff[11] = { 0x81, 0x0d, 0x08, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	unsigned char rbuff[1024];
+	int i, j;
+	for( i = 1; i < 20; i++ )
+	for( j = 1; j < 20; j++ )
+	{
+		databuff[2] = i;
+		databuff[3] = j;
+		int transferred;
+		wch_link_command( devh, databuff, 11, &transferred, rbuff, 1024 );
+		int k;
+		printf( "%d, %d: %d: ", i, j, transferred );
+		for( k = 0; k < transferred; k++ ) printf( "%02x ", rbuff[k] );
+		printf( "\n" );
+		usleep(10000);
+	}
+
+	// Close out.
+	wch_link_command( devh, "\x81\x0d\x01\xff", 4, 0, 0, 0 );
+}
diff --git a/minichlink/wch_query.c b/minichlink/wch_query.c
index 844f3e53170739eb2a660fc3ee31e01343aed210..2bab1f74c2761040bda80c2697c230026ebab0f0 100644
--- a/minichlink/wch_query.c
+++ b/minichlink/wch_query.c
@@ -6,7 +6,7 @@
 int main()
 {
 	
-	libusb_device_handle * devh = wch_link_base_setup();
+	libusb_device_handle * devh = wch_link_base_setup(0);
 	int transferred;
 	int status;
 	char rbuff[1024];
diff --git a/minichlink/wch_reset.c b/minichlink/wch_reset.c
index be2d3899f85371a6d6c1127536831942c53c2a0b..df8cadb7c3fcd2ab738482b3002260f8787e8a62 100644
--- a/minichlink/wch_reset.c
+++ b/minichlink/wch_reset.c
@@ -5,7 +5,7 @@
 
 int main()
 {
-	libusb_device_handle * devh = wch_link_base_setup();
+	libusb_device_handle * devh = wch_link_base_setup(0);
 
 	// Issue reset
 	wch_link_command( devh, "\x81\x0b\x01\x01", 4, 0, 0, 0 );
diff --git a/minichlink/wch_write_simple.c b/minichlink/wch_write_simple.c
index de314889dccb5ba1dd4ee8d2eb36fa06dabbf355..838a881fd2f9fa19f5fdefe798b31622713b120a 100644
--- a/minichlink/wch_write_simple.c
+++ b/minichlink/wch_write_simple.c
@@ -73,7 +73,7 @@ int main( int argc, char ** argv )
 		return -9;
 	}
 	
-	libusb_device_handle * devh = wch_link_base_setup();
+	libusb_device_handle * devh = wch_link_base_setup(0);
 	int transferred;
 	wch_link_command( devh, "\x81\x06\x01\x01", 4, 0, 0, 0 );
 	wch_link_command( devh, "\x81\x06\x01\x01", 4, 0, 0, 0 ); // Not sure why but it seems to work better when we request twice.