diff options
| author | Priit Laes <[email protected]> | 2024-01-05 14:58:57 +0200 |
|---|---|---|
| committer | Priit Laes <[email protected]> | 2024-01-05 15:01:05 +0200 |
| commit | 890ceae4e5b353ac85d7030ea7b344c18a1d663e (patch) | |
| tree | 15893e72e92935948a0c8cc7bef139a0d134d492 /tests/link_ram_cortex_m.x | |
| parent | 17346fdfc22a34d651d9d30bcc35125916ee44b5 (diff) | |
tests: Use unified link_ram_cortex_m.x file for all Cortex M targets
Diffstat (limited to 'tests/link_ram_cortex_m.x')
| -rw-r--r-- | tests/link_ram_cortex_m.x | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/tests/link_ram_cortex_m.x b/tests/link_ram_cortex_m.x new file mode 100644 index 000000000..5cb23a642 --- /dev/null +++ b/tests/link_ram_cortex_m.x | |||
| @@ -0,0 +1,276 @@ | |||
| 1 | /* ##### EMBASSY NOTE | ||
| 2 | Originally from https://github.com/rust-embedded/cortex-m/blob/master/cortex-m-rt/link.x.in | ||
| 3 | Adjusted to put everything in RAM | ||
| 4 | */ | ||
| 5 | |||
| 6 | /* # Developer notes | ||
| 7 | |||
| 8 | - Symbols that start with a double underscore (__) are considered "private" | ||
| 9 | |||
| 10 | - Symbols that start with a single underscore (_) are considered "semi-public"; they can be | ||
| 11 | overridden in a user linker script, but should not be referred from user code (e.g. `extern "C" { | ||
| 12 | static mut __sbss }`). | ||
| 13 | |||
| 14 | - `EXTERN` forces the linker to keep a symbol in the final binary. We use this to make sure a | ||
| 15 | symbol if not dropped if it appears in or near the front of the linker arguments and "it's not | ||
| 16 | needed" by any of the preceding objects (linker arguments) | ||
| 17 | |||
| 18 | - `PROVIDE` is used to provide default values that can be overridden by a user linker script | ||
| 19 | |||
| 20 | - On alignment: it's important for correctness that the VMA boundaries of both .bss and .data *and* | ||
| 21 | the LMA of .data are all 4-byte aligned. These alignments are assumed by the RAM initialization | ||
| 22 | routine. There's also a second benefit: 4-byte aligned boundaries means that you won't see | ||
| 23 | "Address (..) is out of bounds" in the disassembly produced by `objdump`. | ||
| 24 | */ | ||
| 25 | |||
| 26 | /* Provides information about the memory layout of the device */ | ||
| 27 | /* This will be provided by the user (see `memory.x`) or by a Board Support Crate */ | ||
| 28 | INCLUDE memory.x | ||
| 29 | |||
| 30 | /* # Entry point = reset vector */ | ||
| 31 | EXTERN(__RESET_VECTOR); | ||
| 32 | EXTERN(Reset); | ||
| 33 | ENTRY(Reset); | ||
| 34 | |||
| 35 | /* # Exception vectors */ | ||
| 36 | /* This is effectively weak aliasing at the linker level */ | ||
| 37 | /* The user can override any of these aliases by defining the corresponding symbol themselves (cf. | ||
| 38 | the `exception!` macro) */ | ||
| 39 | EXTERN(__EXCEPTIONS); /* depends on all the these PROVIDED symbols */ | ||
| 40 | |||
| 41 | EXTERN(DefaultHandler); | ||
| 42 | |||
| 43 | PROVIDE(NonMaskableInt = DefaultHandler); | ||
| 44 | EXTERN(HardFaultTrampoline); | ||
| 45 | PROVIDE(MemoryManagement = DefaultHandler); | ||
| 46 | PROVIDE(BusFault = DefaultHandler); | ||
| 47 | PROVIDE(UsageFault = DefaultHandler); | ||
| 48 | PROVIDE(SecureFault = DefaultHandler); | ||
| 49 | PROVIDE(SVCall = DefaultHandler); | ||
| 50 | PROVIDE(DebugMonitor = DefaultHandler); | ||
| 51 | PROVIDE(PendSV = DefaultHandler); | ||
| 52 | PROVIDE(SysTick = DefaultHandler); | ||
| 53 | |||
| 54 | PROVIDE(DefaultHandler = DefaultHandler_); | ||
| 55 | PROVIDE(HardFault = HardFault_); | ||
| 56 | |||
| 57 | /* # Interrupt vectors */ | ||
| 58 | EXTERN(__INTERRUPTS); /* `static` variable similar to `__EXCEPTIONS` */ | ||
| 59 | |||
| 60 | /* # Pre-initialization function */ | ||
| 61 | /* If the user overrides this using the `pre_init!` macro or by creating a `__pre_init` function, | ||
| 62 | then the function this points to will be called before the RAM is initialized. */ | ||
| 63 | PROVIDE(__pre_init = DefaultPreInit); | ||
| 64 | |||
| 65 | /* # Sections */ | ||
| 66 | SECTIONS | ||
| 67 | { | ||
| 68 | PROVIDE(_ram_start = ORIGIN(RAM)); | ||
| 69 | PROVIDE(_ram_end = ORIGIN(RAM) + LENGTH(RAM)); | ||
| 70 | PROVIDE(_stack_start = _ram_end); | ||
| 71 | |||
| 72 | /* ## Sections in RAM */ | ||
| 73 | /* ### Vector table */ | ||
| 74 | .vector_table ORIGIN(RAM) : | ||
| 75 | { | ||
| 76 | __vector_table = .; | ||
| 77 | |||
| 78 | /* Initial Stack Pointer (SP) value. | ||
| 79 | * We mask the bottom three bits to force 8-byte alignment. | ||
| 80 | * Despite having an assert for this later, it's possible that a separate | ||
| 81 | * linker script could override _stack_start after the assert is checked. | ||
| 82 | */ | ||
| 83 | LONG(_stack_start & 0xFFFFFFF8); | ||
| 84 | |||
| 85 | /* Reset vector */ | ||
| 86 | KEEP(*(.vector_table.reset_vector)); /* this is the `__RESET_VECTOR` symbol */ | ||
| 87 | |||
| 88 | /* Exceptions */ | ||
| 89 | __exceptions = .; /* start of exceptions */ | ||
| 90 | KEEP(*(.vector_table.exceptions)); /* this is the `__EXCEPTIONS` symbol */ | ||
| 91 | __eexceptions = .; /* end of exceptions */ | ||
| 92 | |||
| 93 | /* Device specific interrupts */ | ||
| 94 | KEEP(*(.vector_table.interrupts)); /* this is the `__INTERRUPTS` symbol */ | ||
| 95 | } > RAM | ||
| 96 | |||
| 97 | PROVIDE(_stext = ADDR(.vector_table) + SIZEOF(.vector_table)); | ||
| 98 | |||
| 99 | /* ### .text */ | ||
| 100 | .text _stext : | ||
| 101 | { | ||
| 102 | __stext = .; | ||
| 103 | *(.Reset); | ||
| 104 | |||
| 105 | *(.text .text.*); | ||
| 106 | |||
| 107 | /* The HardFaultTrampoline uses the `b` instruction to enter `HardFault`, | ||
| 108 | so must be placed close to it. */ | ||
| 109 | *(.HardFaultTrampoline); | ||
| 110 | *(.HardFault.*); | ||
| 111 | |||
| 112 | . = ALIGN(4); /* Pad .text to the alignment to workaround overlapping load section bug in old lld */ | ||
| 113 | __etext = .; | ||
| 114 | } > RAM | ||
| 115 | |||
| 116 | /* ### .rodata */ | ||
| 117 | .rodata : ALIGN(4) | ||
| 118 | { | ||
| 119 | . = ALIGN(4); | ||
| 120 | __srodata = .; | ||
| 121 | *(.rodata .rodata.*); | ||
| 122 | |||
| 123 | /* 4-byte align the end (VMA) of this section. | ||
| 124 | This is required by LLD to ensure the LMA of the following .data | ||
| 125 | section will have the correct alignment. */ | ||
| 126 | . = ALIGN(4); | ||
| 127 | __erodata = .; | ||
| 128 | } > RAM | ||
| 129 | |||
| 130 | /* ## Sections in RAM */ | ||
| 131 | /* ### .data */ | ||
| 132 | .data : ALIGN(4) | ||
| 133 | { | ||
| 134 | . = ALIGN(4); | ||
| 135 | __sdata = .; | ||
| 136 | *(.data .data.*); | ||
| 137 | . = ALIGN(4); /* 4-byte align the end (VMA) of this section */ | ||
| 138 | } > RAM | ||
| 139 | /* Allow sections from user `memory.x` injected using `INSERT AFTER .data` to | ||
| 140 | * use the .data loading mechanism by pushing __edata. Note: do not change | ||
| 141 | * output region or load region in those user sections! */ | ||
| 142 | . = ALIGN(4); | ||
| 143 | __edata = .; | ||
| 144 | |||
| 145 | /* LMA of .data */ | ||
| 146 | __sidata = LOADADDR(.data); | ||
| 147 | |||
| 148 | /* ### .gnu.sgstubs | ||
| 149 | This section contains the TrustZone-M veneers put there by the Arm GNU linker. */ | ||
| 150 | /* Security Attribution Unit blocks must be 32 bytes aligned. */ | ||
| 151 | /* Note that this pads the RAM usage to 32 byte alignment. */ | ||
| 152 | .gnu.sgstubs : ALIGN(32) | ||
| 153 | { | ||
| 154 | . = ALIGN(32); | ||
| 155 | __veneer_base = .; | ||
| 156 | *(.gnu.sgstubs*) | ||
| 157 | . = ALIGN(32); | ||
| 158 | } > RAM | ||
| 159 | /* Place `__veneer_limit` outside the `.gnu.sgstubs` section because veneers are | ||
| 160 | * always inserted last in the section, which would otherwise be _after_ the `__veneer_limit` symbol. | ||
| 161 | */ | ||
| 162 | . = ALIGN(32); | ||
| 163 | __veneer_limit = .; | ||
| 164 | |||
| 165 | /* ### .bss */ | ||
| 166 | .bss (NOLOAD) : ALIGN(4) | ||
| 167 | { | ||
| 168 | . = ALIGN(4); | ||
| 169 | __sbss = .; | ||
| 170 | *(.bss .bss.*); | ||
| 171 | *(COMMON); /* Uninitialized C statics */ | ||
| 172 | . = ALIGN(4); /* 4-byte align the end (VMA) of this section */ | ||
| 173 | } > RAM | ||
| 174 | /* Allow sections from user `memory.x` injected using `INSERT AFTER .bss` to | ||
| 175 | * use the .bss zeroing mechanism by pushing __ebss. Note: do not change | ||
| 176 | * output region or load region in those user sections! */ | ||
| 177 | . = ALIGN(4); | ||
| 178 | __ebss = .; | ||
| 179 | |||
| 180 | /* ### .uninit */ | ||
| 181 | .uninit (NOLOAD) : ALIGN(4) | ||
| 182 | { | ||
| 183 | . = ALIGN(4); | ||
| 184 | __suninit = .; | ||
| 185 | *(.uninit .uninit.*); | ||
| 186 | . = ALIGN(4); | ||
| 187 | __euninit = .; | ||
| 188 | } > RAM | ||
| 189 | |||
| 190 | /* Place the heap right after `.uninit` in RAM */ | ||
| 191 | PROVIDE(__sheap = __euninit); | ||
| 192 | |||
| 193 | /* ## .got */ | ||
| 194 | /* Dynamic relocations are unsupported. This section is only used to detect relocatable code in | ||
| 195 | the input files and raise an error if relocatable code is found */ | ||
| 196 | .got (NOLOAD) : | ||
| 197 | { | ||
| 198 | KEEP(*(.got .got.*)); | ||
| 199 | } | ||
| 200 | |||
| 201 | /* ## Discarded sections */ | ||
| 202 | /DISCARD/ : | ||
| 203 | { | ||
| 204 | /* Unused exception related info that only wastes space */ | ||
| 205 | *(.ARM.exidx); | ||
| 206 | *(.ARM.exidx.*); | ||
| 207 | *(.ARM.extab.*); | ||
| 208 | } | ||
| 209 | } | ||
| 210 | |||
| 211 | /* Do not exceed this mark in the error messages below | */ | ||
| 212 | /* # Alignment checks */ | ||
| 213 | ASSERT(ORIGIN(RAM) % 4 == 0, " | ||
| 214 | ERROR(cortex-m-rt): the start of the RAM region must be 4-byte aligned"); | ||
| 215 | |||
| 216 | ASSERT(__sdata % 4 == 0 && __edata % 4 == 0, " | ||
| 217 | BUG(cortex-m-rt): .data is not 4-byte aligned"); | ||
| 218 | |||
| 219 | ASSERT(__sidata % 4 == 0, " | ||
| 220 | BUG(cortex-m-rt): the LMA of .data is not 4-byte aligned"); | ||
| 221 | |||
| 222 | ASSERT(__sbss % 4 == 0 && __ebss % 4 == 0, " | ||
| 223 | BUG(cortex-m-rt): .bss is not 4-byte aligned"); | ||
| 224 | |||
| 225 | ASSERT(__sheap % 4 == 0, " | ||
| 226 | BUG(cortex-m-rt): start of .heap is not 4-byte aligned"); | ||
| 227 | |||
| 228 | ASSERT(_stack_start % 8 == 0, " | ||
| 229 | ERROR(cortex-m-rt): stack start address is not 8-byte aligned. | ||
| 230 | If you have set _stack_start, check it's set to an address which is a multiple of 8 bytes. | ||
| 231 | If you haven't, stack starts at the end of RAM by default. Check that both RAM | ||
| 232 | origin and length are set to multiples of 8 in the `memory.x` file."); | ||
| 233 | |||
| 234 | /* # Position checks */ | ||
| 235 | |||
| 236 | /* ## .vector_table | ||
| 237 | * | ||
| 238 | * If the *start* of exception vectors is not 8 bytes past the start of the | ||
| 239 | * vector table, then we somehow did not place the reset vector, which should | ||
| 240 | * live 4 bytes past the start of the vector table. | ||
| 241 | */ | ||
| 242 | ASSERT(__exceptions == ADDR(.vector_table) + 0x8, " | ||
| 243 | BUG(cortex-m-rt): the reset vector is missing"); | ||
| 244 | |||
| 245 | ASSERT(__eexceptions == ADDR(.vector_table) + 0x40, " | ||
| 246 | BUG(cortex-m-rt): the exception vectors are missing"); | ||
| 247 | |||
| 248 | ASSERT(SIZEOF(.vector_table) > 0x40, " | ||
| 249 | ERROR(cortex-m-rt): The interrupt vectors are missing. | ||
| 250 | Possible solutions, from most likely to less likely: | ||
| 251 | - Link to a svd2rust generated device crate | ||
| 252 | - Check that you actually use the device/hal/bsp crate in your code | ||
| 253 | - Disable the 'device' feature of cortex-m-rt to build a generic application (a dependency | ||
| 254 | may be enabling it) | ||
| 255 | - Supply the interrupt handlers yourself. Check the documentation for details."); | ||
| 256 | |||
| 257 | /* ## .text */ | ||
| 258 | ASSERT(ADDR(.vector_table) + SIZEOF(.vector_table) <= _stext, " | ||
| 259 | ERROR(cortex-m-rt): The .text section can't be placed inside the .vector_table section | ||
| 260 | Set _stext to an address greater than the end of .vector_table (See output of `nm`)"); | ||
| 261 | |||
| 262 | ASSERT(_stext + SIZEOF(.text) < ORIGIN(RAM) + LENGTH(RAM), " | ||
| 263 | ERROR(cortex-m-rt): The .text section must be placed inside the RAM memory. | ||
| 264 | Set _stext to an address smaller than 'ORIGIN(RAM) + LENGTH(RAM)'"); | ||
| 265 | |||
| 266 | /* # Other checks */ | ||
| 267 | ASSERT(SIZEOF(.got) == 0, " | ||
| 268 | ERROR(cortex-m-rt): .got section detected in the input object files | ||
| 269 | Dynamic relocations are not supported. If you are linking to C code compiled using | ||
| 270 | the 'cc' crate then modify your build script to compile the C code _without_ | ||
| 271 | the -fPIC flag. See the documentation of the `cc::Build.pic` method for details."); | ||
| 272 | /* Do not exceed this mark in the error messages above | */ | ||
| 273 | |||
| 274 | /* Provides weak aliases (cf. PROVIDED) for device specific interrupt handlers */ | ||
| 275 | /* This will usually be provided by a device crate generated using svd2rust (see `device.x`) */ | ||
| 276 | INCLUDE device.x | ||
