extern unsigned int _sram_end;
extern unsigned int _data_vma_start;
extern unsigned int _data_vma_end;
extern unsigned int _data_lma_start;
extern unsigned int _bss_vma_start;
extern unsigned int _bss_vma_end;

#define RCC_AHB1 ((volatile unsigned int * const) 0x40023830)
#define GPIOC_MODER ((volatile unsigned int * const) 0x40020800)
#define GPIOC_ODR ((volatile unsigned int * const) 0x40020814)

static void
delay (void)
{
  volatile unsigned int i;
  for (i = 0; i < 500000; i++);
}

static void
reset_handler (void)
{
  unsigned int *src, *dst;

  /* relocate .data to sram  */
  src = &_data_lma_start;
  dst = &_data_vma_start;

  while (dst < &_data_vma_end)
    *(dst++) = *(src++);

  /* initialize .bss  */
  dst = &_bss_vma_start;

  while (dst < &_bss_vma_end)
    *(dst++) = 0;

  /* blink blink  */
  *RCC_AHB1 |= (1u << 2);
  *GPIOC_MODER &= ~(3u << 26);
  *GPIOC_MODER |= (1u << 26);

  while (1)
    {
      *GPIOC_ODR ^= (1u << 13);
      delay ();
    }
}

__attribute__ ((section (".vtbl"), used))
static unsigned long const vector_table[] = {
  (unsigned long) &_sram_end,
  (unsigned long) reset_handler,
};
