reorganize startup code
This commit is contained in:
parent
90c3627a70
commit
00ed06384b
4 changed files with 63 additions and 148 deletions
|
@ -11,7 +11,8 @@ OBJS += startup.o system.o
|
||||||
CCPU = -march=rv32imac -mabi=ilp32
|
CCPU = -march=rv32imac -mabi=ilp32
|
||||||
MCPU = $(CCPU)
|
MCPU = $(CCPU)
|
||||||
TRIP = riscv32-unknown-none-elf
|
TRIP = riscv32-unknown-none-elf
|
||||||
CFLAGS+= -Oz -flto
|
CFLAGS+= -Oz
|
||||||
|
CFLAGS+= -flto
|
||||||
CFLAGS+= -fmessage-length=0 -fsigned-char -I/usr/include/newlib
|
CFLAGS+= -fmessage-length=0 -fsigned-char -I/usr/include/newlib
|
||||||
#CFLAGS+= -fconstexpr-steps=2097152
|
#CFLAGS+= -fconstexpr-steps=2097152
|
||||||
CFLAGS+= --target=$(TRIP) $(MCPU)
|
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.
|
# 16-bit instrukce se do toho asi dostanou až na úrovni LLVM linkeru.
|
||||||
# Bohužel to není nikde pořádně popsáno.
|
# Bohužel to není nikde pořádně popsáno.
|
||||||
LFLAGS+= -mllvm -mattr=+c
|
LFLAGS+= -mllvm -mattr=+c
|
||||||
LFLAGS+= -lto-O3 -nostdlib
|
LFLAGS+= -lto-O3
|
||||||
|
LFLAGS+= -nostdlib
|
||||||
LDLIBS+= -L./$(TARGET) -T generated_CH32V203F8P6.ld
|
LDLIBS+= -L./$(TARGET) -T generated_CH32V203F8P6.ld
|
||||||
|
|
|
@ -7,12 +7,14 @@ SIZE = $(PREFIX)size
|
||||||
DUMP = $(PREFIX)objdump
|
DUMP = $(PREFIX)objdump
|
||||||
COPY = $(PREFIX)objcopy
|
COPY = $(PREFIX)objcopy
|
||||||
OBJS += startup.o system.o
|
OBJS += startup.o system.o
|
||||||
CFLAGS+= -Os -flto
|
CFLAGS+= -Os
|
||||||
|
CFLAGS+= -flto
|
||||||
CCPU = -march=rv32imac -mabi=ilp32
|
CCPU = -march=rv32imac -mabi=ilp32
|
||||||
MCPU = $(CCPU)
|
MCPU = $(CCPU)
|
||||||
|
|
||||||
CFLAGS+= $(MCPU) -msmall-data-limit=8 -mno-save-restore -fmessage-length=0 -fsigned-char -I/usr/include/newlib
|
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,--Map=$(@:%.elf=%.map),--gc-sections
|
||||||
#LFLAGS+= -Wl,--print-sysroot -- chyba ld ?
|
#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
|
LDLIBS+= -lgcc -L./$(TARGET) -T generated_CH32V203F8P6.ld
|
||||||
|
|
|
@ -1,55 +1,18 @@
|
||||||
#include "CH32V20xxx.h"
|
#include "CH32V20xxx.h"
|
||||||
typedef __SIZE_TYPE__ size_t;
|
typedef __SIZE_TYPE__ size_t;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
extern void handle_reset () __attribute__((naked,nothrow,used));
|
[[using gnu: naked,used]] extern void handle_reset () noexcept;
|
||||||
extern void user_prog () __attribute__((used));
|
[[gnu::used]] extern int main ();
|
||||||
extern int main () __attribute__((used));
|
[[gnu::used]] extern void SystemInit();
|
||||||
extern void SystemInit() __attribute__((used));
|
|
||||||
// This is required to allow pure virtual functions to be defined.
|
// This is required to allow pure virtual functions to be defined.
|
||||||
extern void __cxa_pure_virtual() { while (1); }
|
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.
|
// If you don't override a specific handler, it will just spin forever.
|
||||||
void DefaultIRQHandler( void ) {
|
[[gnu::interrupt]] void DefaultIRQHandler( void ) {
|
||||||
// Infinite Loop
|
// Infinite Loop
|
||||||
for (;;);
|
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
|
RCC.INTR.B.CSSC = RESET; // clear the clock security int flag
|
||||||
}
|
}
|
||||||
#define ALIAS(f) __attribute__((nothrow,weak,alias(#f),used))
|
#define ALIAS(f) __attribute__((nothrow,weak,alias(#f),used))
|
||||||
|
@ -136,13 +99,9 @@ extern "C" {
|
||||||
void OSCWakeUp_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
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);
|
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 [] = {
|
const pHandler InterruptVector [] = {
|
||||||
Init,
|
Init,
|
||||||
|
@ -220,94 +179,6 @@ const pHandler InterruptVector [] = {
|
||||||
OSCWakeUp_IRQHandler, /* OSC Wake Up */
|
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() {
|
void Init() {
|
||||||
asm volatile( R"---(
|
asm volatile( R"---(
|
||||||
.align 1
|
.align 1
|
||||||
|
@ -346,14 +217,10 @@ R"---(
|
||||||
|
|
||||||
/* Takhle RISC-V přejde do uživatelského programu. */
|
/* Takhle RISC-V přejde do uživatelského programu. */
|
||||||
csrw mepc, %[user]
|
csrw mepc, %[user]
|
||||||
|
/* Zinicializovat proměnné, hodiny a až poté konstruktory */
|
||||||
|
call SystemInit
|
||||||
mret
|
mret
|
||||||
)---"
|
)---"
|
||||||
: : [user]"r"(user_prog)/*, "InterruptVector" (InterruptVector)*/
|
: : [user]"r"(main)
|
||||||
: "t0", "memory" );
|
: "t0", "memory" );
|
||||||
}
|
}
|
||||||
void user_prog () {
|
|
||||||
SystemInit ();
|
|
||||||
__init_array();
|
|
||||||
main();
|
|
||||||
for (;;);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,46 @@
|
||||||
#include "CH32V20xxx.h"
|
#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 {
|
enum CLKSRC : uint32_t {
|
||||||
CLK_HSI = 0u,
|
CLK_HSI = 0u,
|
||||||
CLK_HSE,
|
CLK_HSE,
|
||||||
|
@ -7,6 +48,7 @@ enum CLKSRC : uint32_t {
|
||||||
};
|
};
|
||||||
// HSE i HSI mají frekvenci 8 MHz
|
// HSE i HSI mají frekvenci 8 MHz
|
||||||
void SystemInit(void) {
|
void SystemInit(void) {
|
||||||
|
init_variables();
|
||||||
/// TODO
|
/// TODO
|
||||||
EXTEND.EXTEND_CTR.B.PLL_HSI_PRE = SET; // HSI used for PLL, not divided
|
EXTEND.EXTEND_CTR.B.PLL_HSI_PRE = SET; // HSI used for PLL, not divided
|
||||||
RCC.CFGR0.modify([](RCC_Type::CFGR0_DEF & r) -> uint32_t {
|
RCC.CFGR0.modify([](RCC_Type::CFGR0_DEF & r) -> uint32_t {
|
||||||
|
@ -28,4 +70,6 @@ void SystemInit(void) {
|
||||||
// USE PLL
|
// USE PLL
|
||||||
RCC.CFGR0.B.SW = CLK_PLL ;
|
RCC.CFGR0.B.SW = CLK_PLL ;
|
||||||
while (RCC.CFGR0.B.SWS != CLK_PLL);
|
while (RCC.CFGR0.B.SWS != CLK_PLL);
|
||||||
|
|
||||||
|
call_constructors();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue