/**
 * @file    startup_app.s
 * @brief   Application firmware startup file
 *
 * Same vector table structure as bootloader, but VTOR is set
 * to __APP_BASE__ by the bootloader before jumping here.
 *
 * Stack pointer is already configured by bootloader.
 */

.syntax unified
.cpu cortex-m4
.fpu softvfp
.thumb

/* Vector table (at __APP_BASE__) */
.word   _estack
.word   Reset_Handler
.word   NMI_Handler
.word   HardFault_Handler
.word   MemManage_Handler
.word   BusFault_Handler
.word   UsageFault_Handler
.word   0
.word   0
.word   0
.word   0
.word   SVC_Handler
.word   DebugMon_Handler
.word   0
.word   PendSV_Handler
.word   SysTick_Handler

.rept 87
.word   Default_Handler
.endr

.section .text.Reset_Handler
.weak   Reset_Handler
.type   Reset_Handler, %function
Reset_Handler:
    /* Copy .data from flash to SRAM */
    ldr   r1, =_sidata
    ldr   r2, =_sdata
    ldr   r3, =_edata
    subs  r3, r2
    ble   .L_clear_bss
.L_copy_data:
    ldrb  r4, [r1], #1
    strb  r4, [r2], #1
    subs  r3, #1
    bgt   .L_copy_data

.L_clear_bss:
    ldr   r2, =_sbss
    ldr   r3, =_ebss
    movs  r0, #0
    subs  r3, r2
    ble   .L_init_done
.L_zero_bss:
    strb  r0, [r2], #1
    subs  r3, #1
    bgt   .L_zero_bss

.L_init_done:
    /* Set VTOR to app base (redundant, bootloader already did it) */
    ldr   r0, =__APP_BASE__
    ldr   r1, =0xE000ED08
    str   r0, [r1]

    /* Initialize system clock */
    bl    SystemClock_Init

    /* Initialize HAL library */
    bl    HAL_Init

    /* Call main */
    bl    main

.L_loop:
    b     .L_loop
.size Reset_Handler, .-Reset_Handler

/* System clock init */
.section .text.SystemClock_Init
.weak   SystemClock_Init
.type   SystemClock_Init, %function
SystemClock_Init:
    /* Enable HSE */
    ldr   r0, =0x40023800
    ldr   r1, [r0, #0x00]
    orr   r1, r1, #0x00010000
    str   r1, [r0, #0x00]
.L_wait_hse:
    ldr   r1, [r0, #0x00]
    tst   r1, #0x00020000
    beq   .L_wait_hse

    /* Flash latency 2 WS */
    ldr   r1, =0x40022000
    ldr   r2, [r1]
    orr   r2, r2, #0x05
    str   r2, [r1]

    /* PLL: HSE/2 *18 /2 = 72MHz */
    ldr   r1, =0x40023804
    ldr   r2, =(2 << 0) | (18 << 8) | (0 << 16) | (2 << 24)
    str   r2, [r1]

    ldr   r1, [r0, #0x00]
    orr   r1, r1, #0x01000000
    str   r1, [r0, #0x00]
.L_wait_pll:
    ldr   r1, [r0, #0x00]
    tst   r1, #0x02000000
    beq   .L_wait_pll

    ldr   r1, [r0, #0x08]
    bic   r1, r1, #0x03
    orr   r1, r1, #0x02
    str   r1, [r0, #0x08]
.L_wait_sw:
    ldr   r1, [r0, #0x08]
    and   r1, r1, #0x0C
    cmp   r1, #0x08
    bne   .L_wait_sw

    bx    lr

.macro weak_handler name
.section .text.Default_Handler
.weak \name
.type \name, %function
\name:
    b     .
.endm

weak_handler NMI_Handler
weak_handler HardFault_Handler
weak_handler MemManage_Handler
weak_handler BusFault_Handler
weak_handler UsageFault_Handler
weak_handler SVC_Handler
weak_handler DebugMon_Handler
weak_handler PendSV_Handler
weak_handler SysTick_Handler
weak_handler Default_Handler

.end
