1/* 2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7#include "pico.h" 8#include "pico/asm_helper.S" 9 10#include "pico/platform/cpu_regs.h" 11 12#include "hardware/regs/addressmap.h" 13#include "hardware/regs/sio.h" 14#include "pico/binary_info/defs.h" 15#include "boot/picobin.h" 16#include "pico/bootrom.h" 17 18#ifdef NDEBUG 19#ifndef COLLAPSE_IRQS 20#define COLLAPSE_IRQS 21#endif 22#endif 23 24pico_default_asm_setup 25 26.section .vectors, "ax" 27.align 2 28 29.global __vectors, __VECTOR_TABLE 30__VECTOR_TABLE: 31__vectors: 32.word __StackTop 33.word _reset_handler 34.word isr_nmi 35.word isr_hardfault 36.word isr_invalid // Reserved, should never fire 37.word isr_invalid // Reserved, should never fire 38.word isr_invalid // Reserved, should never fire 39.word isr_invalid // Reserved, should never fire 40.word isr_invalid // Reserved, should never fire 41.word isr_invalid // Reserved, should never fire 42.word isr_invalid // Reserved, should never fire 43.word isr_svcall 44.word isr_invalid // Reserved, should never fire 45.word isr_invalid // Reserved, should never fire 46.word isr_pendsv 47.word isr_systick 48#if PICO_NO_STORED_VECTOR_TABLE && !PICO_NO_FLASH // note in no flash binary, we only have the single RAM vector table anyway 49#if PICO_NO_RAM_VECTOR_TABLE 50#error Can't specify PICO_NO_STORED_VECTOR_TABLE and PICO_NO_RAM_VECTOR_TABLE 51#endif 52// we don't include any IRQ vectors; we will initialize them during runtime_init in the RAM vector table 53#else 54 55.macro if_irq_word num func 56.if \num < NUM_IRQS 57.word \func 58.endif 59.endm 60 61// we include a lot of these to allow for different number of IRQs. 62// if_irq_word will only include IRQs that are valid, but we can't 63// use a macro loop because isr_irqx MUST appear in the source 64// as CMSIS rename exceptions #defines it to another value 65if_irq_word 0 isr_irq0 66if_irq_word 1 isr_irq1 67if_irq_word 2 isr_irq2 68if_irq_word 3 isr_irq3 69if_irq_word 4 isr_irq4 70if_irq_word 5 isr_irq5 71if_irq_word 6 isr_irq6 72if_irq_word 7 isr_irq7 73if_irq_word 8 isr_irq8 74if_irq_word 9 isr_irq9 75if_irq_word 10 isr_irq10 76if_irq_word 11 isr_irq11 77if_irq_word 12 isr_irq12 78if_irq_word 13 isr_irq13 79if_irq_word 14 isr_irq14 80if_irq_word 15 isr_irq15 81if_irq_word 16 isr_irq16 82if_irq_word 17 isr_irq17 83if_irq_word 18 isr_irq18 84if_irq_word 19 isr_irq19 85if_irq_word 20 isr_irq20 86if_irq_word 21 isr_irq21 87if_irq_word 22 isr_irq22 88if_irq_word 23 isr_irq23 89if_irq_word 24 isr_irq24 90if_irq_word 25 isr_irq25 91if_irq_word 26 isr_irq26 92if_irq_word 27 isr_irq27 93if_irq_word 28 isr_irq28 94if_irq_word 29 isr_irq29 95if_irq_word 30 isr_irq30 96if_irq_word 31 isr_irq31 97if_irq_word 32 isr_irq32 98if_irq_word 33 isr_irq33 99if_irq_word 34 isr_irq34 100if_irq_word 35 isr_irq35 101if_irq_word 36 isr_irq36 102if_irq_word 37 isr_irq37 103if_irq_word 38 isr_irq38 104if_irq_word 39 isr_irq39 105if_irq_word 40 isr_irq40 106if_irq_word 41 isr_irq41 107if_irq_word 42 isr_irq42 108if_irq_word 43 isr_irq43 109if_irq_word 44 isr_irq44 110if_irq_word 45 isr_irq45 111if_irq_word 46 isr_irq46 112if_irq_word 47 isr_irq47 113if_irq_word 48 isr_irq48 114if_irq_word 49 isr_irq49 115if_irq_word 50 isr_irq50 116if_irq_word 51 isr_irq51 117if_irq_word 52 isr_irq52 118if_irq_word 53 isr_irq53 119if_irq_word 54 isr_irq54 120if_irq_word 55 isr_irq55 121if_irq_word 56 isr_irq56 122if_irq_word 57 isr_irq57 123if_irq_word 58 isr_irq58 124if_irq_word 59 isr_irq59 125if_irq_word 60 isr_irq60 126if_irq_word 61 isr_irq61 127if_irq_word 62 isr_irq62 128if_irq_word 63 isr_irq63 129if_irq_word 64 isr_irq64 130if_irq_word 65 isr_irq65 131if_irq_word 66 isr_irq66 132if_irq_word 67 isr_irq67 133if_irq_word 68 isr_irq68 134if_irq_word 69 isr_irq69 135if_irq_word 70 isr_irq70 136if_irq_word 71 isr_irq71 137if_irq_word 72 isr_irq72 138if_irq_word 73 isr_irq73 139if_irq_word 74 isr_irq74 140if_irq_word 75 isr_irq75 141if_irq_word 76 isr_irq76 142if_irq_word 77 isr_irq77 143if_irq_word 78 isr_irq78 144if_irq_word 79 isr_irq79 145#if NUM_IRQS > 80 146#error more IRQ entries required 147#endif 148#endif 149 150// all default exception handlers do nothing, and we can check for them being set to our 151// default values by seeing if they point to somewhere between __defaults_isrs_start and __default_isrs_end 152.global __default_isrs_start 153__default_isrs_start: 154 155// Declare a weak symbol for each ISR. 156// By default, they will fall through to the undefined IRQ handler below (breakpoint), 157// but can be overridden by C functions with correct name. 158 159.macro decl_isr_bkpt name 160.weak \name 161.type \name,%function 162.thumb_func 163\name: 164 bkpt #0 165.endm 166 167// these are separated out for clarity 168decl_isr_bkpt isr_invalid 169decl_isr_bkpt isr_nmi 170decl_isr_bkpt isr_hardfault 171decl_isr_bkpt isr_svcall 172decl_isr_bkpt isr_pendsv 173decl_isr_bkpt isr_systick 174 175.global __default_isrs_end 176__default_isrs_end: 177 178.altmacro 179.macro decl_isr name 180#if !PICO_NO_STORED_VECTOR_TABLE | PICO_NO_FLASH 181// We declare a weak label, so user can override 182.weak \name 183#else 184// We declare a strong label, so user can't override (their version would not automatically be used) 185#endif 186.type \name,%function 187.thumb_func 188\name: 189.endm 190 191.macro if_irq_decl num func 192.if \num < NUM_IRQS 193decl_isr \func 194.endif 195.endm 196 197if_irq_decl 0 isr_irq0 198if_irq_decl 1 isr_irq1 199if_irq_decl 2 isr_irq2 200if_irq_decl 3 isr_irq3 201if_irq_decl 4 isr_irq4 202if_irq_decl 5 isr_irq5 203if_irq_decl 6 isr_irq6 204if_irq_decl 7 isr_irq7 205if_irq_decl 8 isr_irq8 206if_irq_decl 9 isr_irq9 207if_irq_decl 10 isr_irq10 208if_irq_decl 11 isr_irq11 209if_irq_decl 12 isr_irq12 210if_irq_decl 13 isr_irq13 211if_irq_decl 14 isr_irq14 212if_irq_decl 15 isr_irq15 213if_irq_decl 16 isr_irq16 214if_irq_decl 17 isr_irq17 215if_irq_decl 18 isr_irq18 216if_irq_decl 19 isr_irq19 217if_irq_decl 20 isr_irq20 218if_irq_decl 21 isr_irq21 219if_irq_decl 22 isr_irq22 220if_irq_decl 23 isr_irq23 221if_irq_decl 24 isr_irq24 222if_irq_decl 25 isr_irq25 223if_irq_decl 26 isr_irq26 224if_irq_decl 27 isr_irq27 225if_irq_decl 28 isr_irq28 226if_irq_decl 29 isr_irq29 227if_irq_decl 30 isr_irq30 228if_irq_decl 31 isr_irq31 229if_irq_decl 32 isr_irq32 230if_irq_decl 33 isr_irq33 231if_irq_decl 34 isr_irq34 232if_irq_decl 35 isr_irq35 233if_irq_decl 36 isr_irq36 234if_irq_decl 37 isr_irq37 235if_irq_decl 38 isr_irq38 236if_irq_decl 39 isr_irq39 237if_irq_decl 40 isr_irq40 238if_irq_decl 41 isr_irq41 239if_irq_decl 42 isr_irq42 240if_irq_decl 43 isr_irq43 241if_irq_decl 44 isr_irq44 242if_irq_decl 45 isr_irq45 243if_irq_decl 46 isr_irq46 244if_irq_decl 47 isr_irq47 245if_irq_decl 48 isr_irq48 246if_irq_decl 49 isr_irq49 247if_irq_decl 50 isr_irq50 248if_irq_decl 51 isr_irq51 249if_irq_decl 52 isr_irq52 250if_irq_decl 53 isr_irq53 251if_irq_decl 54 isr_irq54 252if_irq_decl 55 isr_irq55 253if_irq_decl 56 isr_irq56 254if_irq_decl 57 isr_irq57 255if_irq_decl 58 isr_irq58 256if_irq_decl 59 isr_irq59 257if_irq_decl 60 isr_irq60 258if_irq_decl 61 isr_irq61 259if_irq_decl 62 isr_irq62 260if_irq_decl 63 isr_irq63 261if_irq_decl 64 isr_irq64 262if_irq_decl 65 isr_irq65 263if_irq_decl 66 isr_irq66 264if_irq_decl 67 isr_irq67 265if_irq_decl 68 isr_irq68 266if_irq_decl 69 isr_irq69 267if_irq_decl 70 isr_irq70 268if_irq_decl 71 isr_irq71 269if_irq_decl 72 isr_irq72 270if_irq_decl 73 isr_irq73 271if_irq_decl 74 isr_irq74 272if_irq_decl 75 isr_irq75 273if_irq_decl 76 isr_irq76 274if_irq_decl 77 isr_irq77 275if_irq_decl 78 isr_irq78 276if_irq_decl 79 isr_irq79 277#if NUM_IRQS > 80 278#error more IRQ entries required 279#endif 280 281// All unhandled USER IRQs fall through to here 282.global __unhandled_user_irq 283.thumb_func 284__unhandled_user_irq: 285 mrs r0, ipsr 286 subs r0, #16 287.global unhandled_user_irq_num_in_r0 288unhandled_user_irq_num_in_r0: 289 bkpt #0 290 291// ---------------------------------------------------------------------------- 292 293.section .binary_info_header, "a" 294 295// Header must be in first 256 bytes of main image (i.e. excluding flash boot2). 296// For flash builds we put it immediately after vector table; for NO_FLASH the 297// vectors are at a +0x100 offset because the bootrom enters RAM images directly 298// at their lowest address, so we put the header in the VTOR alignment hole. 299 300#if !PICO_NO_BINARY_INFO 301binary_info_header: 302.word BINARY_INFO_MARKER_START 303.word __binary_info_start 304.word __binary_info_end 305.word data_cpy_table // we may need to decode pointers that are in RAM at runtime. 306.word BINARY_INFO_MARKER_END 307#endif 308 309#include "embedded_start_block.inc.S" 310 311// ---------------------------------------------------------------------------- 312 313.section .reset, "ax" 314 315// On flash builds, the vector table comes first in the image (conventional). 316// On NO_FLASH builds, the reset handler section comes first, as the entry 317// point is at offset 0 (fixed due to bootrom), and VTOR is highly-aligned. 318// Image is entered in various ways: 319// 320// - NO_FLASH builds are entered from beginning by UF2 bootloader 321// 322// - Flash builds vector through the table into _reset_handler from boot2 323// 324// - Either type can be entered via _entry_point by the debugger, and flash builds 325// must then be sent back round the boot sequence to properly initialise flash 326 327// ELF entry point: 328.type _entry_point,%function 329.thumb_func 330.global _entry_point 331_entry_point: 332 333#if PICO_NO_FLASH 334 // on the NO_FLASH case, we do not do a rest thru bootrom below, so the RCP may or may not have been initialized: 335 // 336 // in the normal (e.g. UF2 download etc. case) we will have passed thru bootrom initialization, but if 337 // a NO_FLASH binary is loaded by the debugger, and run directly after a reset, then we won't have. 338 // 339 // we must therefore initialize the RCP if it hasn't already been 340 341#if HAS_REDUNDANCY_COPROCESSOR 342 // just enable the RCP which is fine if it already was (we assume no other co-processors are enabled at this point to save space) 343 ldr r0, = PPB_BASE + M33_CPACR_OFFSET 344 movs r1, #ARM_CPU_PREFIXED(CPACR_CP7_BITS) 345 str r1, [r0] 346 // only initialize canary seeds if they haven't been (as to do so twice is a fault) 347 mrc p7, #1, apsr_nzcv, c0, c0, #0 348 bmi 1f 349 // i dont think it much matters what we initialized to, as to have gotten here we must have not 350 // gone thru the bootrom (which a secure boot would have) 351 mcrr p7, #8, r0, r0, c0 352 mcrr p7, #8, r0, r0, c1 353 sev 3541: 355#endif 356 ldr r0, =__vectors 357 // Vector through our own table (SP, VTOR will not have been set up at 358 // this point). Same path for debugger entry and bootloader entry. 359#else 360 // Debugger tried to run code after loading, so SSI is in 03h-only mode. 361 // Go back through bootrom + boot2 to properly initialise flash. 362 ldr r0, =BOOTROM_VTABLE_OFFSET 363#endif 364 365_enter_vtable_in_r0: 366 ldr r1, =(PPB_BASE + ARM_CPU_PREFIXED(VTOR_OFFSET)) 367 str r0, [r1] 368 ldmia r0!, {r1, r2} 369 msr msp, r1 370 bx r2 371 372// Reset handler: 373// - initialises .data 374// - clears .bss 375// - calls runtime_init 376// - calls main 377// - calls exit (which should eventually hang the processor via _exit) 378 379.type _reset_handler,%function 380.thumb_func 381_reset_handler: 382 // Only core 0 should run the C runtime startup code; core 1 is normally 383 // sleeping in the bootrom at this point but check to be sure (e.g. if 384 // debugger put core 1 at the ELF entry point for some reason) 385 ldr r0, =(SIO_BASE + SIO_CPUID_OFFSET) 386 ldr r0, [r0] 387#if __ARM_ARCH_6M__ 388 cmp r0, #0 389 beq 1f 390#else 391 cbz r0, 1f 392#endif 393hold_non_core0_in_bootrom: 394 // Send back to the ROM to wait for core 0 to launch it. 395 ldr r0, =BOOTROM_VTABLE_OFFSET 396 b _enter_vtable_in_r0 3971: 398 399#if !PICO_RP2040 && PICO_EMBED_XIP_SETUP && !PICO_NO_FLASH 400 // Execute boot2 on the core 0 stack (it also gets copied into BOOTRAM due 401 // to inclusion in the data copy table below). Note the reference 402 // to __boot2_entry_point here is what prevents the .boot2 section from 403 // being garbage-collected. 404_copy_xip_setup: 405 ldr r1, =__boot2_entry_point 406 mov r3, sp 407 add sp, #-256 408 mov r2, sp 409 bl data_cpy 410_call_xip_setup: 411 mov r0, sp 412 adds r0, #1 413 blx r0 414 add sp, #256 415#endif 416 417 // In a NO_FLASH binary, don't perform .data etc copy, since it's loaded 418 // in-place by the SRAM load. Still need to clear .bss 419#if !PICO_NO_FLASH 420 adr r4, data_cpy_table 421 422 // assume there is at least one entry 4231: 424 ldmia r4!, {r1-r3} 425 cmp r1, #0 426 beq 2f 427 bl data_cpy 428 b 1b 4292: 430#endif 431 432 // Zero out the BSS 433 ldr r1, =__bss_start__ 434 ldr r2, =__bss_end__ 435 movs r0, #0 436 b bss_fill_test 437bss_fill_loop: 438 stm r1!, {r0} 439bss_fill_test: 440 cmp r1, r2 441 bne bss_fill_loop 442 443platform_entry: // symbol for stack traces 444 // Use 32-bit jumps, in case these symbols are moved out of branch range 445 // (e.g. if main is in SRAM and crt0 in flash) 446#if !__ARM_ARCH_6M__ 447 // Make sure stack limit is 0 - the user can set it themselves 448 // todo probably worth adding to the EXE_DEF in the future 449 movs r0, #0 450 msr msplim, r0 451#endif 452 ldr r1, =runtime_init 453 blx r1 454 ldr r1, =main 455 blx r1 456 ldr r1, =exit 457 blx r1 458 // exit should not return. If it does, hang the core. 4591: // separate label because _exit can be moved out of branch range 460 bkpt #0 461 b 1b 462 463 464#if !PICO_NO_FLASH 465data_cpy_loop: 466 ldm r1!, {r0} 467 stm r2!, {r0} 468data_cpy: 469 cmp r2, r3 470 blo data_cpy_loop 471 bx lr 472#endif 473 474// Note the data copy table is still included for NO_FLASH builds, even though 475// we skip the copy, because it is listed in binary info 476 477.align 2 478data_cpy_table: 479#if PICO_RP2350 && PICO_EMBED_XIP_SETUP && !PICO_NO_FLASH 480.word __boot2_start__ 481.word BOOTRAM_BASE 482.word BOOTRAM_BASE + 256 483#endif 484 485#if PICO_COPY_TO_RAM 486.word __ram_text_source__ 487.word __ram_text_start__ 488.word __ram_text_end__ 489#endif 490.word __etext 491.word __data_start__ 492.word __data_end__ 493 494.word __scratch_x_source__ 495.word __scratch_x_start__ 496.word __scratch_x_end__ 497 498.word __scratch_y_source__ 499.word __scratch_y_start__ 500.word __scratch_y_end__ 501 502.word 0 // null terminator 503 504// ---------------------------------------------------------------------------- 505// Provide safe defaults for _exit and runtime_init 506// Full implementations usually provided by platform.c 507 508.weak runtime_init 509.type runtime_init,%function 510.thumb_func 511runtime_init: 512 bx lr 513 514// ---------------------------------------------------------------------------- 515// Stack/heap dummies to set size 516 517// Prior to SDK 1.5.1 these were `.section .stack` without the `, "a"`... Clang linker gives a warning about this, 518// however setting it explicitly to `, "a"` makes GCC *now* discard the section unless it is also KEEP. This 519// seems like very surprising behavior! 520// 521// Strictly the most correct thing to do (as .stack and .heap are unreferenced) is to mark them as "a", and also KEEP, which 522// works correctly for both GCC and Clang, however doing so may break anyone who already has custom linker scripts without 523// the KEEP. Therefore we will only add the "a" on Clang, but will also use KEEP to our own linker scripts. 524 525.macro spacer_section name 526#if PICO_ASSEMBLER_IS_CLANG 527.section \name, "a" 528#else 529.section \name 530#endif 531.endm 532 533spacer_section .stack 534// align to allow for memory protection (although this alignment is pretty much ignored by linker script) 535.p2align 5 536 .equ StackSize, PICO_STACK_SIZE 537.space StackSize 538 539spacer_section .heap 540.p2align 2 541 .equ HeapSize, PICO_HEAP_SIZE 542.space HeapSize 543 544#include "embedded_end_block.inc.S" 545