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