1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "pico/runtime.h"
8 #include "pico/runtime_init.h"
9 
10 
hard_assertion_failure(void)11 void __weak hard_assertion_failure(void) {
12     panic("Hard assert");
13 }
14 
runtime_run_initializers_from(uintptr_t * from)15 static void runtime_run_initializers_from(uintptr_t *from) {
16 
17     // Start and end points of the constructor list,
18     // defined by the linker script.
19     extern uintptr_t __preinit_array_end;
20 
21     // Call each function in the list, based on the mask
22     // We have to take the address of the symbols, as __preinit_array_start *is*
23     // the first function value, not the address of it.
24     for (uintptr_t *p = from; p < &__preinit_array_end; p++) {
25         uintptr_t val = *p;
26         ((void (*)(void))val)();
27     }
28 }
29 
runtime_run_initializers(void)30 void runtime_run_initializers(void) {
31     extern uintptr_t __preinit_array_start;
32     runtime_run_initializers_from(&__preinit_array_start);
33 }
34 
35 // We keep the per-core initializers in the standard __preinit_array so a standard C library
36 // initialization will force the core 0 initialization, however we also want to be able to find
37 // them after the fact so that we can run them on core 1. Per core initializers have sections
38 // __preinit_array.ZZZZZ.nnnnn i.e. the ZZZZZ sorts below all the standard __preinit_array.nnnnn
39 // values, and then we sort within the ZZZZZ.
40 //
41 // We create a dummy initializer in __preinit_array.YYYYY (between the standard initializers
42 // and the per core initializers), so we find the first per core initializer. Whilst we could
43 // have done this via an entry in the linker script, we want to preserve backwards compatibility
44 // with RP2040 custom linker scripts.
first_per_core_initializer(void)45 static void first_per_core_initializer(void) {}
46 PICO_RUNTIME_INIT_FUNC(first_per_core_initializer, "YYYYY");
47 
runtime_run_per_core_initializers(void)48 void runtime_run_per_core_initializers(void) {
49     runtime_run_initializers_from(&__pre_init_first_per_core_initializer);
50 }