;*******************************************************************************
; (c) Copyright 2015 Microsemi SoC Products Group. All rights reserved.
;  SmartFusion2  startup code for Keil-MDK.
; 
;  SmartFusion2 vector table and startup code for ARM tool chain.
; 
;  SVN $Revision: 7683 $
;  SVN $Date: 2015-08-21 17:06:30 +0100 (Fri, 21 Aug 2015) $
;

; *------- <<< Use Configuration Wizard in Context Menu >>> ------------------


; <h> Stack Configuration
;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Stack_Size      EQU     0x00001000

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
stack_start
Stack_Mem       SPACE   Stack_Size
__initial_sp
stack_end


; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Heap_Size       EQU     0x00000000

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit


                PRESERVE8
                THUMB


;===============================================================================
; Vector Table Mapped to Address 0 at Reset
                AREA    RESET, DATA, READONLY
                EXPORT  __Vectors
                EXPORT  __Vectors_End
                EXPORT  __Vectors_Size

__Vectors       DCD     __initial_sp               ; Top of Stack
                DCD     Reset_Handler              ; Reset Handler
                DCD     NMI_Handler                ; NMI Handler
                DCD     HardFault_Handler          ; Hard Fault Handler
                DCD     MemManage_Handler          ; MPU Fault Handler
                DCD     BusFault_Handler           ; Bus Fault Handler
                DCD     UsageFault_Handler         ; Usage Fault Handler
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     SVC_Handler                ; SVCall Handler
                DCD     DebugMon_Handler           ; Debug Monitor Handler
                DCD     0                          ; Reserved
                DCD     PendSV_Handler             ; PendSV Handler
                DCD     SysTick_Handler            ; SysTick Handler

                ; External Interrupts
                DCD     WdogWakeup_IRQHandler
                DCD     RTC_Wakeup_IRQHandler
                DCD     SPI0_IRQHandler
                DCD     SPI1_IRQHandler
                DCD     I2C0_IRQHandler
                DCD     I2C0_SMBAlert_IRQHandler
                DCD     I2C0_SMBus_IRQHandler
                DCD     I2C1_IRQHandler
                DCD     I2C1_SMBAlert_IRQHandler
                DCD     I2C1_SMBus_IRQHandler
                DCD     UART0_IRQHandler
                DCD     UART1_IRQHandler
                DCD     EthernetMAC_IRQHandler
                DCD     DMA_IRQHandler
                DCD     Timer1_IRQHandler
                DCD     Timer2_IRQHandler
                DCD     CAN_IRQHandler
                DCD     ENVM0_IRQHandler
                DCD     ENVM1_IRQHandler
                DCD     ComBlk_IRQHandler
                DCD     USB_IRQHandler
                DCD     USB_DMA_IRQHandler
                DCD     PLL_Lock_IRQHandler
                DCD     PLL_LockLost_IRQHandler
                DCD     CommSwitchError_IRQHandler
                DCD     CacheError_IRQHandler
                DCD     DDR_IRQHandler
                DCD     HPDMA_Complete_IRQHandler
                DCD     HPDMA_Error_IRQHandler
                DCD     ECC_Error_IRQHandler
                DCD     MDDR_IOCalib_IRQHandler
                DCD     FAB_PLL_Lock_IRQHandler
                DCD     FAB_PLL_LockLost_IRQHandler
                DCD     FIC64_IRQHandler
                DCD     FabricIrq0_IRQHandler
                DCD     FabricIrq1_IRQHandler
                DCD     FabricIrq2_IRQHandler
                DCD     FabricIrq3_IRQHandler
                DCD     FabricIrq4_IRQHandler
                DCD     FabricIrq5_IRQHandler
                DCD     FabricIrq6_IRQHandler
                DCD     FabricIrq7_IRQHandler
                DCD     FabricIrq8_IRQHandler
                DCD     FabricIrq9_IRQHandler
                DCD     FabricIrq10_IRQHandler
                DCD     FabricIrq11_IRQHandler
                DCD     FabricIrq12_IRQHandler
                DCD     FabricIrq13_IRQHandler
                DCD     FabricIrq14_IRQHandler
                DCD     FabricIrq15_IRQHandler                
                DCD     GPIO0_IRQHandler
                DCD     GPIO1_IRQHandler
                DCD     GPIO2_IRQHandler
                DCD     GPIO3_IRQHandler
                DCD     GPIO4_IRQHandler
                DCD     GPIO5_IRQHandler
                DCD     GPIO6_IRQHandler
                DCD     GPIO7_IRQHandler
                DCD     GPIO8_IRQHandler
                DCD     GPIO9_IRQHandler
                DCD     GPIO10_IRQHandler
                DCD     GPIO11_IRQHandler
                DCD     GPIO12_IRQHandler
                DCD     GPIO13_IRQHandler
                DCD     GPIO14_IRQHandler
                DCD     GPIO15_IRQHandler
                DCD     GPIO16_IRQHandler
                DCD     GPIO17_IRQHandler
                DCD     GPIO18_IRQHandler
                DCD     GPIO19_IRQHandler
                DCD     GPIO20_IRQHandler
                DCD     GPIO21_IRQHandler
                DCD     GPIO22_IRQHandler
                DCD     GPIO23_IRQHandler
                DCD     GPIO24_IRQHandler
                DCD     GPIO25_IRQHandler
                DCD     GPIO26_IRQHandler
                DCD     GPIO27_IRQHandler
                DCD     GPIO28_IRQHandler
                DCD     GPIO29_IRQHandler
                DCD     GPIO30_IRQHandler
                DCD     GPIO31_IRQHandler

__Vectors_End

__Vectors_Size  EQU     __Vectors_End - __Vectors

;===============================================================================
; Reset Handler
;
                AREA    |.text|, CODE, READONLY

Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  SystemInit
                IMPORT  low_level_init
                IMPORT  __main
                
                ;---------------------------------------------------------------
                ; Initialize stack RAM content to initialize the error detection
                ; and correction (EDAC). This is done if EDAC is enabled for the
                ; eSRAM blocks or the ECC/SECDED is enabled for the MDDR.
                ; Register R11 is used to keep track of the RAM intialization
                ; decision outcome for later use for heap RAM initialization at
                ; the end of the startup code.
                ; Please note that the stack has to be located in eSRAM at this
                ; point and cannot be located in MDDR since MDDR is not available
                ; at this point.
                ; The bits of the content of register R11 have the foolwing
                ; meaning:
                ;  reg11[0]: eSRAM EDAC enabled
                ;  reg11[1]: MDDR ECC/SECDED enabled
                ;
                MOV R11, #0
                LDR R0, SF2_MDDR_MODE_CR
                LDR R0, [R0]
                LDR R1, SF2_EDAC_CR
                LDR R1, [R1]
                AND R1, R1, #3
                AND R0, R0, #0x1C
                CMP R0, #0x14
                BNE check_esram_edac
                ORR R11, R11, #2
check_esram_edac
                CMP R1, #0
                BEQ check_stack_init
                ORR R11, R11, #1
check_stack_init
                CMP R11, #0
                BEQ call_system_init
clear_stack
                LDR R0, =stack_start
                LDR R1, =stack_end
                LDR R2, RAM_INIT_PATTERN
                BL  fill_memory                       ; fill_memory takes r0 - r2 as arguments uses r4, r5, r6, r7, r8, r9, and does not preserve contents */
        
                ;---------------------------------------------------------------
                ; Call SystemInit() to perform Libero specified configuration.
                ;
call_system_init
                LDR     R0, =SystemInit
                BLX     R0
                LDR     R0, =low_level_init
                BLX     R0
                
                ;---------------------------------------------------------------
                ; Modify MDDR configuration if ECC/SECDED is enabled for MDDR.
                ; Enable write combining on MDDR bridge, disable non-bufferable
                ; regions.
                ;
adjust_mddr_cfg
                AND R10, R11, #0x2
                CMP R10, #0
                BEQ branch_to_main
                LDR R0, SF2_DDRB_NB_SIZE
                LDR R1, SF2_DDRB_CR
                LDR R2, [R0]
                LDR R3, [R1]
                push {R0, R1, R2, R3}
                MOV R2, #0
                MOV R3, #0xFF
                STR R2, [R0]
                STR R3, [R1]

                ; --------------------------------------------------------------
                ; Initialize heap RAM content to initialize the error detection
                ; and correction (EDAC). We use the decision made earlier in the
                ; startup code of whether or not the stack RAM should be
                ; initialized. This decision is held in register R11. A non-zero
                ; value indicates that the RAM content should be initialized.
                ;
clear_heap
                CMP R11, #0
                BEQ branch_to_main
                LDR R0, =__heap_base
                LDR R1, =__heap_limit
                LDR R2, HEAP_INIT_PATTERN
                BL  fill_memory                       ; fill_memory takes r0 - r2 as arguments uses r4, r5, r6, r7, r8, r9, and does not preserve contents */
                
                ;---------------------------------------------------------------
                ; Branch to __main
                ;
branch_to_main
                LDR     R0, =__main
                BX      R0
                ENDP
                    
SF2_EDAC_CR         DCD     0x40038038
SF2_DDRB_NB_SIZE    DCD     0x40038030
SF2_DDRB_CR         DCD     0x40038034
SF2_MDDR_MODE_CR    DCD     0x40020818
RAM_INIT_PATTERN    DCD     0x00000000
HEAP_INIT_PATTERN   DCD     0x00000000
                
;------------------------------------------------------------------------------
; * fill_memory.
; * @brief Fills memory with Pattern contained in r2
; * This routine uses the stmne instruction to copy 4 words at a time which is very efficient
; * The instruction can only write to word aligned memory, hence the code at the start and end of this routine
; * to handle possible unaligned bytes at start and end.
; *
; * @param param1 r0: start address
; * @param param2 r1: end address
; * @param param3 r2: FILL PATTETN
; *
; * @note note: Most efficient if memory is aligned. on 4 word (16 byte)
; * bounderies
; * Stack is not used in this routine
; * register contents r4, r5, r6, r7, r8, r9, will are used and will be returned undefined 
; * @return none - Used Registers are not preserved
; */

fill_memory PROC
     ;push {r4, r5, r6, r7, r8, r9, lr}  We will not use stack as may be not available */
    cmp r0, r1
    beq fill_memory_exit         ; Exit early if source and destination the same */
 ; copy non-aligned bytes at the start */
    and.w  r6, r0, #3            ; see if non-alaigned bytes at the start   */
    cmp r6, #0
    beq fill_memory_end_start    ; no spare bytes at start, continue    */
    mov    r5, #4
    sub.w  r4, r5, r6            ; now have number of non-aligned bytes in r4 */
    mov  r7, #8
    mul  r8, r7, r6              ; calculate number of shifts required to initalise pattern for non-aligned bytes */
    mov  r9, r2                  ; copy pattern */
    ror  r9, r9, r8              ; Rotate right to keep pattern consistent */
fill_memory_spare_bytes_start   ; From above, R0 contains source address, R1 contains destination address */
    cmp r4, #0                   ; no spare bytes at end- end now   */
    beq fill_memory_end_start
    strb r9, [r0]                ; fill byte */
    ror.w  r9, r9, r7            ; Rotate right by one byte for the next time, to keep pattern consistent */
    add r0, r0, #1               ; add one to address */
    subs r4, r4, #1              ; subtract one from byte count 1   */
    b fill_memory_spare_bytes_start
fill_memory_end_start
    mov  r6, #0
    mov  r7, r1                   ; save end address */
    subs r1, r1, r0               ; Calculate number of bytes to fill */
    mov  r8,r1                    ; Save copy of byte count */
    asrs r1,r1, #4                ; Div by 16 to get number of chunks to move */
    mov  r9, r2                   ; copy pattern */
    mov  r4, r2                   ; copy pattern */
    mov  r5, r2                   ; copy pattern */
    cmp r1, r6                    ; compare to see if all chunks copied */
    beq fill_memory_spare_bytes_end
fill_memory_loop
    it ne
    stmne r0!, {r2, r4, r5, r9}   ; copy pattern- note: stmne instruction must me word aligned (address in r0) */
    add.w r6, r6, #1              ; use Thumb2- make sure condition code reg. not updated */
    cmp r1, r6                    ; compare to see if all chunks copied */
    bne fill_memory_loop
fill_memory_spare_bytes_end       ; copy spare bytes at the end if any */
    and.w r8, r8, #15             ; get spare bytes  --check can you do an ands?  */
fill_memory_spare_end_loop        ; From above, R0 contains source address, R1 contains destination address */
    cmp r8, #0                    ; no spare bytes at end- end now  */
    beq fill_memory_exit
    strb r2, [r0]
    ror.w  r2, r2, #8             ; Rotate right by one byte for the next time, to keep pattern consistent */
    add r0, r0, #1                ; add one to address */
    subs r8, r8, #1               ; subtract one from byte count 1  */
    b fill_memory_spare_end_loop
fill_memory_exit
    bx  lr                        ; We will not use pop as stack may be not available */
    ENDP



;===============================================================================
; Dummy Exception Handlers (infinite loops which can be modified)                

NMI_Handler     PROC
                EXPORT  NMI_Handler                [WEAK]
                B       .
                ENDP
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler          [WEAK]
                B       .
                ENDP
MemManage_Handler\
                PROC
                EXPORT  MemManage_Handler          [WEAK]
                B       .
                ENDP
BusFault_Handler\
                PROC
                EXPORT  BusFault_Handler           [WEAK]
                B       .
                ENDP
UsageFault_Handler\
                PROC
                EXPORT  UsageFault_Handler         [WEAK]
                B       .
                ENDP
SVC_Handler     PROC
                EXPORT  SVC_Handler                [WEAK]
                B       .
                ENDP
DebugMon_Handler\
                PROC
                EXPORT  DebugMon_Handler           [WEAK]
                B       .
                ENDP
PendSV_Handler  PROC
                EXPORT  PendSV_Handler             [WEAK]
                B       .
                ENDP
SysTick_Handler PROC
                EXPORT  SysTick_Handler            [WEAK]
                B       .
                ENDP

Default_Handler PROC

                EXPORT  WdogWakeup_IRQHandler           [WEAK]
                EXPORT  RTC_Wakeup_IRQHandler           [WEAK]
                EXPORT  SPI0_IRQHandler                 [WEAK]
                EXPORT  SPI1_IRQHandler                 [WEAK]
                EXPORT  I2C0_IRQHandler                 [WEAK]
                EXPORT  I2C0_SMBAlert_IRQHandler        [WEAK]
                EXPORT  I2C0_SMBus_IRQHandler           [WEAK]
                EXPORT  I2C1_IRQHandler                 [WEAK]
                EXPORT  I2C1_SMBAlert_IRQHandler        [WEAK]
                EXPORT  I2C1_SMBus_IRQHandler           [WEAK]
                EXPORT  UART0_IRQHandler                [WEAK]
                EXPORT  UART1_IRQHandler                [WEAK]
                EXPORT  EthernetMAC_IRQHandler          [WEAK]
                EXPORT  DMA_IRQHandler                  [WEAK]
                EXPORT  Timer1_IRQHandler               [WEAK]
                EXPORT  Timer2_IRQHandler               [WEAK]
                EXPORT  CAN_IRQHandler                  [WEAK]
                EXPORT  ENVM0_IRQHandler                [WEAK]
                EXPORT  ENVM1_IRQHandler                [WEAK]
                EXPORT  ComBlk_IRQHandler               [WEAK]
                EXPORT  USB_IRQHandler                  [WEAK]
                EXPORT  USB_DMA_IRQHandler              [WEAK]
                EXPORT  PLL_Lock_IRQHandler             [WEAK]
                EXPORT  PLL_LockLost_IRQHandler         [WEAK]
                EXPORT  CommSwitchError_IRQHandler      [WEAK]
                EXPORT  CacheError_IRQHandler           [WEAK]
                EXPORT  DDR_IRQHandler                  [WEAK]
                EXPORT  HPDMA_Complete_IRQHandler       [WEAK]
                EXPORT  HPDMA_Error_IRQHandler          [WEAK]
                EXPORT  ECC_Error_IRQHandler            [WEAK]
                EXPORT  MDDR_IOCalib_IRQHandler         [WEAK]
                EXPORT  FAB_PLL_Lock_IRQHandler         [WEAK]
                EXPORT  FAB_PLL_LockLost_IRQHandler     [WEAK]
                EXPORT  FIC64_IRQHandler                [WEAK]
                EXPORT  FabricIrq0_IRQHandler           [WEAK]
                EXPORT  FabricIrq1_IRQHandler           [WEAK]
                EXPORT  FabricIrq2_IRQHandler           [WEAK]
                EXPORT  FabricIrq3_IRQHandler           [WEAK]
                EXPORT  FabricIrq4_IRQHandler           [WEAK]
                EXPORT  FabricIrq5_IRQHandler           [WEAK]
                EXPORT  FabricIrq6_IRQHandler           [WEAK]
                EXPORT  FabricIrq7_IRQHandler           [WEAK]
                EXPORT  FabricIrq8_IRQHandler           [WEAK]
                EXPORT  FabricIrq9_IRQHandler           [WEAK]
                EXPORT  FabricIrq10_IRQHandler          [WEAK]
                EXPORT  FabricIrq11_IRQHandler          [WEAK]
                EXPORT  FabricIrq12_IRQHandler          [WEAK]
                EXPORT  FabricIrq13_IRQHandler          [WEAK]
                EXPORT  FabricIrq14_IRQHandler          [WEAK]
                EXPORT  FabricIrq15_IRQHandler          [WEAK]                
                EXPORT  GPIO0_IRQHandler                [WEAK]
                EXPORT  GPIO1_IRQHandler                [WEAK]
                EXPORT  GPIO2_IRQHandler                [WEAK]
                EXPORT  GPIO3_IRQHandler                [WEAK]
                EXPORT  GPIO4_IRQHandler                [WEAK]
                EXPORT  GPIO5_IRQHandler                [WEAK]
                EXPORT  GPIO6_IRQHandler                [WEAK]
                EXPORT  GPIO7_IRQHandler                [WEAK]
                EXPORT  GPIO8_IRQHandler                [WEAK]
                EXPORT  GPIO9_IRQHandler                [WEAK]
                EXPORT  GPIO10_IRQHandler               [WEAK]
                EXPORT  GPIO11_IRQHandler               [WEAK]
                EXPORT  GPIO12_IRQHandler               [WEAK]
                EXPORT  GPIO13_IRQHandler               [WEAK]
                EXPORT  GPIO14_IRQHandler               [WEAK]
                EXPORT  GPIO15_IRQHandler               [WEAK]
                EXPORT  GPIO16_IRQHandler               [WEAK]
                EXPORT  GPIO17_IRQHandler               [WEAK]
                EXPORT  GPIO18_IRQHandler               [WEAK]
                EXPORT  GPIO19_IRQHandler               [WEAK]
                EXPORT  GPIO20_IRQHandler               [WEAK]
                EXPORT  GPIO21_IRQHandler               [WEAK]
                EXPORT  GPIO22_IRQHandler               [WEAK]
                EXPORT  GPIO23_IRQHandler               [WEAK]
                EXPORT  GPIO24_IRQHandler               [WEAK]
                EXPORT  GPIO25_IRQHandler               [WEAK]
                EXPORT  GPIO26_IRQHandler               [WEAK]
                EXPORT  GPIO27_IRQHandler               [WEAK]
                EXPORT  GPIO28_IRQHandler               [WEAK]
                EXPORT  GPIO29_IRQHandler               [WEAK]
                EXPORT  GPIO30_IRQHandler               [WEAK]
                EXPORT  GPIO31_IRQHandler               [WEAK]


WdogWakeup_IRQHandler
RTC_Wakeup_IRQHandler
SPI0_IRQHandler
SPI1_IRQHandler
I2C0_IRQHandler
I2C0_SMBAlert_IRQHandler
I2C0_SMBus_IRQHandler
I2C1_IRQHandler
I2C1_SMBAlert_IRQHandler
I2C1_SMBus_IRQHandler
UART0_IRQHandler
UART1_IRQHandler
EthernetMAC_IRQHandler
DMA_IRQHandler
Timer1_IRQHandler
Timer2_IRQHandler
CAN_IRQHandler
ENVM0_IRQHandler
ENVM1_IRQHandler
ComBlk_IRQHandler
USB_IRQHandler
USB_DMA_IRQHandler
PLL_Lock_IRQHandler
PLL_LockLost_IRQHandler
CommSwitchError_IRQHandler
CacheError_IRQHandler
DDR_IRQHandler
HPDMA_Complete_IRQHandler
HPDMA_Error_IRQHandler
ECC_Error_IRQHandler
MDDR_IOCalib_IRQHandler
FAB_PLL_Lock_IRQHandler
FAB_PLL_LockLost_IRQHandler
FIC64_IRQHandler
FabricIrq0_IRQHandler
FabricIrq1_IRQHandler
FabricIrq2_IRQHandler
FabricIrq3_IRQHandler
FabricIrq4_IRQHandler
FabricIrq5_IRQHandler
FabricIrq6_IRQHandler
FabricIrq7_IRQHandler
FabricIrq8_IRQHandler 
FabricIrq9_IRQHandler 
FabricIrq10_IRQHandler
FabricIrq11_IRQHandler
FabricIrq12_IRQHandler
FabricIrq13_IRQHandler
FabricIrq14_IRQHandler
FabricIrq15_IRQHandler
GPIO0_IRQHandler
GPIO1_IRQHandler
GPIO2_IRQHandler
GPIO3_IRQHandler
GPIO4_IRQHandler
GPIO5_IRQHandler
GPIO6_IRQHandler
GPIO7_IRQHandler
GPIO8_IRQHandler
GPIO9_IRQHandler
GPIO10_IRQHandler
GPIO11_IRQHandler
GPIO12_IRQHandler
GPIO13_IRQHandler
GPIO14_IRQHandler
GPIO15_IRQHandler
GPIO16_IRQHandler
GPIO17_IRQHandler
GPIO18_IRQHandler
GPIO19_IRQHandler
GPIO20_IRQHandler
GPIO21_IRQHandler
GPIO22_IRQHandler
GPIO23_IRQHandler
GPIO24_IRQHandler
GPIO25_IRQHandler
GPIO26_IRQHandler
GPIO27_IRQHandler
GPIO28_IRQHandler
GPIO29_IRQHandler
GPIO30_IRQHandler
GPIO31_IRQHandler
                B       .

                ENDP

mscc_post_hw_cfg_init PROC
                EXPORT  mscc_post_hw_cfg_init           [WEAK]
                BX LR
                ENDP
                
                ALIGN


;===============================================================================
; User Initial Stack & Heap

                IF      :DEF:__MICROLIB
                
                EXPORT  __initial_sp
                EXPORT  __heap_base
                EXPORT  __heap_limit
                
                ELSE
                
                IMPORT  __use_two_region_memory
                EXPORT  __user_initial_stackheap
__user_initial_stackheap

                LDR     R0, =  Heap_Mem
                LDR     R1, =(Stack_Mem + Stack_Size)
                LDR     R2, = (Heap_Mem +  Heap_Size)
                LDR     R3, = Stack_Mem
                BX      LR

                ALIGN

                ENDIF


                END
