1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
#include "kern/init.h"
#include "arch.h"
#include "arch/stm32l4xxx/peripherals/clock.h"
#include "arch/stm32l4xxx/peripherals/system.h"
#include "kern/log.h"
static volatile _no_init init_level_t initlevel;
init_level_t get_system_init_level()
{
return initlevel;
}
/* Forward-declare the main function. This is implemented in main.c. */
int main();
/* These are defined in the linker script. */
#ifdef ARCH_STM32L4
extern uint32_t INIT_DATA_VALUES;
extern uint32_t DATA_SEGMENT_START;
extern uint32_t DATA_SEGMENT_STOP;
extern uint32_t TEXT_START;
extern uint32_t TEXT_STOP;
extern uint32_t BSS_START;
extern uint32_t BSS_END;
extern void (*INIT_ROUTINES_FLASH_START)();
extern void (*INIT_ROUTINES_FLASH_STOP)();
extern uint32_t INIT_0_END;
extern uint32_t INIT_1_END;
extern uint32_t INIT_2_END;
extern uint32_t INIT_3_END;
extern uint32_t INIT_4_END;
extern uint32_t INIT_5_END;
extern uint32_t INIT_6_END;
extern uint32_t INIT_7_END;
extern uint32_t WAT;
#define MAGIC_COOKIE 0xDEADBEEF
/* Test that data segment is properly set. */
static uint32_t magic_cookie = MAGIC_COOKIE;
init2()
{
volatile uint32_t bss_start_ptr = (uint32_t)&BSS_START;
volatile uint32_t bss_end_ptr = (uint32_t)&BSS_END;
volatile uint32_t init_data_values_ptr = (uint32_t)&INIT_DATA_VALUES;
volatile uint32_t data_segment_start_ptr = (uint32_t)&DATA_SEGMENT_START;
volatile uint32_t data_segment_stop_ptr = (uint32_t)&DATA_SEGMENT_STOP;
klogf("Copy data segments from flash ... \n");
klogf(" .data ...\n");
klogf(" set (%p - %p)\n", &DATA_SEGMENT_START, &DATA_SEGMENT_STOP);
klogf(" from (%p)\n", &INIT_DATA_VALUES);
if ((data_segment_start_ptr | data_segment_start_ptr) & 3) {
panic(".data segment not aligned with sizeof(uint32_t)!\n");
}
if (init_data_values_ptr & 3) {
panic("init data values pointer not aligned with sizeof(uint32_t)!\n");
}
/* Next, we'll copy the data sections from flash to ram. */
uint32_t* src;
uint32_t* dest;
src = &INIT_DATA_VALUES;
dest = &DATA_SEGMENT_START;
/* Copy the values from flash into the data segment. */
while (dest < &DATA_SEGMENT_STOP) {
*(dest++) = *(src++);
}
klogf(" .bss ...\n");
klogf(" clear (%p - %p)\n", &BSS_START, &BSS_END);
if ((bss_start_ptr | bss_end_ptr) & 3) {
panic(".bss data segment not aligned with sizeof(uint32_t)!\n");
}
/* Everything in the BSS segment is set to zero. */
dest = &BSS_START;
while (dest != &BSS_END) {
*(dest++) = 0;
}
if (magic_cookie != MAGIC_COOKIE) {
panic("Data Segment Initialization Failed!");
}
klogf("Done!\n");
}
init3()
{
/* Set the vector offset table to be at the start
* of FLASH memory. */
SCB.vto_r = 0x08000000;
}
void run_init_routines()
{
void* init_boundaries[] = {
&INIT_0_END,
&INIT_1_END,
&INIT_2_END,
&INIT_3_END,
&INIT_4_END,
&INIT_5_END,
&INIT_6_END,
&INIT_7_END,
};
void (**initfn)();
klogf("WAT: %p\n", &WAT);
klogf(
"Init routines at (%p - %p)\n",
&INIT_ROUTINES_FLASH_START,
&INIT_ROUTINES_FLASH_STOP);
klogf(
"Data segment at (%p - %p) from (%p)\n",
&DATA_SEGMENT_START,
&DATA_SEGMENT_STOP,
&INIT_DATA_VALUES);
klogf(
"Bss segment at (%p - %p)\n",
&BSS_START,
&BSS_END);
klogf(
"Heap at (%p - %p)\n",
&HEAP_START,
&HEAP_STOP);
klogf(
"Text at (%p - %p)\n",
&TEXT_START,
&TEXT_STOP);
klogf( "Init Boundary 0: %p\n", &INIT_0_END);
klogf( "Init Boundary 1: %p\n", &INIT_1_END);
klogf( "Init Boundary 2: %p\n", &INIT_2_END);
// for (size_t i = 0; i < sizeof(init_boundaries) / sizeof(void*); ++ i) {
// klogf("Init Boundary %d at %p\n", i, init_boundaries[i]);
// }
/* Enable a higher clock speed. This is the first thing we do
* beacuse it will boost the boot up time. */
set_system_clock_MHz(80);
klogf("[Init Level 0]\n");
for (initfn = &INIT_ROUTINES_FLASH_START; initfn < &INIT_ROUTINES_FLASH_STOP;
++initfn) {
while (initfn >= init_boundaries[initlevel] && initlevel < INIT_LEVEL_7) {
++initlevel;
klogf("[Init Level %d]\n", initlevel);
}
klogf("Calling (%p)\n", initfn);
(*initfn)();
}
}
/*
* Runs before main. Initializes the data and bss segments by loading them
* into memory.
*/
_Noreturn void on_reset()
{
initialize_logging();
initlevel = INIT_LEVEL_0;
run_init_routines();
while (initlevel < INIT_LEVEL_7) {
++initlevel;
klogf("[Init Level %d]\n", initlevel);
}
/* Jump to main. */
main();
for (;;)
;
}
#endif /* ARCH_STM32L4 */
|