From 890ceae4e5b353ac85d7030ea7b344c18a1d663e Mon Sep 17 00:00:00 2001 From: Priit Laes Date: Fri, 5 Jan 2024 14:58:57 +0200 Subject: tests: Use unified link_ram_cortex_m.x file for all Cortex M targets --- tests/link_ram_cortex_m.x | 276 ++++++++++++++++++++++++++++++++++++++++++++++ tests/nrf/build.rs | 2 +- tests/nrf/link_ram.x | 276 ---------------------------------------------- tests/rp/build.rs | 2 +- tests/rp/link_ram.x | 255 ------------------------------------------ tests/rp/memory.x | 4 + tests/stm32/build.rs | 2 +- tests/stm32/link_ram.x | 254 ------------------------------------------ 8 files changed, 283 insertions(+), 788 deletions(-) create mode 100644 tests/link_ram_cortex_m.x delete mode 100644 tests/nrf/link_ram.x delete mode 100644 tests/rp/link_ram.x create mode 100644 tests/rp/memory.x delete mode 100644 tests/stm32/link_ram.x (limited to 'tests') 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 @@ +/* ##### EMBASSY NOTE + Originally from https://github.com/rust-embedded/cortex-m/blob/master/cortex-m-rt/link.x.in + Adjusted to put everything in RAM +*/ + +/* # Developer notes + +- Symbols that start with a double underscore (__) are considered "private" + +- Symbols that start with a single underscore (_) are considered "semi-public"; they can be + overridden in a user linker script, but should not be referred from user code (e.g. `extern "C" { + static mut __sbss }`). + +- `EXTERN` forces the linker to keep a symbol in the final binary. We use this to make sure a + symbol if not dropped if it appears in or near the front of the linker arguments and "it's not + needed" by any of the preceding objects (linker arguments) + +- `PROVIDE` is used to provide default values that can be overridden by a user linker script + +- On alignment: it's important for correctness that the VMA boundaries of both .bss and .data *and* + the LMA of .data are all 4-byte aligned. These alignments are assumed by the RAM initialization + routine. There's also a second benefit: 4-byte aligned boundaries means that you won't see + "Address (..) is out of bounds" in the disassembly produced by `objdump`. +*/ + +/* Provides information about the memory layout of the device */ +/* This will be provided by the user (see `memory.x`) or by a Board Support Crate */ +INCLUDE memory.x + +/* # Entry point = reset vector */ +EXTERN(__RESET_VECTOR); +EXTERN(Reset); +ENTRY(Reset); + +/* # Exception vectors */ +/* This is effectively weak aliasing at the linker level */ +/* The user can override any of these aliases by defining the corresponding symbol themselves (cf. + the `exception!` macro) */ +EXTERN(__EXCEPTIONS); /* depends on all the these PROVIDED symbols */ + +EXTERN(DefaultHandler); + +PROVIDE(NonMaskableInt = DefaultHandler); +EXTERN(HardFaultTrampoline); +PROVIDE(MemoryManagement = DefaultHandler); +PROVIDE(BusFault = DefaultHandler); +PROVIDE(UsageFault = DefaultHandler); +PROVIDE(SecureFault = DefaultHandler); +PROVIDE(SVCall = DefaultHandler); +PROVIDE(DebugMonitor = DefaultHandler); +PROVIDE(PendSV = DefaultHandler); +PROVIDE(SysTick = DefaultHandler); + +PROVIDE(DefaultHandler = DefaultHandler_); +PROVIDE(HardFault = HardFault_); + +/* # Interrupt vectors */ +EXTERN(__INTERRUPTS); /* `static` variable similar to `__EXCEPTIONS` */ + +/* # Pre-initialization function */ +/* If the user overrides this using the `pre_init!` macro or by creating a `__pre_init` function, + then the function this points to will be called before the RAM is initialized. */ +PROVIDE(__pre_init = DefaultPreInit); + +/* # Sections */ +SECTIONS +{ + PROVIDE(_ram_start = ORIGIN(RAM)); + PROVIDE(_ram_end = ORIGIN(RAM) + LENGTH(RAM)); + PROVIDE(_stack_start = _ram_end); + + /* ## Sections in RAM */ + /* ### Vector table */ + .vector_table ORIGIN(RAM) : + { + __vector_table = .; + + /* Initial Stack Pointer (SP) value. + * We mask the bottom three bits to force 8-byte alignment. + * Despite having an assert for this later, it's possible that a separate + * linker script could override _stack_start after the assert is checked. + */ + LONG(_stack_start & 0xFFFFFFF8); + + /* Reset vector */ + KEEP(*(.vector_table.reset_vector)); /* this is the `__RESET_VECTOR` symbol */ + + /* Exceptions */ + __exceptions = .; /* start of exceptions */ + KEEP(*(.vector_table.exceptions)); /* this is the `__EXCEPTIONS` symbol */ + __eexceptions = .; /* end of exceptions */ + + /* Device specific interrupts */ + KEEP(*(.vector_table.interrupts)); /* this is the `__INTERRUPTS` symbol */ + } > RAM + + PROVIDE(_stext = ADDR(.vector_table) + SIZEOF(.vector_table)); + + /* ### .text */ + .text _stext : + { + __stext = .; + *(.Reset); + + *(.text .text.*); + + /* The HardFaultTrampoline uses the `b` instruction to enter `HardFault`, + so must be placed close to it. */ + *(.HardFaultTrampoline); + *(.HardFault.*); + + . = ALIGN(4); /* Pad .text to the alignment to workaround overlapping load section bug in old lld */ + __etext = .; + } > RAM + + /* ### .rodata */ + .rodata : ALIGN(4) + { + . = ALIGN(4); + __srodata = .; + *(.rodata .rodata.*); + + /* 4-byte align the end (VMA) of this section. + This is required by LLD to ensure the LMA of the following .data + section will have the correct alignment. */ + . = ALIGN(4); + __erodata = .; + } > RAM + + /* ## Sections in RAM */ + /* ### .data */ + .data : ALIGN(4) + { + . = ALIGN(4); + __sdata = .; + *(.data .data.*); + . = ALIGN(4); /* 4-byte align the end (VMA) of this section */ + } > RAM + /* Allow sections from user `memory.x` injected using `INSERT AFTER .data` to + * use the .data loading mechanism by pushing __edata. Note: do not change + * output region or load region in those user sections! */ + . = ALIGN(4); + __edata = .; + + /* LMA of .data */ + __sidata = LOADADDR(.data); + + /* ### .gnu.sgstubs + This section contains the TrustZone-M veneers put there by the Arm GNU linker. */ + /* Security Attribution Unit blocks must be 32 bytes aligned. */ + /* Note that this pads the RAM usage to 32 byte alignment. */ + .gnu.sgstubs : ALIGN(32) + { + . = ALIGN(32); + __veneer_base = .; + *(.gnu.sgstubs*) + . = ALIGN(32); + } > RAM + /* Place `__veneer_limit` outside the `.gnu.sgstubs` section because veneers are + * always inserted last in the section, which would otherwise be _after_ the `__veneer_limit` symbol. + */ + . = ALIGN(32); + __veneer_limit = .; + + /* ### .bss */ + .bss (NOLOAD) : ALIGN(4) + { + . = ALIGN(4); + __sbss = .; + *(.bss .bss.*); + *(COMMON); /* Uninitialized C statics */ + . = ALIGN(4); /* 4-byte align the end (VMA) of this section */ + } > RAM + /* Allow sections from user `memory.x` injected using `INSERT AFTER .bss` to + * use the .bss zeroing mechanism by pushing __ebss. Note: do not change + * output region or load region in those user sections! */ + . = ALIGN(4); + __ebss = .; + + /* ### .uninit */ + .uninit (NOLOAD) : ALIGN(4) + { + . = ALIGN(4); + __suninit = .; + *(.uninit .uninit.*); + . = ALIGN(4); + __euninit = .; + } > RAM + + /* Place the heap right after `.uninit` in RAM */ + PROVIDE(__sheap = __euninit); + + /* ## .got */ + /* Dynamic relocations are unsupported. This section is only used to detect relocatable code in + the input files and raise an error if relocatable code is found */ + .got (NOLOAD) : + { + KEEP(*(.got .got.*)); + } + + /* ## Discarded sections */ + /DISCARD/ : + { + /* Unused exception related info that only wastes space */ + *(.ARM.exidx); + *(.ARM.exidx.*); + *(.ARM.extab.*); + } +} + +/* Do not exceed this mark in the error messages below | */ +/* # Alignment checks */ +ASSERT(ORIGIN(RAM) % 4 == 0, " +ERROR(cortex-m-rt): the start of the RAM region must be 4-byte aligned"); + +ASSERT(__sdata % 4 == 0 && __edata % 4 == 0, " +BUG(cortex-m-rt): .data is not 4-byte aligned"); + +ASSERT(__sidata % 4 == 0, " +BUG(cortex-m-rt): the LMA of .data is not 4-byte aligned"); + +ASSERT(__sbss % 4 == 0 && __ebss % 4 == 0, " +BUG(cortex-m-rt): .bss is not 4-byte aligned"); + +ASSERT(__sheap % 4 == 0, " +BUG(cortex-m-rt): start of .heap is not 4-byte aligned"); + +ASSERT(_stack_start % 8 == 0, " +ERROR(cortex-m-rt): stack start address is not 8-byte aligned. +If you have set _stack_start, check it's set to an address which is a multiple of 8 bytes. +If you haven't, stack starts at the end of RAM by default. Check that both RAM +origin and length are set to multiples of 8 in the `memory.x` file."); + +/* # Position checks */ + +/* ## .vector_table + * + * If the *start* of exception vectors is not 8 bytes past the start of the + * vector table, then we somehow did not place the reset vector, which should + * live 4 bytes past the start of the vector table. + */ +ASSERT(__exceptions == ADDR(.vector_table) + 0x8, " +BUG(cortex-m-rt): the reset vector is missing"); + +ASSERT(__eexceptions == ADDR(.vector_table) + 0x40, " +BUG(cortex-m-rt): the exception vectors are missing"); + +ASSERT(SIZEOF(.vector_table) > 0x40, " +ERROR(cortex-m-rt): The interrupt vectors are missing. +Possible solutions, from most likely to less likely: +- Link to a svd2rust generated device crate +- Check that you actually use the device/hal/bsp crate in your code +- Disable the 'device' feature of cortex-m-rt to build a generic application (a dependency +may be enabling it) +- Supply the interrupt handlers yourself. Check the documentation for details."); + +/* ## .text */ +ASSERT(ADDR(.vector_table) + SIZEOF(.vector_table) <= _stext, " +ERROR(cortex-m-rt): The .text section can't be placed inside the .vector_table section +Set _stext to an address greater than the end of .vector_table (See output of `nm`)"); + +ASSERT(_stext + SIZEOF(.text) < ORIGIN(RAM) + LENGTH(RAM), " +ERROR(cortex-m-rt): The .text section must be placed inside the RAM memory. +Set _stext to an address smaller than 'ORIGIN(RAM) + LENGTH(RAM)'"); + +/* # Other checks */ +ASSERT(SIZEOF(.got) == 0, " +ERROR(cortex-m-rt): .got section detected in the input object files +Dynamic relocations are not supported. If you are linking to C code compiled using +the 'cc' crate then modify your build script to compile the C code _without_ +the -fPIC flag. See the documentation of the `cc::Build.pic` method for details."); +/* Do not exceed this mark in the error messages above | */ + +/* Provides weak aliases (cf. PROVIDED) for device specific interrupt handlers */ +/* This will usually be provided by a device crate generated using svd2rust (see `device.x`) */ +INCLUDE device.x diff --git a/tests/nrf/build.rs b/tests/nrf/build.rs index 93e2a28cf..71c82a70f 100644 --- a/tests/nrf/build.rs +++ b/tests/nrf/build.rs @@ -4,7 +4,7 @@ use std::{env, fs}; fn main() -> Result<(), Box> { let out = PathBuf::from(env::var("OUT_DIR").unwrap()); - fs::write(out.join("link_ram.x"), include_bytes!("link_ram.x")).unwrap(); + fs::write(out.join("link_ram.x"), include_bytes!("../link_ram_cortex_m.x")).unwrap(); println!("cargo:rustc-link-search={}", out.display()); println!("cargo:rerun-if-changed=link_ram.x"); diff --git a/tests/nrf/link_ram.x b/tests/nrf/link_ram.x deleted file mode 100644 index 5cb23a642..000000000 --- a/tests/nrf/link_ram.x +++ /dev/null @@ -1,276 +0,0 @@ -/* ##### EMBASSY NOTE - Originally from https://github.com/rust-embedded/cortex-m/blob/master/cortex-m-rt/link.x.in - Adjusted to put everything in RAM -*/ - -/* # Developer notes - -- Symbols that start with a double underscore (__) are considered "private" - -- Symbols that start with a single underscore (_) are considered "semi-public"; they can be - overridden in a user linker script, but should not be referred from user code (e.g. `extern "C" { - static mut __sbss }`). - -- `EXTERN` forces the linker to keep a symbol in the final binary. We use this to make sure a - symbol if not dropped if it appears in or near the front of the linker arguments and "it's not - needed" by any of the preceding objects (linker arguments) - -- `PROVIDE` is used to provide default values that can be overridden by a user linker script - -- On alignment: it's important for correctness that the VMA boundaries of both .bss and .data *and* - the LMA of .data are all 4-byte aligned. These alignments are assumed by the RAM initialization - routine. There's also a second benefit: 4-byte aligned boundaries means that you won't see - "Address (..) is out of bounds" in the disassembly produced by `objdump`. -*/ - -/* Provides information about the memory layout of the device */ -/* This will be provided by the user (see `memory.x`) or by a Board Support Crate */ -INCLUDE memory.x - -/* # Entry point = reset vector */ -EXTERN(__RESET_VECTOR); -EXTERN(Reset); -ENTRY(Reset); - -/* # Exception vectors */ -/* This is effectively weak aliasing at the linker level */ -/* The user can override any of these aliases by defining the corresponding symbol themselves (cf. - the `exception!` macro) */ -EXTERN(__EXCEPTIONS); /* depends on all the these PROVIDED symbols */ - -EXTERN(DefaultHandler); - -PROVIDE(NonMaskableInt = DefaultHandler); -EXTERN(HardFaultTrampoline); -PROVIDE(MemoryManagement = DefaultHandler); -PROVIDE(BusFault = DefaultHandler); -PROVIDE(UsageFault = DefaultHandler); -PROVIDE(SecureFault = DefaultHandler); -PROVIDE(SVCall = DefaultHandler); -PROVIDE(DebugMonitor = DefaultHandler); -PROVIDE(PendSV = DefaultHandler); -PROVIDE(SysTick = DefaultHandler); - -PROVIDE(DefaultHandler = DefaultHandler_); -PROVIDE(HardFault = HardFault_); - -/* # Interrupt vectors */ -EXTERN(__INTERRUPTS); /* `static` variable similar to `__EXCEPTIONS` */ - -/* # Pre-initialization function */ -/* If the user overrides this using the `pre_init!` macro or by creating a `__pre_init` function, - then the function this points to will be called before the RAM is initialized. */ -PROVIDE(__pre_init = DefaultPreInit); - -/* # Sections */ -SECTIONS -{ - PROVIDE(_ram_start = ORIGIN(RAM)); - PROVIDE(_ram_end = ORIGIN(RAM) + LENGTH(RAM)); - PROVIDE(_stack_start = _ram_end); - - /* ## Sections in RAM */ - /* ### Vector table */ - .vector_table ORIGIN(RAM) : - { - __vector_table = .; - - /* Initial Stack Pointer (SP) value. - * We mask the bottom three bits to force 8-byte alignment. - * Despite having an assert for this later, it's possible that a separate - * linker script could override _stack_start after the assert is checked. - */ - LONG(_stack_start & 0xFFFFFFF8); - - /* Reset vector */ - KEEP(*(.vector_table.reset_vector)); /* this is the `__RESET_VECTOR` symbol */ - - /* Exceptions */ - __exceptions = .; /* start of exceptions */ - KEEP(*(.vector_table.exceptions)); /* this is the `__EXCEPTIONS` symbol */ - __eexceptions = .; /* end of exceptions */ - - /* Device specific interrupts */ - KEEP(*(.vector_table.interrupts)); /* this is the `__INTERRUPTS` symbol */ - } > RAM - - PROVIDE(_stext = ADDR(.vector_table) + SIZEOF(.vector_table)); - - /* ### .text */ - .text _stext : - { - __stext = .; - *(.Reset); - - *(.text .text.*); - - /* The HardFaultTrampoline uses the `b` instruction to enter `HardFault`, - so must be placed close to it. */ - *(.HardFaultTrampoline); - *(.HardFault.*); - - . = ALIGN(4); /* Pad .text to the alignment to workaround overlapping load section bug in old lld */ - __etext = .; - } > RAM - - /* ### .rodata */ - .rodata : ALIGN(4) - { - . = ALIGN(4); - __srodata = .; - *(.rodata .rodata.*); - - /* 4-byte align the end (VMA) of this section. - This is required by LLD to ensure the LMA of the following .data - section will have the correct alignment. */ - . = ALIGN(4); - __erodata = .; - } > RAM - - /* ## Sections in RAM */ - /* ### .data */ - .data : ALIGN(4) - { - . = ALIGN(4); - __sdata = .; - *(.data .data.*); - . = ALIGN(4); /* 4-byte align the end (VMA) of this section */ - } > RAM - /* Allow sections from user `memory.x` injected using `INSERT AFTER .data` to - * use the .data loading mechanism by pushing __edata. Note: do not change - * output region or load region in those user sections! */ - . = ALIGN(4); - __edata = .; - - /* LMA of .data */ - __sidata = LOADADDR(.data); - - /* ### .gnu.sgstubs - This section contains the TrustZone-M veneers put there by the Arm GNU linker. */ - /* Security Attribution Unit blocks must be 32 bytes aligned. */ - /* Note that this pads the RAM usage to 32 byte alignment. */ - .gnu.sgstubs : ALIGN(32) - { - . = ALIGN(32); - __veneer_base = .; - *(.gnu.sgstubs*) - . = ALIGN(32); - } > RAM - /* Place `__veneer_limit` outside the `.gnu.sgstubs` section because veneers are - * always inserted last in the section, which would otherwise be _after_ the `__veneer_limit` symbol. - */ - . = ALIGN(32); - __veneer_limit = .; - - /* ### .bss */ - .bss (NOLOAD) : ALIGN(4) - { - . = ALIGN(4); - __sbss = .; - *(.bss .bss.*); - *(COMMON); /* Uninitialized C statics */ - . = ALIGN(4); /* 4-byte align the end (VMA) of this section */ - } > RAM - /* Allow sections from user `memory.x` injected using `INSERT AFTER .bss` to - * use the .bss zeroing mechanism by pushing __ebss. Note: do not change - * output region or load region in those user sections! */ - . = ALIGN(4); - __ebss = .; - - /* ### .uninit */ - .uninit (NOLOAD) : ALIGN(4) - { - . = ALIGN(4); - __suninit = .; - *(.uninit .uninit.*); - . = ALIGN(4); - __euninit = .; - } > RAM - - /* Place the heap right after `.uninit` in RAM */ - PROVIDE(__sheap = __euninit); - - /* ## .got */ - /* Dynamic relocations are unsupported. This section is only used to detect relocatable code in - the input files and raise an error if relocatable code is found */ - .got (NOLOAD) : - { - KEEP(*(.got .got.*)); - } - - /* ## Discarded sections */ - /DISCARD/ : - { - /* Unused exception related info that only wastes space */ - *(.ARM.exidx); - *(.ARM.exidx.*); - *(.ARM.extab.*); - } -} - -/* Do not exceed this mark in the error messages below | */ -/* # Alignment checks */ -ASSERT(ORIGIN(RAM) % 4 == 0, " -ERROR(cortex-m-rt): the start of the RAM region must be 4-byte aligned"); - -ASSERT(__sdata % 4 == 0 && __edata % 4 == 0, " -BUG(cortex-m-rt): .data is not 4-byte aligned"); - -ASSERT(__sidata % 4 == 0, " -BUG(cortex-m-rt): the LMA of .data is not 4-byte aligned"); - -ASSERT(__sbss % 4 == 0 && __ebss % 4 == 0, " -BUG(cortex-m-rt): .bss is not 4-byte aligned"); - -ASSERT(__sheap % 4 == 0, " -BUG(cortex-m-rt): start of .heap is not 4-byte aligned"); - -ASSERT(_stack_start % 8 == 0, " -ERROR(cortex-m-rt): stack start address is not 8-byte aligned. -If you have set _stack_start, check it's set to an address which is a multiple of 8 bytes. -If you haven't, stack starts at the end of RAM by default. Check that both RAM -origin and length are set to multiples of 8 in the `memory.x` file."); - -/* # Position checks */ - -/* ## .vector_table - * - * If the *start* of exception vectors is not 8 bytes past the start of the - * vector table, then we somehow did not place the reset vector, which should - * live 4 bytes past the start of the vector table. - */ -ASSERT(__exceptions == ADDR(.vector_table) + 0x8, " -BUG(cortex-m-rt): the reset vector is missing"); - -ASSERT(__eexceptions == ADDR(.vector_table) + 0x40, " -BUG(cortex-m-rt): the exception vectors are missing"); - -ASSERT(SIZEOF(.vector_table) > 0x40, " -ERROR(cortex-m-rt): The interrupt vectors are missing. -Possible solutions, from most likely to less likely: -- Link to a svd2rust generated device crate -- Check that you actually use the device/hal/bsp crate in your code -- Disable the 'device' feature of cortex-m-rt to build a generic application (a dependency -may be enabling it) -- Supply the interrupt handlers yourself. Check the documentation for details."); - -/* ## .text */ -ASSERT(ADDR(.vector_table) + SIZEOF(.vector_table) <= _stext, " -ERROR(cortex-m-rt): The .text section can't be placed inside the .vector_table section -Set _stext to an address greater than the end of .vector_table (See output of `nm`)"); - -ASSERT(_stext + SIZEOF(.text) < ORIGIN(RAM) + LENGTH(RAM), " -ERROR(cortex-m-rt): The .text section must be placed inside the RAM memory. -Set _stext to an address smaller than 'ORIGIN(RAM) + LENGTH(RAM)'"); - -/* # Other checks */ -ASSERT(SIZEOF(.got) == 0, " -ERROR(cortex-m-rt): .got section detected in the input object files -Dynamic relocations are not supported. If you are linking to C code compiled using -the 'cc' crate then modify your build script to compile the C code _without_ -the -fPIC flag. See the documentation of the `cc::Build.pic` method for details."); -/* Do not exceed this mark in the error messages above | */ - -/* Provides weak aliases (cf. PROVIDED) for device specific interrupt handlers */ -/* This will usually be provided by a device crate generated using svd2rust (see `device.x`) */ -INCLUDE device.x diff --git a/tests/rp/build.rs b/tests/rp/build.rs index 93e2a28cf..71c82a70f 100644 --- a/tests/rp/build.rs +++ b/tests/rp/build.rs @@ -4,7 +4,7 @@ use std::{env, fs}; fn main() -> Result<(), Box> { let out = PathBuf::from(env::var("OUT_DIR").unwrap()); - fs::write(out.join("link_ram.x"), include_bytes!("link_ram.x")).unwrap(); + fs::write(out.join("link_ram.x"), include_bytes!("../link_ram_cortex_m.x")).unwrap(); println!("cargo:rustc-link-search={}", out.display()); println!("cargo:rerun-if-changed=link_ram.x"); diff --git a/tests/rp/link_ram.x b/tests/rp/link_ram.x deleted file mode 100644 index 86a11e875..000000000 --- a/tests/rp/link_ram.x +++ /dev/null @@ -1,255 +0,0 @@ -/* ##### EMBASSY NOTE - Originally from https://github.com/rust-embedded/cortex-m-rt/blob/master/link.x.in - Adjusted to put everything in RAM -*/ - -/* # Developer notes - -- Symbols that start with a double underscore (__) are considered "private" - -- Symbols that start with a single underscore (_) are considered "semi-public"; they can be - overridden in a user linker script, but should not be referred from user code (e.g. `extern "C" { - static mut __sbss }`). - -- `EXTERN` forces the linker to keep a symbol in the final binary. We use this to make sure a - symbol if not dropped if it appears in or near the front of the linker arguments and "it's not - needed" by any of the preceding objects (linker arguments) - -- `PROVIDE` is used to provide default values that can be overridden by a user linker script - -- On alignment: it's important for correctness that the VMA boundaries of both .bss and .data *and* - the LMA of .data are all 4-byte aligned. These alignments are assumed by the RAM initialization - routine. There's also a second benefit: 4-byte aligned boundaries means that you won't see - "Address (..) is out of bounds" in the disassembly produced by `objdump`. -*/ - -/* Provides information about the memory layout of the device */ -MEMORY { - RAM : ORIGIN = 0x20000000, LENGTH = 256K -} - -/* # Entry point = reset vector */ -EXTERN(__RESET_VECTOR); -EXTERN(Reset); -ENTRY(Reset); - -/* # Exception vectors */ -/* This is effectively weak aliasing at the linker level */ -/* The user can override any of these aliases by defining the corresponding symbol themselves (cf. - the `exception!` macro) */ -EXTERN(__EXCEPTIONS); /* depends on all the these PROVIDED symbols */ - -EXTERN(DefaultHandler); - -PROVIDE(NonMaskableInt = DefaultHandler); -EXTERN(HardFaultTrampoline); -PROVIDE(MemoryManagement = DefaultHandler); -PROVIDE(BusFault = DefaultHandler); -PROVIDE(UsageFault = DefaultHandler); -PROVIDE(SecureFault = DefaultHandler); -PROVIDE(SVCall = DefaultHandler); -PROVIDE(DebugMonitor = DefaultHandler); -PROVIDE(PendSV = DefaultHandler); -PROVIDE(SysTick = DefaultHandler); - -PROVIDE(DefaultHandler = DefaultHandler_); -PROVIDE(HardFault = HardFault_); - -/* # Interrupt vectors */ -EXTERN(__INTERRUPTS); /* `static` variable similar to `__EXCEPTIONS` */ - -/* # Pre-initialization function */ -/* If the user overrides this using the `pre_init!` macro or by creating a `__pre_init` function, - then the function this points to will be called before the RAM is initialized. */ -PROVIDE(__pre_init = DefaultPreInit); - -/* # Sections */ -SECTIONS -{ - PROVIDE(_stack_start = ORIGIN(RAM) + LENGTH(RAM)); - - /* ## Sections in RAM */ - /* ### Vector table */ - .vector_table ORIGIN(RAM) : - { - /* Initial Stack Pointer (SP) value */ - LONG(_stack_start); - - /* Reset vector */ - KEEP(*(.vector_table.reset_vector)); /* this is the `__RESET_VECTOR` symbol */ - __reset_vector = .; - - /* Exceptions */ - KEEP(*(.vector_table.exceptions)); /* this is the `__EXCEPTIONS` symbol */ - __eexceptions = .; - - /* Device specific interrupts */ - KEEP(*(.vector_table.interrupts)); /* this is the `__INTERRUPTS` symbol */ - } > RAM - - PROVIDE(_stext = ADDR(.vector_table) + SIZEOF(.vector_table)); - - /* ### .text */ - .text _stext : - { - __stext = .; - *(.Reset); - - *(.text .text.*); - - /* The HardFaultTrampoline uses the `b` instruction to enter `HardFault`, - so must be placed close to it. */ - *(.HardFaultTrampoline); - *(.HardFault.*); - - . = ALIGN(4); /* Pad .text to the alignment to workaround overlapping load section bug in old lld */ - __etext = .; - } > RAM - - /* ### .rodata */ - .rodata : ALIGN(4) - { - . = ALIGN(4); - __srodata = .; - *(.rodata .rodata.*); - - /* 4-byte align the end (VMA) of this section. - This is required by LLD to ensure the LMA of the following .data - section will have the correct alignment. */ - . = ALIGN(4); - __erodata = .; - } > RAM - - /* ## Sections in RAM */ - /* ### .data */ - .data : ALIGN(4) - { - . = ALIGN(4); - __sdata = .; - __edata = .; - *(.data .data.*); - . = ALIGN(4); /* 4-byte align the end (VMA) of this section */ - } > RAM - /* Allow sections from user `memory.x` injected using `INSERT AFTER .data` to - * use the .data loading mechanism by pushing __edata. Note: do not change - * output region or load region in those user sections! */ - . = ALIGN(4); - - /* LMA of .data */ - __sidata = LOADADDR(.data); - - /* ### .gnu.sgstubs - This section contains the TrustZone-M veneers put there by the Arm GNU linker. */ - /* Security Attribution Unit blocks must be 32 bytes aligned. */ - /* Note that this pads the RAM usage to 32 byte alignment. */ - .gnu.sgstubs : ALIGN(32) - { - . = ALIGN(32); - __veneer_base = .; - *(.gnu.sgstubs*) - . = ALIGN(32); - __veneer_limit = .; - } > RAM - - /* ### .bss */ - .bss (NOLOAD) : ALIGN(4) - { - . = ALIGN(4); - __sbss = .; - *(.bss .bss.*); - *(COMMON); /* Uninitialized C statics */ - . = ALIGN(4); /* 4-byte align the end (VMA) of this section */ - } > RAM - /* Allow sections from user `memory.x` injected using `INSERT AFTER .bss` to - * use the .bss zeroing mechanism by pushing __ebss. Note: do not change - * output region or load region in those user sections! */ - . = ALIGN(4); - __ebss = .; - - /* ### .uninit */ - .uninit (NOLOAD) : ALIGN(4) - { - . = ALIGN(4); - __suninit = .; - *(.uninit .uninit.*); - . = ALIGN(4); - __euninit = .; - } > RAM - - /* Place the heap right after `.uninit` in RAM */ - PROVIDE(__sheap = __euninit); - - /* ## .got */ - /* Dynamic relocations are unsupported. This section is only used to detect relocatable code in - the input files and raise an error if relocatable code is found */ - .got (NOLOAD) : - { - KEEP(*(.got .got.*)); - } - - /* ## Discarded sections */ - /DISCARD/ : - { - /* Unused exception related info that only wastes space */ - *(.ARM.exidx); - *(.ARM.exidx.*); - *(.ARM.extab.*); - } -} - -/* Do not exceed this mark in the error messages below | */ -/* # Alignment checks */ -ASSERT(ORIGIN(RAM) % 4 == 0, " -ERROR(cortex-m-rt): the start of the RAM region must be 4-byte aligned"); - -ASSERT(__sdata % 4 == 0 && __edata % 4 == 0, " -BUG(cortex-m-rt): .data is not 4-byte aligned"); - -ASSERT(__sidata % 4 == 0, " -BUG(cortex-m-rt): the LMA of .data is not 4-byte aligned"); - -ASSERT(__sbss % 4 == 0 && __ebss % 4 == 0, " -BUG(cortex-m-rt): .bss is not 4-byte aligned"); - -ASSERT(__sheap % 4 == 0, " -BUG(cortex-m-rt): start of .heap is not 4-byte aligned"); - -/* # Position checks */ - -/* ## .vector_table */ -ASSERT(__reset_vector == ADDR(.vector_table) + 0x8, " -BUG(cortex-m-rt): the reset vector is missing"); - -ASSERT(__eexceptions == ADDR(.vector_table) + 0x40, " -BUG(cortex-m-rt): the exception vectors are missing"); - -ASSERT(SIZEOF(.vector_table) > 0x40, " -ERROR(cortex-m-rt): The interrupt vectors are missing. -Possible solutions, from most likely to less likely: -- Link to a svd2rust generated device crate -- Check that you actually use the device/hal/bsp crate in your code -- Disable the 'device' feature of cortex-m-rt to build a generic application (a dependency -may be enabling it) -- Supply the interrupt handlers yourself. Check the documentation for details."); - -/* ## .text */ -ASSERT(ADDR(.vector_table) + SIZEOF(.vector_table) <= _stext, " -ERROR(cortex-m-rt): The .text section can't be placed inside the .vector_table section -Set _stext to an address greater than the end of .vector_table (See output of `nm`)"); - -ASSERT(_stext + SIZEOF(.text) < ORIGIN(RAM) + LENGTH(RAM), " -ERROR(cortex-m-rt): The .text section must be placed inside the RAM memory. -Set _stext to an address smaller than 'ORIGIN(RAM) + LENGTH(RAM)'"); - -/* # Other checks */ -ASSERT(SIZEOF(.got) == 0, " -ERROR(cortex-m-rt): .got section detected in the input object files -Dynamic relocations are not supported. If you are linking to C code compiled using -the 'cc' crate then modify your build script to compile the C code _without_ -the -fPIC flag. See the documentation of the `cc::Build.pic` method for details."); -/* Do not exceed this mark in the error messages above | */ - - -/* Provides weak aliases (cf. PROVIDED) for device specific interrupt handlers */ -/* This will usually be provided by a device crate generated using svd2rust (see `device.x`) */ -INCLUDE device.x \ No newline at end of file diff --git a/tests/rp/memory.x b/tests/rp/memory.x new file mode 100644 index 000000000..bf0041d7d --- /dev/null +++ b/tests/rp/memory.x @@ -0,0 +1,4 @@ +/* Provides information about the memory layout of the device */ +MEMORY { + RAM : ORIGIN = 0x20000000, LENGTH = 256K +} diff --git a/tests/stm32/build.rs b/tests/stm32/build.rs index c5d0e40d6..f32a7b2f8 100644 --- a/tests/stm32/build.rs +++ b/tests/stm32/build.rs @@ -4,7 +4,7 @@ use std::{env, fs}; fn main() -> Result<(), Box> { let out = PathBuf::from(env::var("OUT_DIR").unwrap()); - fs::write(out.join("link_ram.x"), include_bytes!("link_ram.x")).unwrap(); + fs::write(out.join("link_ram.x"), include_bytes!("../link_ram_cortex_m.x")).unwrap(); println!("cargo:rustc-link-search={}", out.display()); println!("cargo:rustc-link-arg-bins=--nmagic"); diff --git a/tests/stm32/link_ram.x b/tests/stm32/link_ram.x deleted file mode 100644 index 26da86baa..000000000 --- a/tests/stm32/link_ram.x +++ /dev/null @@ -1,254 +0,0 @@ -/* ##### EMBASSY NOTE - Originally from https://github.com/rust-embedded/cortex-m-rt/blob/master/link.x.in - Adjusted to put everything in RAM -*/ - -/* # Developer notes - -- Symbols that start with a double underscore (__) are considered "private" - -- Symbols that start with a single underscore (_) are considered "semi-public"; they can be - overridden in a user linker script, but should not be referred from user code (e.g. `extern "C" { - static mut __sbss }`). - -- `EXTERN` forces the linker to keep a symbol in the final binary. We use this to make sure a - symbol if not dropped if it appears in or near the front of the linker arguments and "it's not - needed" by any of the preceding objects (linker arguments) - -- `PROVIDE` is used to provide default values that can be overridden by a user linker script - -- On alignment: it's important for correctness that the VMA boundaries of both .bss and .data *and* - the LMA of .data are all 4-byte aligned. These alignments are assumed by the RAM initialization - routine. There's also a second benefit: 4-byte aligned boundaries means that you won't see - "Address (..) is out of bounds" in the disassembly produced by `objdump`. -*/ - -/* Provides information about the memory layout of the device */ -/* This will be provided by the user (see `memory.x`) or by a Board Support Crate */ -INCLUDE memory.x - -/* # Entry point = reset vector */ -EXTERN(__RESET_VECTOR); -EXTERN(Reset); -ENTRY(Reset); - -/* # Exception vectors */ -/* This is effectively weak aliasing at the linker level */ -/* The user can override any of these aliases by defining the corresponding symbol themselves (cf. - the `exception!` macro) */ -EXTERN(__EXCEPTIONS); /* depends on all the these PROVIDED symbols */ - -EXTERN(DefaultHandler); - -PROVIDE(NonMaskableInt = DefaultHandler); -EXTERN(HardFaultTrampoline); -PROVIDE(MemoryManagement = DefaultHandler); -PROVIDE(BusFault = DefaultHandler); -PROVIDE(UsageFault = DefaultHandler); -PROVIDE(SecureFault = DefaultHandler); -PROVIDE(SVCall = DefaultHandler); -PROVIDE(DebugMonitor = DefaultHandler); -PROVIDE(PendSV = DefaultHandler); -PROVIDE(SysTick = DefaultHandler); - -PROVIDE(DefaultHandler = DefaultHandler_); -PROVIDE(HardFault = HardFault_); - -/* # Interrupt vectors */ -EXTERN(__INTERRUPTS); /* `static` variable similar to `__EXCEPTIONS` */ - -/* # Pre-initialization function */ -/* If the user overrides this using the `pre_init!` macro or by creating a `__pre_init` function, - then the function this points to will be called before the RAM is initialized. */ -PROVIDE(__pre_init = DefaultPreInit); - -/* # Sections */ -SECTIONS -{ - PROVIDE(_stack_start = ORIGIN(RAM) + LENGTH(RAM)); - - /* ## Sections in RAM */ - /* ### Vector table */ - .vector_table ORIGIN(RAM) : - { - /* Initial Stack Pointer (SP) value */ - LONG(_stack_start); - - /* Reset vector */ - KEEP(*(.vector_table.reset_vector)); /* this is the `__RESET_VECTOR` symbol */ - __reset_vector = .; - - /* Exceptions */ - KEEP(*(.vector_table.exceptions)); /* this is the `__EXCEPTIONS` symbol */ - __eexceptions = .; - - /* Device specific interrupts */ - KEEP(*(.vector_table.interrupts)); /* this is the `__INTERRUPTS` symbol */ - } > RAM - - PROVIDE(_stext = ADDR(.vector_table) + SIZEOF(.vector_table)); - - /* ### .text */ - .text _stext : - { - __stext = .; - *(.Reset); - - *(.text .text.*); - - /* The HardFaultTrampoline uses the `b` instruction to enter `HardFault`, - so must be placed close to it. */ - *(.HardFaultTrampoline); - *(.HardFault.*); - - . = ALIGN(4); /* Pad .text to the alignment to workaround overlapping load section bug in old lld */ - __etext = .; - } > RAM - - /* ### .rodata */ - .rodata : ALIGN(4) - { - . = ALIGN(4); - __srodata = .; - *(.rodata .rodata.*); - - /* 4-byte align the end (VMA) of this section. - This is required by LLD to ensure the LMA of the following .data - section will have the correct alignment. */ - . = ALIGN(4); - __erodata = .; - } > RAM - - /* ## Sections in RAM */ - /* ### .data */ - .data : ALIGN(4) - { - . = ALIGN(4); - __sdata = .; - __edata = .; - *(.data .data.*); - . = ALIGN(4); /* 4-byte align the end (VMA) of this section */ - } > RAM - /* Allow sections from user `memory.x` injected using `INSERT AFTER .data` to - * use the .data loading mechanism by pushing __edata. Note: do not change - * output region or load region in those user sections! */ - . = ALIGN(4); - - /* LMA of .data */ - __sidata = LOADADDR(.data); - - /* ### .gnu.sgstubs - This section contains the TrustZone-M veneers put there by the Arm GNU linker. */ - /* Security Attribution Unit blocks must be 32 bytes aligned. */ - /* Note that this pads the RAM usage to 32 byte alignment. */ - .gnu.sgstubs : ALIGN(32) - { - . = ALIGN(32); - __veneer_base = .; - *(.gnu.sgstubs*) - . = ALIGN(32); - __veneer_limit = .; - } > RAM - - /* ### .bss */ - .bss (NOLOAD) : ALIGN(4) - { - . = ALIGN(4); - __sbss = .; - *(.bss .bss.*); - *(COMMON); /* Uninitialized C statics */ - . = ALIGN(4); /* 4-byte align the end (VMA) of this section */ - } > RAM - /* Allow sections from user `memory.x` injected using `INSERT AFTER .bss` to - * use the .bss zeroing mechanism by pushing __ebss. Note: do not change - * output region or load region in those user sections! */ - . = ALIGN(4); - __ebss = .; - - /* ### .uninit */ - .uninit (NOLOAD) : ALIGN(4) - { - . = ALIGN(4); - __suninit = .; - *(.uninit .uninit.*); - . = ALIGN(4); - __euninit = .; - } > RAM - - /* Place the heap right after `.uninit` in RAM */ - PROVIDE(__sheap = __euninit); - - /* ## .got */ - /* Dynamic relocations are unsupported. This section is only used to detect relocatable code in - the input files and raise an error if relocatable code is found */ - .got (NOLOAD) : - { - KEEP(*(.got .got.*)); - } - - /* ## Discarded sections */ - /DISCARD/ : - { - /* Unused exception related info that only wastes space */ - *(.ARM.exidx); - *(.ARM.exidx.*); - *(.ARM.extab.*); - } -} - -/* Do not exceed this mark in the error messages below | */ -/* # Alignment checks */ -ASSERT(ORIGIN(RAM) % 4 == 0, " -ERROR(cortex-m-rt): the start of the RAM region must be 4-byte aligned"); - -ASSERT(__sdata % 4 == 0 && __edata % 4 == 0, " -BUG(cortex-m-rt): .data is not 4-byte aligned"); - -ASSERT(__sidata % 4 == 0, " -BUG(cortex-m-rt): the LMA of .data is not 4-byte aligned"); - -ASSERT(__sbss % 4 == 0 && __ebss % 4 == 0, " -BUG(cortex-m-rt): .bss is not 4-byte aligned"); - -ASSERT(__sheap % 4 == 0, " -BUG(cortex-m-rt): start of .heap is not 4-byte aligned"); - -/* # Position checks */ - -/* ## .vector_table */ -ASSERT(__reset_vector == ADDR(.vector_table) + 0x8, " -BUG(cortex-m-rt): the reset vector is missing"); - -ASSERT(__eexceptions == ADDR(.vector_table) + 0x40, " -BUG(cortex-m-rt): the exception vectors are missing"); - -ASSERT(SIZEOF(.vector_table) > 0x40, " -ERROR(cortex-m-rt): The interrupt vectors are missing. -Possible solutions, from most likely to less likely: -- Link to a svd2rust generated device crate -- Check that you actually use the device/hal/bsp crate in your code -- Disable the 'device' feature of cortex-m-rt to build a generic application (a dependency -may be enabling it) -- Supply the interrupt handlers yourself. Check the documentation for details."); - -/* ## .text */ -ASSERT(ADDR(.vector_table) + SIZEOF(.vector_table) <= _stext, " -ERROR(cortex-m-rt): The .text section can't be placed inside the .vector_table section -Set _stext to an address greater than the end of .vector_table (See output of `nm`)"); - -ASSERT(_stext + SIZEOF(.text) < ORIGIN(RAM) + LENGTH(RAM), " -ERROR(cortex-m-rt): The .text section must be placed inside the RAM memory. -Set _stext to an address smaller than 'ORIGIN(RAM) + LENGTH(RAM)'"); - -/* # Other checks */ -ASSERT(SIZEOF(.got) == 0, " -ERROR(cortex-m-rt): .got section detected in the input object files -Dynamic relocations are not supported. If you are linking to C code compiled using -the 'cc' crate then modify your build script to compile the C code _without_ -the -fPIC flag. See the documentation of the `cc::Build.pic` method for details."); -/* Do not exceed this mark in the error messages above | */ - - -/* Provides weak aliases (cf. PROVIDED) for device specific interrupt handlers */ -/* This will usually be provided by a device crate generated using svd2rust (see `device.x`) */ -INCLUDE device.x \ No newline at end of file -- cgit