/* The linker script snippet is adapted from the `hopter` crate. Some symbol and section names are prefixed with "hopter" to avoid conflict. Original version: https://github.com/rust-embedded/cortex-m/blob/24380715ce37c5f658033195464ffa3ba22985f4/hopter/link.x.in */ /* # 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 is 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 */ ENTRY(HopterReset); EXTERN(__HOPTER_RESET_VECTOR); /* depends on the `HopterReset` symbol */ /* # Exception vectors */ EXTERN(__HOPTER_EXCEPTIONS); /* depends on all the these PROVIDED symbols */ EXTERN(HopterDefaultHandler); EXTERN(HopterHardFaultTrampoline); PROVIDE(NonMaskableInt = HopterDefaultHandler); PROVIDE(MemoryManagement = HopterDefaultHandler); PROVIDE(BusFault = HopterDefaultHandler); PROVIDE(UsageFault = HopterDefaultHandler); PROVIDE(SecureFault = HopterDefaultHandler); PROVIDE(SVCall = HopterDefaultHandler); PROVIDE(DebugMonitor = HopterDefaultHandler); PROVIDE(PendSV = HopterDefaultHandler); PROVIDE(SysTick = HopterDefaultHandler); PROVIDE(ADC = HopterDefaultHandler); PROVIDE(CAN1_RX0 = HopterDefaultHandler); PROVIDE(CAN1_RX1 = HopterDefaultHandler); PROVIDE(CAN1_SCE = HopterDefaultHandler); PROVIDE(CAN1_TX = HopterDefaultHandler); PROVIDE(CAN2_RX0 = HopterDefaultHandler); PROVIDE(CAN2_RX1 = HopterDefaultHandler); PROVIDE(CAN2_SCE = HopterDefaultHandler); PROVIDE(CAN2_TX = HopterDefaultHandler); PROVIDE(CAN3_RX0 = HopterDefaultHandler); PROVIDE(CAN3_RX1 = HopterDefaultHandler); PROVIDE(CAN3_SCE = HopterDefaultHandler); PROVIDE(CAN3_TX = HopterDefaultHandler); PROVIDE(CRYP = HopterDefaultHandler); PROVIDE(CRYPTO = HopterDefaultHandler); PROVIDE(DCMI = HopterDefaultHandler); PROVIDE(DFSDM1_FLT0 = HopterDefaultHandler); PROVIDE(DFSDM1_FLT1 = HopterDefaultHandler); PROVIDE(DFSDM2_FILTER1 = HopterDefaultHandler); PROVIDE(DFSDM2_FILTER2 = HopterDefaultHandler); PROVIDE(DFSDM2_FILTER3 = HopterDefaultHandler); PROVIDE(DFSDM2_FILTER4 = HopterDefaultHandler); PROVIDE(DMA1_STREAM0 = HopterDefaultHandler); PROVIDE(DMA1_STREAM1 = HopterDefaultHandler); PROVIDE(DMA1_STREAM2 = HopterDefaultHandler); PROVIDE(DMA1_STREAM3 = HopterDefaultHandler); PROVIDE(DMA1_STREAM4 = HopterDefaultHandler); PROVIDE(DMA1_STREAM5 = HopterDefaultHandler); PROVIDE(DMA1_STREAM6 = HopterDefaultHandler); PROVIDE(DMA1_STREAM7 = HopterDefaultHandler); PROVIDE(DMA2D = HopterDefaultHandler); PROVIDE(DMA2_STREAM0 = HopterDefaultHandler); PROVIDE(DMA2_STREAM1 = HopterDefaultHandler); PROVIDE(DMA2_STREAM2 = HopterDefaultHandler); PROVIDE(DMA2_STREAM3 = HopterDefaultHandler); PROVIDE(DMA2_STREAM4 = HopterDefaultHandler); PROVIDE(DMA2_STREAM5 = HopterDefaultHandler); PROVIDE(DMA2_STREAM6 = HopterDefaultHandler); PROVIDE(DMA2_STREAM7 = HopterDefaultHandler); PROVIDE(DSIHOST = HopterDefaultHandler); PROVIDE(ETH = HopterDefaultHandler); PROVIDE(ETH_WKUP = HopterDefaultHandler); PROVIDE(EXTI0 = HopterDefaultHandler); PROVIDE(EXTI1 = HopterDefaultHandler); PROVIDE(EXTI15_10 = HopterDefaultHandler); PROVIDE(EXTI17_RTC_ALARM = HopterDefaultHandler); PROVIDE(EXTI19 = HopterDefaultHandler); PROVIDE(EXTI2 = HopterDefaultHandler); PROVIDE(EXTI20 = HopterDefaultHandler); PROVIDE(EXTI3 = HopterDefaultHandler); PROVIDE(EXTI4 = HopterDefaultHandler); PROVIDE(EXTI9_5 = HopterDefaultHandler); PROVIDE(FLASH = HopterDefaultHandler); PROVIDE(FMC = HopterDefaultHandler); PROVIDE(FPU = HopterDefaultHandler); PROVIDE(FSMC = HopterDefaultHandler); PROVIDE(HASH_RNG = HopterDefaultHandler); PROVIDE(I2C1_ER = HopterDefaultHandler); PROVIDE(I2C1_ERR = HopterDefaultHandler); PROVIDE(I2C1_EV = HopterDefaultHandler); PROVIDE(I2C1_EVT = HopterDefaultHandler); PROVIDE(I2C2_ER = HopterDefaultHandler); PROVIDE(I2C2_ERR = HopterDefaultHandler); PROVIDE(I2C2_EV = HopterDefaultHandler); PROVIDE(I2C2_EVT = HopterDefaultHandler); PROVIDE(I2C3_ER = HopterDefaultHandler); PROVIDE(I2C3_EV = HopterDefaultHandler); PROVIDE(I2C4_ER = HopterDefaultHandler); PROVIDE(I2C4_EV = HopterDefaultHandler); PROVIDE(I2CFMP1ERROR = HopterDefaultHandler); PROVIDE(I2CFMP1EVENT = HopterDefaultHandler); PROVIDE(I2CFMP1_ERROR = HopterDefaultHandler); PROVIDE(I2CFMP1_EVENT = HopterDefaultHandler); PROVIDE(LCD_TFT = HopterDefaultHandler); PROVIDE(LCD_TFT_1 = HopterDefaultHandler); PROVIDE(LPTIM1 = HopterDefaultHandler); PROVIDE(LPTIM1_OR_IT_EIT_23 = HopterDefaultHandler); PROVIDE(LTDC = HopterDefaultHandler); PROVIDE(LTDC_ER = HopterDefaultHandler); PROVIDE(OTG_FS = HopterDefaultHandler); PROVIDE(OTG_FS_WKUP = HopterDefaultHandler); PROVIDE(OTG_HS = HopterDefaultHandler); PROVIDE(OTG_HS_EP1_IN = HopterDefaultHandler); PROVIDE(OTG_HS_EP1_OUT = HopterDefaultHandler); PROVIDE(OTG_HS_WKUP = HopterDefaultHandler); PROVIDE(PVD = HopterDefaultHandler); PROVIDE(PWM1_UP = HopterDefaultHandler); PROVIDE(QUADSPI = HopterDefaultHandler); PROVIDE(QUAD_SPI = HopterDefaultHandler); PROVIDE(RCC = HopterDefaultHandler); PROVIDE(RNG = HopterDefaultHandler); PROVIDE(RTC_ALARM = HopterDefaultHandler); PROVIDE(RTC_WKUP = HopterDefaultHandler); PROVIDE(SAI1 = HopterDefaultHandler); PROVIDE(SDIO = HopterDefaultHandler); PROVIDE(SPI1 = HopterDefaultHandler); PROVIDE(SPI2 = HopterDefaultHandler); PROVIDE(SPI3 = HopterDefaultHandler); PROVIDE(SPI4 = HopterDefaultHandler); PROVIDE(SPI5 = HopterDefaultHandler); PROVIDE(SPI6 = HopterDefaultHandler); PROVIDE(TAMP_STAMP = HopterDefaultHandler); PROVIDE(TIM12 = HopterDefaultHandler); PROVIDE(TIM13 = HopterDefaultHandler); PROVIDE(TIM14 = HopterDefaultHandler); PROVIDE(TIM1_BRK_TIM9 = HopterDefaultHandler); PROVIDE(TIM1_CC = HopterDefaultHandler); PROVIDE(TIM1_TRG_COM_TIM11 = HopterDefaultHandler); PROVIDE(TIM1_UP_TIM10 = HopterDefaultHandler); PROVIDE(TIM2 = HopterDefaultHandler); PROVIDE(TIM3 = HopterDefaultHandler); PROVIDE(TIM4 = HopterDefaultHandler); PROVIDE(TIM5 = HopterDefaultHandler); PROVIDE(TIM6_DAC = HopterDefaultHandler); PROVIDE(TIM6_DAC1 = HopterDefaultHandler); PROVIDE(TIM6_DACUNDER = HopterDefaultHandler); PROVIDE(TIM6_GLB_IT_DAC1_DAC2 = HopterDefaultHandler); PROVIDE(TIM7 = HopterDefaultHandler); PROVIDE(TIM8_BRK_TIM12 = HopterDefaultHandler); PROVIDE(TIM8_CC = HopterDefaultHandler); PROVIDE(TIM8_TRG_COM_TIM14 = HopterDefaultHandler); PROVIDE(TIM8_UP_TIM13 = HopterDefaultHandler); PROVIDE(UART10 = HopterDefaultHandler); PROVIDE(UART4 = HopterDefaultHandler); PROVIDE(UART5 = HopterDefaultHandler); PROVIDE(UART7 = HopterDefaultHandler); PROVIDE(UART8 = HopterDefaultHandler); PROVIDE(UART9 = HopterDefaultHandler); PROVIDE(USART1 = HopterDefaultHandler); PROVIDE(USART2 = HopterDefaultHandler); PROVIDE(USART3 = HopterDefaultHandler); PROVIDE(USART4 = HopterDefaultHandler); PROVIDE(USART6 = HopterDefaultHandler); PROVIDE(USART7 = HopterDefaultHandler); PROVIDE(USART8 = HopterDefaultHandler); PROVIDE(WWDG = HopterDefaultHandler); /* # Interrupt vectors */ EXTERN(__HOPTER_INTERRUPTS); /* `static` variable similar to `__HOPTER_EXCEPTIONS` */ /* This is where the contiguous call stack will be allocated. */ /* The stack grows downward. */ __contiguous_stack_bottom = ORIGIN(RAM) + _contiguous_stack_length; __ram_end = ORIGIN(RAM) + LENGTH(RAM); /* # Sections */ SECTIONS { /* ## Sections in FLASH */ /* ### Vector table */ .hopter_vector_table ORIGIN(FLASH) : { /* Initial Stack Pointer (SP) value */ LONG(__contiguous_stack_bottom); /* Reset vector */ KEEP(*(.hopter_vector_table.reset_vector)); /* this is the `__RESET_VECTOR` symbol */ __hopter_reset_vector = .; /* Exceptions */ KEEP(*(.hopter_vector_table.exceptions)); /* this is the `__EXCEPTIONS` symbol */ __eexceptions = .; /* Device specific interrupts */ KEEP(*(.hopter_vector_table.interrupts)); /* this is the `__INTERRUPTS` symbol */ } > FLASH PROVIDE(_stext = ADDR(.hopter_vector_table) + SIZEOF(.hopter_vector_table)); /* ### .text */ .text _stext : { /* place these 2 close to each other or the `b` instruction will fail to link */ *(.HopterReset); *(.text .text.*); . = ALIGN(16); __etext = .; } > FLASH /* ### .rodata */ .rodata __etext : ALIGN(16) { *(.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 = .; } > FLASH /* ### .ARM.exidx */ .ARM.exidx __erodata : ALIGN(4) { . = ALIGN(4); __sarm_exidx = .; *(.ARM.exidx .ARM.exidx.*); /* Not sure if we need the below line. */ /* *(.ARM.exidx.*); */ /* 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); __earm_exidx = .; } > FLASH /* ### .ARM.extab */ .ARM.extab __earm_exidx : ALIGN(4) { . = ALIGN(4); __sarm_extab = .; *(.ARM.extab .ARM.extab.*); /* 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); __earm_extab = .; } > FLASH /* ## Sections in RAM */ /* ### contiguous stack */ .cont_stack (NOLOAD) : ALIGN(4) { . = ORIGIN(RAM); FILL(0); . = __contiguous_stack_bottom; } > RAM /* ### .data */ .data : ALIGN(4) { . = ALIGN(4); __sdata = .; *(.data .data.*); . = ALIGN(4); /* 4-byte align the end (VMA) of this section */ __edata = .; } > RAM AT>FLASH /* LMA of .data */ __sidata = LOADADDR(.data); /* ### .bss */ .bss (NOLOAD) : ALIGN(4) { . = ALIGN(4); __sbss = .; *(.bss .bss.*); . = ALIGN(4); /* 4-byte align the end (VMA) of this section */ __ebss = .; } > RAM AT>FLASH /* Place the heap right after `.bss` */ . = ALIGN(4); __sheap = .; /* ## .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 : ALIGN(4) { KEEP(*(.got .got.*)); } /* ## Discarded sections */ /DISCARD/ : { /* These are the special sections defined in `cortex-m-rt`. Many crates have the `cortex-m-rt` crate as their dependency. However, these sections conflict with Hopter's definition. We keep only Hopter's version, i.e., those with similar names but prefixed with "hopter", and discard the `cortex-m-rt` version. */ *(.PreResetTrampoline); *(.vector_table.reset_vector); *(.vector_table.exceptions); *(.vector_table.interrupts); *(.HardFaultTrampoline); *(.HardFault.*); } } /* Do not exceed this mark in the error messages below | */ /* # Alignment checks */ ASSERT(ORIGIN(FLASH) % 4 == 0, " ERROR(hopter): the start of the FLASH region must be 4-byte aligned"); ASSERT(ORIGIN(RAM) % 4 == 0, " ERROR(hopter): the start of the RAM region must be 4-byte aligned"); ASSERT(__sdata % 4 == 0 && __edata % 4 == 0, " BUG(hopter): .data is not 4-byte aligned"); ASSERT(__sidata % 4 == 0, " BUG(hopter): the LMA of .data is not 4-byte aligned"); ASSERT(__sbss % 4 == 0 && __ebss % 4 == 0, " BUG(hopter): .bss is not 4-byte aligned"); ASSERT(__sheap % 4 == 0, " BUG(hopter): start of .heap is not 4-byte aligned"); /* # Position checks */ /* ## .vector_table */ ASSERT(__hopter_reset_vector == ADDR(.hopter_vector_table) + 0x8, " BUG(hopter): the reset vector is missing"); ASSERT(__eexceptions == ADDR(.hopter_vector_table) + 0x40, " BUG(hopter): the exception vectors are missing"); ASSERT(SIZEOF(.hopter_vector_table) > 0x40, " ERROR(hopter): The interrupt vectors are missing. Possible solutions, from most likely to less likely: - Link to a svd2rust generated device crate - Disable the 'device' feature of hopter to build a generic application (a dependency may be enabling it) - Supply the interrupt handlers yourself. Check the documentation for details."); /* ## .text */ ASSERT(ADDR(.hopter_vector_table) + SIZEOF(.hopter_vector_table) <= _stext, " ERROR(hopter): The .text section can't be placed inside the .hopter_vector_table section Set _stext to an address greater than the end of .hopter_vector_table (See output of `nm`)"); ASSERT(_stext + SIZEOF(.text) < ORIGIN(FLASH) + LENGTH(FLASH), " ERROR(hopter): The .text section must be placed inside the FLASH memory. Set _stext to an address smaller than 'ORIGIN(FLASH) + LENGTH(FLASH)'"); /* # Other checks */ ASSERT(SIZEOF(.got) == 0, " ERROR(hopter): .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 | */ ASSERT(SIZEOF(.hopter_vector_table) <= 0x400, " There can't be more than 240 interrupt handlers. This may be a bug in your device crate, or you may have registered more than 240 interrupt handlers.");