1/**************************************************************************//**
2 * @file     startup_psoc6_02_cm0plus.S
3 * @brief    CMSIS Core Device Startup File for
4 *           ARMCM0plus Device Series
5 * @version  V5.00
6 * @date     02. March 2016
7 ******************************************************************************/
8/*
9 * Copyright (c) 2009-2016 ARM Limited. All rights reserved.
10 *
11 * SPDX-License-Identifier: Apache-2.0
12 *
13 * Licensed under the Apache License, Version 2.0 (the License); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 */
25
26    /* Address of the NMI handler */
27    #define CY_NMI_HANLDER_ADDR         0x0000000D
28
29    /* The CPU VTOR register */
30    #define CY_CPU_VTOR_ADDR            0xE000ED08
31
32    /* Copy flash vectors and data section to RAM */
33    #define __STARTUP_COPY_MULTIPLE
34
35    /* Clear single BSS section */
36    #define __STARTUP_CLEAR_BSS
37
38    .syntax    unified
39    .arch    armv6-m
40
41    .section .stack
42    .align    3
43#ifdef __STACK_SIZE
44    .equ    Stack_Size, __STACK_SIZE
45#else
46    .equ    Stack_Size, 0x00001000
47#endif
48    .globl    __StackTop
49    .globl    __StackLimit
50__StackLimit:
51    .space    Stack_Size
52    .size    __StackLimit, . - __StackLimit
53__StackTop:
54    .size    __StackTop, . - __StackTop
55
56    .section .heap
57    .align    3
58#ifdef __HEAP_SIZE
59    .equ    Heap_Size, __HEAP_SIZE
60#else
61    .equ    Heap_Size, 0x00000400
62#endif
63    .globl    __HeapBase
64    .globl    __HeapLimit
65__HeapBase:
66    .if    Heap_Size
67    .space    Heap_Size
68    .endif
69    .size    __HeapBase, . - __HeapBase
70__HeapLimit:
71    .size    __HeapLimit, . - __HeapLimit
72
73    .section .vectors
74    .align 2
75    .globl    __Vectors
76__Vectors:
77    .long    __StackTop            /* Top of Stack */
78    .long    Reset_Handler         /* Reset Handler */
79    .long    CY_NMI_HANLDER_ADDR   /* NMI Handler */
80    .long    HardFault_Handler     /* Hard Fault Handler */
81    .long    0                     /* Reserved */
82    .long    0                     /* Reserved */
83    .long    0                     /* Reserved */
84    .long    0                     /* Reserved */
85    .long    0                     /* Reserved */
86    .long    0                     /* Reserved */
87    .long    0                     /* Reserved */
88    .long    SVC_Handler           /* SVCall Handler */
89    .long    0                     /* Reserved */
90    .long    0                     /* Reserved */
91    .long    PendSV_Handler        /* PendSV Handler */
92    .long    SysTick_Handler       /* SysTick Handler */
93
94     /* External interrupts                             Description */
95    .long    NvicMux0_IRQHandler                     /* CPU User Interrupt #0 */
96    .long    NvicMux1_IRQHandler                     /* CPU User Interrupt #1 */
97    .long    NvicMux2_IRQHandler                     /* CPU User Interrupt #2 */
98    .long    NvicMux3_IRQHandler                     /* CPU User Interrupt #3 */
99    .long    NvicMux4_IRQHandler                     /* CPU User Interrupt #4 */
100    .long    NvicMux5_IRQHandler                     /* CPU User Interrupt #5 */
101    .long    NvicMux6_IRQHandler                     /* CPU User Interrupt #6 */
102    .long    NvicMux7_IRQHandler                     /* CPU User Interrupt #7 */
103    .long    Internal0_IRQHandler                    /* Internal SW Interrupt #0 */
104    .long    Internal1_IRQHandler                    /* Internal SW Interrupt #1 */
105    .long    Internal2_IRQHandler                    /* Internal SW Interrupt #2 */
106    .long    Internal3_IRQHandler                    /* Internal SW Interrupt #3 */
107    .long    Internal4_IRQHandler                    /* Internal SW Interrupt #4 */
108    .long    Internal5_IRQHandler                    /* Internal SW Interrupt #5 */
109    .long    Internal6_IRQHandler                    /* Internal SW Interrupt #6 */
110    .long    Internal7_IRQHandler                    /* Internal SW Interrupt #7 */
111
112    .size    __Vectors, . - __Vectors
113    .equ    __VectorsSize, . - __Vectors
114
115    .section .ram_vectors
116    .align 2
117    .globl __ramVectors
118__ramVectors:
119    .space  __VectorsSize
120    .size   __ramVectors, . - __ramVectors
121
122
123    .text
124    .thumb
125    .thumb_func
126    .align  2
127
128    /*
129     * Device startup customization
130     *
131     * Note. The global resources are not yet initialized (for example global variables, peripherals, clocks)
132     * because this function is executed as the first instruction in the ResetHandler.
133     * The PDL is also not initialized to use the proper register offsets.
134     * The user of this function is responsible for initializing the PDL and resources before using them.
135     */
136    .weak   Cy_OnResetUser
137    .func   Cy_OnResetUser, Cy_OnResetUser
138    .type   Cy_OnResetUser, %function
139
140Cy_OnResetUser:
141    bx lr
142    .size   Cy_OnResetUser, . - Cy_OnResetUser
143    .endfunc
144
145    /* Reset handler */
146    .weak    Reset_Handler
147    .type    Reset_Handler, %function
148
149Reset_Handler:
150    bl Cy_OnResetUser
151    cpsid i
152
153/*  Firstly it copies data from read only memory to RAM. There are two schemes
154 *  to copy. One can copy more than one sections. Another can only copy
155 *  one section.  The former scheme needs more instructions and read-only
156 *  data to implement than the latter.
157 *  Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes.  */
158
159#ifdef __STARTUP_COPY_MULTIPLE
160/*  Multiple sections scheme.
161 *
162 *  Between symbol address __copy_table_start__ and __copy_table_end__,
163 *  there are array of triplets, each of which specify:
164 *    offset 0: LMA of start of a section to copy from
165 *    offset 4: VMA of start of a section to copy to
166 *    offset 8: size of the section to copy. Must be multiply of 4
167 *
168 *  All addresses must be aligned to 4 bytes boundary.
169 */
170    ldr    r4, =__copy_table_start__
171    ldr    r5, =__copy_table_end__
172
173.L_loop0:
174    cmp    r4, r5
175    bge    .L_loop0_done
176    ldr    r1, [r4]
177    ldr    r2, [r4, #4]
178    ldr    r3, [r4, #8]
179
180.L_loop0_0:
181    subs    r3, #4
182    blt    .L_loop0_0_done
183    ldr    r0, [r1, r3]
184    str    r0, [r2, r3]
185    b    .L_loop0_0
186
187.L_loop0_0_done:
188    adds    r4, #12
189    b    .L_loop0
190
191.L_loop0_done:
192#else
193/*  Single section scheme.
194 *
195 *  The ranges of copy from/to are specified by following symbols
196 *    __etext: LMA of start of the section to copy from. Usually end of text
197 *    __data_start__: VMA of start of the section to copy to
198 *    __data_end__: VMA of end of the section to copy to
199 *
200 *  All addresses must be aligned to 4 bytes boundary.
201 */
202    ldr    r1, =__etext
203    ldr    r2, =__data_start__
204    ldr    r3, =__data_end__
205
206    subs    r3, r2
207    ble    .L_loop1_done
208
209.L_loop1:
210    subs    r3, #4
211    ldr    r0, [r1,r3]
212    str    r0, [r2,r3]
213    bgt    .L_loop1
214
215.L_loop1_done:
216#endif /*__STARTUP_COPY_MULTIPLE */
217
218/*  This part of work usually is done in C library startup code. Otherwise,
219 *  define this macro to enable it in this startup.
220 *
221 *  There are two schemes too. One can clear multiple BSS sections. Another
222 *  can only clear one section. The former is more size expensive than the
223 *  latter.
224 *
225 *  Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former.
226 *  Otherwise define macro __STARTUP_CLEAR_BSS to choose the later.
227 */
228#ifdef __STARTUP_CLEAR_BSS_MULTIPLE
229/*  Multiple sections scheme.
230 *
231 *  Between symbol address __copy_table_start__ and __copy_table_end__,
232 *  there are array of tuples specifying:
233 *    offset 0: Start of a BSS section
234 *    offset 4: Size of this BSS section. Must be multiply of 4
235 */
236    ldr    r3, =__zero_table_start__
237    ldr    r4, =__zero_table_end__
238
239.L_loop2:
240    cmp    r3, r4
241    bge    .L_loop2_done
242    ldr    r1, [r3]
243    ldr    r2, [r3, #4]
244    movs    r0, 0
245
246.L_loop2_0:
247    subs    r2, #4
248    blt    .L_loop2_0_done
249    str    r0, [r1, r2]
250    b    .L_loop2_0
251.L_loop2_0_done:
252
253    adds    r3, #8
254    b    .L_loop2
255.L_loop2_done:
256#elif defined (__STARTUP_CLEAR_BSS)
257/*  Single BSS section scheme.
258 *
259 *  The BSS section is specified by following symbols
260 *    __bss_start__: start of the BSS section.
261 *    __bss_end__: end of the BSS section.
262 *
263 *  Both addresses must be aligned to 4 bytes boundary.
264 */
265    ldr    r1, =__bss_start__
266    ldr    r2, =__bss_end__
267
268    movs    r0, 0
269
270    subs    r2, r1
271    ble    .L_loop3_done
272
273.L_loop3:
274    subs    r2, #4
275    str    r0, [r1, r2]
276    bgt    .L_loop3
277.L_loop3_done:
278#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */
279
280    /* Update Vector Table Offset Register. */
281    ldr r0, =__ramVectors
282    ldr r1, =CY_CPU_VTOR_ADDR
283    str r0, [r1]
284    dsb 0xF
285
286#ifndef __NO_SYSTEM_INIT
287    bl    SystemInit
288#endif
289
290    bl    main
291
292    /* Should never get here */
293    b   .
294
295    .pool
296    .size    Reset_Handler, . - Reset_Handler
297
298    .align    1
299    .thumb_func
300    .weak    Default_Handler
301    .type    Default_Handler, %function
302Default_Handler:
303    b    .
304    .size    Default_Handler, . - Default_Handler
305    .weak    Cy_SysLib_FaultHandler
306    .type    Cy_SysLib_FaultHandler, %function
307
308Cy_SysLib_FaultHandler:
309    b    .
310    .size    Cy_SysLib_FaultHandler, . - Cy_SysLib_FaultHandler
311    .type Fault_Handler, %function
312
313Fault_Handler:
314    /* Storing LR content for Creator call stack trace */
315    push {LR}
316    movs r0, #4
317    mov r1, LR
318    tst r0, r1
319    beq .L_MSP
320    mrs r0, PSP
321    b .L_API_call
322.L_MSP:
323    mrs r0, MSP
324    /* Compensation of stack pointer address due to pushing 4 bytes of LR */
325    adds r0, r0, #4
326.L_API_call:
327    bl Cy_SysLib_FaultHandler
328    b   .
329    .size    Fault_Handler, . - Fault_Handler
330
331.macro    def_fault_Handler    fault_handler_name
332    .weak    \fault_handler_name
333    .set    \fault_handler_name, Fault_Handler
334    .endm
335
336/*    Macro to define default handlers. Default handler
337 *    will be weak symbol and just dead loops. They can be
338 *    overwritten by other handlers */
339    .macro    def_irq_handler    handler_name
340    .weak    \handler_name
341    .set    \handler_name, Default_Handler
342    .endm
343
344    def_irq_handler    NMI_Handler
345
346    def_fault_Handler  HardFault_Handler
347
348    def_irq_handler    SVC_Handler
349    def_irq_handler    PendSV_Handler
350    def_irq_handler    SysTick_Handler
351
352    def_irq_handler  NvicMux0_IRQHandler                     /* CPU User Interrupt #0 */
353    def_irq_handler  NvicMux1_IRQHandler                     /* CPU User Interrupt #1 */
354    def_irq_handler  NvicMux2_IRQHandler                     /* CPU User Interrupt #2 */
355    def_irq_handler  NvicMux3_IRQHandler                     /* CPU User Interrupt #3 */
356    def_irq_handler  NvicMux4_IRQHandler                     /* CPU User Interrupt #4 */
357    def_irq_handler  NvicMux5_IRQHandler                     /* CPU User Interrupt #5 */
358    def_irq_handler  NvicMux6_IRQHandler                     /* CPU User Interrupt #6 */
359    def_irq_handler  NvicMux7_IRQHandler                     /* CPU User Interrupt #7 */
360    def_irq_handler  Internal0_IRQHandler                    /* Internal SW Interrupt #0 */
361    def_irq_handler  Internal1_IRQHandler                    /* Internal SW Interrupt #1 */
362    def_irq_handler  Internal2_IRQHandler                    /* Internal SW Interrupt #2 */
363    def_irq_handler  Internal3_IRQHandler                    /* Internal SW Interrupt #3 */
364    def_irq_handler  Internal4_IRQHandler                    /* Internal SW Interrupt #4 */
365    def_irq_handler  Internal5_IRQHandler                    /* Internal SW Interrupt #5 */
366    def_irq_handler  Internal6_IRQHandler                    /* Internal SW Interrupt #6 */
367    def_irq_handler  Internal7_IRQHandler                    /* Internal SW Interrupt #7 */
368
369    .end
370
371
372/* [] END OF FILE */
373