/* * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ #include "hardware/regs/m0plus.h" #include "hardware/platform_defs.h" #include "hardware/regs/addressmap.h" #include "hardware/regs/sio.h" #include "pico/binary_info/defs.h" #ifdef NDEBUG #ifndef COLLAPSE_IRQS #define COLLAPSE_IRQS #endif #endif .syntax unified .cpu cortex-m0plus .thumb .section .vectors, "ax" .align 2 .global __vectors __vectors: .word __StackTop .word _reset_handler .word isr_nmi .word isr_hardfault .word isr_invalid // Reserved, should never fire .word isr_invalid // Reserved, should never fire .word isr_invalid // Reserved, should never fire .word isr_invalid // Reserved, should never fire .word isr_invalid // Reserved, should never fire .word isr_invalid // Reserved, should never fire .word isr_invalid // Reserved, should never fire .word isr_svcall .word isr_invalid // Reserved, should never fire .word isr_invalid // Reserved, should never fire .word isr_pendsv .word isr_systick .word isr_irq0 .word isr_irq1 .word isr_irq2 .word isr_irq3 .word isr_irq4 .word isr_irq5 .word isr_irq6 .word isr_irq7 .word isr_irq8 .word isr_irq9 .word isr_irq10 .word isr_irq11 .word isr_irq12 .word isr_irq13 .word isr_irq14 .word isr_irq15 .word isr_irq16 .word isr_irq17 .word isr_irq18 .word isr_irq19 .word isr_irq20 .word isr_irq21 .word isr_irq22 .word isr_irq23 .word isr_irq24 .word isr_irq25 .word isr_irq26 .word isr_irq27 .word isr_irq28 .word isr_irq29 .word isr_irq30 .word isr_irq31 // Declare a weak symbol for each ISR. // By default, they will fall through to the undefined IRQ handler below (breakpoint), // but can be overridden by C functions with correct name. .macro decl_isr_bkpt name .weak \name .type \name,%function .thumb_func \name: bkpt #0 .endm // these are separated out for clarity decl_isr_bkpt isr_invalid decl_isr_bkpt isr_nmi decl_isr_bkpt isr_hardfault decl_isr_bkpt isr_svcall decl_isr_bkpt isr_pendsv decl_isr_bkpt isr_systick .macro decl_isr name .weak \name .type \name,%function .thumb_func \name: .endm decl_isr isr_irq0 decl_isr isr_irq1 decl_isr isr_irq2 decl_isr isr_irq3 decl_isr isr_irq4 decl_isr isr_irq5 decl_isr isr_irq6 decl_isr isr_irq7 decl_isr isr_irq8 decl_isr isr_irq9 decl_isr isr_irq10 decl_isr isr_irq11 decl_isr isr_irq12 decl_isr isr_irq13 decl_isr isr_irq14 decl_isr isr_irq15 decl_isr isr_irq16 decl_isr isr_irq17 decl_isr isr_irq18 decl_isr isr_irq19 decl_isr isr_irq20 decl_isr isr_irq21 decl_isr isr_irq22 decl_isr isr_irq23 decl_isr isr_irq24 decl_isr isr_irq25 decl_isr isr_irq26 decl_isr isr_irq27 decl_isr isr_irq28 decl_isr isr_irq29 decl_isr isr_irq30 decl_isr isr_irq31 // All unhandled USER IRQs fall through to here .global __unhandled_user_irq .thumb_func __unhandled_user_irq: bl __get_current_exception subs r0, #16 .global unhandled_user_irq_num_in_r0 unhandled_user_irq_num_in_r0: bkpt #0 .section .reset, "ax" // This is the beginning of the image, which is entered from stage2 or bootrom USB MSD watchdog reboot // note if we are NO_FLASH then start: below is currently identical anyway, so save 4 bytes #if !PICO_NO_FLASH // We simply install our own vector table and redirect through it ldr r0, =__vectors b __vector_entry #endif // ELF entry point generally called when we load an ELF via debugger .type _entry_point,%function .thumb_func .global _entry_point _entry_point: #if PICO_NO_FLASH // non flash ldr r0, =__vectors #else // todo clear watchdog? // When using flash, we install and use the ROM vector table to go thru regular bootrom/stage2 flash sequence movs r0, #0 #endif __vector_entry: ldr r1, =(PPB_BASE + M0PLUS_CPUID_OFFSET) str r0, [r1, #8] ldmia r0!, {r1, r2} msr msp, r1 bx r2 // ---------------------------------------------------------------------------- // Reset handler: // - initialises .data // - clears .bss // - calls runtime_init // - calls main // - calls exit (which should eventually hang the processor via _exit) .type _reset_handler,%function .thumb_func _reset_handler: // Hang all cores except core 0 ldr r0, =(SIO_BASE + SIO_CPUID_OFFSET) ldr r0, [r0] cmp r0, #0 bne wait_for_vector adr r4, data_cpy_table // assume there is at least one entry 1: ldmia r4!, {r1-r3} cmp r1, #0 beq 2f bl data_cpy b 1b 2: // Zero out the BSS ldr r1, =__bss_start__ ldr r2, =__bss_end__ movs r0, #0 b bss_fill_test bss_fill_loop: stm r1!, {r0} bss_fill_test: cmp r1, r2 bne bss_fill_loop platform_entry: // symbol for stack traces // Use 32-bit jumps, in case these symbols are moved out of branch range // (e.g. if main is in SRAM and crt0 in flash) ldr r1, =runtime_init blx r1 ldr r1, =main blx r1 ldr r1, =exit blx r1 // exit should not return. If it does, hang the core. // (fall thru into our hang _exit impl .weak _exit .type _exit,%function .thumb_func _exit: 1: // separate label because _exit can be moved out of branch range bkpt #0 b 1b data_cpy_loop: ldm r1!, {r0} stm r2!, {r0} data_cpy: cmp r2, r3 blo data_cpy_loop bx lr #if !PICO_NO_BINARY_INFO binary_info_header: .word BINARY_INFO_MARKER_START .word __binary_info_start .word __binary_info_end .word data_cpy_table // we may need to decode pointers that are in RAM at runtime. .word BINARY_INFO_MARKER_END #endif .align 2 data_cpy_table: #if PICO_COPY_TO_RAM .word __ram_text_source__ .word __ram_text_start__ .word __ram_text_end__ #endif .word __etext .word __data_start__ .word __data_end__ .word __scratch_x_source__ .word __scratch_x_start__ .word __scratch_x_end__ .word __scratch_y_source__ .word __scratch_y_start__ .word __scratch_y_end__ .word 0 // null terminator // ---------------------------------------------------------------------------- // Provide safe defaults for _exit and runtime_init // Full implementations usually provided by platform.c .weak runtime_init .type runtime_init,%function .thumb_func runtime_init: bx lr // ---------------------------------------------------------------------------- // In case core 1's VTOR has already been moved into flash, we need to handle // core 1 reset. However, we do so by just jumping back into bootrom version of // wait_for_vector wait_for_vector: ldr r0, = 'W' | ('V' << 8) bl rom_func_lookup bx r0 .global __get_current_exception .thumb_func __get_current_exception: mrs r0, ipsr uxtb r0, r0 bx lr // ---------------------------------------------------------------------------- // Stack/heap dummies to set size .section .stack // align to allow for memory protection (although this alignment is pretty much ignored by linker script) .align 5 .equ StackSize, PICO_STACK_SIZE .space StackSize .section .heap .align 2 .equ HeapSize, PICO_HEAP_SIZE .space HeapSize