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