As I already manage to turn the LED on, making it blink is quite straightforward.
/* Memory locations defined by linker script */
extern long __StackTop ;        /* &__StackTop points after end of stack */
void Reset_Handler( void) ;     /* Entry point for execution */
/* Interrupt vector table:
 * 1  Stack Pointer reset value
 * 15 System Exceptions
 * NN Device specific Interrupts
 */
typedef void (*isr_p)( void) ;
isr_p const isr_vector[ 2] __attribute__((section(".isr_vector"))) = {
    (isr_p) &__StackTop,
/* System Exceptions */
    Reset_Handler
} ;
#define RCC                 ((volatile long *) 0x40021000)
#define RCC_AHBENR          RCC[ 5]
#define RCC_AHBENR_IOPBEN   0x00040000  /*  18: I/O port B clock enable */
#define GPIOB               ((volatile long *) 0x48000400)
#define GPIOB_MODER         GPIOB[ 0]
#define GPIOB_ODR           GPIOB[ 5]
void Reset_Handler( void) {
    int delay ;
/* User LED ON */
    RCC_AHBENR |= RCC_AHBENR_IOPBEN ;   /* Enable IOPB periph */
    GPIOB_MODER |= 1 << (1 * 2) ;       /* PB1 Output [01], over default 00 */
    /* OTYPER Push-Pull by default */
    /* PB1 output default LOW at reset */
/* User LED blink */
    for( ;;) {
        for( delay = 1000000 ; delay ; delay--) ;   /* delay between toggling */
        GPIOB_ODR ^= 1 << 1 ;                       /* toggle PB1 (User LED) */
    }
}
I set the value of the delay counter at one million. By default the
internal clock is set to 8MHz at reset, which means the delay will still
be less than one second.
$ make blink.hex
blink.elf
   text    data     bss     dec     hex filename
     68       0       0      68      44 blink.elf
blink.hex
rm blink.o blink.elf
Next, interrupt driven blinking, because active wait delay is just not cool.