315 lines
6.8 KiB
ArmAsm
315 lines
6.8 KiB
ArmAsm
|
/*
|
||
|
* 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
|