diff --git a/ch32v203fun/ch32v203fun.c b/ch32v203fun/ch32v203fun.c
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..20b0912bf59ff9d26ffd47bad694dfc340cff5a5 100644
--- a/ch32v203fun/ch32v203fun.c
+++ b/ch32v203fun/ch32v203fun.c
@@ -0,0 +1,901 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <stdint.h>
+#include <ch32v203fun.h>
+
+int errno;
+
+int mini_vsnprintf(char *buffer, unsigned int buffer_len, const char *fmt, va_list va);
+int mini_vpprintf(int (*puts)(char* s, int len, void* buf), void* buf, const char *fmt, va_list va);
+
+static int __puts_uart(char *s, int len, void *buf)
+{
+	_write( 0, s, len );
+	return len;
+}
+
+int printf(const char* format, ...)
+{
+	va_list args;
+	va_start( args, format );
+	int ret_status = mini_vpprintf(__puts_uart, 0, format, args);
+	va_end( args );
+	return ret_status;
+}
+
+/* Some stuff from MUSL
+
+
+----------------------------------------------------------------------
+Copyright © 2005-2020 Rich Felker, et al.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+----------------------------------------------------------------------
+
+*/
+
+/*
+ * mbstate_t is an opaque object to keep conversion state, during multibyte
+ * stream conversions.  The content must not be referenced by user programs.
+ */
+
+#define CURRENT_UTF8 0
+#define IS_CODEUNIT(c) ((unsigned)(c)-0xdf80 < 0x80)
+#define MB_CUR_MAX (CURRENT_UTF8 ? 4 : 1)
+
+typedef void * mbstate_t;
+
+#ifdef UNICODE
+size_t wcrtomb(char *restrict s, wchar_t wc, mbstate_t *restrict st)
+{
+	if (!s) return 1;
+	if ((unsigned)wc < 0x80) {
+		*s = wc;
+		return 1;
+	} else if (MB_CUR_MAX == 1) {
+		if (!IS_CODEUNIT(wc)) {
+		errno = 0x02; // EILSEQ
+		return -1;
+		}
+		*s = wc;
+		return 1;
+	} else if ((unsigned)wc < 0x800) {
+		*s++ = 0xc0 | (wc>>6);
+		*s = 0x80 | (wc&0x3f);
+		return 2;
+	} else if ((unsigned)wc < 0xd800 || (unsigned)wc-0xe000 < 0x2000) {
+		*s++ = 0xe0 | (wc>>12);
+		*s++ = 0x80 | ((wc>>6)&0x3f);
+		*s = 0x80 | (wc&0x3f);
+		return 3;
+	} else if ((unsigned)wc-0x10000 < 0x100000) {
+		*s++ = 0xf0 | (wc>>18);
+		*s++ = 0x80 | ((wc>>12)&0x3f);
+		*s++ = 0x80 | ((wc>>6)&0x3f);
+		*s = 0x80 | (wc&0x3f);
+		return 4;
+	}
+	errno = 0x02;//EILSEQ;
+	return -1;
+}
+int wctomb(char *s, wchar_t wc)
+{
+	if (!s) return 0;
+	return wcrtomb(s, wc, 0);
+}
+#endif
+size_t strlen(const char *s) { const char *a = s;for (; *s; s++);return s-a; }
+size_t strnlen(const char *s, size_t n) { const char *p = memchr(s, 0, n); return p ? p-s : n;}
+void *memset(void *dest, int c, size_t n) { unsigned char *s = dest; for (; n; n--, s++) *s = c; return dest; }
+char *strcpy(char *d, const char *s) { for (; (*d=*s); s++, d++); return d; }
+char *strncpy(char *d, const char *s, size_t n) { for (; n && (*d=*s); n--, s++, d++); return d; }
+int strcmp(const char *l, const char *r)
+{
+	for (; *l==*r && *l; l++, r++);
+	return *(unsigned char *)l - *(unsigned char *)r;
+}
+int strncmp(const char *_l, const char *_r, size_t n)
+{
+	const unsigned char *l=(void *)_l, *r=(void *)_r;
+	if (!n--) return 0;
+	for (; *l && *r && n && *l == *r ; l++, r++, n--);
+	return *l - *r;
+}
+
+static char *twobyte_strstr(const unsigned char *h, const unsigned char *n)
+{
+	uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1];
+	for (h++; *h && hw != nw; hw = hw<<8 | *++h);
+	return *h ? (char *)h-1 : 0;
+}
+
+static char *threebyte_strstr(const unsigned char *h, const unsigned char *n)
+{
+	uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8;
+	uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8;
+	for (h+=2; *h && hw != nw; hw = (hw|*++h)<<8);
+	return *h ? (char *)h-2 : 0;
+}
+
+static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n)
+{
+	uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
+	uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
+	for (h+=3; *h && hw != nw; hw = hw<<8 | *++h);
+	return *h ? (char *)h-3 : 0;
+}
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+#define BITOP(a,b,op) \
+ ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
+
+static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
+{
+	const unsigned char *z;
+	size_t l, ip, jp, k, p, ms, p0, mem, mem0;
+	size_t byteset[32 / sizeof(size_t)] = { 0 };
+	size_t shift[256];
+
+	/* Computing length of needle and fill shift table */
+	for (l=0; n[l] && h[l]; l++)
+		BITOP(byteset, n[l], |=), shift[n[l]] = l+1;
+	if (n[l]) return 0; /* hit the end of h */
+
+	/* Compute maximal suffix */
+	ip = -1; jp = 0; k = p = 1;
+	while (jp+k<l) {
+		if (n[ip+k] == n[jp+k]) {
+		if (k == p) {
+			jp += p;
+			k = 1;
+		} else k++;
+		} else if (n[ip+k] > n[jp+k]) {
+		jp += k;
+		k = 1;
+		p = jp - ip;
+		} else {
+		ip = jp++;
+		k = p = 1;
+		}
+	}
+	ms = ip;
+	p0 = p;
+
+	/* And with the opposite comparison */
+	ip = -1; jp = 0; k = p = 1;
+	while (jp+k<l) {
+		if (n[ip+k] == n[jp+k]) {
+		if (k == p) {
+			jp += p;
+			k = 1;
+		} else k++;
+		} else if (n[ip+k] < n[jp+k]) {
+		jp += k;
+		k = 1;
+		p = jp - ip;
+		} else {
+		ip = jp++;
+		k = p = 1;
+		}
+	}
+	if (ip+1 > ms+1) ms = ip;
+	else p = p0;
+
+	/* Periodic needle? */
+	if (memcmp(n, n+p, ms+1)) {
+		mem0 = 0;
+		p = MAX(ms, l-ms-1) + 1;
+	} else mem0 = l-p;
+	mem = 0;
+
+	/* Initialize incremental end-of-haystack pointer */
+	z = h;
+
+	/* Search loop */
+	for (;;) {
+		/* Update incremental end-of-haystack pointer */
+		if (z-h < l) {
+		/* Fast estimate for MAX(l,63) */
+		size_t grow = l | 63;
+		const unsigned char *z2 = memchr(z, 0, grow);
+		if (z2) {
+			z = z2;
+			if (z-h < l) return 0;
+		} else z += grow;
+		}
+
+		/* Check last byte first; advance by shift on mismatch */
+		if (BITOP(byteset, h[l-1], &)) {
+		k = l-shift[h[l-1]];
+		if (k) {
+			if (k < mem) k = mem;
+			h += k;
+			mem = 0;
+			continue;
+		}
+		} else {
+		h += l;
+		mem = 0;
+		continue;
+		}
+
+		/* Compare right half */
+		for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
+		if (n[k]) {
+		h += k-ms;
+		mem = 0;
+		continue;
+		}
+		/* Compare left half */
+		for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
+		if (k <= mem) return (char *)h;
+		h += p;
+		mem = mem0;
+	}
+}
+
+char *strstr(const char *h, const char *n)
+{
+	/* Return immediately on empty needle */
+	if (!n[0]) return (char *)h;
+
+	/* Use faster algorithms for short needles */
+	h = strchr(h, *n);
+	if (!h || !n[1]) return (char *)h;
+	if (!h[1]) return 0;
+	if (!n[2]) return twobyte_strstr((void *)h, (void *)n);
+	if (!h[2]) return 0;
+	if (!n[3]) return threebyte_strstr((void *)h, (void *)n);
+	if (!h[3]) return 0;
+	if (!n[4]) return fourbyte_strstr((void *)h, (void *)n);
+
+	return twoway_strstr((void *)h, (void *)n);
+}
+
+char *strchr(const char *s, int c)
+{
+	c = (unsigned char)c;
+	if (!c) return (char *)s + strlen(s);
+	for (; *s && *(unsigned char *)s != c; s++);
+	return (char *)s;
+}
+
+
+void *__memrchr(const void *m, int c, size_t n)
+{
+	const unsigned char *s = m;
+	c = (unsigned char)c;
+	while (n--) if (s[n]==c) return (void *)(s+n);
+	return 0;
+}
+
+char *strrchr(const char *s, int c)
+{
+	return __memrchr(s, c, strlen(s) + 1);
+}
+
+void *memcpy(void *dest, const void *src, size_t n)
+{
+	unsigned char *d = dest;
+	const unsigned char *s = src;
+	for (; n; n--) *d++ = *s++;
+	return dest;
+}
+
+int memcmp(const void *vl, const void *vr, size_t n)
+{
+	const unsigned char *l=vl, *r=vr;
+	for (; n && *l == *r; n--, l++, r++);
+	return n ? *l-*r : 0;
+}
+
+
+void *memmove(void *dest, const void *src, size_t n)
+{
+	char *d = dest;
+	const char *s = src;
+
+	if (d==s) return d;
+	if ((uintptr_t)s-(uintptr_t)d-n <= -2*n) return memcpy(d, s, n);
+
+	if (d<s) {
+		for (; n; n--) *d++ = *s++;
+	} else {
+		while (n) n--, d[n] = s[n];
+	}
+
+	return dest;
+}
+void *memchr(const void *src, int c, size_t n)
+{
+	const unsigned char *s = src;
+	c = (unsigned char)c;
+	for (; n && *s != c; s++, n--);
+	return n ? (void *)s : 0;
+}
+
+int puts(const char *s)
+{
+	int sl = strlen( s );
+	_write(0, s, sl );
+	_write(0, "\n", 1 );
+	return sl + 1;
+}
+
+/*
+ * The Minimal snprintf() implementation
+ *
+ * Copyright (c) 2013,2014 Michal Ludvig <michal@logix.cz>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the auhor nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----
+ *
+ * This is a minimal snprintf() implementation optimised
+ * for embedded systems with a very limited program memory.
+ * mini_snprintf() doesn't support _all_ the formatting
+ * the glibc does but on the other hand is a lot smaller.
+ * Here are some numbers from my STM32 project (.bin file size):
+ *      no snprintf():      10768 bytes
+ *      mini snprintf():    11420 bytes     (+  652 bytes)
+ *      glibc snprintf():   34860 bytes     (+24092 bytes)
+ * Wasting nearly 24kB of memory just for snprintf() on
+ * a chip with 32kB flash is crazy. Use mini_snprintf() instead.
+ *
+ */
+
+#define mini_strlen strlen
+
+static int
+mini_itoa(long value, unsigned int radix, int uppercase, int unsig,
+		  char *buffer)
+{
+	char	*pbuffer = buffer;
+	int	negative = 0;
+	int	i, len;
+
+	/* No support for unusual radixes. */
+	if (radix > 16)
+		return 0;
+
+	if (value < 0 && !unsig) {
+		negative = 1;
+		value = -value;
+	}
+
+	/* This builds the string back to front ... */
+	do {
+		int digit = value % radix;
+		*(pbuffer++) = (digit < 10 ? '0' + digit : (uppercase ? 'A' : 'a') + digit - 10);
+		value /= radix;
+	} while (value > 0);
+
+	if (negative)
+		*(pbuffer++) = '-';
+
+	*(pbuffer) = '\0';
+
+	/* ... now we reverse it (could do it recursively but will
+	 * conserve the stack space) */
+	len = (pbuffer - buffer);
+	for (i = 0; i < len / 2; i++) {
+		char j = buffer[i];
+		buffer[i] = buffer[len-i-1];
+		buffer[len-i-1] = j;
+	}
+
+	return len;
+}
+
+static int
+mini_pad(char* ptr, int len, char pad_char, int pad_to, char *buffer)
+{
+	int i;
+	int overflow = 0;
+	char * pbuffer = buffer;
+	if(pad_to == 0) pad_to = len;
+	if(len > pad_to) {
+		len = pad_to;
+		overflow = 1;
+	}
+	for(i = pad_to - len; i > 0; i --) {
+		*(pbuffer++) = pad_char;
+	}
+	for(i = len; i > 0; i --) {
+		*(pbuffer++) = *(ptr++);
+	}
+	len = pbuffer - buffer;
+	if(overflow) {
+		for (i = 0; i < 3 && pbuffer > buffer; i ++) {
+		*(pbuffer-- - 1) = '*';
+		}
+	}
+	return len;
+}
+
+struct mini_buff {
+	char *buffer, *pbuffer;
+	unsigned int buffer_len;
+};
+
+static int
+_puts(char *s, int len, void *buf)
+{
+	if(!buf) return len;
+	struct mini_buff *b = buf;
+	char * p0 = b->buffer;
+	int i;
+	/* Copy to buffer */
+	for (i = 0; i < len; i++) {
+		if(b->pbuffer == b->buffer + b->buffer_len - 1) {
+		break;
+		}
+		*(b->pbuffer ++) = s[i];
+	}
+	*(b->pbuffer) = 0;
+	return b->pbuffer - p0;
+}
+
+#ifdef MINI_PRINTF_ENABLE_OBJECTS
+static int (*mini_handler) (void* data, void* obj, int ch, int lhint, char** bf) = 0;
+static void (*mini_handler_freeor)(void* data, void*) = 0;
+static void * mini_handler_data = 0;
+
+void mini_printf_set_handler(
+	void* data,
+	int (*handler)(void* data, void* obj, int ch, int len_hint, char** buf),
+	void (*freeor)(void* data, void* buf))
+{
+	mini_handler = handler;
+	mini_handler_freeor = freeor;
+	mini_handler_data = data;
+}
+#endif
+
+int
+mini_vsnprintf(char *buffer, unsigned int buffer_len, const char *fmt, va_list va)
+{
+	struct mini_buff b;
+	b.buffer = buffer;
+	b.pbuffer = buffer;
+	b.buffer_len = buffer_len;
+	if(buffer_len == 0) buffer = (void*) 0;
+	int n = mini_vpprintf(_puts, (buffer != (void*)0)?&b:(void*)0, fmt, va);
+	if(buffer == (void*) 0) {
+		return n;
+	}
+	return b.pbuffer - b.buffer;
+}
+
+int
+mini_vpprintf(int (*puts)(char* s, int len, void* buf), void* buf, const char *fmt, va_list va)
+{
+	char bf[24];
+	char bf2[24];
+	char ch;
+#ifdef MINI_PRINTF_ENABLE_OBJECTS
+	void* obj;
+#endif
+	if(puts == (void*)0) {
+		/* run puts in counting mode. */
+		puts = _puts; buf = (void*)0;
+	}
+	int n = 0;
+	while ((ch=*(fmt++))) {
+		int len;
+		if (ch!='%') {
+		len = 1;
+		len = puts(&ch, len, buf);
+		} else {
+		char pad_char = ' ';
+		int pad_to = 0;
+		char l = 0;
+		char *ptr;
+
+		ch=*(fmt++);
+
+		/* Zero padding requested */
+		if (ch == '0') pad_char = '0';
+		while (ch >= '0' && ch <= '9') {
+			pad_to = pad_to * 10 + (ch - '0');
+			ch=*(fmt++);
+		}
+		if(pad_to > (signed int) sizeof(bf)) {
+			pad_to = sizeof(bf);
+		}
+		if (ch == 'l') {
+			l = 1;
+			ch=*(fmt++);
+		}
+
+		switch (ch) {
+			case 0:
+				goto end;
+			case 'u':
+			case 'd':
+				if(l) {
+				len = mini_itoa(va_arg(va, unsigned long), 10, 0, (ch=='u'), bf2);
+				} else {
+				if(ch == 'u') {
+					len = mini_itoa((unsigned long) va_arg(va, unsigned int), 10, 0, 1, bf2);
+				} else {
+					len = mini_itoa((long) va_arg(va, int), 10, 0, 0, bf2);
+				}
+				}
+				len = mini_pad(bf2, len, pad_char, pad_to, bf);
+				len = puts(bf, len, buf);
+				break;
+
+			case 'x':
+			case 'X':
+				if(l) {
+				len = mini_itoa(va_arg(va, unsigned long), 16, (ch=='X'), 1, bf2);
+				} else {
+				len = mini_itoa((unsigned long) va_arg(va, unsigned int), 16, (ch=='X'), 1, bf2);
+				}
+				len = mini_pad(bf2, len, pad_char, pad_to, bf);
+				len = puts(bf, len, buf);
+				break;
+
+			case 'c' :
+				ch = (char)(va_arg(va, int));
+				len = mini_pad(&ch, 1, pad_char, pad_to, bf);
+				len = puts(bf, len, buf);
+				break;
+
+			case 's' :
+				ptr = va_arg(va, char*);
+				len = mini_strlen(ptr);
+				if (pad_to > 0) {
+				len = mini_pad(ptr, len, pad_char, pad_to, bf);
+				len = puts(bf, len, buf);
+				} else {
+				len = puts(ptr, len, buf);
+				}
+				break;
+#ifdef MINI_PRINTF_ENABLE_OBJECTS
+				case 'O' :  /* Object by content (e.g. str) */
+			case 'R' :  /* Object by representation (e.g. repr)*/
+				obj = va_arg(va, void*);
+				len = mini_handler(mini_handler_data, obj, ch, pad_to, &ptr);
+				if (pad_to > 0) {
+				len = mini_pad(ptr, len, pad_char, pad_to, bf);
+				len = puts(bf, len, buf);
+				} else {
+				len = puts(ptr, len, buf);
+				}
+				mini_handler_freeor(mini_handler_data, ptr);
+				break;
+#endif
+			default:
+				len = 1;
+				len = puts(&ch, len, buf);
+				break;
+		}
+		}
+		n = n + len;
+	}
+	end:
+	return n;
+}
+
+
+int
+mini_snprintf(char* buffer, unsigned int buffer_len, const char *fmt, ...)
+{
+	int ret;
+	va_list va;
+	va_start(va, fmt);
+	ret = mini_vsnprintf(buffer, buffer_len, fmt, va);
+	va_end(va);
+
+	return ret;
+}
+
+int
+mini_pprintf(int (*puts)(char*s, int len, void* buf), void* buf, const char *fmt, ...)
+{
+	int ret;
+	va_list va;
+	va_start(va, fmt);
+	ret = mini_vpprintf(puts, buf, fmt, va);
+	va_end(va);
+
+	return ret;
+}
+
+/*
+	C version of CH32V203 Startup .s file from WCH
+	This file is public domain where possible or the following where not:
+	Copyright 2023 Charles Lohr, Alexander Mandera, under the MIT-x11 or NewBSD licenses, you choose.
+*/
+
+#ifdef CPLUSPLUS
+// Method to call the C++ constructors
+void __libc_init_array(void);
+#endif
+
+int main() __attribute__((used));
+void SystemInit( void ) __attribute__((used));
+
+extern uint32_t * _sbss;
+extern uint32_t * _ebss;
+extern uint32_t * _data_lma;
+extern uint32_t * _data_vma;
+extern uint32_t * _edata;
+
+// If you don't override a specific handler, it will just spin forever.
+void DefaultIRQHandler( void )
+{
+	// Infinite Loop
+	asm volatile( "1: j 1b" );
+}
+
+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 Ecall_M_Mode_Handler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void Ecall_U_Mode_Handler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void Break_Point_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));
+void WWDG_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void PVD_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void TAMPER_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void RTC_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void FLASH_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void RCC_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void EXTI0_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void EXTI1_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void EXTI2_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void EXTI3_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void EXTI4_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void DMA1_Channel1_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void DMA1_Channel2_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void DMA1_Channel3_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void DMA1_Channel4_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void DMA1_Channel5_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void DMA1_Channel6_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void DMA1_Channel7_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void ADC1_2_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void USB_HP_CAN1_TX_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void USB_LP_CAN1_RX0_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void CAN1_RX1_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void CAN1_SCE_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void EXTI9_5_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void TIM1_BRK_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void TIM1_UP_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void TIM1_TRG_COM_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void TIM1_CC_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void TIM2_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void TIM3_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void TIM4_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void I2C1_EV_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void I2C1_ER_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void I2C2_EV_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void I2C2_ER_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void SPI1_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void SPI2_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void USART1_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void USART2_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void USART3_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void EXTI15_10_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void RTCAlarm_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void USBWakeUp_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void USBHD_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void USBHDWakeUp_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void ETH_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void ETHWakeUp_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void TIM5_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void OSC32KCal_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void OSCWakeUp_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void UART4_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+void DMA1_Channel8_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
+
+void InterruptVector()         __attribute__((naked)) __attribute((section(".init"))) __attribute((weak,alias("InterruptVectorDefault")));
+void InterruptVectorDefault()  __attribute__((naked)) __attribute((section(".init")));
+
+void InterruptVectorDefault()
+{
+	asm volatile( "\n\
+	.align	1\n\
+	.option   push;\n\
+	.option norvc;\n\
+	j handle_reset\n\
+	.word   0 \n\
+	.word   NMI_Handler                /* NMI */ \n\
+	.word   HardFault_Handler          /* Hard Fault */ \n\
+	.word   0 \n\
+	.word   Ecall_M_Mode_Handler       /* Ecall M Mode */ \n\
+	.word   0 \n\
+	.word   0 \n\
+	.word   Ecall_U_Mode_Handler       /* Ecall U Mode */ \n\
+	.word   Break_Point_Handler        /* Break Point */ \n\
+	.word   0 \n\
+	.word   0 \n\
+	.word   SysTick_Handler            /* SysTick */ \n\
+	.word   0 \n\
+	.word   SW_Handler                 /* SW */ \n\
+	.word   0 \n\
+	/* External Interrupts */ \n\
+	.word   WWDG_IRQHandler            /* Window Watchdog */ \n\
+	.word   PVD_IRQHandler             /* PVD through EXTI Line detect */ \n\
+	.word   TAMPER_IRQHandler          /* TAMPER */ \n\
+	.word   RTC_IRQHandler             /* RTC */ \n\
+	.word   FLASH_IRQHandler           /* Flash */ \n\
+	.word   RCC_IRQHandler             /* RCC */ \n\
+	.word   EXTI0_IRQHandler           /* EXTI Line 0 */ \n\
+	.word   EXTI1_IRQHandler           /* EXTI Line 1 */ \n\
+	.word   EXTI2_IRQHandler           /* EXTI Line 2 */ \n\
+	.word   EXTI3_IRQHandler           /* EXTI Line 3 */ \n\
+	.word   EXTI4_IRQHandler           /* EXTI Line 4 */ \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_2_IRQHandler          /* ADC1_2 */ \n\
+	.word   USB_HP_CAN1_TX_IRQHandler  /* USB HP and CAN1 TX */ \n\
+	.word   USB_LP_CAN1_RX0_IRQHandler /* USB LP and CAN1RX0 */ \n\
+	.word   CAN1_RX1_IRQHandler        /* CAN1 RX1 */ \n\
+	.word   CAN1_SCE_IRQHandler        /* CAN1 SCE */ \n\
+	.word   EXTI9_5_IRQHandler         /* EXTI Line 9..5 */ \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\
+	.word   TIM3_IRQHandler            /* TIM3 */ \n\
+	.word   TIM4_IRQHandler            /* TIM4 */ \n\
+	.word   I2C1_EV_IRQHandler         /* I2C1 Event */ \n\
+	.word   I2C1_ER_IRQHandler         /* I2C1 Error */ \n\
+	.word   I2C2_EV_IRQHandler         /* I2C2 Event */ \n\
+	.word   I2C2_ER_IRQHandler         /* I2C2 Error */ \n\
+	.word   SPI1_IRQHandler            /* SPI1 */ \n\
+	.word   SPI2_IRQHandler            /* SPI2 */ \n\
+	.word   USART1_IRQHandler          /* USART1 */ \n\
+	.word   USART2_IRQHandler          /* USART2 */ \n\
+	.word   USART3_IRQHandler          /* USART3 */ \n\
+	.word   EXTI15_10_IRQHandler       /* EXTI Line 15..10 */ \n\
+	.word   RTCAlarm_IRQHandler        /* RTC Alarm through EXTI Line */ \n\
+	.word   USBWakeUp_IRQHandler       /* USB Wake up from suspend */ \n\
+	.word   USBHD_IRQHandler           /* USBHD Break */ \n\
+	.word   USBHDWakeUp_IRQHandler     /* USBHD Wake up from suspend */ \n\
+	.word   ETH_IRQHandler             /* ETH global */ \n\
+	.word   ETHWakeUp_IRQHandler       /* ETH Wake up */ \n\
+	.word   0                          /* BLE BB */ \n\
+	.word   0                          /* BLE LLE */ \n\
+	.word   TIM5_IRQHandler            /* TIM5 */ \n\
+	.word   UART4_IRQHandler           /* UART4 */ \n\
+	.word   DMA1_Channel8_IRQHandler   /* DMA1 Channel8 */ \n\
+	.word   OSC32KCal_IRQHandler       /* OSC32KCal */ \n\
+	.word   OSCWakeUp_IRQHandler       /* OSC Wake Up */ \n\
+	.option pop;\n");
+
+}
+
+void handle_reset()
+{
+	asm volatile( "\n\
+.option push\n\
+.option norelax\n\
+	la gp, __global_pointer$\n\
+.option pop\n\
+	la sp, _eusrstack\n"
+#if __GNUC__ > 10
+  ".option arch, +zicsr\n"
+#endif
+  // Setup the interrupt vector, processor status and INTSYSCR.
+  "	li a0, 0x80\n\
+	csrw mstatus, a0\n\
+	li a3, 0x3\n\
+	la a0, InterruptVector\n\
+	or a0, a0, a3\n\
+	csrw mtvec, a0\n"
+	: : : "a0", "a3", "memory");
+
+	// Careful: Use registers to prevent overwriting of self-data.
+	// This clears out BSS.
+	asm volatile(
+"	la a0, _sbss\n\
+	la a1, _ebss\n\
+	li a2, 0\n\
+	bge a0, a1, 2f\n\
+1:	sw a2, 0(a0)\n\
+	addi a0, a0, 4\n\
+	blt a0, a1, 1b\n\
+2:"
+			// This loads DATA from FLASH to RAM.
+"	la a0, _data_lma\n\
+	la a1, _data_vma\n\
+	la a2, _edata\n\
+1:	beq a1, a2, 2f\n\
+	lw a3, 0(a0)\n\
+	sw a3, 0(a1)\n\
+	addi a0, a0, 4\n\
+	addi a1, a1, 4\n\
+	bne a1, a2, 1b\n\
+2:\n"
+#ifdef CPLUSPLUS
+		// Call __libc_init_array function
+"	call %0 \n\t"
+: : "i" (__libc_init_array)
+#else
+: :
+#endif
+: "a0", "a1", "a2", "a3", "memory"
+);
+
+	SETUP_SYSTICK_HCLK
+
+	// set mepc to be main as the root app.
+	asm volatile(
+"	csrw mepc, %[main]\n"
+"	mret\n" : : [main]"r"(main) );
+}
+
+void SystemInit48HSI( void )
+{
+	EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
+
+	RCC->CFGR0 = RCC_HPRE_DIV1 | RCC_PPRE2_DIV1 | RCC_PPRE1_DIV2;
+	RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
+	RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL6);
+	RCC->INTR = 0x009F0000;
+
+	/* Enable PLL */
+	RCC->CTLR |= RCC_PLLON;
+
+	/* Wait till PLL is ready */
+	while((RCC->CTLR & RCC_PLLRDY) == 0) {}
+
+	/* Select PLL as system clock source */
+	RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
+	RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+
+	/* Wait till PLL is used as system clock source */
+	while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) {}
+}
\ No newline at end of file
diff --git a/ch32v203fun/ch32v203fun.h b/ch32v203fun/ch32v203fun.h
index 139ba2c4e2624861167de5953f55ad78656758dd..eea1d523c9fd3f847e4614f09f663c0500ede77a 100644
--- a/ch32v203fun/ch32v203fun.h
+++ b/ch32v203fun/ch32v203fun.h
@@ -12,6 +12,8 @@
 * microcontroller manufactured by Nanjing Qinheng Microelectronics.
 *******************************************************************************/
 
+#include <stdint.h>
+
 /* IO definitions */
 #ifdef __cplusplus
 #define     __I     volatile                /*!< defines 'read only' permissions      */
@@ -6691,7 +6693,9 @@ typedef enum
 
 #ifdef __cplusplus
 };
-#endif /* __CH32V00x_CONF_H */
+#endif
+
+#endif  /* __CH32V00x_CONF_H */
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////////////////
@@ -7355,7 +7359,7 @@ void DefaultIRQHandler( void ) __attribute__((section(".text.vector_handler")))
 #define Delay_Us(n) DelaySysTick( (n) * DELAY_US_TIME )
 #define Delay_Ms(n) DelaySysTick( (n) * DELAY_MS_TIME )
 
-#ifndef ASSEMBLER
+#ifndef __ASSEMBLER__
 
 void DelaySysTick( uint32_t n );
 
@@ -7363,7 +7367,8 @@ void DelaySysTick( uint32_t n );
 int main() __attribute__((used));
 void SystemInit(void) __attribute__((used));
 
-// TODO: Initialization functions
+// Initialization functions
+void SystemInit48HSI( void );
 
 // TODO: Debug and UART
 
diff --git a/ch32v203fun/ch32v203fun.ld b/ch32v203fun/ch32v203fun.ld
index eee50128b155ba419b25f45da6039b5359796a9f..b4dfea7da7e7b92541cdcfe6475225cb98b30952 100644
--- a/ch32v203fun/ch32v203fun.ld
+++ b/ch32v203fun/ch32v203fun.ld
@@ -1,186 +1,147 @@
-/* Source: https://github.com/openwch/ch32v20x/blob/main/EVT/EXAM/SRC/Ld/Link.ld */
-
-ENTRY( _start )
-
-__stack_size = 2048;
-
-PROVIDE( _stack_size = __stack_size );
-
+ENTRY( InterruptVector )
 
 MEMORY
 {
-/* CH32V20x_D6 - CH32V203F6-CH32V203G6-CH32V203K6-CH32V203C6 */
-/*
-	FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 32K
-	RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 10K
-*/
-
-/* CH32V20x_D6 - CH32V203K8-CH32V203C8-CH32V203G8-CH32V203F8 */
-/**/
 	FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K
-	RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
-
-
-/* CH32V20x_D8 - CH32V203RB
-   CH32V20x_D8W - CH32V208x
-   FLASH + RAM supports the following configuration
-   FLASH-128K + RAM-64K
-   FLASH-144K + RAM-48K
-   FLASH-160K + RAM-32K
-
-	FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 160K
-	RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
-*/
+	RAM (xrw)  : ORIGIN = 0x20000000, LENGTH = 20K
 }
 
-
 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
 
-	.init :
-	{
-		_sinit = .;
-		. = ALIGN(4);
-		KEEP(*(SORT_NONE(.init)))
-		. = ALIGN(4);
-		_einit = .;
-	} >FLASH AT>FLASH
-
-  .vector :
-  {
-      *(.vector);
-	  . = ALIGN(64);
-  } >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
+    PROVIDE( _etext = . );
+    PROVIDE( _eitcm = . );  
 
-	.dalign :
-	{
-		. = ALIGN(4);
-		PROVIDE(_data_vma = .);
-	} >RAM AT>FLASH
+    .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
+    .dlalign :
+    {
+      . = ALIGN(4); 
+      PROVIDE(_data_lma = .);
+    } >FLASH AT>FLASH
 
-	.data :
-	{
-    	*(.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
+    .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 = . );
 
-	.bss :
-	{
-		. = ALIGN(4);
-		PROVIDE( _sbss = .);
-  	    *(.sbss*)
-        *(.gnu.linkonce.sb.*)
-		*(.bss*)
-     	*(.gnu.linkonce.b.*)
-		*(COMMON*)
-		. = ALIGN(4);
-		PROVIDE( _ebss = .);
-	} >RAM AT>FLASH
+	PROVIDE( _eusrstack = ORIGIN(RAM) + LENGTH(RAM));	
+}
 
-	PROVIDE( _end = _ebss);
-	PROVIDE( end = . );
 
-    .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :
-    {
-        PROVIDE( _heap_end = . );
-        . = ALIGN(4);
-        PROVIDE(_susrstack = . );
-        . = . + __stack_size;
-        PROVIDE( _eusrstack = .);
-    } >RAM
 
-}
\ No newline at end of file
diff --git a/examples_v203/blink/Makefile b/examples_v203/blink/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..cc04b7b02057e4a1e8add6e0a2f3c6f97b1793a7
--- /dev/null
+++ b/examples_v203/blink/Makefile
@@ -0,0 +1,10 @@
+all : flash
+
+TARGET:=blink
+
+include ../../ch32v203fun/ch32v203fun.mk
+
+flash : cv_flash
+clean : cv_clean
+
+
diff --git a/examples_v203/blink/blink.c b/examples_v203/blink/blink.c
new file mode 100644
index 0000000000000000000000000000000000000000..48f8383f16905b0d162b15b401e3f1cef322dab9
--- /dev/null
+++ b/examples_v203/blink/blink.c
@@ -0,0 +1,25 @@
+// Could be defined here, or in the processor defines.
+#define SYSTEM_CORE_CLOCK 48000000
+
+#include "ch32v203fun.h"
+#include <stdio.h>
+
+int main()
+{
+	SystemInit48HSI();
+
+	// Enable GPIOs
+	RCC->APB2PCENR |= RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOC;
+
+	// GPIO A15 Push-Pull
+	GPIOA->CFGHR &= ~((uint32_t)0x0F<<(4*7));
+	GPIOA->CFGHR |= (uint32_t)(GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*7);
+
+	while(1)
+	{
+		GPIOA->BSHR = (1<<15);	 // Turn on GPIO
+		Delay_Ms( 250 );
+		GPIOA->BSHR = (1<<(16+15)); // Turn off GPIO
+		Delay_Ms( 250 );
+	}
+}