diff --git a/V203/ch32v203/clang.mk b/V203/ch32v203/clang.mk index dd26df0..8bf0312 100644 --- a/V203/ch32v203/clang.mk +++ b/V203/ch32v203/clang.mk @@ -11,7 +11,8 @@ OBJS += startup.o system.o CCPU = -march=rv32imac -mabi=ilp32 MCPU = $(CCPU) TRIP = riscv32-unknown-none-elf -CFLAGS+= -Oz -flto +CFLAGS+= -Oz +CFLAGS+= -flto CFLAGS+= -fmessage-length=0 -fsigned-char -I/usr/include/newlib #CFLAGS+= -fconstexpr-steps=2097152 CFLAGS+= --target=$(TRIP) $(MCPU) @@ -19,5 +20,6 @@ LFLAGS+= --Map=$(@:%.elf=%.map) --gc-sections # 16-bit instrukce se do toho asi dostanou až na úrovni LLVM linkeru. # Bohužel to není nikde pořádně popsáno. LFLAGS+= -mllvm -mattr=+c -LFLAGS+= -lto-O3 -nostdlib +LFLAGS+= -lto-O3 +LFLAGS+= -nostdlib LDLIBS+= -L./$(TARGET) -T generated_CH32V203F8P6.ld diff --git a/V203/ch32v203/gcc.mk b/V203/ch32v203/gcc.mk index 9377baa..8c640be 100644 --- a/V203/ch32v203/gcc.mk +++ b/V203/ch32v203/gcc.mk @@ -7,12 +7,14 @@ SIZE = $(PREFIX)size DUMP = $(PREFIX)objdump COPY = $(PREFIX)objcopy OBJS += startup.o system.o -CFLAGS+= -Os -flto +CFLAGS+= -Os +CFLAGS+= -flto CCPU = -march=rv32imac -mabi=ilp32 MCPU = $(CCPU) CFLAGS+= $(MCPU) -msmall-data-limit=8 -mno-save-restore -fmessage-length=0 -fsigned-char -I/usr/include/newlib LFLAGS+= -Wl,--Map=$(@:%.elf=%.map),--gc-sections #LFLAGS+= -Wl,--print-sysroot -- chyba ld ? -LFLAGS+= -flto -O3 $(MCPU) -nostartfiles -nostdlib +LFLAGS+= -flto +LFLAGS+= -Os $(MCPU) -nostartfiles -nostdlib LDLIBS+= -lgcc -L./$(TARGET) -T generated_CH32V203F8P6.ld diff --git a/V203/ch32v203/startup.cpp b/V203/ch32v203/startup.cpp index 2102490..8a3503d 100644 --- a/V203/ch32v203/startup.cpp +++ b/V203/ch32v203/startup.cpp @@ -1,55 +1,18 @@ #include "CH32V20xxx.h" typedef __SIZE_TYPE__ size_t; extern "C" { - extern void handle_reset () __attribute__((naked,nothrow,used)); - extern void user_prog () __attribute__((used)); - extern int main () __attribute__((used)); - extern void SystemInit() __attribute__((used)); + [[using gnu: naked,used]] extern void handle_reset () noexcept; + [[gnu::used]] extern int main (); + [[gnu::used]] extern void SystemInit(); // This is required to allow pure virtual functions to be defined. extern void __cxa_pure_virtual() { while (1); } - // These magic symbols are provided by the linker. - extern uint32_t _sbss; - extern uint32_t _ebss; - extern uint32_t _data_lma; - extern uint32_t _data_vma; - extern uint32_t _edata; - - extern void (*__preinit_array_start[]) (void) __attribute__((weak)); - extern void (*__preinit_array_end[]) (void) __attribute__((weak)); - extern void (*__init_array_start[]) (void) __attribute__((weak)); - extern void (*__init_array_end[]) (void) __attribute__((weak)); - - static void __init_array () { - uint32_t * dst, * end; - - /* Zero fill the bss section */ - dst = &_sbss; - end = &_ebss; - while (dst < end) * dst++ = 0U; - /* Copy data section from flash to RAM */ - uint32_t * src; - src = &_data_lma; - dst = &_data_vma; - end = &_edata; - if (src != dst) { - while (dst < end) * dst++ = * src++; - } - - size_t count; - /* Pro Cortex-Mx bylo toto zbytečné, lze předpokládat, že je to tak i zde. - count = __preinit_array_end - __preinit_array_start; - for (unsigned i = 0; i < count; i++) __preinit_array_start[i](); - */ - count = __init_array_end - __init_array_start; - for (unsigned i = 0; i < count; i++) __init_array_start[i](); - } // If you don't override a specific handler, it will just spin forever. - void DefaultIRQHandler( void ) { + [[gnu::interrupt]] void DefaultIRQHandler( void ) { // Infinite Loop for (;;); } - void NMI_RCC_CSS_IRQHandler( void ) { + [[gnu::interrupt]] void NMI_RCC_CSS_IRQHandler( void ) { RCC.INTR.B.CSSC = RESET; // clear the clock security int flag } #define ALIAS(f) __attribute__((nothrow,weak,alias(#f),used)) @@ -136,13 +99,9 @@ extern "C" { void OSCWakeUp_IRQHandler( void ) ALIAS(DefaultIRQHandler); - void Init() __attribute__((used,section(".init"))); - /* Tohle je patrně nedomyšlené, sekce .vector není definována. - void InterruptVector() __attribute__((nothrow,naked,section(".vector"),weak,alias("InterruptVectorDefault"))); - void InterruptVectorDefault() __attribute__((nothrow,naked,section(".vector"))); - */ typedef void (*pHandler) (void); - extern const pHandler InterruptVector [] __attribute__((section(".text.vector"),aligned(8))); + [[using gnu: used,section(".init")]] void Init(); + [[using gnu: section(".text.vector"),aligned(8)]] extern const pHandler InterruptVector []; }; const pHandler InterruptVector [] = { Init, @@ -220,94 +179,6 @@ const pHandler InterruptVector [] = { OSCWakeUp_IRQHandler, /* OSC Wake Up */ }; -#if 0 -void InterruptVectorDefault() noexcept { - asm volatile( R"---( - .align 1 - .option norvc; - .word Init - - .word 0 - .word NMI_Handler /* NMI */ - .word HardFault_Handler /* Hard Fault */ - .word 0 - - .word Ecall_M_Mode_Handler /* Ecall M Mode */ - .word 0 - .word 0 - .word Ecall_U_Mode_Handler /* Ecall U Mode */ - .word Break_Point_Handler /* Break Point */ - .word 0 - .word 0 - - - .word SysTick_Handler /* SysTick Handler */ - .word 0 - .word SW_Handler /* SW Handler */ - .word 0 - /* External Interrupts */ - .word WWDG_IRQHandler /* Window Watchdog */ - .word PVD_IRQHandler /* PVD through EXTI Line detect */ - .word TAMPER_IRQHandler /* TAMPER */ - .word RTC_IRQHandler /* RTC */ - .word FLASH_IRQHandler /* Flash */ - .word RCC_IRQHandler /* RCC */ - .word EXTI0_IRQHandler /* EXTI Line 0 */ - .word EXTI1_IRQHandler /* EXTI Line 1 */ - .word EXTI2_IRQHandler /* EXTI Line 2 */ - .word EXTI3_IRQHandler /* EXTI Line 3 */ - .word EXTI4_IRQHandler /* EXTI Line 4 */ - .word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */ - .word DMA1_Channel2_IRQHandler /* DMA1 Channel 2 */ - .word DMA1_Channel3_IRQHandler /* DMA1 Channel 3 */ - .word DMA1_Channel4_IRQHandler /* DMA1 Channel 4 */ - .word DMA1_Channel5_IRQHandler /* DMA1 Channel 5 */ - .word DMA1_Channel6_IRQHandler /* DMA1 Channel 6 */ - .word DMA1_Channel7_IRQHandler /* DMA1 Channel 7 */ - .word ADC1_2_IRQHandler /* ADC1_2 */ - - .word USB_HP_CAN1_TX_IRQHandler /* USB HP and CAN1 TX */ - .word USB_LP_CAN1_RX0_IRQHandler /* USB LP and CAN1RX0 */ - .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ - .word CAN1_SCE_IRQHandler /* CAN1 SCE */ - - .word EXTI9_5_IRQHandler /* EXTI Line 9..5 */ - .word TIM1_BRK_IRQHandler /* TIM1 Break */ - .word TIM1_UP_IRQHandler /* TIM1 Update */ - .word TIM1_TRG_COM_IRQHandler /* TIM1 Trigger and Commutation */ - .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ - .word TIM2_IRQHandler /* TIM2 */ - .word TIM3_IRQHandler /* TIM3 */ - .word TIM4_IRQHandler /* TIM4 */ - .word I2C1_EV_IRQHandler /* I2C1 Event */ - .word I2C1_ER_IRQHandler /* I2C1 Error */ - .word I2C2_EV_IRQHandler /* I2C2 Event */ - .word I2C2_ER_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXTI15_10_IRQHandler /* EXTI Line 15..10 */ - .word RTCAlarm_IRQHandler /* RTC Alarm through EXTI Line */ - - .word USBWakeUp_IRQHandler /* USB Wake up from suspend */ - .word USBHD_IRQHandler /* USBHD Break */ - - .word USBHDWakeUp_IRQHandler /* USBHD Wake up from suspend */ - .word ETH_IRQHandler /* ETH global */ - .word ETHWakeUp_IRQHandler /* ETH Wake up */ - .word 0 /* BLE BB */ - .word 0 /* BLE LLE */ - .word TIM5_IRQHandler /* TIM5 */ - .word UART4_IRQHandler /* UART4 */ - .word DMA1_Channel8_IRQHandler /* DMA1 Channel8 */ - .word OSC32KCal_IRQHandler /* OSC32KCal */ - .word OSCWakeUp_IRQHandler /* OSC Wake Up */ - -)---"); -} -#endif void Init() { asm volatile( R"---( .align 1 @@ -346,14 +217,10 @@ R"---( /* Takhle RISC-V přejde do uživatelského programu. */ csrw mepc, %[user] + /* Zinicializovat proměnné, hodiny a až poté konstruktory */ + call SystemInit mret )---" -: : [user]"r"(user_prog)/*, "InterruptVector" (InterruptVector)*/ +: : [user]"r"(main) : "t0", "memory" ); } -void user_prog () { - SystemInit (); - __init_array(); - main(); - for (;;); -} diff --git a/V203/ch32v203/system.cpp b/V203/ch32v203/system.cpp index e1d1868..25174a7 100644 --- a/V203/ch32v203/system.cpp +++ b/V203/ch32v203/system.cpp @@ -1,5 +1,46 @@ #include "CH32V20xxx.h" -extern "C" void SystemInit (); +typedef __SIZE_TYPE__ size_t; +extern "C" { + // These magic symbols are provided by the linker. + extern uint32_t _sbss; + extern uint32_t _ebss; + extern uint32_t _data_lma; + extern uint32_t _data_vma; + extern uint32_t _edata; + + [[gnu::weak]] extern void (*__preinit_array_start[]) (void); + [[gnu::weak]] extern void (*__preinit_array_end[]) (void); + [[gnu::weak]] extern void (*__init_array_start[]) (void); + [[gnu::weak]] extern void (*__init_array_end[]) (void); + + [[gnu::used]] extern void SystemInit (); +}; +static void init_variables () { + uint32_t * dst, * end; + + /* Zero fill the bss section */ + dst = &_sbss; + end = &_ebss; + while (dst < end) * dst++ = 0U; + /* Copy data section from flash to RAM */ + uint32_t * src; + src = &_data_lma; + dst = &_data_vma; + end = &_edata; + if (src != dst) { + while (dst < end) * dst++ = * src++; + } +} +static void call_constructors () { + size_t count; + /* Pro Cortex-Mx bylo toto zbytečné, lze předpokládat, že je to tak i zde. + count = __preinit_array_end - __preinit_array_start; + for (unsigned i = 0; i < count; i++) __preinit_array_start[i](); + */ + count = __init_array_end - __init_array_start; + for (unsigned i = 0; i < count; i++) __init_array_start[i](); +} + enum CLKSRC : uint32_t { CLK_HSI = 0u, CLK_HSE, @@ -7,6 +48,7 @@ enum CLKSRC : uint32_t { }; // HSE i HSI mají frekvenci 8 MHz void SystemInit(void) { + init_variables(); /// TODO EXTEND.EXTEND_CTR.B.PLL_HSI_PRE = SET; // HSI used for PLL, not divided RCC.CFGR0.modify([](RCC_Type::CFGR0_DEF & r) -> uint32_t { @@ -28,4 +70,6 @@ void SystemInit(void) { // USE PLL RCC.CFGR0.B.SW = CLK_PLL ; while (RCC.CFGR0.B.SWS != CLK_PLL); + + call_constructors(); }