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 "hardware/regs/m0plus.h"
11#include "hardware/regs/addressmap.h"
12#include "hardware/regs/sio.h"
13#include "pico/binary_info/defs.h"
14
15#ifdef NDEBUG
16#ifndef COLLAPSE_IRQS
17#define COLLAPSE_IRQS
18#endif
19#endif
20
21pico_default_asm_setup
22
23.section .vectors, "ax"
24.align 2
25
26.global __vectors, __VECTOR_TABLE
27__VECTOR_TABLE:
28__vectors:
29.word __StackTop
30.word _reset_handler
31.word isr_nmi
32.word isr_hardfault
33.word isr_invalid // Reserved, should never fire
34.word isr_invalid // Reserved, should never fire
35.word isr_invalid // Reserved, should never fire
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_svcall
41.word isr_invalid // Reserved, should never fire
42.word isr_invalid // Reserved, should never fire
43.word isr_pendsv
44.word isr_systick
45.word isr_irq0
46.word isr_irq1
47.word isr_irq2
48.word isr_irq3
49.word isr_irq4
50.word isr_irq5
51.word isr_irq6
52.word isr_irq7
53.word isr_irq8
54.word isr_irq9
55.word isr_irq10
56.word isr_irq11
57.word isr_irq12
58.word isr_irq13
59.word isr_irq14
60.word isr_irq15
61.word isr_irq16
62.word isr_irq17
63.word isr_irq18
64.word isr_irq19
65.word isr_irq20
66.word isr_irq21
67.word isr_irq22
68.word isr_irq23
69.word isr_irq24
70.word isr_irq25
71.word isr_irq26
72.word isr_irq27
73.word isr_irq28
74.word isr_irq29
75.word isr_irq30
76.word isr_irq31
77
78// all default exception handlers do nothing, and we can check for them being set to our
79// default values by seeing if they point to somewhere between __defaults_isrs_start and __default_isrs_end
80.global __default_isrs_start
81__default_isrs_start:
82
83// Declare a weak symbol for each ISR.
84// By default, they will fall through to the undefined IRQ handler below (breakpoint),
85// but can be overridden by C functions with correct name.
86
87.macro decl_isr_bkpt name
88.weak \name
89.type \name,%function
90.thumb_func
91\name:
92    bkpt #0
93.endm
94
95// these are separated out for clarity
96decl_isr_bkpt isr_invalid
97decl_isr_bkpt isr_nmi
98decl_isr_bkpt isr_hardfault
99decl_isr_bkpt isr_svcall
100decl_isr_bkpt isr_pendsv
101decl_isr_bkpt isr_systick
102
103.global __default_isrs_end
104__default_isrs_end:
105
106.macro decl_isr name
107.weak \name
108.type \name,%function
109.thumb_func
110\name:
111.endm
112
113decl_isr isr_irq0
114decl_isr isr_irq1
115decl_isr isr_irq2
116decl_isr isr_irq3
117decl_isr isr_irq4
118decl_isr isr_irq5
119decl_isr isr_irq6
120decl_isr isr_irq7
121decl_isr isr_irq8
122decl_isr isr_irq9
123decl_isr isr_irq10
124decl_isr isr_irq11
125decl_isr isr_irq12
126decl_isr isr_irq13
127decl_isr isr_irq14
128decl_isr isr_irq15
129decl_isr isr_irq16
130decl_isr isr_irq17
131decl_isr isr_irq18
132decl_isr isr_irq19
133decl_isr isr_irq20
134decl_isr isr_irq21
135decl_isr isr_irq22
136decl_isr isr_irq23
137decl_isr isr_irq24
138decl_isr isr_irq25
139decl_isr isr_irq26
140decl_isr isr_irq27
141decl_isr isr_irq28
142decl_isr isr_irq29
143decl_isr isr_irq30
144decl_isr isr_irq31
145
146// All unhandled USER IRQs fall through to here
147.global __unhandled_user_irq
148.thumb_func
149__unhandled_user_irq:
150    mrs  r0, ipsr
151    subs r0, #16
152.global unhandled_user_irq_num_in_r0
153unhandled_user_irq_num_in_r0:
154    bkpt #0
155
156// ----------------------------------------------------------------------------
157
158.section .binary_info_header, "a"
159
160// Header must be in first 256 bytes of main image (i.e. excluding flash boot2).
161// For flash builds we put it immediately after vector table; for NO_FLASH the
162// vectors are at a +0x100 offset because the bootrom enters RAM images directly
163// at their lowest address, so we put the header in the VTOR alignment hole.
164
165#if !PICO_NO_BINARY_INFO
166binary_info_header:
167.word BINARY_INFO_MARKER_START
168.word __binary_info_start
169.word __binary_info_end
170.word data_cpy_table // we may need to decode pointers that are in RAM at runtime.
171.word BINARY_INFO_MARKER_END
172#endif
173
174// ----------------------------------------------------------------------------
175
176.section .reset, "ax"
177
178// On flash builds, the vector table comes first in the image (conventional).
179// On NO_FLASH builds, the reset handler section comes first, as the entry
180// point is at offset 0 (fixed due to bootrom), and VTOR is highly-aligned.
181// Image is entered in various ways:
182//
183// - NO_FLASH builds are entered from beginning by UF2 bootloader
184//
185// - Flash builds vector through the table into _reset_handler from boot2
186//
187// - Either type can be entered via _entry_point by the debugger, and flash builds
188//   must then be sent back round the boot sequence to properly initialise flash
189
190// ELF entry point:
191.type _entry_point,%function
192.thumb_func
193.global _entry_point
194_entry_point:
195
196#if PICO_NO_FLASH
197    // Vector through our own table (SP, VTOR will not have been set up at
198    // this point). Same path for debugger entry and bootloader entry.
199    ldr r0, =__vectors
200#else
201    // Debugger tried to run code after loading, so SSI is in 03h-only mode.
202    // Go back through bootrom + boot2 to properly initialise flash.
203    movs r0, #0
204#endif
205    ldr r1, =(PPB_BASE + M0PLUS_VTOR_OFFSET)
206    str r0, [r1]
207    ldmia r0!, {r1, r2}
208    msr msp, r1
209    bx r2
210
211// Reset handler:
212// - initialises .data
213// - clears .bss
214// - calls runtime_init
215// - calls main
216// - calls exit (which should eventually hang the processor via _exit)
217
218.type _reset_handler,%function
219.thumb_func
220_reset_handler:
221    // Only core 0 should run the C runtime startup code; core 1 is normally
222    // sleeping in the bootrom at this point but check to be sure
223    ldr r0, =(SIO_BASE + SIO_CPUID_OFFSET)
224    ldr r0, [r0]
225    cmp r0, #0
226    bne hold_non_core0_in_bootrom
227
228    // In a NO_FLASH binary, don't perform .data copy, since it's loaded
229    // in-place by the SRAM load. Still need to clear .bss
230#if !PICO_NO_FLASH
231    adr r4, data_cpy_table
232
233    // assume there is at least one entry
2341:
235    ldmia r4!, {r1-r3}
236    cmp r1, #0
237    beq 2f
238    bl data_cpy
239    b 1b
2402:
241#endif
242
243    // Zero out the BSS
244    ldr r1, =__bss_start__
245    ldr r2, =__bss_end__
246    movs r0, #0
247    b bss_fill_test
248bss_fill_loop:
249    stm r1!, {r0}
250bss_fill_test:
251    cmp r1, r2
252    bne bss_fill_loop
253
254platform_entry: // symbol for stack traces
255    // Use 32-bit jumps, in case these symbols are moved out of branch range
256    // (e.g. if main is in SRAM and crt0 in flash)
257    ldr r1, =runtime_init
258    blx r1
259    ldr r1, =main
260    blx r1
261    ldr r1, =exit
262    blx r1
263    // exit should not return.  If it does, hang the core.
264    // (fall thru into our hang _exit impl
2651: // separate label because _exit can be moved out of branch range
266    bkpt #0
267    b 1b
268
269#if !PICO_NO_FLASH
270data_cpy_loop:
271    ldm r1!, {r0}
272    stm r2!, {r0}
273data_cpy:
274    cmp r2, r3
275    blo data_cpy_loop
276    bx lr
277#endif
278
279// Note the data copy table is still included for NO_FLASH builds, even though
280// we skip the copy, because it is listed in binary info
281
282.align 2
283data_cpy_table:
284#if PICO_COPY_TO_RAM
285.word __ram_text_source__
286.word __ram_text_start__
287.word __ram_text_end__
288#endif
289.word __etext
290.word __data_start__
291.word __data_end__
292
293.word __scratch_x_source__
294.word __scratch_x_start__
295.word __scratch_x_end__
296
297.word __scratch_y_source__
298.word __scratch_y_start__
299.word __scratch_y_end__
300
301.word 0 // null terminator
302
303// ----------------------------------------------------------------------------
304// Provide safe defaults for _exit and runtime_init
305// Full implementations usually provided by platform.c
306
307.weak runtime_init
308.type runtime_init,%function
309.thumb_func
310runtime_init:
311    bx lr
312
313// ----------------------------------------------------------------------------
314// If core 1 somehow gets into crt0 due to a spectacular VTOR mishap, we need to
315// catch it and send back to the sleep-and-launch code in the bootrom. Shouldn't
316// happen (it should sleep in the ROM until given an entry point via the
317// cross-core FIFOs) but it's good to be defensive.
318
319hold_non_core0_in_bootrom:
320    ldr r0, = 'W' | ('V' << 8)
321    bl rom_func_lookup
322    bx r0
323
324// ----------------------------------------------------------------------------
325// Stack/heap dummies to set size
326
327// Prior to SDK 1.5.1 these were `.section .stack` without the `, "a"`... Clang linker gives a warning about this,
328// however setting it explicitly to `, "a"` makes GCC *now* discard the section unless it is also KEEP. This
329// seems like very surprising behavior!
330//
331// Strictly the most correct thing to do (as .stack and .heap are unreferenced) is to mark them as "a", and also KEEP, which
332// works correctly for both GCC and Clang, however doing so may break anyone who already has custom linker scripts without
333// the KEEP. Therefore we will only add the "a" on Clang, but will also use KEEP to our own linker scripts.
334
335.macro spacer_section name
336#if PICO_ASSEMBLER_IS_CLANG
337.section \name, "a"
338#else
339.section \name
340#endif
341.endm
342
343spacer_section .stack
344// align to allow for memory protection (although this alignment is pretty much ignored by linker script)
345.p2align 5
346    .equ StackSize, PICO_STACK_SIZE
347.space StackSize
348
349spacer_section .heap
350.p2align 2
351    .equ HeapSize, PICO_HEAP_SIZE
352.space HeapSize
353