174 lines
6.9 KiB
C++
174 lines
6.9 KiB
C++
|
#include "CH32V00xxx.h"
|
||
|
typedef __SIZE_TYPE__ size_t;
|
||
|
extern "C" {
|
||
|
extern void handle_reset () __attribute__((naked,nothrow,used));
|
||
|
extern void user_prog () __attribute__((used,noreturn));
|
||
|
extern int main () __attribute__((used));
|
||
|
extern void SystemInit() __attribute__((used));
|
||
|
// This is required to allow pure virtual functions to be defined.
|
||
|
void __cxa_pure_virtual() { while (1); }
|
||
|
void * memset(void * s, int c, size_t n) {
|
||
|
char * p = (char *) s;
|
||
|
for (unsigned i=0u; i<n; i++) p[i] = c;
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
// 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 ) {
|
||
|
// Infinite Loop
|
||
|
for (;;);
|
||
|
}
|
||
|
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))
|
||
|
|
||
|
void NMI_Handler( void ) ALIAS(NMI_RCC_CSS_IRQHandler);
|
||
|
void HardFault_Handler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void SysTick_Handler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void SW_Handler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void WWDG_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void PVD_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void FLASH_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void RCC_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void EXTI7_0_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void AWU_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void DMA1_Channel1_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void DMA1_Channel2_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void DMA1_Channel3_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void DMA1_Channel4_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void DMA1_Channel5_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void DMA1_Channel6_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void DMA1_Channel7_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void ADC1_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void TIM1_BRK_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void TIM1_UP_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void TIM1_TRG_COM_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void TIM1_CC_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void TIM2_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void I2C1_EV_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void I2C1_ER_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void USART1_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
void SPI1_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
||
|
|
||
|
void InterruptVector() __attribute__((nothrow,naked,section(".init"),weak,alias("InterruptVectorDefault")));
|
||
|
void InterruptVectorDefault() __attribute__((nothrow,naked,section(".init")));
|
||
|
};
|
||
|
void InterruptVectorDefault() noexcept {
|
||
|
asm volatile( R"---(
|
||
|
.align 2
|
||
|
.option push
|
||
|
.option norvc
|
||
|
j handle_reset
|
||
|
|
||
|
.word 0
|
||
|
.word NMI_Handler /* NMI Handler */
|
||
|
.word HardFault_Handler /* Hard Fault Handler */
|
||
|
.word 0
|
||
|
.word 0
|
||
|
.word 0
|
||
|
.word 0
|
||
|
.word 0
|
||
|
.word 0
|
||
|
.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 FLASH_IRQHandler /* Flash */
|
||
|
.word RCC_IRQHandler /* RCC */
|
||
|
.word EXTI7_0_IRQHandler /* EXTI Line 7..0 */
|
||
|
.word AWU_IRQHandler /* AWU */
|
||
|
.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_IRQHandler /* ADC1 */
|
||
|
.word I2C1_EV_IRQHandler /* I2C1 Event */
|
||
|
.word I2C1_ER_IRQHandler /* I2C1 Error */
|
||
|
.word USART1_IRQHandler /* USART1 */
|
||
|
.word SPI1_IRQHandler /* SPI1 */
|
||
|
.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 */
|
||
|
.option pop
|
||
|
)---");
|
||
|
}
|
||
|
void handle_reset() noexcept {
|
||
|
asm volatile(R"---(
|
||
|
.option push
|
||
|
.option norelax
|
||
|
la gp, __global_pointer$
|
||
|
.option pop
|
||
|
la sp, _eusrstack
|
||
|
)---"
|
||
|
#if __GNUC__ > 10
|
||
|
".option arch, +zicsr\n"
|
||
|
#endif
|
||
|
// Setup the interrupt vector, processor status and INTSYSCR.
|
||
|
R"---(
|
||
|
li a0, 0x80
|
||
|
csrw mstatus, a0
|
||
|
li a3, 0x3
|
||
|
la a0, InterruptVector
|
||
|
or a0, a0, a3
|
||
|
csrw mtvec, a0
|
||
|
/* Takhle RISC-V přejde do uživatelského programu. */
|
||
|
csrw mepc, %[user]
|
||
|
mret
|
||
|
)---"
|
||
|
: : [user]"r"(user_prog)
|
||
|
: "a0", "a3", "memory" );
|
||
|
}
|
||
|
void user_prog () {
|
||
|
SystemInit ();
|
||
|
__init_array();
|
||
|
main();
|
||
|
for (;;);
|
||
|
}
|