--- /dev/null
+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,
+};
--- /dev/null
+MEMORY
+{
+ flash (rx) : ORIGIN = 0x08000000, LENGTH = 512K
+ sram (rw) : ORIGIN = 0x20000000, LENGTH = 128K
+}
+
+_flash_start = ORIGIN(flash);
+_flash_end = ORIGIN(flash) + LENGTH(flash);
+
+_sram_start = ORIGIN(sram);
+_sram_end = ORIGIN(sram) + LENGTH(sram);
+
+SECTIONS
+{
+ .vtbl :
+ {
+ *(.vtbl)
+ . = 0x400;
+ } >flash
+ .text :
+ {
+ *(.text*)
+ } >flash
+ .rodata :
+ {
+ . = ALIGN(4);
+ *(.rodata*)
+ . = ALIGN(4);
+ } >flash
+ .data :
+ {
+ . = ALIGN(4);
+ *(.data*)
+ . = ALIGN(4);
+ } >sram AT>flash
+ .bss :
+ {
+ . = ALIGN(4);
+ *(.bss*)
+ . = ALIGN(4);
+ } >sram
+}
+
+_data_vma_start = ADDR(.data);
+_data_vma_end = ADDR(.data) + SIZEOF(.data);
+_data_lma_start = LOADADDR(.data);
+
+_bss_vma_start = ADDR(.bss);
+_bss_vma_end = ADDR(.bss) + SIZEOF(.bss);