setup now working, toolchain file is disapointing however.

This commit is contained in:
jakeg00dwin 2025-03-07 14:00:52 -08:00
parent b7debf7eee
commit a80c0f1360
11 changed files with 7430 additions and 334 deletions

35
issues.md Normal file
View file

@ -0,0 +1,35 @@
# Issues
This is to track my blockers and issues with getting the ch32fun repo to
work under cmake and with cpputest.
Q: why isn't it working?
It's giving a riscv internal compiler error. ch32fun.c:114:1
I don't think it's actually a code issue as it's the OG file and the repo
worked fine.
Q: What is different from the repo?
1. I don't dynamically generate the linker script.
2. I'm missing some of the defines.
3. My flags/options look different.
4. Directory layout.
5. Missing the LD file for ch32fun dir.
Q: what steps should I take to reduce the differnces?
- Re-copy the source files.
- Use the same directory structure(mostly)
- Use the `./src/ch32fun/ch32fun.ld` script to generate linker scripts?
Figured out issue,
I needed to ensure the same flags were applied accross the
`main.c`, `ch32fun.c` and the linking step.
Otherwise they pretty much got ignored.
Seems like the toolchain file did jackshit as well.

View file

@ -73,8 +73,6 @@ set(MCU CH32V003)
#Define it for the preprocessor as well. #Define it for the preprocessor as well.
add_compile_definitions(${MCU}=1) add_compile_definitions(${MCU}=1)
#add_definitions(-D${MCU})
################################################## ##################################################
# Advanced Section # Advanced Section
@ -109,8 +107,14 @@ set(C_FLAGS_ARCH "\
# CFLAGS # CFLAGS
#------------------- #-------------------
# None of the linker flags or the cflags seem to do anything.
# They print out from the messages just fine, but they are ignored.
UNSET(CMAKE_C_FLAGS CACHE)
# I'm appending to the existing cflags from the cmake file in the root dir. # I'm appending to the existing cflags from the cmake file in the root dir.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS_ARCH} ${OBJECT_GEN_FLAGS}") #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS_ARCH} ${OBJECT_GEN_FLAGS}")
#set(CMAKE_C_FLAGS_INIT "${CMAKE_C_FLAGS} ${C_FLAGS_ARCH} ${OBJECT_GEN_FLAGS}" CACHE STRING "" FORCE)
#------------------- #-------------------
@ -124,7 +128,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS_ARCH} ${OBJECT_GEN_FLAGS}")
#set(LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/${LINKER_SCRIPT}) #set(LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/${LINKER_SCRIPT})
#set(LINKER_SCRIPT "./src/ch32v003.ld") #set(LINKER_SCRIPT "./src/ch32v003.ld")
set(LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/src/linker_script.ld") #set(LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/src/linker_script.ld")
#set(LD_FLAGS "-lgcc") #set(LD_FLAGS "-lgcc")
set(LD_FLAGS " \ set(LD_FLAGS " \

1684
src/ch32fun.c Executable file

File diff suppressed because it is too large Load diff

995
src/ch32fun.h Executable file
View file

@ -0,0 +1,995 @@
/* SPDX-License-Identifier: MIT */
// This contains a copy of ch32v00x.h and core_riscv.h ch32v00x_conf.h and other misc functions See copyright explanation at the end of the file.
#ifndef __CH32FUN_H
#define __CH32FUN_H
#include "funconfig.h"
/*****************************************************************************
CH32V003 BASICS
1. Be sure to see configuration section below!
2. Backend Initialization
SystemInit();
3. Arduino-like I/O
funGpioInitAll();
funPinMode( PA2, GPIO_CFGLR_OUT_10Mhz_PP );
funDigitalWrite( PA2, FUN_HIGH );
funDigitalWrite( PA2, FUN_LOW );
funAnalogRead( 0 ); // Not Pin number, but rather analog number.
4. Delays
Delay_Us(n)
Delay_Ms(n)
DelaySysTick( uint32_t n );
5. printf
printf, _write may be semihosted, or printed to UART.
poll_input, handle_debug_input may be used with semihsoting to accept input from host.
For UART printf, on:
CH32V003, Port D5, 115200 8n1
CH32V203, Port A9, 115200 8n1
Modifications can be made to SetupUart, or your own version as desired.
6. ISR Control Routines
__enable_irq(); // For global interrupt enable
__disable_irq(); // For global interrupt disable
__isenabled_irq(); // For seeing if interrupts are enabled.
NVIC_EnableIRQ(IRQn_Type IRQn) // To enable a specific interrupt
7. Hardware MMIO structs, i.e.
SysTick->CNT = current system tick counter (can be Hclk or Hclk/8)
TIM2->CH1CVR = direct control over a PWM output
8. Default debug behavior, when semihosting:
a. You get access to DidDebuggerAttach() - so you can see if a debugger has attached.
b. WaitForDebuggerToAttach( int timeout_ms ) - if timeout_ms == 0, will wait for forever.
c. printf will wait 120ms (configurable) to make sure it doesn't drop data. Otherwise,
printf will fast-path to exit after the first timeout. It will still do the string
formatting, but will not wait on output. Timeout is configured with
FUNCONF_DEBUGPRINTF_TIMEOUT.
d. If you hard fault, it will wait indefinitely for a debugger to attach, once attached,
will printf the fault cause, and the memory address of the fault. Space can be saved
by setting FUNCONF_DEBUG_HARDFAULT to 0.
*/
/******************************************************************************
* CH32V003 Fun Configs; please define any non-default options in funconfig.h *
#define FUNCONF_USE_PLL 1 // Use built-in 2x PLL
#define FUNCONF_USE_HSI 1 // Use HSI Internal Oscillator
#define FUNCONF_USE_HSE 0 // Use External Oscillator
#define FUNCONF_HSITRIM 0x10 // Use factory calibration on HSI Trim.
#define FUNCONF_SYSTEM_CORE_CLOCK 48000000 // Computed Clock in Hz (Default only for 003, other chips have other defaults)
#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_NULL_PRINTF 0 // Have printf but direct it "nowhere"
#define FUNCONF_SYSTICK_USE_HCLK 0 // Should systick be at 48 MHz (1) or 6MHz (0) on an '003. Typically set to 0 to divide HCLK by 8.
#define FUNCONF_TINYVECTOR 0 // If enabled, Does not allow normal interrupts.
#define FUNCONF_UART_PRINTF_BAUD 115200 // Only used if FUNCONF_USE_UARTPRINTF is set.
#define FUNCONF_DEBUGPRINTF_TIMEOUT 0x80000 // Arbitrary time units, this is around 120ms.
#define FUNCONF_ENABLE_HPE 1 // Enable hardware interrupt stack. Very good on QingKeV4, i.e. x035, v10x, v20x, v30x, but questionable on 003.
// If you are using that, consider using INTERRUPT_DECORATOR as an attribute to your interrupt handlers.
#define FUNCONF_USE_5V_VDD 0 // Enable this if you plan to use your part at 5V - affects USB and PD configration on the x035.
#define FUNCONF_DEBUG_HARDFAULT 1 // Log fatal errors with "printf"
*/
// Sanity check for when porting old code.
#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) || defined(CH32X03x)
#if defined(CH32V003)
#error Cannot define CH32V003 and another arch.
#endif
#endif
#if !defined(FUNCONF_USE_DEBUGPRINTF) && !defined(FUNCONF_USE_UARTPRINTF)
#define FUNCONF_USE_DEBUGPRINTF 1
#endif
#if defined(FUNCONF_USE_UARTPRINTF) && FUNCONF_USE_UARTPRINTF && !defined(FUNCONF_UART_PRINTF_BAUD)
#define FUNCONF_UART_PRINTF_BAUD 115200
#endif
#if defined(FUNCONF_USE_DEBUGPRINTF) && FUNCONF_USE_DEBUGPRINTF && !defined(FUNCONF_DEBUGPRINTF_TIMEOUT)
#define FUNCONF_DEBUGPRINTF_TIMEOUT 0x80000
#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
#define FUNCONF_USE_HSE 0
#endif
#if defined( CH32X03x ) && FUNCONF_USE_HSE
#error No HSE in CH32X03x
#endif
#if !defined( FUNCONF_USE_PLL )
#if defined( CH32X03x )
#define FUNCONF_USE_PLL 0 // No PLL on X03x
#else
#define FUNCONF_USE_PLL 1 // Default to use PLL
#endif
#endif
#if !defined( FUNCONF_DEBUG_HARDFAULT )
#define FUNCONF_DEBUG_HARDFAULT 1
#endif
#if defined( CH32X03x ) && FUNCONF_USE_PLL
#error No PLL on the X03x
#endif
#ifndef FUNCONF_ENABLE_HPE
#define FUNCONF_ENABLE_HPE 0
#endif
#if FUNCONF_ENABLE_HPE == 1
#define INTERRUPT_DECORATOR __attribute__((interrupt("WCH-Interrupt-fast")))
#else
#define INTERRUPT_DECORATOR __attribute__((interrupt))
#endif
#if !defined( FUNCONF_USE_CLK_SEC )
#define FUNCONF_USE_CLK_SEC 1// use clock security system by default
#endif
#ifndef HSE_VALUE
#if defined(CH32V003)
#define HSE_VALUE (24000000) // Value of the External oscillator in Hz, default
#elif defined(CH32V10x)
#define HSE_VALUE (8000000)
#elif defined(CH32V20x)
#if defined(CH32V20x_D8) || defined(CH32V20x_D8W)
#define HSE_VALUE (32000000)
#else
#define HSE_VALUE (8000000)
#endif
#elif defined(CH32V30x)
#define HSE_VALUE (8000000)
#endif
#endif
#ifndef HSI_VALUE
#if defined(CH32V003)
#define HSI_VALUE (24000000) // Value of the Internal oscillator in Hz, default.
#elif defined(CH32X03x)
#define HSI_VALUE (48000000)
#elif defined(CH32V10x)
#define HSI_VALUE (8000000)
#elif defined(CH32V20x)
#define HSI_VALUE (8000000)
#elif defined(CH32V30x)
#define HSI_VALUE (8000000)
#endif
#endif
#ifndef FUNCONF_HSITRIM
#define FUNCONF_HSITRIM 0x10 // Default (Chip default)
#endif
#ifndef FUNCONF_USE_PLL
#define FUNCONF_USE_PLL 1 // Default, Use PLL.
#endif
#if !defined( FUNCONF_PLL_MULTIPLIER )
#if defined(FUNCONF_USE_PLL) && FUNCONF_USE_PLL
#if defined(CH32V10x)
#define FUNCONF_PLL_MULTIPLIER 10 // Default: 8 * 10 = 80 MHz
#elif defined(CH32V20x)
#define FUNCONF_PLL_MULTIPLIER 18 // Default: 8 * 18 = 144 MHz
#elif defined(CH32V30x)
#define FUNCONF_PLL_MULTIPLIER 18 // Default: 8 * 18 = 144 MHz
#else // CH32V003
#define FUNCONF_PLL_MULTIPLIER 2 // Default: 24 * 2 = 48 MHz
#endif
#else
#define FUNCONF_PLL_MULTIPLIER 1
#endif
#endif
#ifndef FUNCONF_SYSTEM_CORE_CLOCK
#if defined(FUNCONF_USE_HSI) && FUNCONF_USE_HSI
#define FUNCONF_SYSTEM_CORE_CLOCK ((HSI_VALUE)*(FUNCONF_PLL_MULTIPLIER))
#elif defined(FUNCONF_USE_HSE) && FUNCONF_USE_HSE
#define FUNCONF_SYSTEM_CORE_CLOCK ((HSE_VALUE)*(FUNCONF_PLL_MULTIPLIER))
#else
#error Must define either FUNCONF_USE_HSI or FUNCONF_USE_HSE to be 1.
#endif
#endif
#ifndef FUNCONF_USE_5V_VDD
#define FUNCONF_USE_5V_VDD 0
#endif
// Default package for CH32V20x
#if defined(CH32V20x)
#if !defined(CH32V20x_D8W) && !defined(CH32V20x_D8) && !defined(CH32V20x_D6)
#define CH32V20x_D6 /* CH32V203F6-CH32V203F8-CH32V203G6-CH32V203G8-CH32V203K6-CH32V203K8-CH32V203C6-CH32V203C8 */
//#define CH32V20x_D8 /* CH32V203RBT6 */
//#define CH32V20x_D8W /* CH32V208 */
#endif
#endif
// Default package for CH32V30x
#if defined(CH32V30x)
#if !defined(CH32V30x_D8) && !defined(CH32V30x_D8C)
//#define CH32V30x_D8 /* CH32V303x */
#define CH32V30x_D8C /* CH32V307x-CH32V305x */
#endif
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////
// Legacy, for EVT, CMSIS
#define __MPU_PRESENT 0 /* Other CH32 devices does not provide an MPU */
#define __Vendor_SysTickConfig 0 /* Set to 1 if different SysTick Config is used */
#ifndef __ASSEMBLER__ // Things before this can be used in assembly.
#include <stdint.h>
#ifdef __cplusplus
#define __I volatile /*!< defines 'read only' permissions */
#else
#define __I volatile const /*!< defines 'read only' permissions */
#endif
#define __O volatile /*!< defines 'write only' permissions */
#define __IO volatile /*!< defines 'read / write' permissions */
#endif // __ASSEMBLER__
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
// Code in this section was originally from __CORE_RISCV_H__
#ifndef __CORE_RISCV_H__
#define __CORE_RISCV_H__
/* define compiler specific symbols */
#if defined(__CC_ARM)
#define __ASM __asm /*!< asm keyword for ARM Compiler */
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
#elif defined(__ICCARM__)
#define __ASM __asm /*!< asm keyword for IAR Compiler */
#define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */
#elif defined(__GNUC__)
#define __ASM __asm /*!< asm keyword for GNU Compiler */
#define __INLINE inline /*!< inline keyword for GNU Compiler */
#elif defined(__TASKING__)
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __ASSEMBLER__
/* Standard Peripheral Library old types (maintained for legacy purpose) */
typedef __I uint32_t vuc32; /* Read Only */
typedef __I uint16_t vuc16; /* Read Only */
typedef __I uint8_t vuc8; /* Read Only */
typedef const uint32_t uc32; /* Read Only */
typedef const uint16_t uc16; /* Read Only */
typedef const uint8_t uc8; /* Read Only */
typedef __I int32_t vsc32; /* Read Only */
typedef __I int16_t vsc16; /* Read Only */
typedef __I int8_t vsc8; /* Read Only */
typedef const int32_t sc32; /* Read Only */
typedef const int16_t sc16; /* Read Only */
typedef const int8_t sc8; /* Read Only */
typedef __IO uint32_t vu32;
typedef __IO uint16_t vu16;
typedef __IO uint8_t vu8;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
typedef __IO int32_t vs32;
typedef __IO int16_t vs16;
typedef __IO int8_t vs8;
typedef int32_t s32;
typedef int16_t s16;
typedef int8_t s8;
typedef __I uint64_t vuc64; /* Read Only */
typedef const uint64_t uc64; /* Read Only */
typedef __I int64_t vsc64; /* Read Only */
typedef const int64_t sc64; /* Read Only */
typedef __IO uint64_t vu64;
typedef uint64_t u64;
typedef __IO int64_t vs64;
typedef int64_t s64;
typedef enum {NoREADY = 0, READY = !NoREADY} ErrorStatus;
typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;
#define RV_STATIC_INLINE static inline
#endif // __ASSEMBLER__
#ifdef CH32V003
#include "ch32v003hw.h"
#elif defined( CH32X03x )
#include "ch32x03xhw.h"
#elif defined( CH32X03x )
#include "ch32x03xhw.h"
#elif defined( CH32V10x )
#include "ch32v10xhw.h"
#elif defined( CH32V20x )
#include "ch32v20xhw.h"
#elif defined( CH32V30x )
#include "ch32v30xhw.h"
#endif
#if defined(__riscv) || defined(__riscv__) || defined( CH32V003FUN_BASE )
#if __GNUC__ > 10
#define ADD_ARCH_ZICSR ".option arch, +zicsr\n"
#else
#define ADD_ARCH_ZICSR
#endif
#ifndef __ASSEMBLER__
// Enable Global Interrupt
RV_STATIC_INLINE void __enable_irq()
{
uint32_t result; __ASM volatile( ADD_ARCH_ZICSR "csrr %0," "mstatus": "=r"(result) );
result |= 0x88; __ASM volatile( ADD_ARCH_ZICSR "csrw mstatus, %0" : : "r" (result) );
}
// Disable Global Interrupt
RV_STATIC_INLINE void __disable_irq()
{
uint32_t result; __ASM volatile( ADD_ARCH_ZICSR "csrr %0," "mstatus": "=r"(result) );
result &= ~0x88; __ASM volatile( ADD_ARCH_ZICSR "csrw mstatus, %0" : : "r" (result) );
}
// Is Global Interrupt enabled (1 = yes, 0 = no)
RV_STATIC_INLINE uint8_t __isenabled_irq(void)
{
uint32_t result; __ASM volatile( ADD_ARCH_ZICSR "csrr %0," "mstatus": "=r"(result) );
return (result & 0x08) != 0u;
}
// Get stack pointer (returns the stack pointer)
RV_STATIC_INLINE uint32_t __get_cpu_sp(void)
{
uint32_t result; __ASM volatile( ADD_ARCH_ZICSR "mv %0, sp" : "=r"(result));
return result;
}
// nop
RV_STATIC_INLINE void __NOP()
{
__ASM volatile( "nop" );
}
// Enable Interrupt (by interrupt number)
RV_STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
{
NVIC->IENR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));
}
// Disable Interrupt (by interrupt number)
RV_STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
{
NVIC->IRER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));
}
// Get Interrupt Enable State, (by number), 1 = Triggered 0 = Not triggered
RV_STATIC_INLINE uint32_t NVIC_GetStatusIRQ(IRQn_Type IRQn)
{
return((uint32_t) ((NVIC->ISR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0));
}
// Get Interrupt Pending State, (by number), 1 = Pending 0 = Not pending
RV_STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
return((uint32_t) ((NVIC->IPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0));
}
// "current number break hang"
RV_STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
NVIC->IPSR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));
}
// Clear Interrupt Pending
RV_STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
NVIC->IPRR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));
}
// Get Interrupt Active State (returns 1 if active)
RV_STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn)
{
return((uint32_t)((NVIC->IACTR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0));
}
// Set Interrupt Priority (priority: bit7: pre-emption priority, bit6: subpriority, bit[5-0]: reserved
RV_STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint8_t priority)
{
NVIC->IPRIOR[(uint32_t)(IRQn)] = priority;
}
/*********************************************************************
* SUSPEND ALL INTERRUPTS EXCEPT
* The following 3 functions serve to suspend all interrupts, except for the one you momentarily need.
* The purpose of this is to not disturb the one interrupt of interest and let it run unimpeded.
* procedure:
* 1. save the enabled IRQs: uint32_t IRQ_backup = NVIC_get_enabled_IRQs();
* 2. disable all IRQs: NVIC_clear_all_IRQs_except(IRQ_of_interest);
* 3. restore the previously enabled IRQs: NVIC_restore_IRQs(IRQ_backup);
*
* bit layout of the IRQ backup
* bit 0 | 1 | 2 | 3 | 4 | 5 | 6 .. 22 | 23 .. 28
* IRQn 2 | 3 | 12 | res | 14 | res | 16 .. 31 | 32 .. 38
* IRQn 2 and 3 aren't actually user-settable (see RM).
*
* Specifying an invalid IRQn_to_keep like 0 will disable all interrupts.
*/
RV_STATIC_INLINE uint32_t NVIC_get_enabled_IRQs()
{
return ( ((NVIC->ISR[0] >> 2) & 0b11) | ((NVIC->ISR[0] >> 12) << 2) | ((NVIC->ISR[1] & 0b1111111) << 23) );
}
RV_STATIC_INLINE void NVIC_clear_all_IRQs_except(uint8_t IRQn_to_keep)
{
if (!(IRQn_to_keep >> 5)) { // IRQn_to_keep < 32
NVIC->IRER[0] = (~0) & (~(1 << IRQn_to_keep));
NVIC->IRER[1] = (~0);
}
else {
IRQn_to_keep = IRQn_to_keep >> 5;
NVIC->IRER[0] = (~0);
NVIC->IRER[1] = (~0) & (~(1 << IRQn_to_keep));
}
}
RV_STATIC_INLINE void NVIC_restore_IRQs(uint32_t old_state)
{
NVIC->IENR[0] = (old_state >> 2) << 12;
NVIC->IENR[1] = old_state >> 23;
}
// WFI - wait for interrupt (like a light sleep)
__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFI(void)
{
NVIC->SCTLR &= ~(1<<3); // wfi
__ASM volatile ("wfi");
}
// WFE - wait for events (more like a deeper sleep)
__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFE(void)
{
uint32_t t;
t = NVIC->SCTLR;
NVIC->SCTLR |= (1<<3)|(1<<5); // (wfi->wfe)+(__sev)
NVIC->SCTLR = (NVIC->SCTLR & ~(1<<5)) | ( t & (1<<5));
__ASM volatile ("wfi");
__ASM volatile ("wfi");
}
/*********************************************************************
* @fn SetVTFIRQ
* @brief Set VTF Interrupt
* @param addr - VTF interrupt service function base address.
* IRQn - Interrupt Numbers
* num - VTF Interrupt Numbers
* NewState - DISABLE or ENABLE
*
* @return none
*/
RV_STATIC_INLINE void SetVTFIRQ(uint32_t addr, IRQn_Type IRQn, uint8_t num, FunctionalState NewState){
if(num > 1) return ;
if (NewState != DISABLE)
{
NVIC->VTFIDR[num] = IRQn;
NVIC->VTFADDR[num] = ((addr&0xFFFFFFFE)|0x1);
}
else{
NVIC->VTFIDR[num] = IRQn;
NVIC->VTFADDR[num] = ((addr&0xFFFFFFFE)&(~0x1));
}
}
// Initiate a system reset request
RV_STATIC_INLINE void NVIC_SystemReset(void)
{
NVIC->CFGR = NVIC_KEY3|(1<<7);
}
// For reading INTSYSCR, for interrupt nesting + hardware stack enable.
static inline uint32_t __get_INTSYSCR(void)
{
uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0, 0x804": "=r"(result));
return result;
}
// For setting INTSYSCR, for interrupt nesting + hardware stack enable.
static inline void __set_INTSYSCR( uint32_t value )
{
__ASM volatile( ADD_ARCH_ZICSR "csrw 0x804, %0" : : "r"(value));
}
#if defined(CH32V30x)
// Return the Floating-Point Accrued Exceptions
static inline uint32_t __get_FFLAGS(void)
{
uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0," "fflags" : "=r" (result) );
return (result);
}
// Set the Floating-Point Accrued Exceptions
static inline void __set_FFLAGS(uint32_t value)
{
__ASM volatile( ADD_ARCH_ZICSR "csrw fflags, %0" : : "r" (value) );
}
// Return the Floating-Point Dynamic Rounding Mode
static inline uint32_t __get_FRM(void)
{
uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0," "frm" : "=r" (result) );
return (result);
}
// Set the Floating-Point Dynamic Rounding Mode
static inline void __set_FRM(uint32_t value)
{
__ASM volatile( ADD_ARCH_ZICSR "csrw frm, %0" : : "r" (value) );
}
// Return the Floating-Point Control and Status Register
static inline uint32_t __get_FCSR(void)
{
uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0," "fcsr" : "=r" (result) );
return (result);
}
// Set the Floating-Point Dynamic Rounding Mode
static inline void __set_FCSR(uint32_t value)
{
__ASM volatile( ADD_ARCH_ZICSR "csrw fcsr, %0" : : "r" (value) );
}
#endif // CH32V30x
// Return the Machine Status Register (MSTATUS)
static inline uint32_t __get_MSTATUS(void)
{
uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0, mstatus": "=r"(result) );
return (result);
}
// Set the Machine Status Register (MSTATUS)
static inline void __set_MSTATUS(uint32_t value)
{
__ASM volatile( ADD_ARCH_ZICSR "csrw mstatus, %0" : : "r"(value) );
}
// Return the Machine ISA Register (MISA)
static inline uint32_t __get_MISA(void)
{
uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0, misa" : "=r"(result));
return (result);
}
// Set the Machine ISA Register (MISA)
static inline void __set_MISA(uint32_t value)
{
__ASM volatile( ADD_ARCH_ZICSR "csrw misa, %0" : : "r"(value));
}
// Return the Machine Trap-Vector Base-Address Register (MTVEC)
static inline uint32_t __get_MTVEC(void)
{
uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0," "mtvec": "=r"(result));
return (result);
}
// * @brief Set the Machine Trap-Vector Base-Address Register (MTVEC)
static inline void __set_MTVEC(uint32_t value)
{
__ASM volatile( ADD_ARCH_ZICSR "csrw mtvec, %0":: "r"(value));
}
// Return the Machine Seratch Register (MSCRATCH)
static inline uint32_t __get_MSCRATCH(void)
{
uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0," "mscratch" : "=r"(result));
return (result);
}
// Set the Machine Seratch Register (MSRATCH)
static inline void __set_MSCRATCH(uint32_t value)
{
__ASM volatile( ADD_ARCH_ZICSR "csrw mscratch, %0" : : "r"(value));
}
// Return the Machine Exception Program Register (MEPC)
static inline uint32_t __get_MEPC(void)
{
uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0," "mepc" : "=r"(result));
return (result);
}
// Set the Machine Exception Program Register (MEPC)
static inline void __set_MEPC(uint32_t value)
{
__ASM volatile( ADD_ARCH_ZICSR "csrw mepc, %0" : : "r"(value));
}
// Return the Machine Cause Register (MCAUSE)
static inline uint32_t __get_MCAUSE(void)
{
uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0," "mcause": "=r"(result));
return (result);
}
// Set the Machine Cause Register (MCAUSE)
static inline void __set_MCAUSE(uint32_t value)
{
__ASM volatile( ADD_ARCH_ZICSR "csrw mcause, %0":: "r"(value));
}
// Return the Machine Trap Value Register (MTVAL)
static inline uint32_t __get_MTVAL(void)
{
uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0," "mtval" : "=r" (result) );
return (result);
}
// Set the Machine Trap Value Register (MTVAL)
static inline void __set_MTVAL(uint32_t value)
{
__ASM volatile ( ADD_ARCH_ZICSR "csrw mtval, %0" : : "r" (value) );
}
// Return Vendor ID Register (MVENDORID)
static inline uint32_t __get_MVENDORID(void)
{
uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0, mvendorid": "=r"(result));
return (result);
}
// Return Machine Architecture ID Register (MARCHID)
static inline uint32_t __get_MARCHID(void)
{
uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0, marchid": "=r"(result));
return (result);
}
// Return Machine Implementation ID Register (MIPID)
static inline uint32_t __get_MIMPID(void)
{
uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0, mimpid": "=r"(result));
return (result);
}
// Return Hart ID Register MHARTID
static inline uint32_t __get_MHARTID(void)
{
uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0, mhartid": "=r"(result));
return (result);
}
#if defined(CH32V003) && CH32V003
// Return DBGMCU_CR Register value
static inline uint32_t __get_DEBUG_CR(void)
{
uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0, 0x7C0" : "=r" (result) );
return (result);
}
// Set the DBGMCU_CR Register value
static inline void __set_DEBUG_CR(uint32_t value)
{
__ASM volatile( ADD_ARCH_ZICSR "csrw 0x7C0, %0" : : "r" (value) );
}
// Return stack pointer register (SP)
static inline uint32_t __get_SP(void)
{
uint32_t result;
__ASM volatile( "mv %0,""sp": "=r"(result):);
return (result);
}
#endif // CH32V003
#endif // !assembler
// _JBTYPE using long long to make sure the alignment is align to 8 byte,
// otherwise in rv32imafd, store/restore FPR may mis-align.
#define _JBTYPE long long
#if defined( __riscv_abi_rve )
#define _JBLEN ((4*sizeof(long))/sizeof(long))
#elif defined( __riscv_float_abi_double )
#define _JBLEN ((14*sizeof(long) + 12*sizeof(double))/sizeof(long))
#elif defined( __riscv_float_abi_single )
#define _JBLEN ((14*sizeof(long) + 12*sizeof(float))/sizeof(long))
#else
#define _JBLEN ((14*sizeof(long))/sizeof(long))
#endif
#ifndef __ASSEMBLER__
#ifdef _JBLEN
#ifdef _JBTYPE
typedef _JBTYPE jmp_buf[_JBLEN];
#else
typedef int jmp_buf[_JBLEN];
#endif // _JBTYPE
#endif // _JBLEN
int setjmp( jmp_buf env );
void longjmp( jmp_buf env, int val );
#endif
#endif // defined(__riscv) || defined(__riscv__) || defined( CH32V003FUN_BASE )
#ifdef __cplusplus
}
#endif
#endif/* __CORE_RISCV_H__ */
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C" {
#endif
/* SYSTICK info
* time on the ch32v003 is kept by the SysTick counter (32bit)
* by default, it will operate at (FUNCONF_SYSTEM_CORE_CLOCK / 8) = 6MHz
* more info at https://github.com/cnlohr/ch32v003fun/wiki/Time
*/
#if defined( FUNCONF_SYSTICK_USE_HCLK ) && FUNCONF_SYSTICK_USE_HCLK && !defined(CH32V10x)
#define DELAY_US_TIME ((FUNCONF_SYSTEM_CORE_CLOCK)/1000000)
#define DELAY_MS_TIME ((FUNCONF_SYSTEM_CORE_CLOCK)/1000)
#else // Use systick = hclk/8
#define DELAY_US_TIME ((FUNCONF_SYSTEM_CORE_CLOCK)/8000000)
#define DELAY_MS_TIME ((FUNCONF_SYSTEM_CORE_CLOCK)/8000)
#endif
#define Delay_Us(n) DelaySysTick( (n) * DELAY_US_TIME )
#define Delay_Ms(n) DelaySysTick( (n) * DELAY_MS_TIME )
#define Ticks_from_Us(n) (n * DELAY_US_TIME)
#define Ticks_from_Ms(n) (n * DELAY_MS_TIME)
// Add a certain number of nops. Note: These are usually executed in pairs
// and take two cycles, so you typically would use 0, 2, 4, etc.
#define ADD_N_NOPS( n ) asm volatile( ".rept " #n "\nc.nop\n.endr" );
// Arduino-like GPIO Functionality
#define GpioOf( pin ) ((GPIO_TypeDef *)(GPIOA_BASE + 0x400 * ((pin)>>4)))
#define FUN_HIGH 0x1
#define FUN_LOW 0x0
#define FUN_OUTPUT (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)
#define FUN_INPUT (GPIO_CNF_IN_FLOATING)
// For pins, use things like PA8, PB15
// For configuration, use things like GPIO_CFGLR_OUT_10Mhz_PP
#define funDigitalWrite( pin, value ) { GpioOf( pin )->BSHR = 1<<((!(value))*16 + ((pin) & 0xf)); }
#if defined(CH32X03x)
#define funGpioInitAll() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC ); }
#define funPinMode( pin, mode ) { *((&GpioOf(pin)->CFGLR)+((pin&0x8)>>3)) = ( (*((&GpioOf(pin)->CFGLR)+((pin&0x8)>>3))) & (~(0xf<<(4*((pin)&0x7))))) | ((mode)<<(4*((pin)&0x7))); }
#elif defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x)
#define funGpioInitAll() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD ); }
#define funPinMode( pin, mode ) { *((&GpioOf(pin)->CFGLR)+((pin&0x8)>>3)) = ( (*((&GpioOf(pin)->CFGLR)+((pin&0x8)>>3))) & (~(0xf<<(4*((pin)&0x7))))) | ((mode)<<(4*((pin)&0x7))); }
#define funGpioInitB() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB ); }
#else
#define funGpioInitAll() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD ); }
#define funPinMode( pin, mode ) { GpioOf(pin)->CFGLR = (GpioOf(pin)->CFGLR & (~(0xf<<(4*((pin)&0xf))))) | ((mode)<<(4*((pin)&0xf))); }
#endif
#define funGpioInitA() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA ); }
#define funGpioInitC() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOC ); }
#define funGpioInitD() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOD ); }
#define funDigitalRead( pin ) ((int)((GpioOf(pin)->INDR >> ((pin)&0xf)) & 1))
#define ANALOG_0 0
#define ANALOG_1 1
#define ANALOG_2 2
#define ANALOG_3 3
#define ANALOG_4 4
#define ANALOG_5 5
#define ANALOG_6 6
#define ANALOG_7 7
#define ANALOG_8 8
#define ANALOG_9 9
#define ANALOG_10 10
#define ANALOG_11 11
#ifndef __ASSEMBLER__
#if defined(__riscv) || defined(__riscv__) || defined( CH32V003FUN_BASE )
// Stuff that can only be compiled on device (not for the programmer, or other host programs)
// Initialize the ADC calibrate it and set some sane defaults.
void funAnalogInit( void );
// Read an analog input (not a GPIO pin number)
// Be sure to call funAnalogInit first.
int funAnalogRead( int nAnalogNumber );
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
void DelaySysTick( uint32_t n );
// Depending on a LOT of factors, it's about 6 cycles per n.
// **DO NOT send it zero or less.**
#ifndef __MACOSX__
#ifndef __DELAY_TINY_DEFINED__
#define __DELAY_TINY_DEFINED__
static inline void Delay_Tiny( int n ) {
__ASM volatile( "\
mv a5, %[n]\n\
1: \
c.addi a5, -1\n\
c.bnez a5, 1b" : : [n]"r"(n) : "a5" );
}
#endif
#endif
#endif //defined(__riscv) || defined(__riscv__) || defined( CH32V003FUN_BASE )
// Tricky: We need to make sure main and SystemInit() are preserved.
int main() __attribute__((used));
void SystemInit(void);
#ifdef FUNCONF_UART_PRINTF_BAUD
#define UART_BAUD_RATE FUNCONF_UART_PRINTF_BAUD
#else
#define UART_BAUD_RATE 115200
#endif
// Debug UART baud rate register calculation. Works assuming HCLK prescaler is off.
// Computes UART_BRR = CORE_CLOCK / BAUD_RATE with rounding to closest integer
#define UART_BRR (((FUNCONF_SYSTEM_CORE_CLOCK) + (UART_BAUD_RATE)/2) / (UART_BAUD_RATE))
// Put an output debug UART on Pin D5.
// You can write to this with printf(...) or puts(...)
void SetupUART( int uartBRR );
// Returns 1 if timeout reached, 0 otherwise.
// If timeout_ms == 0, wait indefinitely.
// Use DidDebuggerAttach() For a zero-wait way of seeing if it attached.
int WaitForDebuggerToAttach( int timeout_ms );
// Returns 1 if a debugger has activated the debug module.
#define DidDebuggerAttach() (!*DMSTATUS_SENTINEL)
// Returns 1 if a debugger has activated the debug module.
#define DebugPrintfBufferFree() (!(*DMDATA0 & 0x80))
// Just a definition to the internal _write function.
int _write(int fd, const char *buf, int size);
// Call this to busy-wait the polling of input.
void poll_input( void );
// Receiving bytes from host. Override if you wish.
void handle_debug_input( int numbytes, uint8_t * data );
// Functions from ch32fun.c
#include <stdarg.h>
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 );
int mini_snprintf(char* buffer, unsigned int buffer_len, const char *fmt, ...);
int mini_pprintf(int (*puts)(char*s, int len, void* buf), void* buf, const char *fmt, ...);
#endif // __ASSEMBLER__
/*
* This file contains various parts of the official WCH EVT Headers which
* were originally under a restrictive license.
*
* The collection of this file was generated by
* cnlohr, 2023-02-18 and
* AlexanderMandera, 2023-06-23
* It was significantly reworked into several files cnlohr, 2025-01-29
*
* While originally under a restrictive copyright, WCH has approved use
* under MIT-licensed use, because of inclusion in Zephyr, as well as other
* open-source licensed projects.
*
* These copies of the headers from WCH are available now under:
*
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
*
* 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.
*/
#ifdef __cplusplus
};
#endif
#endif // __CH32FUN_H

View file

@ -1,192 +0,0 @@
/* Filename: ch32v003.ld
* Author: Jake Goodwin Email: jakegoodwin@gorge.works
* Date: 2025-02-28
* Description: A linker file for the WCH uC `ch32v003` that links with
* the newlib C library for functionality.
*/
/*
* I've added tons of comments so that when I come back to this file in a
* couple of months I remember what I was doing.
*/
/*Sets the Entry point address in header of final ELF file. */
ENTRY( InterruptVector )
/*The CH32V003 has 16KiB of "Code Flash" it actually has more I think.*/
/*The CH32V003 has 2048Bytes of SRAM*/
MEMORY
{
/*Attributes:*/
/*R -- Read-Only Sections*/
/*W -- Read and Write Sections*/
/*X -- Sections contain executable code*/
/*A -- Allocated sections */
/*I or L -- Initialized sections */
/*! -- Invert the Meaning of any attribute */
/*Syntax:*/
/*<name> (attr) : ORIGIN=<origin addr>, LENGTH = <sizeK> */
/*The Flash is usally listed as it's origin being at zero in linker scripts
* that you can find. The refernce manual shows it starting at 0x0800 0000
* but this is actually an alias that could also point to system memory of
* the area for the boot flash.
*/
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 16K
BOOT1 (rx) : ORIGIN = 0x1FFFF000, LENGTH = 1920 /*System flash/boot*/
VENDR (rx) : ORIGIN = 0x1FFFF7C0, LENGTH = 128 /*Vendor Bytes*/
OPTIB (rx) : ORIGIN = 0x1FFFF800, LENGTH = 64 /*Option Bytes*/
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 2K
}
/* Sections command is used to create differnt output sections in the final elf
* executable */
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
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
.dalign :
{
. = ALIGN(4);
PROVIDE(_data_vma = .);
} >RAM AT>FLASH
.dlalign :
{
. = ALIGN(4);
PROVIDE(_data_lma = .);
} >FLASH AT>FLASH
.data :
{
. = ALIGN(4);
__global_pointer$ = . + 0x3fc; /* This gets set in the startup code. This allows -mrelax'd code to be smaller by acting as a sort of quick reference in the gp register. */
*(.gnu.linkonce.r.*)
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
*(.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 = . );
PROVIDE( _eusrstack = ORIGIN(RAM) + LENGTH(RAM));
/DISCARD/ : {
*(.note .note.*)
*(.eh_frame .eh_frame.*)
*(.comment .comment.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
*(.ARM.exidx*)
}
}

4700
src/ch32v003hw.h Normal file

File diff suppressed because it is too large Load diff

Binary file not shown.

7
src/funconfig.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef _FUNCONFIG_H
#define _FUNCONFIG_H
#define CH32V003 1
#endif

View file

@ -1,122 +0,0 @@
ENTRY( InterruptVector )
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 16K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 2K
}
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
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 :
{
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
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
.data :
{
. = ALIGN(4);
__global_pointer$ = . + 0x3fc;
*(.gnu.linkonce.r.*)
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
*(.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 = . );
PROVIDE( _eusrstack = ORIGIN(RAM) + LENGTH(RAM));
/DISCARD/ : {
*(.note .note.*)
*(.eh_frame .eh_frame.*)
*(.comment .comment.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
*(.ARM.exidx*)
}
}

View file

@ -1,5 +1,5 @@
#include "ch32fun.h" #include "ch32fun.h"
//#include <stdio.h> #include <stdio.h>
int main(void) int main(void)
{ {

View file

@ -1,15 +0,0 @@
# Author: Jake Goodwin
# Date: 2025-02-28
# Version: v0.0.0
# Description:
# File Name: startup_ch32v003.S
# Extra Info:
# CPU: QingKeV2
# ISA: RV32EC -- 32bit RISC-V Embedded subset with compressed instructions.
# NOTE: Only has half the normal 32 registers, so 16 registers, they are
# X0-x15