1/* 2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7#include "pico.h" 8 9#include "hardware/regs/addressmap.h" 10#include "hardware/regs/rvcsr.h" 11#include "pico/binary_info/defs.h" 12#include "boot/picobin.h" 13#include "pico/bootrom_constants.h" 14 15#ifdef NDEBUG 16#ifndef COLLAPSE_IRQS 17#define COLLAPSE_IRQS 18#endif 19#endif 20 21#if !defined(PICO_CRT0_INCLUDE_PICOBIN_IMAGE_TYPE_ITEM) 22#define PICO_CRT0_INCLUDE_PICOBIN_IMAGE_TYPE_ITEM 1 23#endif 24 25#ifndef PICO_CRT0_INCLUDE_PICOBIN_BLOCK 26#define PICO_CRT0_INCLUDE_PICOBIN_BLOCK PICO_CRT0_INCLUDE_PICOBIN_IMAGE_TYPE_ITEM 27#endif 28 29#ifndef PICO_CRT0_INCLUDE_PICOBIN_END_BLOCK 30#define PICO_CRT0_INCLUDE_PICOBIN_END_BLOCK (PICO_CRT0_INCLUDE_PICOBIN_BLOCK && !PICO_NO_FLASH) 31#endif 32 33// If vectors are in RAM, we put them in the .data section, so that they are 34// preloaded by _reset_handler (assuming this is not a loaded-in-place 35// binary). 36#if PICO_NO_RAM_VECTOR_TABLE || PICO_NO_FLASH 37.section .vectors, "ax" 38#else 39.section .data 40#endif 41 42.p2align 6 43.global __vectors, __VECTOR_TABLE 44__VECTOR_TABLE: 45__vectors: 46 47// Hardware vector table for standard RISC-V interrupts, indicated by `mtvec`. 48 49.option push 50.option norvc 51.option norelax 52j isr_riscv_machine_exception 53.word 0 54.word 0 55j isr_riscv_machine_soft_irq 56.word 0 57.word 0 58.word 0 59j isr_riscv_machine_timer 60.word 0 61.word 0 62.word 0 63// j isr_riscv_machine_external_irq -> inlined below 64.option pop 65 66// External IRQ dispatch, inlined into the last vector table slot. Note if 67// this code is modified, the VTABLE_FIRST_IRQ define in platform_defs.h also 68// needs to be modified (it identifies the beginning of the soft vector table) 69.global isr_riscv_machine_external_irq 70.weak isr_riscv_machine_external_irq 71isr_riscv_machine_external_irq: 72 // Save caller saves and exception return state whilst IRQs are disabled. 73 // We can't be preempted during this time, but if a higher-priority IRQ 74 // arrives before we read meinext, that will be the one we enter. 75 addi sp, sp, -80 76 sw ra, 0(sp) 77 sw t0, 4(sp) 78 sw t1, 8(sp) 79 sw t2, 12(sp) 80 sw a0, 16(sp) 81 sw a1, 20(sp) 82 sw a2, 24(sp) 83 sw a3, 28(sp) 84 sw a4, 32(sp) 85 sw a5, 36(sp) 86 sw a6, 40(sp) 87 sw a7, 44(sp) 88 sw t3, 48(sp) 89 sw t4, 52(sp) 90 sw t5, 56(sp) 91 sw t6, 60(sp) 92 csrr a0, mepc 93 csrr a1, mstatus 94 sw a0, 64(sp) 95 sw a1, 68(sp) 96save_meicontext: 97 // Make sure to set meicontext.clearts to clear+save mie.msie/mtie along 98 // with ext IRQ context. We don't let these preempt ext IRQs because they 99 // clear meicontext.mreteirq, which breaks __get_current_exception(). 100 csrrsi a2, RVCSR_MEICONTEXT_OFFSET, RVCSR_MEICONTEXT_CLEARTS_BITS 101 sw a2, 72(sp) 102 103get_first_irq: 104 // Sample the current highest-priority active IRQ (left-shifted by 2) from 105 // meinext, and write 1 to meinext.update to update meicontext with the 106 // preemption priority and IRQ number of this IRQ 107 csrrsi a0, RVCSR_MEINEXT_OFFSET, RVCSR_MEINEXT_UPDATE_BITS 108 // MSB will be set if there is no active IRQ at the current priority level 109 bltz a0, no_more_irqs 110dispatch_irq: 111 // Preemption priority was configured by meinext update, so enable preemption: 112 csrsi mstatus, 0x8 113 // <- from this point we can be preempted by a higher-priority interrupt. 114 // meinext is pre-shifted by 2, so only an add is required to index table 115 lui a1, %hi(__soft_vector_table) 116 add a1, a1, a0 117 lw a1, %lo(__soft_vector_table)(a1) 118 jalr ra, a1 119 // Disable IRQs on returning so we can sample the next IRQ 120 csrci mstatus, 0x8 121get_next_irq: 122 // Get the next-highest-priority IRQ that is active at this level. If 123 // there is such an IRQ, update meicontext with new preemption priority. 124 csrrsi a0, RVCSR_MEINEXT_OFFSET, RVCSR_MEINEXT_UPDATE_BITS 125 // MSB will be set if there is no active IRQ at the current priority level 126 bgez a0, dispatch_irq 127 128no_more_irqs: 129 // Restore saved context and return from IRQ 130 lw a0, 64(sp) 131 lw a1, 68(sp) 132 lw a2, 72(sp) 133 csrw mepc, a0 134 csrw mstatus, a1 135 csrw RVCSR_MEICONTEXT_OFFSET, a2 136 lw ra, 0(sp) 137 lw t0, 4(sp) 138 lw t1, 8(sp) 139 lw t2, 12(sp) 140 // skip a0 for now 141 lw a1, 20(sp) 142 lw a2, 24(sp) 143 lw a3, 28(sp) 144 lw a4, 32(sp) 145 lw a5, 36(sp) 146 lw a6, 40(sp) 147 lw a7, 44(sp) 148 lw t3, 48(sp) 149 lw t4, 52(sp) 150 lw t5, 56(sp) 151 lw t6, 60(sp) 152 // Before popping the stack frame, check if there is a new IRQ, and if so, 153 // abandon the mret and take the IRQ. This avoids a worst-case (restore -> 154 // mret -> enter -> save) latency. Note since we have already restored 155 // meicontext, we will have to re-save it, to re-clear mtie/msie. 156check_irq_before_exit: 157 csrr a0, RVCSR_MEINEXT_OFFSET 158 bgez a0, save_meicontext 159 lw a0, 16(sp) 160 addi sp, sp, 80 161 mret 162 163// Default software vector table for system interrupts, routed through 164// mip.meip. Note this is assumed in e.g. hardware_irq to begin exactly 0x34 165// words after the hardware vector table indicated by mtvec (defined above). 166.p2align 4 167.global __soft_vector_table 168__soft_vector_table: 169.word isr_irq0 170.word isr_irq1 171.word isr_irq2 172.word isr_irq3 173.word isr_irq4 174.word isr_irq5 175.word isr_irq6 176.word isr_irq7 177.word isr_irq8 178.word isr_irq9 179.word isr_irq10 180.word isr_irq11 181.word isr_irq12 182.word isr_irq13 183.word isr_irq14 184.word isr_irq15 185.word isr_irq16 186.word isr_irq17 187.word isr_irq18 188.word isr_irq19 189.word isr_irq20 190.word isr_irq21 191.word isr_irq22 192.word isr_irq23 193.word isr_irq24 194.word isr_irq25 195.word isr_irq26 196.word isr_irq27 197.word isr_irq28 198.word isr_irq29 199.word isr_irq30 200.word isr_irq31 201.word isr_irq32 202.word isr_irq33 203.word isr_irq34 204.word isr_irq35 205.word isr_irq36 206.word isr_irq37 207.word isr_irq38 208.word isr_irq39 209.word isr_irq40 210.word isr_irq41 211.word isr_irq42 212.word isr_irq43 213.word isr_irq44 214.word isr_irq45 215.word isr_irq46 216.word isr_irq47 217.word isr_irq48 218.word isr_irq49 219.word isr_irq50 220.word isr_irq51 221 222// all default trap handlers do nothing, and we can check for them being set to our 223// default values by seeing if they point to somewhere between __defaults_isrs_start and __default_isrs_end 224.global __default_isrs_start 225__default_isrs_start: 226 227// Declare a weak symbol for each ISR. 228// By default, they will fall through to the undefined IRQ handler below (breakpoint), 229// but can be overridden by C functions with correct name. 230 231.macro decl_isr name 232.weak \name 233\name: 234.endm 235 236.macro decl_isr_bkpt name 237.weak \name 238\name: 239 ebreak 240.endm 241 242// hardware_exception on RISC-V defines its own weak handler 243#if !PICO_CRT0_NO_ISR_RISCV_MACHINE_EXCEPTION 244// Breakpoint will just cause another exception and trash the exception 245// state, since there is no double fault lockup on RISC-V. Instead, just 246// sleep the core indefinitely, or until debugger connects. 247decl_isr isr_riscv_machine_exception 248#endif 249 250// Note the mip.mtip is also available as SIO_IRQ_MTIMECMP, and this may be a 251// better option, because it plays nicely with interrupt preemption. 252decl_isr_bkpt isr_riscv_machine_timer 253decl_isr_bkpt isr_riscv_machine_soft_irq 254 255decl_isr isr_irq0 256decl_isr isr_irq1 257decl_isr isr_irq2 258decl_isr isr_irq3 259decl_isr isr_irq4 260decl_isr isr_irq5 261decl_isr isr_irq6 262decl_isr isr_irq7 263decl_isr isr_irq8 264decl_isr isr_irq9 265decl_isr isr_irq10 266decl_isr isr_irq11 267decl_isr isr_irq12 268decl_isr isr_irq13 269decl_isr isr_irq14 270decl_isr isr_irq15 271decl_isr isr_irq16 272decl_isr isr_irq17 273decl_isr isr_irq18 274decl_isr isr_irq19 275decl_isr isr_irq20 276decl_isr isr_irq21 277decl_isr isr_irq22 278decl_isr isr_irq23 279decl_isr isr_irq24 280decl_isr isr_irq25 281decl_isr isr_irq26 282decl_isr isr_irq27 283decl_isr isr_irq28 284decl_isr isr_irq29 285decl_isr isr_irq30 286decl_isr isr_irq31 287decl_isr isr_irq32 288decl_isr isr_irq33 289decl_isr isr_irq34 290decl_isr isr_irq35 291decl_isr isr_irq36 292decl_isr isr_irq37 293decl_isr isr_irq38 294decl_isr isr_irq39 295decl_isr isr_irq40 296decl_isr isr_irq41 297decl_isr isr_irq42 298decl_isr isr_irq43 299decl_isr isr_irq44 300decl_isr isr_irq45 301decl_isr isr_irq46 302decl_isr isr_irq47 303decl_isr isr_irq48 304decl_isr isr_irq49 305decl_isr isr_irq50 306decl_isr isr_irq51 307 // fall through 308 309// All unhandled USER IRQs fall through to here. Note there is no way to get 310// the "current exception" on RISC-V (as there is no such thing -- the 311// hardware does not model the exception lifecycle like on Arm) so instead we 312// just pass the IRQ number into the IRQ handler in a0. 313.global __unhandled_user_irq 314__unhandled_user_irq: 315.global unhandled_user_irq_num_in_a0 316unhandled_user_irq_num_in_a0: 317 // The dispatch code will have left IRQ << 2 in a0 from its meinext read, 318 // so just need to shift it back down 319 srli a0, a0, 2 320 ebreak 321 322.global __default_isrs_end 323__default_isrs_end: 324 325// ---------------------------------------------------------------------------- 326 327.section .binary_info_header, "a" 328 329// Header must be in first 256 bytes of main image (i.e. excluding flash boot2). 330// For flash builds we put it immediately after vector table; for NO_FLASH the 331// vectors are at a +0x100 offset because the bootrom enters RAM images directly 332// at their lowest address, so we put the header in the VTOR alignment hole. 333 334#if !PICO_NO_BINARY_INFO 335binary_info_header: 336.word BINARY_INFO_MARKER_START 337.word __binary_info_start 338.word __binary_info_end 339.word data_cpy_table // we may need to decode pointers that are in RAM at runtime. 340.word BINARY_INFO_MARKER_END 341#endif 342 343#include "embedded_start_block.inc.S" 344 345// ---------------------------------------------------------------------------- 346 347.section .reset, "ax" 348 349// On flash builds, the vector table comes first in the image (conventional). 350// On NO_FLASH builds, the reset handler section comes first, as the entry 351// point is at offset 0 (fixed due to bootrom), and VTOR is highly-aligned. 352// Image is entered in various ways: 353// 354// - NO_FLASH builds are entered from beginning by UF2 bootloader 355// 356// - Flash builds vector through the table into _reset_handler from boot2 357// 358// - Either type can be entered via _entry_point by the debugger, and flash builds 359// must then be sent back round the boot sequence to properly initialise flash 360 361// ELF entry point: 362.global _entry_point 363_entry_point: 364 365#if PICO_NO_FLASH 366 // Go through our own reset handler. Same path for debugger entry and 367 // bootloader entry. 368 j _reset_handler 369#else 370 // Debugger tried to run code after loading, so SSI is in 03h-only mode. 371 // Go back through bootrom + boot2 to properly initialise flash. 372 j reenter_bootrom 373#endif 374 375// Reset handler: 376// - initialises .data 377// - clears .bss 378// - calls runtime_init 379// - calls main 380// - calls exit (which should eventually hang the processor via _exit) 381 382_reset_handler: 383.option push 384.option norelax 385 la gp, __global_pointer$ 386.option pop 387 la sp, __StackTop 388 // Leave interrupts globally disabled for now, we will set that up later 389 // in runtime_init_per_core_h3_irq_registers. Still worth installing the vector table: 390 la a0, __vectors + 1 391 csrw mtvec, a0 392 393 // Only core 0 should run the C runtime startup code; core 1 is normally 394 // sleeping in the bootrom at this point but check to be sure 395 csrr a0, mhartid 396 bnez a0, reenter_bootrom 397 398#if PICO_RP2350 && PICO_EMBED_XIP_SETUP && !PICO_NO_FLASH 399 // Execute boot2 on the core 0 stack (it also gets copied into BOOTRAM due 400 // to inclusion in the data copy table below) 401_copy_xip_setup: 402 mv a2, sp 403 addi sp, sp, -256 404 mv a0, sp 405 la a1, __boot2_entry_point 4061: 407 // Iterate forward, as sequential flash access is faster 408 lw a3, (a1) 409 sw a3, (a0) 410 addi a0, a0, 4 411 addi a1, a1, 4 412 bltu a0, a2, 1b 413_call_xip_setup: 414 jalr sp 415 addi sp, sp, 256 416#endif 417 418 // In a NO_FLASH binary, don't perform .data etc copy, since it's loaded 419 // in-place by the SRAM load. Still need to clear .bss 420#if !PICO_NO_FLASH 421 la a4, data_cpy_table 422 423 // assume there is at least one entry 4241: 425 lw a1, 0(a4) 426 beqz a1, 2f 427 lw a2, 4(a4) 428 lw a3, 8(a4) 429 addi a4, a4, 12 430 jal data_cpy 431 j 1b 4322: 433#endif 434 435 // Zero out the BSS 436 la a1, __bss_start__ 437 la a2, __bss_end__ 438 j bss_fill_test 439bss_fill_loop: 440 sw zero, (a1) 441 addi a1, a1, 4 442bss_fill_test: 443 bne a1, a2, bss_fill_loop 444 445platform_entry: // symbol for stack traces 446 // Use `call` pseudo-instruction instead of a bare `jal` so that the 447 // linker can use longer sequences if these are out of `jal` range. Will 448 // still get relaxed to a `jal` if possible. 449 // call runtime_init_per_core_h3_irq_registers (now called in runtime_init) 450 call runtime_init 451 call main 452 call exit 453 // exit should not return. If it does, hang the core. 454 // (fall thru into our hang _exit impl 4551: // separate label because _exit can be moved out of branch range 456 ebreak 457 j 1b 458 459data_cpy_loop: 460 lw a0, (a1) 461 sw a0, (a2) 462 addi a1, a1, 4 463 addi a2, a2, 4 464data_cpy: 465 bltu a2, a3, data_cpy_loop 466 ret 467 468.align 2 469data_cpy_table: 470#if PICO_RP2350 && PICO_EMBED_XIP_SETUP && !PICO_NO_FLASH 471.word __boot2_start__ 472.word BOOTRAM_BASE 473.word BOOTRAM_BASE + 256 474#endif 475#if PICO_COPY_TO_RAM 476.word __ram_text_source__ 477.word __ram_text_start__ 478.word __ram_text_end__ 479#endif 480.word __etext 481.word __data_start__ 482.word __data_end__ 483 484.word __scratch_x_source__ 485.word __scratch_x_start__ 486.word __scratch_x_end__ 487 488.word __scratch_y_source__ 489.word __scratch_y_start__ 490.word __scratch_y_end__ 491 492.word 0 // null terminator 493 494// ---------------------------------------------------------------------------- 495// Provide safe defaults for _exit and runtime_init 496// Full implementations usually provided by platform.c 497 498.weak runtime_init 499runtime_init: 500 ret 501 502// ---------------------------------------------------------------------------- 503// If core 1 somehow gets into crt0, we need to catch it and send back to the 504// sleep-and-launch code in the bootrom. Shouldn't happen (it should sleep in 505// the ROM until given an entry point via the cross-core FIFOs) but it's good 506// to be defensive. 507 508// Enter through the shared reset handler: on core 1 this should quickly reach 509// the wait-for-vector code. 510reenter_bootrom: 511 512#ifdef RASPBERRYPI_AMETHYST_FPGA 513 // todo remove once 64k bootrom support is not required: vvvvvvvvvvvvvvvvvvvvv 514 // Try jumping 32k higher and see if we get a fault :) 515 li a0, BOOTROM_ENTRY_OFFSET + 32 * 1024 516 la a1, 1f 517 csrw mtvec, a1 518 jr a0 519 // Go here if we trapped: 520.p2align 2 5211: 522#endif 523 524 li a0, BOOTROM_ENTRY_OFFSET 525 jr a0 526 527// ---------------------------------------------------------------------------- 528// IRQ register clearing 529 530// Enable interrupts globally, but disable all interrupt sources. 531// 532// This is put in the .text section as it is called again on core 1 launch. In 533// COPY_TO_RAM binaries, the .reset section is always in flash, whereas .text 534// is in SRAM, and we try to avoid running any code from flash after entering 535// user code in a COPY_TO_RAM binary. Note because of this we don't call this 536// function here in crt0 until after the flash-to-RAM copying is finished. 537 538.section .text 539.global runtime_init_per_core_h3_irq_registers 540runtime_init_per_core_h3_irq_registers: 541 // First clear all IRQ force array bits. Iterate over array registers 0 542 // through 3 inclusive, allowing for up to 64 IRQs. Don't clear the 543 // enable array as earlier (non-per-core) init stages may have already 544 // set up IRQs. 545 li a0, 3 5461: 547 csrw RVCSR_MEIFA_OFFSET, a0 548 addi a0, a0, -1 549 bgez a0, 1b 550 // Setting the global external IRQ enable in mie prepares us to enable 551 // IRQs one-by-one later. Also clear the soft IRQ and timer IRQ enables: 552 li a0, RVCSR_MIE_MEIE_BITS 553 csrw mie, a0 554 // Set the global IRQ: we will now take any individual interrupt that is 555 // pending && enabled 556 csrsi mstatus, RVCSR_MSTATUS_MIE_BITS 557 // Take this chance to clear mscratch, which is used to detect nested 558 // exceptions in isr_riscv_machine_exception: 559 csrw mscratch, zero 560 ret 561 562// ---------------------------------------------------------------------------- 563// Stack/heap dummies to set size 564 565// Prior to SDK 1.5.1 these were `.section .stack` without the `, "a"`... Clang linker gives a warning about this, 566// however setting it explicitly to `, "a"` makes GCC *now* discard the section unless it is also KEEP. This 567// seems like very surprising behavior! 568// 569// Strictly the most correct thing to do (as .stack and .heap are unreferenced) is to mark them as "a", and also KEEP, which 570// works correctly for both GCC and Clang, however doing so may break anyone who already has custom linker scripts without 571// the KEEP. Therefore we will only add the "a" on Clang, but will also use KEEP to our own linker scripts. 572 573.macro spacer_section name 574#if PICO_ASSEMBLER_IS_CLANG 575.section \name, "a" 576#else 577.section \name 578#endif 579.endm 580 581spacer_section .stack 582// align to allow for memory protection (although this alignment is pretty much ignored by linker script) 583.p2align 5 584 .equ StackSize, PICO_STACK_SIZE 585.space StackSize 586 587spacer_section .heap 588.p2align 2 589 .equ HeapSize, PICO_HEAP_SIZE 590.space HeapSize 591 592#include "embedded_end_block.inc.S" 593 594