#include "CH32V00xxx.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));
  // 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 ) {
      // 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 (;;);
}