1+ #include <stdbool.h>
2+ #include <stdint.h>
3+
4+ // type for constructors
5+ typedef void (* entry_constructor )(void );
6+
7+ // declaration to the main function
8+ int main ();
9+
10+ /**
11+ * @brief Reset handler when the target starts running. This function
12+ * initilizes the bss and data segements
13+ *
14+ * @details declares all linker variables as extern. Then we refer to the
15+ * value using the &operator as the variables is at a valid data address.
16+ *
17+ * Functions that need to be called before main are run should have the
18+ * attribute "__constructor__". When marked the function will be added to
19+ * the ".init_array" segment and called before main is called.
20+ *
21+ */
22+ void __attribute__((__noreturn__ , __naked__ )) __reset_handler () {
23+ // initialize the stack pointer. As we are running from ram
24+ // the stack pointer is not setup yet. Move it to the stack
25+ // end segment to prevent a hardfault
26+ extern uint32_t __stack_end ;
27+ asm volatile ("mov sp, %0" : : "r" (& __stack_end ) : );
28+
29+ extern uint8_t __bss_start ;
30+ extern uint8_t __bss_end ;
31+
32+ // set the bss section to 0x00
33+ for (uint32_t i = 0 ; i < (& __bss_end - & __bss_start ); i ++ ) {
34+ ((volatile uint8_t * )(& __bss_start ))[i ] = 0x00 ;
35+ }
36+
37+ extern const entry_constructor __preinit_array_start ;
38+ extern const entry_constructor __preinit_array_end ;
39+
40+ // excecute all the preinit constructors
41+ for (uint32_t i = 0 ; i < (& __preinit_array_end - & __preinit_array_start ); i ++ ) {
42+ // call the preinit calls
43+ (& __preinit_array_start )[i ]();
44+ }
45+
46+ extern const entry_constructor __init_array_start ;
47+ extern const entry_constructor __init_array_end ;
48+
49+ // excecute all the global constructors
50+ for (uint32_t i = 0 ; i < (& __init_array_end - & __init_array_start ); i ++ ) {
51+ // call every constructor we have
52+ (& __init_array_start )[i ]();
53+ }
54+
55+ // run main
56+ (void )main ();
57+
58+ extern const entry_constructor __fini_array_start ;
59+ extern const entry_constructor __fini_array_end ;
60+
61+ // run all the destructors. Should never be called but if it happens
62+ // it should work
63+ for (uint32_t i = 0 ; i < (& __fini_array_end - & __fini_array_start ); i ++ ) {
64+ // call every destructor we have
65+ (& __fini_array_start )[i ]();
66+ }
67+
68+ // we should never be here. If this happens loop to make
69+ // sure we never exit the reset handler
70+ while (true) {};
71+ }
72+
73+ /**
74+ * @brief Default handler that locks the cpu.
75+ *
76+ */
77+ void __default_handler () {
78+ // do nothing and wait
79+ while (true) {}
80+ }
81+
82+ // called when a vft entry is not yet filled in
83+ void __cxa_pure_virtual () {}
0 commit comments