diff --git a/ch32v003fun/ch32v003fun.c b/ch32v003fun/ch32v003fun.c
index 12f693b4fb2c72b9cb3d1b318b52630a5d4354a8..ae83a418ef2dfdcb976b62c86a5d47fa3d2a6302 100644
--- a/ch32v003fun/ch32v003fun.c
+++ b/ch32v003fun/ch32v003fun.c
@@ -684,7 +684,24 @@ void DefaultIRQHandler( void )
 
 // This makes it so that all of the interrupt handlers just alias to
 // DefaultIRQHandler unless they are individually overridden.
+
+#if defined(FUNCONF_USE_CLK_SEC) && FUNCONF_USE_CLK_SEC
+/**
+ * @brief 	Non Maskabke Interrupt handler
+ * 			Invoked when the Clock Security system
+ * 			detects the failure of the HSE oscilator.
+ * 			The sys clock is switched to HSI.
+ * 			Clears the CSSF flag in RCC->INTR
+ */
+void NMI_RCC_CSS_IRQHandler( void )
+{
+	RCC->INTR |= RCC_CSSC;	// clear the clock security int flag
+}
+
+void NMI_Handler( void ) 				 __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("NMI_RCC_CSS_IRQHandler"))) __attribute__((used));
+#else 
 void NMI_Handler( void )                 __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+#endif
 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));
 void SW_Handler( void )                  __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
@@ -1000,52 +1017,55 @@ void SystemInit()
 	#define HSEBYP 0
 #endif
 
-	#if defined(FUNCONF_USE_PLL) && FUNCONF_USE_PLL
-		#define BASE_CFGR0 RCC_HPRE_DIV1 | RCC_PLLSRC_HSI_Mul2    // HCLK = SYSCLK = APB1 And, enable PLL
-	#else
-		#define BASE_CFGR0 RCC_HPRE_DIV1      // HCLK = SYSCLK = APB1 And, no pll.
-	#endif
+#if defined(FUNCONF_USE_CLK_SEC) && FUNCONF_USE_CLK_SEC
+	#define RCC_CSS RCC_CSSON									 	// Enable clock security system
+#else
+	#define RCC_CSS 0
+#endif
+
+// HSI always ON - needed for the Debug subsystem
+#define BASE_CTLR	(((FUNCONF_HSITRIM) << 3) | RCC_HSION | HSEBYP | RCC_CSS)
+//#define BASE_CTLR	(((FUNCONF_HSITRIM) << 3) | HSEBYP | RCC_CSS)	// disable HSI in HSE modes
 
 #if defined(FUNCONF_USE_HSI) && FUNCONF_USE_HSI
 	#if defined(FUNCONF_USE_PLL) && FUNCONF_USE_PLL
-		RCC->CFGR0 = BASE_CFGR0;
-		RCC->CTLR  = RCC_HSION | RCC_PLLON | ((FUNCONF_HSITRIM) << 3); // Use HSI, but enable PLL.
+		RCC->CFGR0 = RCC_HPRE_DIV1 | RCC_PLLSRC_HSI_Mul2;
+		RCC->CTLR  = BASE_CTLR | RCC_HSION | RCC_PLLON; 			// Use HSI, enable PLL.
 	#else
-		RCC->CFGR0 = BASE_CFGR0;                                // PLLCLK = HCLK = SYSCLK = APB1
-		RCC->CTLR  = RCC_HSION | ((FUNCONF_HSITRIM) << 3);      // Use HSI, Only.
+		RCC->CFGR0 = RCC_HPRE_DIV1;                               	// PLLCLK = HCLK = SYSCLK = APB1
+		RCC->CTLR  = BASE_CTLR | RCC_HSION;     					// Use HSI, Only.
 	#endif
 #endif
 
 #if defined(FUNCONF_USE_HSE) && FUNCONF_USE_HSE
-
-	RCC->CTLR  = RCC_HSION | RCC_HSEON | RCC_PLLON | HSEBYP;       // Keep HSI and PLL on just in case, while turning on HSE
-
-	// Values lifted from the EVT.  There is little to no documentation on what this does.
-	while(!(RCC->CTLR&RCC_HSERDY));
+	// seems that remapping PA1_2 via AFIO is not required?
+	//RCC->APB2PCENR |= RCC_APB2Periph_AFIO;							// enable AFIO
+	//AFIO->PCFR1 |= GPIO_Remap_PA1_2;								// remap PA1 PA2 to XTAL
+	RCC->CTLR  = BASE_CTLR | RCC_HSION | RCC_HSEON ;				// Keep HSI on while turning on HSE
+	while(!(RCC->CTLR & RCC_HSERDY));   							// Wait till HSE is ready
+	RCC->CFGR0 = RCC_PLLSRC_HSE_Mul2 | RCC_SW_HSE;					// Switch to HSE and set the PLL source
+	while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x04);		// Wait till HSE is used as system clock source
+	RCC->CTLR  = BASE_CTLR | RCC_HSEON;								// (switch off HSI - optional)
+	// sysclk = HSE now
 
 	#if defined(FUNCONF_USE_PLL) && FUNCONF_USE_PLL
-		RCC->CFGR0 = BASE_CFGR0 | RCC_SW_HSE;
-		RCC->CTLR  = RCC_HSEON | RCC_PLLON | HSEBYP;                    // Turn off HSI.
-	#else
-		RCC->CFGR0 = BASE_CFGR0 | RCC_SW_HSE;
-		RCC->CTLR  = RCC_HSEON | HSEBYP;                                // Turn off PLL and HSI.
+		RCC->CTLR = BASE_CTLR | RCC_HSEON | RCC_PLLON;				// start PLL
 	#endif
 #endif
 
 #if FUNCONF_SYSTEM_CORE_CLOCK > 25000000
-	FLASH->ACTLR = FLASH_ACTLR_LATENCY_1;                   //+1 Cycle Latency
+	FLASH->ACTLR = FLASH_ACTLR_LATENCY_1;                   		//+1 Cycle Latency
 #else
-	FLASH->ACTLR = FLASH_ACTLR_LATENCY_0;                   // +0 Cycle Latency
+	FLASH->ACTLR = FLASH_ACTLR_LATENCY_0;                   		// +0 Cycle Latency
 #endif
 
-
-	RCC->INTR  = 0x009F0000;                               // Clear PLL, CSSC, HSE, HSI and LSI ready flags.
+	RCC->INTR  = 0x009F0000;                               			// Clear PLL, CSSC, HSE, HSI and LSI ready flags.
 
 #if defined(FUNCONF_USE_PLL) && FUNCONF_USE_PLL
-	// From SetSysClockTo_48MHZ_HSI
-	while((RCC->CTLR & RCC_PLLRDY) == 0);                       // Wait till PLL is ready
-	RCC->CFGR0 = BASE_CFGR0 | 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
+	while((RCC->CTLR & RCC_PLLRDY) == 0);                       	// Wait till PLL is ready
+	uint32_t tmp32 = RCC->CFGR0 & ~(0x03);							// clr the SW
+	RCC->CFGR0 = tmp32 | 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
 #endif
 
 #if defined( FUNCONF_USE_UARTPRINTF ) && FUNCONF_USE_UARTPRINTF
@@ -1054,7 +1074,6 @@ void SystemInit()
 #if defined( FUNCONF_USE_DEBUGPRINTF ) && FUNCONF_USE_DEBUGPRINTF
 	SetupDebugPrintf();
 #endif
-
 }
 
 // C++ Support
diff --git a/ch32v003fun/ch32v003fun.h b/ch32v003fun/ch32v003fun.h
index c8b7f99e89e11acee21c9f20ceec86d40a4523dd..3e07c245afd787ddb2209581f3b1ac02fbc99996 100644
--- a/ch32v003fun/ch32v003fun.h
+++ b/ch32v003fun/ch32v003fun.h
@@ -14,6 +14,7 @@
 #define FUNCONF_HSITRIM 0x10            // Use factory calibration on HSI Trim.
 #define FUNCONF_SYSTEM_CORE_CLOCK  48000000  // Computed Clock in Hz.
 #define FUNCONF_HSE_BYPASS 0            // Use HSE Bypass feature (for oscillator input)
+#define FUNCONF_USE_CLK_SEC	1			// Use clock security system, enabled by default
 #define FUNCONF_USE_DEBUGPRINTF 1
 #define FUNCONF_USE_UARTPRINTF  0
 #define FUNCONF_SYSTICK_USE_HCLK 0      // Should systick be at 48 MHz or 6MHz?
@@ -34,6 +35,9 @@
 	#define FUNCONF_DEBUGPRINTF_TIMEOUT 160000
 #endif
 
+#if defined(FUNCONF_USE_HSI) && defined(FUNCONF_USE_HSE) && FUNCONF_USE_HSI && FUNCONF_USE_HSE
+       #error FUNCONF_USE_HSI and FUNCONF_USE_HSE cannot both be set
+#endif
 
 #if !defined( FUNCONF_USE_HSI ) && !defined( FUNCONF_USE_HSE )
 	#define FUNCONF_USE_HSI 1 // Default to use HSI
@@ -44,6 +48,10 @@
 	#define FUNCONF_USE_PLL 1 // Default to use PLL
 #endif
 
+#if !defined( FUNCONF_USE_CLK_SEC )
+	#define FUNCONF_USE_CLK_SEC  1// use clock security system by default
+#endif	
+
 #ifndef HSE_VALUE
 	#define HSE_VALUE                 (24000000) // Value of the External oscillator in Hz, default
 #endif
@@ -5074,6 +5082,10 @@ extern "C" {
 #ifndef __ASSEMBLER__
 void handle_reset()            __attribute__((naked)) __attribute((section(".text.handle_reset"))) __attribute__((used));
 void DefaultIRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute__((naked)) __attribute__((used));
+// used to clear the CSS flag in case of clock fail switch
+#if defined(FUNCONF_USE_CLK_SEC) && FUNCONF_USE_CLK_SEC
+	void NMI_RCC_CSS_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute__((naked)) __attribute__((used));
+#endif
 #endif
 
 // For debug writing to the debug interface.
diff --git a/examples/sysclk_config/Makefile b/examples/sysclk_config/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..106c4b21952c6eef833a5abf63caeff8d23fd318
--- /dev/null
+++ b/examples/sysclk_config/Makefile
@@ -0,0 +1,9 @@
+all : flash
+
+TARGET:=sysclk_config
+
+include ../../ch32v003fun/ch32v003fun.mk
+
+flash : cv_flash
+clean : cv_clean
+
diff --git a/examples/sysclk_config/funconfig.h b/examples/sysclk_config/funconfig.h
new file mode 100644
index 0000000000000000000000000000000000000000..c47418bd4725a481c7c8fdce10b0b6da7b89a1e1
--- /dev/null
+++ b/examples/sysclk_config/funconfig.h
@@ -0,0 +1,12 @@
+#ifndef _FUNCONFIG_H
+#define _FUNCONFIG_H
+
+#define FUNCONF_USE_HSE 1  			// external crystal on PA1 PA2
+#define FUNCONF_USE_HSI 0    		// internal 24MHz clock oscillator
+#define FUNCONF_USE_PLL 1			// use PLL x2
+#define FUNCONF_HSE_BYPASS 0 		// bypass the HSE when using an external clock source
+									// requires enabled HSE
+#define FUNCONF_USE_CLK_SEC	1		// clock security system
+#define CH32V003        1
+
+#endif // _FUNCONFIG_Hma
diff --git a/examples/sysclk_config/readme.md b/examples/sysclk_config/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..5f6fb6a12fa707aa24f7d54864b641326942e19f
--- /dev/null
+++ b/examples/sysclk_config/readme.md
@@ -0,0 +1,64 @@
+# System Clock configuration example  
+This project demonstrates various system clock configurations for the CH32V003 MCU and shows a way to unbrick the MCU in case the debug system is not responding.  
+### SysClk configuration
+There are two main sources for the internal clock:  
+1. HSI - internal 24MHz oscillator
+2. HSE - external crystal or clock source  
+
+HSE bypass has to be set if an external clock generator is used - supplying the clock signal  to the OSCI/PA1 pin.
+
+These two sources can feed the PLL (x2) and once the PLL is stable it can be used as 3rd sysclk source.  
+
+Configuring the clock happens in the `funconfig.h` file:  
+```
+#define FUNCONF_USE_HSE 1  			// external crystal on PA1 PA2
+#define FUNCONF_USE_HSI 0    		// internal 24MHz clock oscillator
+#define FUNCONF_USE_PLL 1 			// use PLL x2
+#define FUNCONF_HSE_BYPASS 0 		// bypass the HSE when using an external clock source
+									// requires enabled HSE
+#define CH32V003        1
+```
+In the above example the MCU is clocked from the onboard 24MHz crystal multiplied x2 by the PLL resulting in a 48MHz system clock.  
+Use `make flash monitor` to compile/upload the firmware and open the debug printf terminal. It should print out all the details about the current clock configuration:  
+```
+System Clock Configuration Example
+====================================
+HSI Enabled
+HSI trim = 16
+HSI cal = 36
+HSE Enabled
+PLL Enabled
+PLL Source = HSE
+Clk Security Enabled
+HSE bypass Disabled
+Sysclk source = PLL 
+MCO output: Disabled
+```  
+This message is printed out via the SWIO debug line and using UART, with TX on pin PD5.
+## More details about the clock system  
+According to the [debug system datasheet](https://github.com/openwch/ch32v003/blob/main/RISC-V%20QingKeV2%20Microprocessor%20Debug%20Manual.pdf) for the CH32V003, the HSI is required to access the chip via SWIO pin. The examples provided by WCH confirm it, in their code configuring the HSE modes does not switch the HSI off, it's left always on. This poses a problem for low power projects when all non required subsystems should be turned off. The real measured difference between the HSE only and with HSI running in background was about 800µA.  
+Once the HSI is disabled, the power cycled, the programmer no longer can access the chip via SWIO pin, resulting in error mesages and known "bricking". 
+"Unbricking" using the available programmers and software in most cases works. However. i've encountered situations when only using a combination of WCHLinkE and the WCHLinkUtility software on Windows was able to revive the MCU.  
+As a countermeasure the CSS (Clock Security System) is enabled and allows emergency HSI restore action. The CSS monitors the HSE and if it fails, the HSI is turned on back by the hardware and set as the sysclock source. This reenables the debug channel.  
+A way to reliable "unbrick" the MCU if the HSI has been disabled is to **make the HSE fail by shorting the OSCI/PA1 pin to GND**. Once done, the MCU will run on half the clock rate if the PLL was enabled. HSI will be active and the used can access the chip using usual methods.  
+## MCO - clock output  
+MCU clock output (pin PC4) can be configure using the following funtion:
+
+`MCO_cfg(cfg);`  
+where cfg value is one from the list below:
+```
+MCO_DISABLED 
+MCO_OUT_SYSCLK
+MCO_OUT_HSI	
+MCO_OUT_HSE	
+MCO_OUT_PLL	
+```  
+## Custom NMI interrupt handler  
+Uncommenting `#define USE_CUSTOM_NMI_HANDLER` enables the local custom NMI irq handler. The Non Maskabe Interrupt is triggered by the RCC Clock Security System when the HSE fails. It can be used for other tasks like clock recovery or other ways to detect the clock fail.  
+## PA1 PA2 Testing  
+PA1 and PA2 are the HSE pins. According to the datasheet the PA12_RM bit in the AFIO_PCFR1 register has to be 1 for the crystal to work. However, the tests show that the HSE is taking control over these pins no matter what the configuration is. 
+The example performs a few configuration changes trying to make the HSE fail and trigger the NMI interrupt. Please report if it was successful.
+## Reuse printf for UART  
+Project also shows how to reuse the printf implementation for both channels: via debug line and UART. Experimenting with clock sources might end up with debug channel disabled, UART being the only way to get out the messages.  
+
+
diff --git a/examples/sysclk_config/sysclk_config.c b/examples/sysclk_config/sysclk_config.c
new file mode 100644
index 0000000000000000000000000000000000000000..b9f6c91c19e6b6ff66fc816f2bcc82e46831e592
--- /dev/null
+++ b/examples/sysclk_config/sysclk_config.c
@@ -0,0 +1,283 @@
+/**
+ * @file sysclk_config.c
+ * @author Piotr Zapart
+ * @brief Testing various sysclock configurations for the ch32v003
+ * 			LED Pin definition for the NanoCH32V003 board
+ * 			Try different conbinations in the funconfig.h file, ie:
+ * 
+ * 				#define FUNCONF_USE_HSI 1    
+ *				#define FUNCONF_USE_PLL 1       
+ *				#define CH32V003        1
+ * 
+ * 				#define FUNCONF_USE_HSE 1    
+ *				#define FUNCONF_USE_PLL 0       
+ *				#define CH32V003        1
+ * 
+ * @version 1.0
+ * @date 2023-07-19
+ */
+
+// LED is on D.6 (nanoCH32 board)
+
+/* Uncomment this to enable an MNI interrrupt handler override
+ * and peform other tasks than the default Clock security system
+ * flag clear. 
+ */
+//#define USE_CUSTOM_NMI_HANDLER
+
+#define LED_PIN     6				
+
+#include <stdarg.h>
+#include "ch32v003fun.h"
+#include <stdio.h>
+#include "ch32v003_GPIO_branchless.h"
+
+const char msg_sep[] = "====================================\r\n";
+const char msg_title[] = "System Clock Configuration Example\r\n";
+const char msg_en[] = "Enabled";
+const char msg_dis[] = "Disabled";
+const char *msg_clkSrc[] = {"HSI ", "HSE" , "PLL "};
+const char *msg_mco[] = {"Disabled", "SYSCLK", "HSI 24MHz", "HSE", "PLL"};
+const char msg_clkFail[] = "HSE Fail, switched to HSI, no PLL\r\n";
+
+typedef enum
+{
+	SYSCLK_HSI, 
+	SYSCLK_HSI_PLL,
+	SYSCLK_HSE,
+	SYSCLK_HSE_PLL,
+	SYSCLK_EXTCLK,
+	SYSCLK_EXTCLK_PLL
+}rcc_sysclk_status_e;
+
+typedef enum
+{
+	MCO_DISABLED 		= 0,
+	MCO_OUT_SYSCLK 		= (4<<24),
+	MCO_OUT_HSI			= (5<<24),
+	MCO_OUT_HSE			= (6<<24),
+	MCO_OUT_PLL			= (7<<24)
+}mco_cfg_e;
+
+void print_sysclk_cfg(void);
+static inline void MCO_cfg(mco_cfg_e cfg);
+static inline uint8_t getMCOidx(uint32_t mco);
+void xtal_pin_test(void);
+void UART_setup(int uartBRR);
+int UART_write(int fd, const char *buf, int size);
+static int UART_puts(char *s, int len, void *buf);
+int UART_printf(const char* format, ...);		
+int mini_vpprintf(int (*puts)(char* s, int len, void* buf), void* buf, const char *fmt, va_list va);
+
+volatile uint8_t HSE_fail_flag = 0;		// used in custom NMI handler to signal a HSE fail
+
+// --------------------------------------------------------
+static inline void MCO_cfg(mco_cfg_e cfg)
+{
+	RCC->CFGR0 &= ~RCC_CFGR0_MCO;
+	RCC->CFGR0 |=  cfg & RCC_CFGR0_MCO;
+}
+// --------------------------------------------------------
+static inline uint8_t getMCOidx(uint32_t mco)
+{
+	mco >>= 24;
+	return (mco ? mco-3 : mco);
+}
+// --------------------------------------------------------
+/**
+ * @brief prints out al the clock related details on both
+ * 		channels: debug printf and UART in cas the HSI is
+ * 		disabled and the debug channel can no longer work.
+ */
+void print_sysclk_cfg(void)
+{
+	uint32_t ctlr = RCC->CTLR;
+	uint32_t cfgr0 = RCC->CFGR0;
+	const char *msg_out;
+	uint32_t tmp;
+
+	printf("%s", msg_sep); UART_printf("%s", msg_sep);
+	printf("%s", msg_title); UART_printf("%s", msg_title);
+	printf("%s", msg_sep); UART_printf("%s", msg_sep);
+	// HSI state
+	msg_out = ctlr & RCC_HSION ? msg_en : msg_dis;
+	printf("HSI %s\r\n", msg_out); 
+	UART_printf("HSI %s\r\n", msg_out);
+	// HSI trim value
+	tmp = (ctlr & RCC_HSITRIM)>>3;
+	printf("HSI trim = %ld\r\n", tmp); 
+	UART_printf("HSI trim = %ld\r\n",tmp); 
+	// HSI callibration value
+	tmp = (ctlr & RCC_HSICAL)>>8;
+	printf("HSI cal = %ld\r\n",tmp); 
+	UART_printf("HSI cal = %ld\r\n",tmp);
+	// HSE state
+	msg_out = ctlr & RCC_HSEON ? msg_en : msg_dis;
+	printf("HSE %s\r\n", msg_out); 
+	UART_printf("HSE %s\r\n", msg_out);
+	// PLL state
+	msg_out = ctlr & RCC_PLLON ? msg_en : msg_dis;
+	printf("PLL %s\r\n", msg_out); 
+	UART_printf("PLL %s\r\n", msg_out);
+	// PLL Source
+	msg_out = msg_clkSrc[(cfgr0 & (1<<16))>>16];
+	printf("PLL Source = %s\r\n", msg_out); 
+	UART_printf("PLL Source = %s\r\n", msg_out);
+	// Clock Security system
+	msg_out = ctlr & RCC_CSSON ? msg_en : msg_dis;
+	printf("Clk Security %s\r\n", msg_out);
+	UART_printf("Clk Security %s\r\n", msg_out);
+	// HSE bypass
+	msg_out = ctlr & RCC_HSEBYP ? msg_en : msg_dis;
+	printf("HSE bypass %s\r\n", msg_out);
+	UART_printf("HSE bypass %s\r\n", msg_out);
+	// Sysclock source
+	msg_out = msg_clkSrc[(cfgr0 & 0x0C)>>2];
+	printf("Sysclk source = %s\r\n", msg_out);
+	UART_printf("Sysclk source = %s\r\n", msg_out);
+	// MCO setting
+	msg_out = msg_mco[getMCOidx(cfgr0 & RCC_CFGR0_MCO)];
+	printf("MCO output: %s\r\n", msg_out);	
+	UART_printf("MCO output: %s\r\n", msg_out);	
+}
+// --------------------------------------------------------
+void UART_setup( 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);
+	
+	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;
+}
+// --------------------------------------------------------
+int UART_write(int fd, const char *buf, int size)
+{
+	for(int i = 0; i < size; i++){
+	    while( !(USART1->STATR & USART_FLAG_TC));
+	    USART1->DATAR = *buf++;
+	}
+	return size;
+}
+// --------------------------------------------------------
+static int UART_puts(char *s, int len, void *buf)
+{
+	UART_write( 0, s, len );
+	return len;
+}
+// --------------------------------------------------------
+int UART_printf(const char* format, ...)
+{
+	va_list args;
+	va_start( args, format );
+	int ret_status = mini_vpprintf(UART_puts, 0, format, args);
+	va_end( args );
+	return ret_status;
+}
+// --------------------------------------------------------
+int main()
+{	
+	SystemInit();                                        
+	UART_setup(UART_BRR);
+	GPIO_port_enable(GPIO_port_D);
+    GPIO_pinMode(GPIOv_from_PORT_PIN(GPIO_port_D, LED_PIN), GPIO_pinMode_O_pushPull, GPIO_Speed_10MHz);
+	GPIO_digitalWrite(GPIOv_from_PORT_PIN(GPIO_port_D, LED_PIN), low);	
+	// needed for MCO output
+    GPIO_port_enable(GPIO_port_C);
+    GPIO_pinMode(GPIOv_from_PORT_PIN(GPIO_port_C, 4), GPIO_pinMode_O_pushPullMux, GPIO_Speed_50MHz);
+	MCO_cfg(MCO_OUT_SYSCLK);
+	print_sysclk_cfg();
+
+#if defined(FUNCONF_USE_HSE)
+/**
+ * Various test to abuse the PA1 and PA2 xtal pins and show that HSE is taking
+ * full control over the pins.
+ */
+	xtal_pin_test();
+#endif
+
+	while(1)
+    {
+		// blink onboard led to show the mcu is running
+        GPIO_digitalWrite(GPIOv_from_PORT_PIN(GPIO_port_D, LED_PIN), high);
+        Delay_Ms(100);
+        GPIO_digitalWrite(GPIOv_from_PORT_PIN(GPIO_port_D, LED_PIN), low);
+        Delay_Ms(100);
+		// detect clock failsafe, if HSE was enabled but the current source is HSI/NoPLL -
+		// the clock security system did it's job.
+#if defined(FUNCONF_USE_HSE)
+	#if defined(USE_CUSTOM_NMI_HANDLER)
+		if (HSE_fail_flag)
+		{
+			printf("%s%s%s", msg_sep, msg_clkFail, msg_sep);
+			HSE_fail_flag = 0;
+		}
+	#else
+		if (FUNCONF_USE_HSE && (RCC->CFGR0 & 0x0C) == 0x00)
+		{
+			printf("%s%s%s", msg_sep, msg_clkFail, msg_sep);
+			// UART, depending on the crystal value and PLL setting, most likely will
+			// have bad baudrate setting unless the original clock was HSE only, 24MHz, No PLL
+			//UART_printf("%s%s%s", msg_sep, msg_clkFail, msg_sep);
+		}
+	#endif // END USE_CUSTOM_NMI_HANDLER
+#endif		
+    }
+}
+#if defined(FUNCONF_USE_HSE)
+void xtal_pin_test(void)
+{
+	printf(msg_sep);
+	printf("Testing if PA1 and PA2 config has any impact on HSE.\r\n");
+	printf("Any positive result should trigger the HSE Fail.\r\n");
+	printf("AFIO_PCFR1[PA12RM] = %d\r\n", (AFIO->PCFR1 & AFIO_PCFR1_PA12_REMAP) != 0);
+	printf("PA1+PA2 as PP output, write 0\r\n");
+	GPIO_pinMode(GPIOv_from_PORT_PIN(GPIO_port_A, 1), GPIO_pinMode_O_pushPull, GPIO_Speed_10MHz);
+	GPIO_pinMode(GPIOv_from_PORT_PIN(GPIO_port_A, 2), GPIO_pinMode_O_pushPull, GPIO_Speed_10MHz);
+	GPIO_digitalWrite(GPIOv_from_PORT_PIN(GPIO_port_A, 1), low);
+	GPIO_digitalWrite(GPIOv_from_PORT_PIN(GPIO_port_A, 2), low);
+	Delay_Ms(100);
+	
+	printf("PA1+PA2 as PP out Mux, enable TIM1, PWM on CH2\r\n");
+	GPIO_pinMode(GPIOv_from_PORT_PIN(GPIO_port_A, 1), GPIO_pinMode_O_pushPullMux, GPIO_Speed_10MHz);
+	GPIO_pinMode(GPIOv_from_PORT_PIN(GPIO_port_A, 2), GPIO_pinMode_O_pushPullMux, GPIO_Speed_10MHz);
+	RCC->APB2PCENR |= RCC_APB2Periph_TIM1;
+	TIM1->PSC = 0x0000;
+	TIM1->ATRLR = 255;
+	TIM1->SWEVGR |= TIM_UG;
+	TIM1->CCER |= TIM_CC2NE | TIM_CC2NP;
+	TIM1->CHCTLR2 |= TIM_OC2M_2 | TIM_OC2M_1;
+	TIM1->CH2CVR = 128;
+	TIM1->BDTR |= TIM_MOE;
+	TIM1->CTLR1 |= TIM_CEN;
+	Delay_Ms(100);
+	RCC->APB2PRSTR |= RCC_APB2Periph_TIM1;	// reset Tim1
+	RCC->APB2PRSTR &= ~RCC_APB2Periph_TIM1;
+
+	printf("Enabling Opamp on  PA1+PA2\r\n");
+	EXTEN->EXTEN_CTR |= EXTEN_OPA_EN;
+	Delay_Ms(100);
+	EXTEN->EXTEN_CTR &= ~EXTEN_OPA_EN;
+}
+
+	#if defined(USE_CUSTOM_NMI_HANDLER) 
+	/**
+	 * @brief override the built in NMI handler to perform 
+	 * 		additional operation except clearing the CSS flag
+	 * 		and letting the MCU run with HSI as the clock source.
+	 * 		This could be ie.: try to recover
+	 * 
+	 */
+	void NMI_Handler(void)
+	{
+		RCC->INTR |= RCC_CSSC;	// clear the clock security int flag
+		HSE_fail_flag = 1;
+	}
+	#endif // END USE_CUSTOM_NMI_HANDLER
+#endif