From fa0acbb0dbddace0ace0b3cbe621dbd74089b202 Mon Sep 17 00:00:00 2001 From: Alexander Mandera <alexander@mandera.eu> Date: Sat, 17 Jun 2023 12:05:06 +0200 Subject: [PATCH] Add ch32v203fun.c and example --- ch32v203fun/ch32v203fun.c | 901 +++++++++++++++++++++++++++++++++++ ch32v203fun/ch32v203fun.h | 11 +- ch32v203fun/ch32v203fun.ld | 301 +++++------- examples_v203/blink/Makefile | 10 + examples_v203/blink/blink.c | 25 + 5 files changed, 1075 insertions(+), 173 deletions(-) create mode 100644 examples_v203/blink/Makefile create mode 100644 examples_v203/blink/blink.c diff --git a/ch32v203fun/ch32v203fun.c b/ch32v203fun/ch32v203fun.c index e69de29..20b0912 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 139ba2c..eea1d52 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 eee5012..b4dfea7 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 0000000..cc04b7b --- /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 0000000..48f8383 --- /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 ); + } +} -- GitLab