-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSTM32WL_FLASH.ld
144 lines (127 loc) · 4.47 KB
/
STM32WL_FLASH.ld
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
/* Entry Point */
/*
technically, I'm not sure if an entry point is necessary since this is an embedded system
and the entry point is hardcoded to be the reset vector. However, if we want to compile an
ELF, an entry point is needed
*/
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of RAM */
_Min_Heap_Size = 0x000; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Memories definition */
/* this information is given in the datasheet or other documentation */
/* if you are using multiple cores, you will want to divide up the flash
and ram so each core gets an exclusive slice of ram and flash. */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x00008000
RAM2 (xrw) : ORIGIN = 0x20008000, LENGTH = 0x00008000
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 0x00040000
}
/* Sections */
SECTIONS
{
/* Interrupt Service Routines must be the first section placed in flash memory.
This is because the interrupt vector table is located at address 0x00 by default.
(technically, this table can be moved once the MCU is running) */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* interrupt table */
. = ALIGN(4);
} > FLASH
/* normal program code instructions is compiled into ".text" sections, and these
sections should also be placed in flash memory */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
. = ALIGN(4);
_etext = .; /* define a global symbol at end of code */
} > FLASH
/* variables defined as constant and other unchanging data is compiled into
".rodata" sections, and these should also be placed in flash memory */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} > FLASH
/*
based on my research, I believe .ARM.extab* and .ARM.exidx* sections are only
generated if code is compiled with the "-fexceptions" flag. This will keep a
record of your stack trace in case you want to use it to unwind the stack or
print it because some exception failed (C doesn't really do exceptions, at
least not natively)
*/
.ARM.extab :
{
. = ALIGN(4);
*(.ARM.extab* .gnu.linkonce.armextab.*)
. = ALIGN(4);
} > FLASH
.ARM :
{
. = ALIGN(4);
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
. = ALIGN(4);
} > FLASH
/* Used by the startup function to initialize data */
_sidata = LOADADDR(.data);
/*
initialized global and static objects are put in the .data section.
functions to be run in RAM are also put in the .data section.
*/
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
*(.RamFunc) /* .RamFunc sections */
*(.RamFunc*) /* .RamFunc* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
/*
"> RAM AT > FLASH" means the data belongs in RAM but is stored in FLASH.
the .data section is for initialized objects meant for RAM, but they cannot
exist in RAM until the MCU is powered up. After power-up, but before calling
main(), the objects are copied from FLASH to their correct location in RAM.
*/
} > RAM AT > FLASH
/* Uninitialized data section into "RAM" type memory */
/*
unitialized (and zero-initialized) global and static objects are put in the .bss section.
the .bss section should be "stored" in RAM, but since RAM is volatile and these variables
are 0, that just means we reserve space for these variables in RAM, and then at startup
we initialize the data in the those reserved spaces to 0.
*/
.bss :
{
. = ALIGN(4);
/* This is used by the startup in order to initialize the .bss section */
_sbss = .; /* define a global symbol at bss start */
*(.bss)
*(.bss*)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
} > RAM
/* stack section, used to check that there is enough RAM left */
.stack :
{
. = ALIGN(8);
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} > RAM
/*
contains metadata about the compiled object.
Things like CPU architecture, CPU name, etc...
*/
.ARM.attributes 0 : { *(.ARM.attributes) }
}