From 1484b71d3a82be2fec6e38ed96e1fda5c62a3abe Mon Sep 17 00:00:00 2001 From: Chris Kay Date: Mon, 1 Oct 2018 14:05:01 +0100 Subject: [PATCH 1/8] build: Prefer -O2 to -O3 This change is being made to claw back some of the bloat caused by certain optimizations that are enabled by -O3. Change-Id: Ide36c162104be784dabbfec16974090591293dde Signed-off-by: Chris Kay --- tools/build_system/rules.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/build_system/rules.mk b/tools/build_system/rules.mk index 2f3b18361..e7cf38b1f 100644 --- a/tools/build_system/rules.mk +++ b/tools/build_system/rules.mk @@ -37,7 +37,7 @@ endif # GCC-specific optimization levels for debug and release modes # DEFAULT_OPT_GCC_DEBUG := g -DEFAULT_OPT_GCC_RELEASE := 3 +DEFAULT_OPT_GCC_RELEASE := 2 # # Compiler options used when building for the host -- GitLab From 2a12c2db8d943a525d26fba3fbc37fd2059ca8a2 Mon Sep 17 00:00:00 2001 From: Chris Kay Date: Wed, 3 Oct 2018 09:52:51 +0100 Subject: [PATCH 2/8] build: Disable -Wdollar-in-identifier-extension warning flag This flag stops Arm Compiler 6 from complaining about the linker-defined symbols. Change-Id: Ide8b3c0315129d04fe1aa1d126cb7131dfd1d553 Signed-off-by: Chris Kay --- arch/src/arm_mm.c | 5 ----- tools/build_system/rules.mk | 3 +++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/src/arm_mm.c b/arch/src/arm_mm.c index 5a434b102..60f04378c 100644 --- a/arch/src/arm_mm.c +++ b/arch/src/arm_mm.c @@ -19,16 +19,11 @@ int arm_mm_init(struct fwk_arch_mm_data *data) fwk_assert(data != NULL); #ifdef __ARMCC_VERSION -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" - extern unsigned int Image$$ARM_LIB_STACKHEAP$$ZI$$Base; extern unsigned int Image$$ARM_LIB_STACKHEAP$$ZI$$Length; data->start = (uintptr_t)(&Image$$ARM_LIB_STACKHEAP$$ZI$$Base); data->size = (size_t)(&Image$$ARM_LIB_STACKHEAP$$ZI$$Length); - -# pragma clang diagnostic pop #else extern unsigned int __stackheap_start__; extern unsigned int __stackheap_size__; diff --git a/tools/build_system/rules.mk b/tools/build_system/rules.mk index e7cf38b1f..44185e637 100644 --- a/tools/build_system/rules.mk +++ b/tools/build_system/rules.mk @@ -97,6 +97,9 @@ CFLAGS_GCC += -Wno-missing-field-initializers # warn about the situations that have not already been fixed. CFLAGS_CLANG += -Wno-missing-braces +# Arm Compiler 6 uses dollar symbols in its linker-defined symbol names +CFLAGS_CLANG += -Wno-dollar-in-identifier-extension + CFLAGS_GCC += -g CFLAGS_GCC += -std=c11 CFLAGS_CLANG += -fshort-enums # Required by RTX -- GitLab From 6ef93e3918f4b803b90c99af8ae129bb31f00c43 Mon Sep 17 00:00:00 2001 From: Chris Kay Date: Wed, 26 Sep 2018 17:30:47 +0100 Subject: [PATCH 3/8] arm: Prefix exception functions with "arm_" This is in order to avoid conflicts with other names in the global namespace. Change-Id: I18f2ec432ef4cc02254e94a4cd02b3c1e789a6fe Signed-off-by: Chris Kay --- arch/src/arm_nvic.c | 6 +++--- arch/src/armv7-m/exception.S | 36 ++++++++++++++++----------------- arch/src/armv7-m/ld.S | 4 ++-- arch/src/armv7-m/reset_arm.S | 6 +++--- arch/src/armv7-m/reset_newlib.S | 6 +++--- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/arch/src/arm_nvic.c b/arch/src/arm_nvic.c index 38e192afb..9fb270134 100644 --- a/arch/src/arm_nvic.c +++ b/arch/src/arm_nvic.c @@ -23,7 +23,7 @@ #include #endif -extern noreturn void exception_invalid(void); +extern noreturn void arm_exception_invalid(void); struct nvic; @@ -310,14 +310,14 @@ int arm_nvic_init(const struct fwk_arch_interrupt_driver **driver) return FWK_E_NOMEM; /* - * Initialize all exception entries to point to the exception_invalid() + * Initialize all exception entries to point to the arm_exception_invalid() * handler. * * Note: Initialization starts from entry 1 since entry 0 is not an * exception pointer but the default stack pointer. */ for (i = 1; i < EXCEPTION_NUM_COUNT; i++) - vector[i] = exception_invalid; + vector[i] = arm_exception_invalid; /* Initialize IRQs */ for (i = 0; i < irq_count; i++) { diff --git a/arch/src/armv7-m/exception.S b/arch/src/armv7-m/exception.S index 18f3c133a..4dc2067fb 100644 --- a/arch/src/armv7-m/exception.S +++ b/arch/src/armv7-m/exception.S @@ -21,30 +21,30 @@ .global exceptions exceptions: - .word exception_invalid /* NMI */ - .word exception_invalid /* HardFault */ - .word exception_invalid /* MemManage */ - .word exception_invalid /* Bus Fault */ - .word exception_invalid /* UsageFault */ - .word exception_invalid /* Reserved */ - .word exception_invalid /* Reserved */ - .word exception_invalid /* Reserved */ - .word exception_invalid /* Reserved */ - .word exception_invalid /* SVCall */ - .word exception_invalid /* DebugMonitor */ - .word exception_invalid /* Reserved */ - .word exception_invalid /* PendSV */ - .word exception_invalid /* SysTick */ + .word arm_exception_invalid /* NMI */ + .word arm_exception_invalid /* HardFault */ + .word arm_exception_invalid /* MemManage */ + .word arm_exception_invalid /* Bus Fault */ + .word arm_exception_invalid /* UsageFault */ + .word arm_exception_invalid /* Reserved */ + .word arm_exception_invalid /* Reserved */ + .word arm_exception_invalid /* Reserved */ + .word arm_exception_invalid /* Reserved */ + .word arm_exception_invalid /* SVCall */ + .word arm_exception_invalid /* DebugMonitor */ + .word arm_exception_invalid /* Reserved */ + .word arm_exception_invalid /* PendSV */ + .word arm_exception_invalid /* SysTick */ .type exceptions, %object .size exceptions, . - exceptions .section .text - .global exception_invalid + .global arm_exception_invalid .thumb_func - .type exception_invalid, %function + .type arm_exception_invalid, %function .eabi_attribute Tag_ABI_align_preserved, 1 -exception_invalid: +arm_exception_invalid: wfi - b exception_invalid + b arm_exception_invalid diff --git a/arch/src/armv7-m/ld.S b/arch/src/armv7-m/ld.S index 2050ca28e..e723cc4f2 100644 --- a/arch/src/armv7-m/ld.S +++ b/arch/src/armv7-m/ld.S @@ -87,7 +87,7 @@ #endif #endif -ENTRY(exception_reset) +ENTRY(arm_exception_reset) MEMORY { #if FIRMWARE_MEM_MODE == FWK_MEM_MODE_SINGLE_REGION @@ -118,7 +118,7 @@ REGION_ALIAS("vstackheap", mem1); SECTIONS { .exception : { LONG(__stack) - LONG(exception_reset | 1) /* The LSB must be set for Thumb functions */ + LONG(arm_exception_reset | 1) /* LSB must be set for Thumb functions */ KEEP(*(.exception)) } > vexception diff --git a/arch/src/armv7-m/reset_arm.S b/arch/src/armv7-m/reset_arm.S index 3e57ba316..06837acba 100644 --- a/arch/src/armv7-m/reset_arm.S +++ b/arch/src/armv7-m/reset_arm.S @@ -12,10 +12,10 @@ .text - .global exception_reset + .global arm_exception_reset .thumb_func - .type exception_reset, %function -exception_reset: + .type arm_exception_reset, %function +arm_exception_reset: bl arm_init_ccr /* Initialize the CCR register */ b __main /* Enter Arm Compiler 6's crt0 */ .pool diff --git a/arch/src/armv7-m/reset_newlib.S b/arch/src/armv7-m/reset_newlib.S index b474d3203..db6912188 100644 --- a/arch/src/armv7-m/reset_newlib.S +++ b/arch/src/armv7-m/reset_newlib.S @@ -12,10 +12,10 @@ .text - .global exception_reset + .global arm_exception_reset .thumb_func - .type exception_reset, %function -exception_reset: + .type arm_exception_reset, %function +arm_exception_reset: b _start /* Enter Newlib's crt0 */ .pool -- GitLab From 6cc95766ba5b0a395ad7b8473911666351b881ad Mon Sep 17 00:00:00 2001 From: Chris Kay Date: Mon, 24 Sep 2018 10:43:40 +0100 Subject: [PATCH 4/8] arm: Convert assembly files to C Minimizing the amount of assembly we use makes it easier to understand the early boot flow and how objects are placed in the ELF image. Additionally, arm_init_ccr() is no longer called before the C runtime initialization is done, and is instead called by main(). Change-Id: Ib539bd45fb707d6948cc925a024cce803051ff8a Signed-off-by: Chris Kay --- arch/src/Makefile | 9 +-- arch/src/arm_main.c | 31 ++++++++ arch/src/armv7-m/config.S | 39 ---------- arch/src/armv7-m/exception.S | 50 ------------- arch/src/armv7-m/exceptions.c | 122 ++++++++++++++++++++++++++++++++ arch/src/armv7-m/ld.S | 6 +- arch/src/armv7-m/reset_arm.S | 21 ------ arch/src/armv7-m/reset_newlib.S | 49 ------------- arch/src/armv7-m/scatter.S | 3 +- tools/build_system/rules.mk | 8 +-- 10 files changed, 158 insertions(+), 180 deletions(-) delete mode 100644 arch/src/armv7-m/config.S delete mode 100644 arch/src/armv7-m/exception.S create mode 100644 arch/src/armv7-m/exceptions.c delete mode 100644 arch/src/armv7-m/reset_arm.S delete mode 100644 arch/src/armv7-m/reset_newlib.S diff --git a/arch/src/Makefile b/arch/src/Makefile index c766542e5..3ef76ef32 100644 --- a/arch/src/Makefile +++ b/arch/src/Makefile @@ -10,18 +10,11 @@ include $(BS_DIR)/toolchain.mk BS_LIB_NAME = arch -BS_LIB_SOURCES_armv7-m += armv7-m/exception.S -BS_LIB_SOURCES_armv7-m += armv7-m/config.S +BS_LIB_SOURCES_armv7-m += armv7-m/exceptions.c BS_LIB_SOURCES_armv7-m += arm_nvic.c BS_LIB_SOURCES_armv7-m += arm_main.c BS_LIB_SOURCES_armv7-m += arm_mm.c -ifeq ($(BS_LINKER),ARM) - BS_LIB_SOURCES_armv7-m += armv7-m/reset_arm.S -else - BS_LIB_SOURCES_armv7-m += armv7-m/reset_newlib.S -endif - BS_LIB_INCLUDES_armv7-m += $(TOP_DIR)/cmsis/CMSIS/Core/Include/ BS_LIB_SOURCES_host += host.c diff --git a/arch/src/arm_main.c b/arch/src/arm_main.c index d4feb76c3..e6faaf524 100644 --- a/arch/src/arm_main.c +++ b/arch/src/arm_main.c @@ -9,8 +9,15 @@ #include #include #include +#include #include +#define SCB_CCR ((FWK_RW uint32_t *)(0xE000ED14)) + +#define SCB_CCR_UNALIGN_TRP_MASK (1U << 3) +#define SCB_CCR_DIV_0_TRP_MASK (1U << 4) +#define SCB_CCR_STKALIGN_MASK (1U << 9) + extern int arm_nvic_init(struct fwk_arch_interrupt_driver **driver); extern int arm_mm_init(struct fwk_arch_mm_data *data); @@ -52,7 +59,31 @@ static struct fwk_arch_init_driver arch_init_driver = { .interrupt = arm_nvic_init, }; +static void arm_init_ccr(void) +{ + /* + * Set up the Configuration Control Register (CCR) in the System Control + * Block (1) by setting the following flag bits: + * + * UNALIGN_TRP [3]: Enable trapping on unaligned word or halfword accesses. + * DIV_0_TRP [4]: Enable trapping on division by zero. + * STKALIGN [9]: Enable automatic DWORD stack-alignment on exception + * entry (2). + * + * All other bits are left in their default state. + * + * (1) ARM® v7-M Architecture Reference Manual, section B3.2.8. + * (2) ARM® v7-M Architecture Reference Manual, section B1.5.7. + */ + + *SCB_CCR |= SCB_CCR_UNALIGN_TRP_MASK; + *SCB_CCR |= SCB_CCR_DIV_0_TRP_MASK; + *SCB_CCR |= SCB_CCR_STKALIGN_MASK; +} + int main(void) { + arm_init_ccr(); + return fwk_arch_init(&arch_init_driver); } diff --git a/arch/src/armv7-m/config.S b/arch/src/armv7-m/config.S deleted file mode 100644 index 48fd05646..000000000 --- a/arch/src/armv7-m/config.S +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Arm SCP/MCP Software - * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Description: - * Architectural configuration. - */ - - .syntax unified - - .text - - .global arm_init_ccr - .thumb_func - .type arm_init_ccr, %function -arm_init_ccr: - /* - * Set up the Configuration Control Register (CCR) in the System Control - * Block (1) by setting the following flag bits: - * - * UNALIGN_TRP [3]: Enable trapping on unaligned word or halfword accesses. - * DIV_0_TRP [4]: Enable trapping on division by zero. - * STKALIGN [9]: Enable automatic DWORD stack-alignment on exception - * entry (2). - * - * All other bits are left in their default state. - * - * (1) ARM® v7-M Architecture Reference Manual, section B3.2.8. - * (2) ARM® v7-M Architecture Reference Manual, section B1.5.7. - */ - ldr r0, =0xE000ED14 /* Load CCR address (architecture-defined) */ - ldr r1, [r0] /* Load existing CCR value */ - orr r1, #0x218 /* Set flag bits */ - str r1, [r0] /* Store modified value back to the CCR */ - - bx lr - .pool diff --git a/arch/src/armv7-m/exception.S b/arch/src/armv7-m/exception.S deleted file mode 100644 index 4dc2067fb..000000000 --- a/arch/src/armv7-m/exception.S +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Arm SCP/MCP Software - * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - - .syntax unified - - .section .exception, "a", %progbits - -/* - * We set up the exception table here. The table is put inside the ".exception" - * section, which is marked as PROGBITS (takes up space in the binary). The - * "exceptions" symbol is given the same ELF attributes as a standard C - * structure (allocatable object) in order to ensure it is properly exported - * or loaded. See the GNU assembler documentation for the exact meaning behind - * the directives provided here. See the .exception section described in the GNU - * linker script for the first two entries of the exception table. - */ - - .global exceptions -exceptions: - .word arm_exception_invalid /* NMI */ - .word arm_exception_invalid /* HardFault */ - .word arm_exception_invalid /* MemManage */ - .word arm_exception_invalid /* Bus Fault */ - .word arm_exception_invalid /* UsageFault */ - .word arm_exception_invalid /* Reserved */ - .word arm_exception_invalid /* Reserved */ - .word arm_exception_invalid /* Reserved */ - .word arm_exception_invalid /* Reserved */ - .word arm_exception_invalid /* SVCall */ - .word arm_exception_invalid /* DebugMonitor */ - .word arm_exception_invalid /* Reserved */ - .word arm_exception_invalid /* PendSV */ - .word arm_exception_invalid /* SysTick */ - - .type exceptions, %object - .size exceptions, . - exceptions - - .section .text - - .global arm_exception_invalid - .thumb_func - .type arm_exception_invalid, %function - .eabi_attribute Tag_ABI_align_preserved, 1 -arm_exception_invalid: - wfi - b arm_exception_invalid diff --git a/arch/src/armv7-m/exceptions.c b/arch/src/armv7-m/exceptions.c new file mode 100644 index 000000000..5578c498a --- /dev/null +++ b/arch/src/armv7-m/exceptions.c @@ -0,0 +1,122 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * ARMv7-M exception handlers. + */ + +#include +#include +#include +#include +#include + +#ifdef __NEWLIB__ +/* + * This function overloads a weak definition provided by Newlib. It is called + * during initialization of the C runtime just after .bss has been zeroed. + */ +void software_init_hook(void) +{ + extern char __data_start_lma__; + extern char __data_start_vma__; + extern char __data_size__; + + char *load = &__data_start_lma__; + char *start = &__data_start_vma__; + unsigned int size = (unsigned int)(&__data_size__); + + if (load != start) + memcpy(start, load, size); +} +#endif + +noreturn void arm_exception_reset(void) +{ + /* + * When entering the firmware, before the framework is entered the following + * things happen: + * 1. The toolchain-specific C runtime is initialized + * For Arm Compiler: + * 1. Zero-initialized data is zeroed + * 2. Initialized data is decompressed and copied + * For GCC/Newlib: + * 1. Zero-initialized data is zeroed + * 2. Initialized data is copied by software_init_hook() + * 2. The main() function is called by the C runtime + */ + +#ifdef __ARMCC_VERSION + extern noreturn void __main(void); + + __main(); +#else + extern noreturn void _start(void); + + _start(); +#endif +} + +noreturn void arm_exception_invalid(void) +{ + while (true) + __WFI(); +} + +enum { + EXCEPTION_RESET, + EXCEPTION_NMI, + EXCEPTION_HARDFAULT, + EXCEPTION_MEMMANAGE, + EXCEPTION_BUSFAULT, + EXCEPTION_USAGEFAULT, + EXCEPTION_RESERVED0, + EXCEPTION_RESERVED1, + EXCEPTION_RESERVED2, + EXCEPTION_RESERVED3, + EXCEPTION_SVCALL, + EXCEPTION_DEBUGMONITOR, + EXCEPTINO_RESERVED4, + EXCEPTION_PENDSV, + EXCEPTION_SYSTICK, +}; + +#ifdef __ARMCC_VERSION +extern char Image$$ARM_LIB_STACKHEAP$$ZI$$Limit; + +# define arm_exception_stack (&Image$$ARM_LIB_STACKHEAP$$ZI$$Limit) +#else +extern char __stack; + +# define arm_exception_stack (&__stack) +#endif + +/* + * Set up the exception table. The structure below is marked as static because + * it doesn't need to be visible outside of this translation unit, but it is + * marked as used to ensure it is not removed by the compiler. It is added to + * the .exceptions section which will be explicitly placed at the beginning of + * the binary by the linker script. + */ + +static const struct { + uintptr_t stack; + uintptr_t exceptions[15]; +} exceptions __attribute__((used, section(".exceptions"))) = { + .stack = (uintptr_t)(arm_exception_stack), + .exceptions = { + [EXCEPTION_RESET] = (uintptr_t)(arm_exception_reset), + [EXCEPTION_NMI] = (uintptr_t)(arm_exception_invalid), + [EXCEPTION_HARDFAULT] = (uintptr_t)(arm_exception_invalid), + [EXCEPTION_MEMMANAGE] = (uintptr_t)(arm_exception_invalid), + [EXCEPTION_BUSFAULT] = (uintptr_t)(arm_exception_invalid), + [EXCEPTION_USAGEFAULT] = (uintptr_t)(arm_exception_invalid), + [EXCEPTION_SVCALL] = (uintptr_t)(arm_exception_invalid), + [EXCEPTION_DEBUGMONITOR] = (uintptr_t)(arm_exception_invalid), + [EXCEPTION_PENDSV] = (uintptr_t)(arm_exception_invalid), + [EXCEPTION_SYSTICK] = (uintptr_t)(arm_exception_invalid), + } +}; diff --git a/arch/src/armv7-m/ld.S b/arch/src/armv7-m/ld.S index e723cc4f2..6c983fa82 100644 --- a/arch/src/armv7-m/ld.S +++ b/arch/src/armv7-m/ld.S @@ -116,10 +116,8 @@ REGION_ALIAS("vstackheap", mem1); #endif SECTIONS { - .exception : { - LONG(__stack) - LONG(arm_exception_reset | 1) /* LSB must be set for Thumb functions */ - KEEP(*(.exception)) + .exceptions : { + KEEP(*(.exceptions)) } > vexception .text : { diff --git a/arch/src/armv7-m/reset_arm.S b/arch/src/armv7-m/reset_arm.S deleted file mode 100644 index 06837acba..000000000 --- a/arch/src/armv7-m/reset_arm.S +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Arm SCP/MCP Software - * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Description: - * C runtime initialization for Arm Compiler 6. - */ - - .syntax unified - - .text - - .global arm_exception_reset - .thumb_func - .type arm_exception_reset, %function -arm_exception_reset: - bl arm_init_ccr /* Initialize the CCR register */ - b __main /* Enter Arm Compiler 6's crt0 */ - .pool diff --git a/arch/src/armv7-m/reset_newlib.S b/arch/src/armv7-m/reset_newlib.S deleted file mode 100644 index db6912188..000000000 --- a/arch/src/armv7-m/reset_newlib.S +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Arm SCP/MCP Software - * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Description: - * C runtime initialization for Newlib. - */ - - .syntax unified - - .text - - .global arm_exception_reset - .thumb_func - .type arm_exception_reset, %function -arm_exception_reset: - b _start /* Enter Newlib's crt0 */ - .pool - -/* - * The following *_init_hook functions are called from _start and provide an - * early opportunity to do some critical runtime setup. From the point of view - * of the runtime, there is no difference between the hardware and software - * hook, but the hardware hook is called before the software hook. Accesses to - * mem1 are invalid until the data residing in it has been initialized by the - * software hook. - */ - - .global hardware_init_hook - .thumb_func - .type hardware_init_hook, %function -hardware_init_hook: - b arm_init_ccr /* Initialize the CCR register */ - .pool - - .global software_init_hook - .thumb_func - .type software_init_hook, %function -software_init_hook: - ldr r0, =__data_start_vma__ - ldr r1, =__data_start_lma__ - ldr r2, =__data_size__ - - cmp r0, r1 - bne memcpy /* Copy .data from ROM to RAM if necessary */ - bx lr /* Otherwise return */ - .pool diff --git a/arch/src/armv7-m/scatter.S b/arch/src/armv7-m/scatter.S index 57a41debd..4c03e6167 100644 --- a/arch/src/armv7-m/scatter.S +++ b/arch/src/armv7-m/scatter.S @@ -93,8 +93,7 @@ LR_MEM0 FIRMWARE_MEM0_BASE FIRMWARE_MEM0_SIZE { ER_EXCEPTION +0 { - *(:gdef:__vectab_stack_and_reset, +FIRST) - *(.exception) + *(.exceptions) } ER_RODATA +0 { diff --git a/tools/build_system/rules.mk b/tools/build_system/rules.mk index 44185e637..1763bb138 100644 --- a/tools/build_system/rules.mk +++ b/tools/build_system/rules.mk @@ -116,13 +116,7 @@ ARFLAGS_GCC = -rc LDFLAGS_GCC += -Wl,--cref -# Force an undefined reference to the exceptions table so that it is included -# even if no code refers to it. -LDFLAGS_GCC += -Wl,--undefined=exceptions -LDFLAGS_ARM += -Wl,--undefined=exceptions - -# Ensure main() is not removed by the linker -LDFLAGS_ARM += -Wl,--undefined=main +LDFLAGS_ARM += -Wl,--undefined=arm_exception_reset BUILTIN_LIBS_GCC := -lc -lgcc -- GitLab From 148c974b20c4c4d8812351af22f6395769915410 Mon Sep 17 00:00:00 2001 From: Chris Kay Date: Fri, 28 Sep 2018 16:42:13 +0100 Subject: [PATCH 5/8] arm: Clean up GNU linker script symbols Change-Id: I97f6736d56d3e1f42a219547833abb1a5f54d03c Signed-off-by: Chris Kay --- arch/src/arm_mm.c | 11 +++++++---- arch/src/armv7-m/exceptions.c | 18 +++++++++--------- arch/src/armv7-m/ld.S | 28 ++++++++++++++++++++-------- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/arch/src/arm_mm.c b/arch/src/arm_mm.c index 60f04378c..66144706f 100644 --- a/arch/src/arm_mm.c +++ b/arch/src/arm_mm.c @@ -25,11 +25,14 @@ int arm_mm_init(struct fwk_arch_mm_data *data) data->start = (uintptr_t)(&Image$$ARM_LIB_STACKHEAP$$ZI$$Base); data->size = (size_t)(&Image$$ARM_LIB_STACKHEAP$$ZI$$Length); #else - extern unsigned int __stackheap_start__; - extern unsigned int __stackheap_size__; + extern char __stackheap_start__; + extern char __stackheap_end__; - data->start = (uintptr_t)(&__stackheap_start__); - data->size = (size_t)(&__stackheap_size__); + uintptr_t start = (uintptr_t)(&__stackheap_start__); + uintptr_t end = (uintptr_t)(&__stackheap_end__); + + data->start = start; + data->size = end - start; #endif return FWK_SUCCESS; diff --git a/arch/src/armv7-m/exceptions.c b/arch/src/armv7-m/exceptions.c index 5578c498a..143f63c67 100644 --- a/arch/src/armv7-m/exceptions.c +++ b/arch/src/armv7-m/exceptions.c @@ -21,16 +21,16 @@ */ void software_init_hook(void) { - extern char __data_start_lma__; - extern char __data_start_vma__; - extern char __data_size__; + extern char __data_load__; + extern char __data_start__; + extern char __data_end__; - char *load = &__data_start_lma__; - char *start = &__data_start_vma__; - unsigned int size = (unsigned int)(&__data_size__); + char *load = &__data_load__; + char *start = &__data_start__; + char *end = &__data_end__; if (load != start) - memcpy(start, load, size); + memcpy(start, load, end - start); } #endif @@ -89,9 +89,9 @@ extern char Image$$ARM_LIB_STACKHEAP$$ZI$$Limit; # define arm_exception_stack (&Image$$ARM_LIB_STACKHEAP$$ZI$$Limit) #else -extern char __stack; +extern char __stackheap_end__; -# define arm_exception_stack (&__stack) +# define arm_exception_stack (&__stackheap_end__) #endif /* diff --git a/arch/src/armv7-m/ld.S b/arch/src/armv7-m/ld.S index 6c983fa82..79a892964 100644 --- a/arch/src/armv7-m/ld.S +++ b/arch/src/armv7-m/ld.S @@ -116,6 +116,18 @@ REGION_ALIAS("vstackheap", mem1); #endif SECTIONS { + /* + * Variables defined here: + * - __data_load__: Load address of .data + * - __data_start__: Start address of .data + * - __data_end__: End address of .data and .data-like orphans + * - __bss_start__: Start address of .bss + * - __bss_end__: End address of .bss and .bss-like orphans + * - __stackheap_start__: Start address of .stackheap + * - __stackheap_end__: End address of .stackheap + * - __stack: Initial stack pointer + */ + .exceptions : { KEEP(*(.exceptions)) } > vexception @@ -141,15 +153,15 @@ SECTIONS { . = ALIGN(STACK_ALIGNMENT); } > vstackheap - __stackheap_start__ = ADDR(.stackheap); - __stackheap_size__ = SIZEOF(.stackheap); - - __data_start_vma__ = ADDR(.data); - __data_start_lma__ = LOADADDR(.data); - __data_size__ = SIZEOF(.data); + __data_load__ = LOADADDR(.data); + __data_start__ = ADDR(.data); + __data_end__ = ADDR(.data) + SIZEOF(.data); __bss_start__ = ADDR(.bss); - __bss_end__ = __bss_start__ + SIZEOF(.bss); + __bss_end__ = ADDR(.bss) + SIZEOF(.bss); + + __stackheap_start__ = ADDR(.stackheap); + __stackheap_end__ = ADDR(.stackheap) + SIZEOF(.stackheap); - __stack = __stackheap_start__ + __stackheap_size__; + __stack = __stackheap_end__; } -- GitLab From 855994d748fde22a3cc4e37eff5340cacf9ac362 Mon Sep 17 00:00:00 2001 From: Chris Kay Date: Thu, 27 Sep 2018 12:08:34 +0100 Subject: [PATCH 6/8] arm: Move linker script configuration to independent header This commit moves common linker script configuration options to an independent header file that is now included from both the Arm Compiler and LD linker scripts. Change-Id: I0ad252cfbbb28cc482a9612da0dac87bb8e9f471 Signed-off-by: Chris Kay --- arch/src/armv7-m/ld.S | 79 +------------------------------------- arch/src/armv7-m/scatter.S | 75 +----------------------------------- arch/src/armv7-m/scatter.h | 76 ++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 152 deletions(-) create mode 100644 arch/src/armv7-m/scatter.h diff --git a/arch/src/armv7-m/ld.S b/arch/src/armv7-m/ld.S index 79a892964..7a36de0b9 100644 --- a/arch/src/armv7-m/ld.S +++ b/arch/src/armv7-m/ld.S @@ -6,86 +6,9 @@ * * Description: * GNU LD linker script. - * - * There are three supported memory layouts for the ARMv7-M architecture: - * - * Layout 1 - Single region: - * - All sections are placed in one contiguous region. - * - This layout uses only the mem0 memory region. - * - The memory is considered RXW by the linker, but the sections can be - * configured later on with different attributes using the MPU. - * - The main stack is placed at the end of mem0. - * - This layout is mainly used by second-stage firmware that is loaded directly - * into a single RAM. - * - * Layout 2 - Dual region with relocation: - * - One region is used for .text and .data (storage). - * - A second region is used for the remaining sections. - * - This layout uses memory regions mem0 and mem1 as the first and second - * regions, respectively. - * - The main stack is placed at the end of mem1. - * - This layout is mainly used by ROM firmware which uses part of the RAM for - * the data sections. - * - * Layout 3 - Dual region without relocation - * - One region is used only for the .text section. - * - A second region is used for all data sections. - * - This layout uses memory regions mem0 and mem1 as the first and second - * regions, respectively. - * - The main stack is placed at the end of mem1. - * - The main difference from layout 2 is that there is no relocation of the - * .data section. - * - This layout is mainly used by second-stage firmware loaded directly into - * two RAM regions. One of the RAM regions is attached to the instruction bus, - * which improves the performance as data and instruction accesses are - * independent. - * - */ - -#define FWK_MEM_MODE_INVALID 0 -#define FWK_MEM_MODE_SINGLE_REGION 1 -#define FWK_MEM_MODE_DUAL_REGION_RELOCATION 2 -#define FWK_MEM_MODE_DUAL_REGION_NO_RELOCATION 3 - -#include - -/* Align the stack on an 8-byte boundary as CCR.STKALIGN is enabled */ -#define STACK_ALIGNMENT 8 - -/* Align the heap on a 4-byte boundary to avoid unaligned accesses */ -#define HEAP_ALIGNMENT 4 - -/* - * Input validation */ -#ifndef FIRMWARE_MEM_MODE - #error "FIRMWARE_MEM_MODE has not been configured" -#endif - -#ifndef FIRMWARE_MEM0_BASE - #error "FIRMWARE_MEM0_BASE has not been configured" -#endif - -#ifndef FIRMWARE_MEM0_SIZE - #error "FIRMWARE_MEM0_SIZE has not been configured" -#endif - -#if ((FIRMWARE_MEM_MODE != FWK_MEM_MODE_SINGLE_REGION) && \ - (FIRMWARE_MEM_MODE != FWK_MEM_MODE_DUAL_REGION_RELOCATION) && \ - (FIRMWARE_MEM_MODE != FWK_MEM_MODE_DUAL_REGION_NO_RELOCATION)) - #error "FIRMWARE_MEM_MODE has been configured improperly" -#endif - -#if FIRMWARE_MEM_MODE != FWK_MEM_MODE_SINGLE_REGION - #ifndef FIRMWARE_MEM1_BASE - #error "FIRMWARE_MEM1_BASE has not been configured" - #endif - - #ifndef FIRMWARE_MEM1_SIZE - #error "FIRMWARE_MEM1_SIZE has not been configured" - #endif -#endif +#include "scatter.h" ENTRY(arm_exception_reset) diff --git a/arch/src/armv7-m/scatter.S b/arch/src/armv7-m/scatter.S index 4c03e6167..a484776d9 100644 --- a/arch/src/armv7-m/scatter.S +++ b/arch/src/armv7-m/scatter.S @@ -6,82 +6,9 @@ * * Description: * Arm Compiler 6 scatter file. - * - * There are three supported memory layouts for the ARMv7-M architecture: - * - * Layout 1 - Single region: - * - All sections are placed in one contiguous region. - * - This layout uses only the mem0 memory region. - * - The memory is considered RXW by the linker, but the sections can be - * configured later on with different attributes using the MPU. - * - The main stack is placed at the end of mem0. - * - This layout is mainly used by second-stage firmware that is loaded directly - * into a single RAM. - * - * Layout 2 - Dual region with relocation: - * - One region is used for .text and .data (storage). - * - A second region is used for the remaining sections. - * - This layout uses memory regions mem0 and mem1 as the first and second - * regions, respectively. - * - The main stack is placed at the end of mem1. - * - This layout is mainly used by ROM firmware which uses part of the RAM for - * the data sections. - * - * Layout 3 - Dual region without relocation - * - One region is used only for the .text section. - * - A second region is used for all data sections. - * - This layout uses memory regions mem0 and mem1 as the first and second - * regions, respectively. - * - The main stack is placed at the end of mem1. - * - The main difference from layout 2 is that there is no relocation of the - * .data section. - * - This layout is mainly used by second-stage firmware loaded directly into - * two RAM regions. One of the RAM regions is attached to the instruction bus, - * which improves the performance as data and instruction accesses are - * independent. - * */ -#define FWK_MEM_MODE_INVALID 0 -#define FWK_MEM_MODE_SINGLE_REGION 1 -#define FWK_MEM_MODE_DUAL_REGION_RELOCATION 2 -#define FWK_MEM_MODE_DUAL_REGION_NO_RELOCATION 3 - -#include - -/* - * Input validation - */ - -#ifndef FIRMWARE_MEM_MODE - #error "FIRMWARE_MEM_MODE has not been configured" -#endif - -#ifndef FIRMWARE_MEM0_BASE - #error "FIRMWARE_MEM0_BASE has not been configured" -#endif - -#ifndef FIRMWARE_MEM0_SIZE - #error "FIRMWARE_MEM0_SIZE has not been configured" -#endif - -#if ((FIRMWARE_MEM_MODE != FWK_MEM_MODE_SINGLE_REGION) && \ - (FIRMWARE_MEM_MODE != FWK_MEM_MODE_DUAL_REGION_RELOCATION) && \ - (FIRMWARE_MEM_MODE != FWK_MEM_MODE_DUAL_REGION_NO_RELOCATION)) - #error "FIRMWARE_MEM_MODE has been configured improperly" -#endif - -#if FIRMWARE_MEM_MODE != FWK_MEM_MODE_SINGLE_REGION - #ifndef FIRMWARE_MEM1_BASE - #error "FIRMWARE_MEM1_BASE has not been configured" - #endif - - #ifndef FIRMWARE_MEM1_SIZE - #error "FIRMWARE_MEM1_SIZE has not been configured" - #endif -#endif - -#define FIRMWARE_MEM0_LIMIT (FIRMWARE_MEM0_BASE + FIRMWARE_MEM0_SIZE) +#include "scatter.h" #if FIRMWARE_MEM_MODE == FWK_MEM_MODE_SINGLE_REGION #define FIRMWARE_MEM1_BASE +0 diff --git a/arch/src/armv7-m/scatter.h b/arch/src/armv7-m/scatter.h new file mode 100644 index 000000000..e0cdaba2a --- /dev/null +++ b/arch/src/armv7-m/scatter.h @@ -0,0 +1,76 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Common linker script configuration options. + * + * There are three supported memory layouts for the ARMv7-M architecture: + * + * Layout 1 - Single region: + * This layout uses a single read/write/execute memory region for all data. + * This is traditionally used by firmware running from a general-purpose + * RAM region. In this configuration MEM0 represents the RAM region, and + * MEM1 is unused. + * + * Layout 2 - Dual region with relocation: + * This layout uses a read/execute memory region for read-only and + * executable data, and a write memory region for writable data. This is + * traditionally used by firmware running from a ROM region. In this + * configuration MEM0 represents the ROM region and MEM1 represents the RAM + * region. + * + * Layout 3 - Dual region without relocation: + * This layout uses an execute memory region for executable data, and a + * read/write memory region for writable data. This is traditionally used + * by firmware running from a RAM region attached to the instruction bus. + * In this configuration MEM0 represents the RAM region attached to the + * instruction bus and MEM1 represents the RAM region attached to the data + * bus. + */ + +#define FWK_MEM_MODE_SINGLE_REGION 0 +#define FWK_MEM_MODE_DUAL_REGION_RELOCATION 1 +#define FWK_MEM_MODE_DUAL_REGION_NO_RELOCATION 2 + +#include + +#ifndef FIRMWARE_MEM_MODE + #error "FIRMWARE_MEM_MODE has not been configured" +#endif + +#if (FIRMWARE_MEM_MODE != FWK_MEM_MODE_SINGLE_REGION) && \ + (FIRMWARE_MEM_MODE != FWK_MEM_MODE_DUAL_REGION_RELOCATION) && \ + (FIRMWARE_MEM_MODE != FWK_MEM_MODE_DUAL_REGION_NO_RELOCATION) + #error "FIRMWARE_MEM_MODE has been configured improperly" +#endif + +#ifndef FIRMWARE_MEM0_BASE + #error "FIRMWARE_MEM0_BASE has not been configured" +#endif + +#ifndef FIRMWARE_MEM0_SIZE + #error "FIRMWARE_MEM0_SIZE has not been configured" +#endif + +#define FIRMWARE_MEM0_LIMIT (FIRMWARE_MEM0_BASE + FIRMWARE_MEM0_SIZE) + +#if FIRMWARE_MEM_MODE != FWK_MEM_MODE_SINGLE_REGION + #ifndef FIRMWARE_MEM1_BASE + #error "FIRMWARE_MEM1_BASE has not been configured" + #endif + + #ifndef FIRMWARE_MEM1_SIZE + #error "FIRMWARE_MEM1_SIZE has not been configured" + #endif + + #define FIRMWARE_MEM1_LIMIT (FIRMWARE_MEM1_BASE + FIRMWARE_MEM1_SIZE) +#endif + +/* Alignment of the heap */ +#define HEAP_ALIGNMENT 4 + +/* Alignment of the stack (CCR.STKALIGN is enabled) */ +#define STACK_ALIGNMENT 8 -- GitLab From b561d567c79a8f95c59b3c89c48ebde6174776a1 Mon Sep 17 00:00:00 2001 From: Chris Kay Date: Thu, 27 Sep 2018 11:43:36 +0100 Subject: [PATCH 7/8] arm: Place RO data in the correct RAM The use case for the dual region memory layout without .data relocation is for firmware with dual RAMs - one on the instruction bus and one on the data bus. The linker scripts currently incorrectly place read-only data in the instruction-optimized RAM when it belongs in the data- optimized RAM. Change-Id: I742ab6907327cd8399b6faf3d3a34507ae1002de Signed-off-by: Chris Kay --- arch/src/armv7-m/ld.S | 76 ++++++++++++++++++++++++++------------ arch/src/armv7-m/scatter.S | 72 ++++++++++++++++++++++++++++++------ 2 files changed, 113 insertions(+), 35 deletions(-) diff --git a/arch/src/armv7-m/ld.S b/arch/src/armv7-m/ld.S index 7a36de0b9..129a19373 100644 --- a/arch/src/armv7-m/ld.S +++ b/arch/src/armv7-m/ld.S @@ -14,28 +14,56 @@ ENTRY(arm_exception_reset) MEMORY { #if FIRMWARE_MEM_MODE == FWK_MEM_MODE_SINGLE_REGION - mem0 : ORIGIN = FIRMWARE_MEM0_BASE, LENGTH = FIRMWARE_MEM0_SIZE -#else + /* + * Single region memory layout: + * - MEM0 accepts: + * - Read-only sections + * - Read-write sections + * - Executable sections + */ + + mem0 (rwx) : ORIGIN = FIRMWARE_MEM0_BASE, LENGTH = FIRMWARE_MEM0_SIZE +#elif FIRMWARE_MEM_MODE == FWK_MEM_MODE_DUAL_REGION_RELOCATION + /* + * Dual region memory layout with initialized data relocation: + * - MEM0 accepts: + * - Read-only sections + * - Executable sections + * + * - MEM1 accepts: + * - Read-write sections + */ + mem0 (rx) : ORIGIN = FIRMWARE_MEM0_BASE, LENGTH = FIRMWARE_MEM0_SIZE - mem1 (!rx) : ORIGIN = FIRMWARE_MEM1_BASE, LENGTH = FIRMWARE_MEM1_SIZE + mem1 (w) : ORIGIN = FIRMWARE_MEM1_BASE, LENGTH = FIRMWARE_MEM1_SIZE +#elif FIRMWARE_MEM_MODE == FWK_MEM_MODE_DUAL_REGION_NO_RELOCATION + /* + * Dual region memory layout without initialized data relocation: + * - MEM0 accepts: + * - Executable sections + * + * - MEM1 accepts: + * - Read-only sections + * - Read-write sections + */ + + mem0 (x) : ORIGIN = FIRMWARE_MEM0_BASE, LENGTH = FIRMWARE_MEM0_SIZE + mem1 (rw) : ORIGIN = FIRMWARE_MEM1_BASE, LENGTH = FIRMWARE_MEM1_SIZE #endif } #if FIRMWARE_MEM_MODE == FWK_MEM_MODE_SINGLE_REGION - REGION_ALIAS("mem1", mem0); -#endif - -REGION_ALIAS("vexception", mem0); -REGION_ALIAS("vtext", mem0); -REGION_ALIAS("vrodata", mem0); -REGION_ALIAS("vdata", mem1); -REGION_ALIAS("vbss", mem1); -REGION_ALIAS("vstackheap", mem1); - -#if FIRMWARE_MEM_MODE == FWK_MEM_MODE_DUAL_REGION_NO_RELOCATION - REGION_ALIAS("ldata", mem1); /* .data is loaded into mem1 by a loader */ -#else - REGION_ALIAS("ldata", mem0); /* .data is loaded into mem1 by crt0 */ + REGION_ALIAS("r", mem0); + REGION_ALIAS("w", mem0); + REGION_ALIAS("x", mem0); +#elif FIRMWARE_MEM_MODE == FWK_MEM_MODE_DUAL_REGION_RELOCATION + REGION_ALIAS("r", mem0); + REGION_ALIAS("w", mem1); + REGION_ALIAS("x", mem0); +#elif FIRMWARE_MEM_MODE == FWK_MEM_MODE_DUAL_REGION_NO_RELOCATION + REGION_ALIAS("r", mem1); + REGION_ALIAS("w", mem1); + REGION_ALIAS("x", mem0); #endif SECTIONS { @@ -53,28 +81,28 @@ SECTIONS { .exceptions : { KEEP(*(.exceptions)) - } > vexception + } > x .text : { *(.text .text.*) - } > vtext + } > x .rodata : { *(.rodata .rodata.*) - } > vrodata + } > r .data : { *(.data .data.*) - } > vdata AT>ldata + } > w AT> r .bss : { *(.bss .bss.*) - } > vbss + } > w .stackheap ALIGN(HEAP_ALIGNMENT) : { - . = ORIGIN(vstackheap) + LENGTH(vstackheap) - (STACK_ALIGNMENT - 1); + . = ORIGIN(w) + LENGTH(w) - (STACK_ALIGNMENT - 1); . = ALIGN(STACK_ALIGNMENT); - } > vstackheap + } > w __data_load__ = LOADADDR(.data); __data_start__ = ADDR(.data); diff --git a/arch/src/armv7-m/scatter.S b/arch/src/armv7-m/scatter.S index a484776d9..0e90df2e9 100644 --- a/arch/src/armv7-m/scatter.S +++ b/arch/src/armv7-m/scatter.S @@ -11,25 +11,75 @@ #include "scatter.h" #if FIRMWARE_MEM_MODE == FWK_MEM_MODE_SINGLE_REGION - #define FIRMWARE_MEM1_BASE +0 - #define FIRMWARE_MEM1_LIMIT (FIRMWARE_MEM0_BASE + FIRMWARE_MEM0_SIZE) - #define FIRMWARE_MEM1_SIZE (FIRMWARE_MEM1_LIMIT - ImageLimit(ER_RODATA)) + /* + * Single region memory layout: + * - MEM0 accepts: + * - Read-only sections + * - Read-write sections + * - Executable sections + */ + + #define FIRMWARE_X_BASE +0 + #define FIRMWARE_R_BASE +0 + #define FIRMWARE_W_BASE +0 +#elif FIRMWARE_MEM_MODE == FWK_MEM_MODE_DUAL_REGION_RELOCATION + /* + * Dual region memory layout with initialized data relocation: + * - MEM0 accepts: + * - Read-only sections + * - Executable sections + * + * - MEM1 accepts: + * - Read-write sections + */ + + #define FIRMWARE_X_BASE +0 + #define FIRMWARE_R_BASE +0 + + #define FIRMWARE_W_BASE FIRMWARE_MEM1_BASE +#elif FIRMWARE_MEM_MODE == FWK_MEM_MODE_DUAL_REGION_NO_RELOCATION + /* + * Dual region memory layout without initialized data relocation: + * - MEM0 accepts: + * - Executable sections + * + * - MEM1 accepts: + * - Read-only sections + * - Read-write sections + */ + + #define FIRMWARE_X_BASE +0 + + #define FIRMWARE_R_BASE FIRMWARE_MEM1_BASE + #define FIRMWARE_W_BASE +0 +#endif + +#if FIRMWARE_MEM_MODE == FWK_MEM_MODE_SINGLE_REGION + #define FIRMWARE_W_LIMIT FIRMWARE_MEM0_LIMIT #else - #define FIRMWARE_MEM1_LIMIT (FIRMWARE_MEM1_BASE + FIRMWARE_MEM1_SIZE) + #define FIRMWARE_W_LIMIT FIRMWARE_MEM1_LIMIT #endif -LR_MEM0 FIRMWARE_MEM0_BASE FIRMWARE_MEM0_SIZE { - ER_EXCEPTION +0 { +LR_FIRMWARE FIRMWARE_MEM0_BASE { + ER_EXCEPTIONS FIRMWARE_X_BASE { *(.exceptions) } - ER_RODATA +0 { - *(+RO) + ER_TEXT +0 { + *(+CODE) + } + + ER_RODATA FIRMWARE_R_BASE { + *(+CONST) + } + + ER_DATA FIRMWARE_W_BASE { + *(+DATA) } - ER_RWDATA FIRMWARE_MEM1_BASE { - *(+RW, +ZI) + ER_BSS +0 { + *(+BSS) } - ARM_LIB_STACKHEAP +0 EMPTY (FIRMWARE_MEM1_LIMIT - ImageLimit(ER_RWDATA)) { } + ARM_LIB_STACKHEAP +0 EMPTY (FIRMWARE_W_LIMIT - +0) { } } -- GitLab From f072b7e4d5519c433e0ead6f23f969b3294725d6 Mon Sep 17 00:00:00 2001 From: Chris Kay Date: Thu, 27 Sep 2018 13:16:54 +0100 Subject: [PATCH 8/8] arm: Enable garbage collection of unused functions/data This patch adds flags enabling the linker to remove functions and data that are not referenced, substantially reducing the size of the final binary. Change-Id: I4b276eb27fed776de78f2dd22c9658609643cb6b Signed-off-by: Chris Kay --- arch/src/armv7-m/ld.S | 48 +++++++++++++++++++++++++++---------- arch/src/armv7-m/scatter.h | 6 ----- tools/build_system/rules.mk | 6 +++++ 3 files changed, 42 insertions(+), 18 deletions(-) diff --git a/arch/src/armv7-m/ld.S b/arch/src/armv7-m/ld.S index 129a19373..7d54f89d3 100644 --- a/arch/src/armv7-m/ld.S +++ b/arch/src/armv7-m/ld.S @@ -87,32 +87,56 @@ SECTIONS { *(.text .text.*) } > x + /* + * .init and .fini below refer to sections containing functions meant to + * run before program startup and after program shutdown. While we don't use + * these functions, Newlib refers to them unconditionally and they are, + * perhaps counterintuitively, stripped from the binary unless marked as + * KEEP. + */ + + .init : { + KEEP(*(.init)) + } > x + + .fini : { + KEEP(*(.fini)) + } > x + .rodata : { *(.rodata .rodata.*) } > r .data : { + __data_load__ = LOADADDR(.data); + __data_start__ = ABSOLUTE(.); + *(.data .data.*) } > w AT> r - .bss : { + .bss (NOLOAD) : { + __bss_start__ = ABSOLUTE(.); + *(.bss .bss.*) } > w - .stackheap ALIGN(HEAP_ALIGNMENT) : { - . = ORIGIN(w) + LENGTH(w) - (STACK_ALIGNMENT - 1); - . = ALIGN(STACK_ALIGNMENT); - } > w + .stackheap (NOLOAD) : { + __stackheap_start__ = ABSOLUTE(.); - __data_load__ = LOADADDR(.data); - __data_start__ = ADDR(.data); - __data_end__ = ADDR(.data) + SIZEOF(.data); + . = ORIGIN(w) + LENGTH(w); - __bss_start__ = ADDR(.bss); - __bss_end__ = ADDR(.bss) + SIZEOF(.bss); + __stackheap_end__ = ABSOLUTE(.); + } > w + + /* + * By default the linker places orphan sections after the section with the + * closest matching attributes. Calculating the end of a section based on + * the beginning of the next one that we know about means we can include BSS + * and DATA sections that we don't know about in these values. + */ - __stackheap_start__ = ADDR(.stackheap); - __stackheap_end__ = ADDR(.stackheap) + SIZEOF(.stackheap); + __data_end__ = __bss_start__; + __bss_end__ = __stackheap_start__; __stack = __stackheap_end__; } diff --git a/arch/src/armv7-m/scatter.h b/arch/src/armv7-m/scatter.h index e0cdaba2a..8afa8979a 100644 --- a/arch/src/armv7-m/scatter.h +++ b/arch/src/armv7-m/scatter.h @@ -68,9 +68,3 @@ #define FIRMWARE_MEM1_LIMIT (FIRMWARE_MEM1_BASE + FIRMWARE_MEM1_SIZE) #endif - -/* Alignment of the heap */ -#define HEAP_ALIGNMENT 4 - -/* Alignment of the stack (CCR.STKALIGN is enabled) */ -#define STACK_ALIGNMENT 8 diff --git a/tools/build_system/rules.mk b/tools/build_system/rules.mk index 1763bb138..6fb61d9c6 100644 --- a/tools/build_system/rules.mk +++ b/tools/build_system/rules.mk @@ -97,6 +97,12 @@ CFLAGS_GCC += -Wno-missing-field-initializers # warn about the situations that have not already been fixed. CFLAGS_CLANG += -Wno-missing-braces +# Place functions and data into their own sections. This allows the linker to +# strip out functions with no references. +CFLAGS_GCC += -ffunction-sections -fdata-sections +LDFLAGS_GCC += -Wl,--gc-sections +LDFLAGS_ARM += -Wl,--remove + # Arm Compiler 6 uses dollar symbols in its linker-defined symbol names CFLAGS_CLANG += -Wno-dollar-in-identifier-extension -- GitLab