reorganize startup code

This commit is contained in:
Kizarm 2024-08-15 19:16:57 +02:00
parent 90c3627a70
commit 00ed06384b
4 changed files with 63 additions and 148 deletions

View file

@ -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

View file

@ -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

View file

@ -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 (;;);
}

View file

@ -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();
}