From ab05acbf89a4774eeb7f8958f8356ff122d737ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Mon, 7 May 2018 16:54:15 +0200 Subject: [PATCH 01/27] core: Mark openocd info variables read-only --- core/sched.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/sched.c b/core/sched.c index 84151433d041..0bd9e0e31771 100644 --- a/core/sched.c +++ b/core/sched.c @@ -65,13 +65,13 @@ static uint32_t runqueue_bitcache = 0; #endif FORCE_USED_SECTION -uint8_t max_threads = sizeof(sched_threads) / sizeof(thread_t*); +const uint8_t max_threads = sizeof(sched_threads) / sizeof(thread_t*); #ifdef DEVELHELP /* OpenOCD can't determine struct offsets and additionally this member is only * available if compiled with DEVELHELP */ FORCE_USED_SECTION -uint8_t _tcb_name_offset = offsetof(thread_t, name); +const uint8_t _tcb_name_offset = offsetof(thread_t, name); #endif #ifdef MODULE_SCHEDSTATISTICS From e52500a75bc42c797e8dac4929f892d4e446a137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Sat, 11 Aug 2018 07:44:04 +0200 Subject: [PATCH 02/27] cortexm_common: Binutils 2.30 ldscript unmodified --- cpu/cortexm_common/ldscripts/cortexm_base.ld | 364 ++++++++++++------- 1 file changed, 232 insertions(+), 132 deletions(-) diff --git a/cpu/cortexm_common/ldscripts/cortexm_base.ld b/cpu/cortexm_common/ldscripts/cortexm_base.ld index c6413900cae1..b43ec5b379c1 100644 --- a/cpu/cortexm_common/ldscripts/cortexm_base.ld +++ b/cpu/cortexm_common/ldscripts/cortexm_base.ld @@ -1,33 +1,12 @@ -/* ---------------------------------------------------------------------------- - * SAM Software Package License - * ---------------------------------------------------------------------------- - * Copyright (c) 2012, Atmel Corporation - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following condition is met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the disclaimer below. - * - * Atmel's name may not be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE - * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * ---------------------------------------------------------------------------- - */ - -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +/* Copyright (C) 2014-2018 Free Software Foundation, Inc. + Copying and distribution of this script, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. */ + +/* Based on the default ldscript in GNU binutils 2.30, adjusted for ROM->RAM + * relocations */ +/* Script for -z combreloc -z now -z relro: combine and sort reloc sections */ +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") OUTPUT_ARCH(arm) SEARCH_DIR(.) @@ -37,115 +16,236 @@ ENTRY(reset_handler_default) /* Section Definitions */ SECTIONS { - .text : + /* Read-only sections, merged into text segment: */ + PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x8000)); . = SEGMENT_START("text-segment", 0x8000); + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.dyn : { - . = ALIGN(4); - _sfixed = .; - _isr_vectors = DEFINED(_isr_vectors) ? _isr_vectors : . ; - KEEP(*(SORT(.vectors*))) - *(.text .text.* .gnu.linkonce.t.*) - *(.glue_7t) *(.glue_7) - *(.rodata .rodata* .gnu.linkonce.r.*) - *(.ARM.extab* .gnu.linkonce.armextab.*) - - /* Support C constructors, and C destructors in both user code - and the C library. This also provides support for C++ code. */ - . = ALIGN(4); - KEEP(*(.init)) - . = ALIGN(4); - __preinit_array_start = .; + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro .rel.data.rel.ro.* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + PROVIDE_HIDDEN (__rel_iplt_start = .); + *(.rel.iplt) + PROVIDE_HIDDEN (__rel_iplt_end = .); + } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + PROVIDE_HIDDEN (__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN (__rela_iplt_end = .); + } + .rel.plt : + { + *(.rel.plt) + } + .rela.plt : + { + *(.rela.plt) + } + .init : + { + KEEP (*(SORT_NONE(.init))) + } + .plt : { *(.plt) } + .iplt : { *(.iplt) } + .text : + { + *(.text.unlikely .text.*_unlikely .text.unlikely.*) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx) + } + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + PROVIDE_HIDDEN (__exidx_end = .); + .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table + .gcc_except_table.*) } + .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } + /* These sections are generated by the Sun/Oracle C++ compiler. */ + .exception_ranges : ONLY_IF_RO { *(.exception_ranges + .exception_ranges*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } + .gnu_extab : ONLY_IF_RW { *(.gnu_extab) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array)) - __preinit_array_end = .; - - . = ALIGN(4); - __init_array_start = .; - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - __init_array_end = .; - - . = ALIGN(0x4); + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) KEEP (*(SORT(.ctors.*))) - KEEP (*crtend.o(.ctors)) - - . = ALIGN(4); - KEEP(*(.fini)) - - . = ALIGN(4); - __fini_array_start = .; - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - __fini_array_end = .; - + KEEP (*(.ctors)) + } + .dtors : + { KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) KEEP (*(SORT(.dtors.*))) - KEEP (*crtend.o(.dtors)) - - . = ALIGN(4); - _efixed = .; /* End of text section */ - } > rom - - /* .ARM.exidx is sorted, so has to go in its own output section. */ - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + .data : { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > rom - PROVIDE_HIDDEN (__exidx_end = .); - - /* exception handling */ - . = ALIGN(4); - .eh_frame : + __data_start = . ; + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + . = .; + __bss_start = .; + __bss_start__ = .; + .bss : { - KEEP (*(.eh_frame)) - } > rom - - . = ALIGN(4); - _etext = .; - - /* stack section */ - .stack (NOLOAD): - { - KEEP (*(.puf)) - . = ALIGN(8); - _sstack = .; - KEEP (*(.isr_stack)) - . = ALIGN(8); - _estack = .; - } > ram - - .relocate : - { - . = ALIGN(4); - _srelocate = .; - *(.ramfunc .ramfunc.*); - *(.data .data.*); - KEEP (*(.openocd .openocd.*)) - . = ALIGN(4); - _erelocate = .; - } > ram AT> rom - - /* .bss section which is used for uninitialized data */ - .bss (NOLOAD) : - { - . = ALIGN(4); - _sbss = . ; - _szero = .; - *(.bss .bss.*) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) - . = ALIGN(4); - _ebss = . ; - _ezero = .; - } > ram - - /* heap section */ - . = ALIGN(4); - _sheap = . ; - _eheap = ORIGIN(ram) + LENGTH(ram); - - /* Populate information about ram size */ - _sram = ORIGIN(ram); - _eram = ORIGIN(ram) + LENGTH(ram); + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + _bss_end__ = . ; __bss_end__ = . ; + . = ALIGN(32 / 8); + . = SEGMENT_START("ldata-segment", .); + . = ALIGN(32 / 8); + __end__ = . ; + _end = .; PROVIDE (end = .); + .stack 0x80000 : + { + _stack = .; + *(.stack) + } + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } + .debug_addr 0 : { *(.debug_addr) } + .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) } + .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } } From 5d67e563138e00ac0467b335c029c3579286e462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Mon, 7 May 2018 16:55:35 +0200 Subject: [PATCH 03/27] cortexm_common: Update ldscript to be more similar to binutils default --- cpu/cortexm_common/ldscripts/cortexm_base.ld | 129 ++++++++++++------- cpu/cortexm_common/vectors_cortexm.c | 15 +-- 2 files changed, 86 insertions(+), 58 deletions(-) diff --git a/cpu/cortexm_common/ldscripts/cortexm_base.ld b/cpu/cortexm_common/ldscripts/cortexm_base.ld index b43ec5b379c1..573b432497ce 100644 --- a/cpu/cortexm_common/ldscripts/cortexm_base.ld +++ b/cpu/cortexm_common/ldscripts/cortexm_base.ld @@ -16,8 +16,13 @@ ENTRY(reset_handler_default) /* Section Definitions */ SECTIONS { - /* Read-only sections, merged into text segment: */ - PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x8000)); . = SEGMENT_START("text-segment", 0x8000); + /* Read-only sections, merged into rom segment: */ + PROVIDE (__executable_start = SEGMENT_START("rom", 0x0)); . = SEGMENT_START("rom", 0x0); + .vectors : + { + _isr_vectors = DEFINED(_isr_vectors) ? _isr_vectors : . ; + KEEP(*(SORT(.vectors*))) + } .interp : { *(.interp) } .note.gnu.build-id : { *(.note.gnu.build-id) } .hash : { *(.hash) } @@ -96,49 +101,45 @@ SECTIONS PROVIDE (etext = .); .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } - PROVIDE_HIDDEN (__exidx_end = .); - .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } + .openocd : + { + KEEP (*(.openocd .openocd.*)) + } > rom + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + PROVIDE_HIDDEN (__exidx_end = .); + .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } - .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table - .gcc_except_table.*) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } /* These sections are generated by the Sun/Oracle C++ compiler. */ - .exception_ranges : ONLY_IF_RO { *(.exception_ranges - .exception_ranges*) } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. */ - . = ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)); - /* Exception handling */ - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } - .gnu_extab : ONLY_IF_RW { *(.gnu_extab) } - .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } - .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } - /* Thread Local Storage sections */ - .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } - .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } - .preinit_array : + .exception_ranges : ONLY_IF_RO { *(.exception_ranges .exception_ranges*) } + /* This violates § 3.2.4.1 of C++ ABI for the ARM Architecture. + * the .preinit_array, .init_array, and .fini_array sections must be writable, + * but must be treated as if they were read-only, to allow for dynamic + * loaders to remap addresses. Ignoring this rule and placing them in ROM + * saves RAM space. */ + .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); - } + } > rom .init_array : { PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) PROVIDE_HIDDEN (__init_array_end = .); - } + } > rom .fini_array : { PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) PROVIDE_HIDDEN (__fini_array_end = .); - } + } > rom .ctors : { /* gcc uses crtbegin.o to find the start of @@ -159,7 +160,7 @@ SECTIONS KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) - } + } > rom .dtors : { KEEP (*crtbegin.o(.dtors)) @@ -167,45 +168,69 @@ SECTIONS KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) - } + } > rom .jcr : { KEEP (*(.jcr)) } - .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } .dynamic : { *(.dynamic) } .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* Writable sections, must be relocated from ROM to RAM during early boot */ .data : { - __data_start = . ; + __data_start = .; *(.data .data.* .gnu.linkonce.d.*) SORT(CONSTRUCTORS) - } - .data1 : { *(.data1) } + } > ram AT> rom + __data_load_start = LOADADDR(.data); + .ramfunc : + { + __ramfunc_start = .; + *(.ramfunc .ramfunc.*) + } > ram AT> rom + __ramfunc_end = .; + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } > ram AT> rom + .gnu_extab : ONLY_IF_RW { *(.gnu_extab) } > ram AT> rom + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } > ram AT> rom + .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } > ram AT> rom + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } > ram AT> rom + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } > ram AT> rom + .data1 : { *(.data1) } > ram AT> rom + __data_end = .; _edata = .; PROVIDE (edata = .); - . = .; - __bss_start = .; - __bss_start__ = .; - .bss : + .bss (NOLOAD) : { + _szero = .; + __bss_start = .; + __bss_start__ = .; *(.dynbss) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) - /* Align here to ensure that the .bss section occupies space up to - _end. Align after .bss to ensure correct alignment even if the - .bss section disappears because there are no input sections. - FIXME: Why do we need it? When there is no .bss section, we don't - pad the .data section. */ - . = ALIGN(. != 0 ? 32 / 8 : 1); - } - _bss_end__ = . ; __bss_end__ = . ; - . = ALIGN(32 / 8); - . = SEGMENT_START("ldata-segment", .); + } > ram . = ALIGN(32 / 8); + _bss_end__ = . ; __bss_end__ = . ; + _ezero = .; __end__ = . ; _end = .; PROVIDE (end = .); - .stack 0x80000 : + .stack (NOLOAD) : { - _stack = .; - *(.stack) - } + KEEP (*(.puf)) + . = ALIGN(8); + _sstack = .; + KEEP (*(.isr_stack)) + . = ALIGN(8); + _estack = .; + } > ram + + /* heap section */ + . = ALIGN(4); + .heap (NOLOAD) : + { + _sheap = . ; + _eheap = ORIGIN(ram) + LENGTH(ram) ; + } > ram + /* Stabs debugging sections. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } @@ -248,4 +273,8 @@ SECTIONS .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) } .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) } /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } + + /* Populate information about ram size */ + _sram = ORIGIN(ram); + _eram = ORIGIN(ram) + LENGTH(ram); } diff --git a/cpu/cortexm_common/vectors_cortexm.c b/cpu/cortexm_common/vectors_cortexm.c index 25b9cf18cbc5..0d5766c24463 100644 --- a/cpu/cortexm_common/vectors_cortexm.c +++ b/cpu/cortexm_common/vectors_cortexm.c @@ -43,11 +43,10 @@ * @brief Memory markers, defined in the linker script * @{ */ -extern uint32_t _sfixed; -extern uint32_t _efixed; extern uint32_t _etext; -extern uint32_t _srelocate; -extern uint32_t _erelocate; +extern uint32_t __data_start; +extern uint32_t __data_end; +extern uint32_t __data_load_start; extern uint32_t _szero; extern uint32_t _ezero; extern uint32_t _sstack; @@ -78,7 +77,6 @@ __attribute__((weak)) void post_startup (void) void reset_handler_default(void) { uint32_t *dst; - uint32_t *src = &_etext; #ifdef MODULE_PUF_SRAM puf_sram_init((uint8_t *)&_srelocate, SEED_RAM_LEN); @@ -98,12 +96,13 @@ void reset_handler_default(void) #endif /* load data section from flash to ram */ - for (dst = &_srelocate; dst < &_erelocate; ) { + uint32_t *src = &__data_load_start; + for (dst = &__data_start; dst < &__data_end; ) { *(dst++) = *(src++); } /* default bss section to zero */ - for (dst = &_szero; dst < &_ezero; ) { - *(dst++) = 0; + for (dst = &_szero; dst < &_ezero; ++dst) { + *dst = 0; } #ifdef MODULE_MPU_STACK_GUARD From 1a4b90611871dff55e51aa9f6b711a36e0adeb8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Wed, 9 May 2018 06:35:43 +0200 Subject: [PATCH 04/27] fixup! cortexm_common: Update ldscript to be more similar to binutils default --- cpu/cortexm_common/ldscripts/cortexm_base.ld | 7 +++---- cpu/cortexm_common/vectors_cortexm.c | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/cpu/cortexm_common/ldscripts/cortexm_base.ld b/cpu/cortexm_common/ldscripts/cortexm_base.ld index 573b432497ce..c638bee1cdc0 100644 --- a/cpu/cortexm_common/ldscripts/cortexm_base.ld +++ b/cpu/cortexm_common/ldscripts/cortexm_base.ld @@ -201,16 +201,15 @@ SECTIONS _edata = .; PROVIDE (edata = .); .bss (NOLOAD) : { - _szero = .; - __bss_start = .; - __bss_start__ = .; + __bss_start = .; + __bss_start__ = .; *(.dynbss) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) } > ram . = ALIGN(32 / 8); _bss_end__ = . ; __bss_end__ = . ; - _ezero = .; + __bss_end = .; __end__ = . ; _end = .; PROVIDE (end = .); .stack (NOLOAD) : diff --git a/cpu/cortexm_common/vectors_cortexm.c b/cpu/cortexm_common/vectors_cortexm.c index 0d5766c24463..9773cdc370d3 100644 --- a/cpu/cortexm_common/vectors_cortexm.c +++ b/cpu/cortexm_common/vectors_cortexm.c @@ -47,8 +47,8 @@ extern uint32_t _etext; extern uint32_t __data_start; extern uint32_t __data_end; extern uint32_t __data_load_start; -extern uint32_t _szero; -extern uint32_t _ezero; +extern uint32_t __bss_start; +extern uint32_t __bss_end; extern uint32_t _sstack; extern uint32_t _estack; extern uint8_t _sram; @@ -101,7 +101,7 @@ void reset_handler_default(void) *(dst++) = *(src++); } /* default bss section to zero */ - for (dst = &_szero; dst < &_ezero; ++dst) { + for (dst = &__bss_start; dst < &__bss_end; ++dst) { *dst = 0; } From 39d5d19552d2abfa22893cc4fd8890090322d8dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Wed, 9 May 2018 06:51:50 +0200 Subject: [PATCH 05/27] kinetis: Adjust ldscript memory segment attributes --- cpu/kinetis/ldscripts/kinetis.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu/kinetis/ldscripts/kinetis.ld b/cpu/kinetis/ldscripts/kinetis.ld index 21f62364ea46..69afef317c45 100644 --- a/cpu/kinetis/ldscripts/kinetis.ld +++ b/cpu/kinetis/ldscripts/kinetis.ld @@ -30,7 +30,7 @@ MEMORY vectors : ORIGIN = _rom_start_addr, LENGTH = _vectors_length flashsec : ORIGIN = _rom_start_addr + _vectors_length, LENGTH = _flashsec_length rom (rx) : ORIGIN = _rom_start_addr + _vectors_length + _flashsec_length, LENGTH = _rom_length - (_vectors_length + _flashsec_length) - ram (!rx) : ORIGIN = _ram_start_addr, LENGTH = _ram_length + ram (w!rx) : ORIGIN = _ram_start_addr, LENGTH = _ram_length } SECTIONS From a7f11256ae3287fed425ef19b7cb4af4239093c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Wed, 9 May 2018 06:57:46 +0200 Subject: [PATCH 06/27] fixup! fixup! cortexm_common: Update ldscript to be more similar to binutils default --- cpu/cortexm_common/ldscripts/cortexm_base.ld | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpu/cortexm_common/ldscripts/cortexm_base.ld b/cpu/cortexm_common/ldscripts/cortexm_base.ld index c638bee1cdc0..25d687f8df63 100644 --- a/cpu/cortexm_common/ldscripts/cortexm_base.ld +++ b/cpu/cortexm_common/ldscripts/cortexm_base.ld @@ -206,7 +206,7 @@ SECTIONS *(.dynbss) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) - } > ram + } . = ALIGN(32 / 8); _bss_end__ = . ; __bss_end__ = . ; __bss_end = .; @@ -220,7 +220,7 @@ SECTIONS KEEP (*(.isr_stack)) . = ALIGN(8); _estack = .; - } > ram + } /* heap section */ . = ALIGN(4); @@ -228,7 +228,7 @@ SECTIONS { _sheap = . ; _eheap = ORIGIN(ram) + LENGTH(ram) ; - } > ram + } /* Stabs debugging sections. */ .stab 0 : { *(.stab) } From f73aead0ce4c000a9a4fec638494956876a7b686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Mon, 14 May 2018 12:46:00 +0200 Subject: [PATCH 07/27] fixup! fixup! fixup! cortexm_common: Update ldscript to be more similar to binutils default --- cpu/cortexm_common/ldscripts/cortexm_base.ld | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cpu/cortexm_common/ldscripts/cortexm_base.ld b/cpu/cortexm_common/ldscripts/cortexm_base.ld index 25d687f8df63..e94fff2ae732 100644 --- a/cpu/cortexm_common/ldscripts/cortexm_base.ld +++ b/cpu/cortexm_common/ldscripts/cortexm_base.ld @@ -173,10 +173,14 @@ SECTIONS .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } .dynamic : { *(.dynamic) } .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + /* The relocation code assumes that the addresses are aligned in both ROM and RAM, + * This alignment section ensures that the LMA is aligned (ROM address) */ + .romalign (NOLOAD) : { . = ALIGN(4); } > rom /* Writable sections, must be relocated from ROM to RAM during early boot */ .data : { + . = ALIGN(4); __data_start = .; *(.data .data.* .gnu.linkonce.d.*) SORT(CONSTRUCTORS) @@ -184,6 +188,7 @@ SECTIONS __data_load_start = LOADADDR(.data); .ramfunc : { + . = ALIGN(4); __ramfunc_start = .; *(.ramfunc .ramfunc.*) } > ram AT> rom @@ -201,6 +206,7 @@ SECTIONS _edata = .; PROVIDE (edata = .); .bss (NOLOAD) : { + . = ALIGN(4); __bss_start = .; __bss_start__ = .; *(.dynbss) From fddad1f989a54bc651c790cf2cec564c87d707b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Mon, 14 May 2018 12:57:58 +0200 Subject: [PATCH 08/27] fixup! fixup! fixup! fixup! cortexm_common: Update ldscript to be more similar to binutils default --- cpu/cortexm_common/ldscripts/cortexm_base.ld | 32 +++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/cpu/cortexm_common/ldscripts/cortexm_base.ld b/cpu/cortexm_common/ldscripts/cortexm_base.ld index e94fff2ae732..8363727e515c 100644 --- a/cpu/cortexm_common/ldscripts/cortexm_base.ld +++ b/cpu/cortexm_common/ldscripts/cortexm_base.ld @@ -22,6 +22,7 @@ SECTIONS { _isr_vectors = DEFINED(_isr_vectors) ? _isr_vectors : . ; KEEP(*(SORT(.vectors*))) + . = ALIGN(4); } .interp : { *(.interp) } .note.gnu.build-id : { *(.note.gnu.build-id) } @@ -83,6 +84,7 @@ SECTIONS .iplt : { *(.iplt) } .text : { + . = ALIGN(4); *(.text.unlikely .text.*_unlikely .text.unlikely.*) *(.text.exit .text.exit.*) *(.text.startup .text.startup.*) @@ -91,7 +93,9 @@ SECTIONS /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx) + . = ALIGN(4); } + . = ALIGN(4); .fini : { KEEP (*(SORT_NONE(.fini))) @@ -99,8 +103,20 @@ SECTIONS PROVIDE (__etext = .); PROVIDE (_etext = .); PROVIDE (etext = .); - .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } - .rodata1 : { *(.rodata1) } + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + . = ALIGN(4); + } + . = ALIGN(4); + .rodata1 : + { + . = ALIGN(4); + *(.rodata1) + . = ALIGN(4); + } + . = ALIGN(4); .openocd : { KEEP (*(.openocd .openocd.*)) @@ -122,23 +138,29 @@ SECTIONS * saves RAM space. */ .preinit_array : { + . = ALIGN(4); PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); } > rom .init_array : { + . = ALIGN(4); PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); } > rom .fini_array : { + . = ALIGN(4); PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); } > rom .ctors : { @@ -173,9 +195,6 @@ SECTIONS .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } .dynamic : { *(.dynamic) } .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } - /* The relocation code assumes that the addresses are aligned in both ROM and RAM, - * This alignment section ensures that the LMA is aligned (ROM address) */ - .romalign (NOLOAD) : { . = ALIGN(4); } > rom /* Writable sections, must be relocated from ROM to RAM during early boot */ .data : @@ -184,6 +203,7 @@ SECTIONS __data_start = .; *(.data .data.* .gnu.linkonce.d.*) SORT(CONSTRUCTORS) + . = ALIGN(4); } > ram AT> rom __data_load_start = LOADADDR(.data); .ramfunc : @@ -191,6 +211,7 @@ SECTIONS . = ALIGN(4); __ramfunc_start = .; *(.ramfunc .ramfunc.*) + . = ALIGN(4); } > ram AT> rom __ramfunc_end = .; /* Exception handling */ @@ -212,6 +233,7 @@ SECTIONS *(.dynbss) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) + . = ALIGN(4); } . = ALIGN(32 / 8); _bss_end__ = . ; __bss_end__ = . ; From 0688e88b1faaae5e16ccccfeda0992bbe4473639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Sat, 25 Aug 2018 14:49:30 +0200 Subject: [PATCH 09/27] squash fix puf_sram init on cortex-m --- cpu/cortexm_common/vectors_cortexm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu/cortexm_common/vectors_cortexm.c b/cpu/cortexm_common/vectors_cortexm.c index 9773cdc370d3..6c8c069566bd 100644 --- a/cpu/cortexm_common/vectors_cortexm.c +++ b/cpu/cortexm_common/vectors_cortexm.c @@ -79,7 +79,7 @@ void reset_handler_default(void) uint32_t *dst; #ifdef MODULE_PUF_SRAM - puf_sram_init((uint8_t *)&_srelocate, SEED_RAM_LEN); + puf_sram_init((uint8_t *)&__data_start, SEED_RAM_LEN); #endif pre_startup(); From ed277c687cd7689a652276df8fd0318603ca880b Mon Sep 17 00:00:00 2001 From: Kaspar Schleiser Date: Fri, 4 May 2018 09:41:53 +0200 Subject: [PATCH 10/27] core: Introduce cross file arrays (XFA) --- core/include/xfa.h | 101 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 core/include/xfa.h diff --git a/core/include/xfa.h b/core/include/xfa.h new file mode 100644 index 000000000000..aad6729dbe79 --- /dev/null +++ b/core/include/xfa.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2016 Kaspar Schleiser + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup core_util + * @brief Cross File Arrays + * @{ + * + * This macro, in combination with an entry in the linker scripts, allows the + * definition of constant arrays to be spread over multiple C compilation + * units. These arrays are called "cross-file arrays" or short xfa. + * + * + * + * @file + * @author Kaspar Schleiser + */ + +#ifndef XFA_H +#define XFA_H + +/** + * @brief helper macro for other XFA_* macros + * + * @internal + */ +#define _XFA(name, prio) __attribute__((used, section(".xfa." #name "." #prio))) + +/** + * @brief Define a cross-file array + * + * This macro defines the symbols necessary to use XFA_START() and XFA_END(). + * It needs to be part of one single compilation unit. + * + * @param[in] type name of the cross-file array + * @param[in] name name of the cross-file array + */ +#define XFA_INIT(type, name) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wpedantic\"") \ + const _XFA(name, 0_) type name [0] = {}; \ + const _XFA(name, 9_) type name ## _end [0] = {}; \ + _Pragma("GCC diagnostic pop") \ + extern unsigned __xfa_dummy + +/** + * @brief Declare an external cross-file array + * + * This macro defines the symbols necessary to use XFA_START() and XFA_END(). + * Think of this as XFA_INIT() but with "extern" keyword. + * It is supposed to be used in compilation units where the cross file array is + * being accessed, but not defined using XFA_INIT. + * + * @param[in] type name of the cross-file array + * @param[in] name name of the cross-file array + */ +#define XFA_USE(type, name) \ + extern const type name [0]; \ + extern const type name ## _end [0]; + +/** + * @brief Define variable in cross-file array + * + * Variables will end up sorted by prio. + * + * Add this to the type in a variable definition, e.g.: + * + * XFA(driver_params, 0) driver_params_t _onboard = { .pin=42 }; + * + * @param[in] name name of the xfa + * @param[in] prio priority within the xfa + */ +#define XFA(xfa_name, prio) _XFA(xfa_name, 5_ ##prio) + +/** + * @brief Add a pointer to cross-file array + * + * Pointers will end up sorted by prio. + * + * @param[in] xfa_name name of the xfa + * @param[in] prio priority within the xfa + * @param[in] name symbol name + * @param[in] entry pointer variable to add to xfa + */ +#define XFA_ADD_PTR(xfa_name, prio, name, entry) \ + _XFA(xfa_name, 5_ ##prio) \ + const typeof(entry) xfa_name ## _ ## prio ## _ ## name = entry + +/** + * @brief Calculate number of entries in cross-file array + * + */ +#define XFA_LEN(type, name) (((char*)name ## _end - (char*)name)/sizeof(type)) + +/** @} */ +#endif /* XFA_H */ From eb933cd171574e9a79737338378cd00f08b42e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Fri, 4 May 2018 06:11:51 +0200 Subject: [PATCH 11/27] squash XFA_CONST --- core/include/xfa.h | 70 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/core/include/xfa.h b/core/include/xfa.h index aad6729dbe79..5fe1892c3aaf 100644 --- a/core/include/xfa.h +++ b/core/include/xfa.h @@ -32,7 +32,31 @@ #define _XFA(name, prio) __attribute__((used, section(".xfa." #name "." #prio))) /** - * @brief Define a cross-file array + * @brief helper macro for other XFA_* macros + * + * @internal + */ +#define _XFA_CONST(name, prio) __attribute__((used, section(".roxfa." #name "." #prio))) + +/** + * @brief Define a read-only cross-file array + * + * This macro defines the symbols necessary to use XFA_START() and XFA_END(). + * It needs to be part of one single compilation unit. + * + * @param[in] type name of the cross-file array + * @param[in] name name of the cross-file array + */ +#define XFA_INIT_CONST(type, name) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wpedantic\"") \ + const _XFA_CONST(name, 0_) type name [0] = {}; \ + const _XFA_CONST(name, 9_) type name ## _end [0] = {}; \ + _Pragma("GCC diagnostic pop") \ + extern unsigned __xfa_dummy + +/** + * @brief Define a writable cross-file array * * This macro defines the symbols necessary to use XFA_START() and XFA_END(). * It needs to be part of one single compilation unit. @@ -43,13 +67,13 @@ #define XFA_INIT(type, name) \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wpedantic\"") \ - const _XFA(name, 0_) type name [0] = {}; \ - const _XFA(name, 9_) type name ## _end [0] = {}; \ + _XFA(name, 0_) type name [0] = {}; \ + _XFA(name, 9_) type name ## _end [0] = {}; \ _Pragma("GCC diagnostic pop") \ extern unsigned __xfa_dummy /** - * @brief Declare an external cross-file array + * @brief Declare an external read-only cross-file array * * This macro defines the symbols necessary to use XFA_START() and XFA_END(). * Think of this as XFA_INIT() but with "extern" keyword. @@ -59,12 +83,27 @@ * @param[in] type name of the cross-file array * @param[in] name name of the cross-file array */ -#define XFA_USE(type, name) \ +#define XFA_USE_CONST(type, name) \ extern const type name [0]; \ extern const type name ## _end [0]; /** - * @brief Define variable in cross-file array + * @brief Declare an external writable cross-file array + * + * This macro defines the symbols necessary to use XFA_START() and XFA_END(). + * Think of this as XFA_INIT() but with "extern" keyword. + * It is supposed to be used in compilation units where the cross file array is + * being accessed, but not defined using XFA_INIT. + * + * @param[in] type name of the cross-file array + * @param[in] name name of the cross-file array + */ +#define XFA_USE(type, name) \ + extern type name [0]; \ + extern type name ## _end [0]; + +/** + * @brief Define variable in writable cross-file array * * Variables will end up sorted by prio. * @@ -77,6 +116,20 @@ */ #define XFA(xfa_name, prio) _XFA(xfa_name, 5_ ##prio) +/** + * @brief Define variable in read-only cross-file array + * + * Variables will end up sorted by prio. + * + * Add this to the type in a variable definition, e.g.: + * + * XFA(driver_params, 0) driver_params_t _onboard = { .pin=42 }; + * + * @param[in] name name of the xfa + * @param[in] prio priority within the xfa + */ +#define XFA_CONST(xfa_name, prio) _XFA_CONST(xfa_name, 5_ ##prio) + /** * @brief Add a pointer to cross-file array * @@ -88,14 +141,13 @@ * @param[in] entry pointer variable to add to xfa */ #define XFA_ADD_PTR(xfa_name, prio, name, entry) \ - _XFA(xfa_name, 5_ ##prio) \ + _XFA_CONST(xfa_name, 5_ ##prio) \ const typeof(entry) xfa_name ## _ ## prio ## _ ## name = entry /** * @brief Calculate number of entries in cross-file array - * */ -#define XFA_LEN(type, name) (((char*)name ## _end - (char*)name)/sizeof(type)) +#define XFA_LEN(type, name) (((const char*)name ## _end - (const char*)name) / sizeof(type)) /** @} */ #endif /* XFA_H */ From 21b36b36697751200261c4d9131b0821bf5ff4cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Tue, 8 May 2018 16:11:12 +0200 Subject: [PATCH 12/27] fixup! squash XFA_CONST --- core/include/xfa.h | 10 +++++----- core/ldscripts/xfa.ld | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 core/ldscripts/xfa.ld diff --git a/core/include/xfa.h b/core/include/xfa.h index 5fe1892c3aaf..0ee9cd86d457 100644 --- a/core/include/xfa.h +++ b/core/include/xfa.h @@ -36,7 +36,7 @@ * * @internal */ -#define _XFA_CONST(name, prio) __attribute__((used, section(".roxfa." #name "." #prio))) +#define _XFA_CONST(name, prio) __attribute__((used, section(".roxfa." #name "." #prio))) const /** * @brief Define a read-only cross-file array @@ -50,10 +50,10 @@ #define XFA_INIT_CONST(type, name) \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wpedantic\"") \ - const _XFA_CONST(name, 0_) type name [0] = {}; \ - const _XFA_CONST(name, 9_) type name ## _end [0] = {}; \ + _XFA_CONST(name, 0_) const type name [0] = {}; \ + _XFA_CONST(name, 9_) const type name ## _end [0] = {}; \ _Pragma("GCC diagnostic pop") \ - extern unsigned __xfa_dummy + extern const unsigned __xfa_dummy /** * @brief Define a writable cross-file array @@ -70,7 +70,7 @@ _XFA(name, 0_) type name [0] = {}; \ _XFA(name, 9_) type name ## _end [0] = {}; \ _Pragma("GCC diagnostic pop") \ - extern unsigned __xfa_dummy + extern const unsigned __xfa_dummy /** * @brief Declare an external read-only cross-file array diff --git a/core/ldscripts/xfa.ld b/core/ldscripts/xfa.ld new file mode 100644 index 000000000000..34b7d7635fe0 --- /dev/null +++ b/core/ldscripts/xfa.ld @@ -0,0 +1,23 @@ +SECTIONS +{ + .data : + { + KEEP (*(SORT(.xfa.*))) + } + __data_start = ADDR(.data); + __data_load_start = LOADADDR(.data); + __data_end = (__data_start + SIZEOF(.data)); + __data_load_end = (__data_load_start + SIZEOF(.data)); +} + +INSERT AFTER .text; + +SECTIONS +{ + .rodata : + { + KEEP (*(SORT(.roxfa.*))) + } +} + +INSERT AFTER .text; From ecc4d74a5a8afe9c673b6c28a19ec366b3757017 Mon Sep 17 00:00:00 2001 From: Kaspar Schleiser Date: Thu, 22 Sep 2016 13:09:58 +0200 Subject: [PATCH 13/27] cpu: native: add xfa ld script --- cpu/native/Makefile.include | 2 ++ cpu/native/ldscripts/xfa.ld | 9 +++++++++ 2 files changed, 11 insertions(+) create mode 100644 cpu/native/ldscripts/xfa.ld diff --git a/cpu/native/Makefile.include b/cpu/native/Makefile.include index 76ddd9ead04c..6ef09a07af6c 100644 --- a/cpu/native/Makefile.include +++ b/cpu/native/Makefile.include @@ -8,6 +8,8 @@ endif USEMODULE += periph USEMODULE += periph_uart +LINKFLAGS += -T$(RIOTCPU)/native/ldscripts/xfa.ld + # include common peripheral initialization USEMODULE += periph_common diff --git a/cpu/native/ldscripts/xfa.ld b/cpu/native/ldscripts/xfa.ld new file mode 100644 index 000000000000..17e507b72c7f --- /dev/null +++ b/cpu/native/ldscripts/xfa.ld @@ -0,0 +1,9 @@ +SECTIONS +{ + .xfa : + { + KEEP (*(SORT(.xfa.*))) + } +} + +INSERT AFTER .init; From a029359ea5a8e2f0145298704b57263f8b39224e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Sun, 6 May 2018 07:15:55 +0200 Subject: [PATCH 14/27] squash native XFA const --- cpu/native/ldscripts/xfa.ld | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/cpu/native/ldscripts/xfa.ld b/cpu/native/ldscripts/xfa.ld index 17e507b72c7f..4e7dd99ff031 100644 --- a/cpu/native/ldscripts/xfa.ld +++ b/cpu/native/ldscripts/xfa.ld @@ -1,9 +1,19 @@ SECTIONS { - .xfa : - { - KEEP (*(SORT(.xfa.*))) - } + .xfa : + { + KEEP (*(SORT(.xfa.*))) + } } -INSERT AFTER .init; +INSERT AFTER .data; + +SECTIONS +{ + .roxfa : + { + KEEP (*(SORT(.roxfa.*))) + } +} + +INSERT AFTER .rodata; From 306f9599b420aa80918efb4c3983b0b1ce0458ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Tue, 8 May 2018 16:13:04 +0200 Subject: [PATCH 15/27] squash XFA use global ldscript for XFA --- Makefile.include | 5 +++++ cpu/native/Makefile.include | 2 -- cpu/native/ldscripts/xfa.ld | 19 ------------------- 3 files changed, 5 insertions(+), 21 deletions(-) delete mode 100644 cpu/native/ldscripts/xfa.ld diff --git a/Makefile.include b/Makefile.include index 06ca9e5b6e2f..888341469b04 100644 --- a/Makefile.include +++ b/Makefile.include @@ -233,6 +233,11 @@ export PREFIX ?= $(if $(TARGET_ARCH),$(TARGET_ARCH)-) # Add standard include directories INCLUDES += -I$(RIOTBASE)/core/include -I$(RIOTBASE)/drivers/include -I$(RIOTBASE)/sys/include +# Augmentation ldscript for cross file arrays (XFA) +# this argument must come before any other -T options on the command line, +# otherwise we get an error message ".text not found for insert" +export LINKFLAGS += -T$(RIOTBASE)/core/ldscripts/xfa.ld + # process provided features -include $(RIOTBOARD)/$(BOARD)/Makefile.features diff --git a/cpu/native/Makefile.include b/cpu/native/Makefile.include index 6ef09a07af6c..76ddd9ead04c 100644 --- a/cpu/native/Makefile.include +++ b/cpu/native/Makefile.include @@ -8,8 +8,6 @@ endif USEMODULE += periph USEMODULE += periph_uart -LINKFLAGS += -T$(RIOTCPU)/native/ldscripts/xfa.ld - # include common peripheral initialization USEMODULE += periph_common diff --git a/cpu/native/ldscripts/xfa.ld b/cpu/native/ldscripts/xfa.ld deleted file mode 100644 index 4e7dd99ff031..000000000000 --- a/cpu/native/ldscripts/xfa.ld +++ /dev/null @@ -1,19 +0,0 @@ -SECTIONS -{ - .xfa : - { - KEEP (*(SORT(.xfa.*))) - } -} - -INSERT AFTER .data; - -SECTIONS -{ - .roxfa : - { - KEEP (*(SORT(.roxfa.*))) - } -} - -INSERT AFTER .rodata; From ede64a198a53e400b9aee2ef7cd297acc7782c8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Sun, 6 May 2018 07:15:17 +0200 Subject: [PATCH 16/27] tests: Add xfa test --- tests/xfa/Makefile | 5 +++++ tests/xfa/main.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ tests/xfa/xfatest.h | 9 +++++++++ tests/xfa/xfatest1.c | 6 ++++++ tests/xfa/xfatest2.c | 6 ++++++ 5 files changed, 70 insertions(+) create mode 100644 tests/xfa/Makefile create mode 100644 tests/xfa/main.c create mode 100644 tests/xfa/xfatest.h create mode 100644 tests/xfa/xfatest1.c create mode 100644 tests/xfa/xfatest2.c diff --git a/tests/xfa/Makefile b/tests/xfa/Makefile new file mode 100644 index 000000000000..abe5a68a5500 --- /dev/null +++ b/tests/xfa/Makefile @@ -0,0 +1,5 @@ +# name of your application +APPLICATION = xfa +include ../Makefile.tests_common + +include $(RIOTBASE)/Makefile.include diff --git a/tests/xfa/main.c b/tests/xfa/main.c new file mode 100644 index 000000000000..7f98fda88177 --- /dev/null +++ b/tests/xfa/main.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015 Kaspar Schleiser + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup test + * @{ + * + * @file + * @brief cross file array (XFA) test application + * + * @author Kaspar Schleiser + * + * @} + */ + +#include +#include + +#include "xfa.h" + +#include "xfatest.h" + +XFA_INIT(xfatest_t, xfatest); + +/* hack to force inclusion of otherwise unused compilation units */ +extern int hack1; +extern int hack2; + +int main(void) +{ + unsigned n = XFA_LEN(xfatest_t, xfatest); + for (unsigned i = 0; i < n; i++) { + printf("%u %s\n", xfatest[i].val, xfatest[i].text); + } + + hack1 = hack2; + + return 0; +} diff --git a/tests/xfa/xfatest.h b/tests/xfa/xfatest.h new file mode 100644 index 000000000000..1511a80e93e3 --- /dev/null +++ b/tests/xfa/xfatest.h @@ -0,0 +1,9 @@ +#ifndef XFATEST_H +#define XFATEST_H + +typedef struct { + unsigned val; + const char *text; +} xfatest_t; + +#endif /* XFATEST_H */ diff --git a/tests/xfa/xfatest1.c b/tests/xfa/xfatest1.c new file mode 100644 index 000000000000..5c92085cf04b --- /dev/null +++ b/tests/xfa/xfatest1.c @@ -0,0 +1,6 @@ +#include "xfa.h" +#include "xfatest.h" + +XFA(xfatest, 0) xfatest_t _xfatest1 = { .val = 1, .text = "xfatest1" }; + +int hack1; diff --git a/tests/xfa/xfatest2.c b/tests/xfa/xfatest2.c new file mode 100644 index 000000000000..a7378a3457c7 --- /dev/null +++ b/tests/xfa/xfatest2.c @@ -0,0 +1,6 @@ +#include "xfa.h" +#include "xfatest.h" + +XFA(xfatest, 0) xfatest_t _xfatest2 = { .val = 2, .text = "xfatest2" }; + +int hack2; From ec15abe79ef21d4dd07d3e81db1f8512168c9b25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Tue, 8 May 2018 16:12:26 +0200 Subject: [PATCH 17/27] squash xfa add const test --- tests/xfa/main.c | 9 ++++++++- tests/xfa/xfatest1.c | 1 + tests/xfa/xfatest2.c | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/xfa/main.c b/tests/xfa/main.c index 7f98fda88177..3143bc7a0938 100644 --- a/tests/xfa/main.c +++ b/tests/xfa/main.c @@ -26,6 +26,7 @@ #include "xfatest.h" XFA_INIT(xfatest_t, xfatest); +XFA_INIT_CONST(xfatest_t, xfatest_const); /* hack to force inclusion of otherwise unused compilation units */ extern int hack1; @@ -33,9 +34,15 @@ extern int hack2; int main(void) { + puts("Cross file array test"); + unsigned n = XFA_LEN(xfatest_t, xfatest); for (unsigned i = 0; i < n; i++) { - printf("%u %s\n", xfatest[i].val, xfatest[i].text); + printf("(%u/%u): %u, \"%s\"\n", i, n, xfatest[i].val, xfatest[i].text); + } + n = XFA_LEN(xfatest_t, xfatest_const); + for (unsigned i = 0; i < n; i++) { + printf("(%u/%u): %u, \"%s\"\n", i, n, xfatest_const[i].val, xfatest_const[i].text); } hack1 = hack2; diff --git a/tests/xfa/xfatest1.c b/tests/xfa/xfatest1.c index 5c92085cf04b..5b6ec26c39a0 100644 --- a/tests/xfa/xfatest1.c +++ b/tests/xfa/xfatest1.c @@ -2,5 +2,6 @@ #include "xfatest.h" XFA(xfatest, 0) xfatest_t _xfatest1 = { .val = 1, .text = "xfatest1" }; +XFA_CONST(xfatest_const, 0) xfatest_t _xfatest_const1 = { .val = 123, .text = "xfatest_const1" }; int hack1; diff --git a/tests/xfa/xfatest2.c b/tests/xfa/xfatest2.c index a7378a3457c7..622967efce63 100644 --- a/tests/xfa/xfatest2.c +++ b/tests/xfa/xfatest2.c @@ -2,5 +2,6 @@ #include "xfatest.h" XFA(xfatest, 0) xfatest_t _xfatest2 = { .val = 2, .text = "xfatest2" }; +XFA_CONST(xfatest_const, 0) xfatest_t _xfatest_const2 = { .val = 45, .text = "xfatest_const2" }; int hack2; From b53ed6115564840aae00e36623ac0b8907c74c9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Wed, 9 May 2018 07:49:35 +0200 Subject: [PATCH 18/27] lpc2387: specify load segment instead of load address for .data --- cpu/lpc2387/ldscripts/lpc2387.ld | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpu/lpc2387/ldscripts/lpc2387.ld b/cpu/lpc2387/ldscripts/lpc2387.ld index 2edb378dd3ea..2a9b0e839d5b 100644 --- a/cpu/lpc2387/ldscripts/lpc2387.ld +++ b/cpu/lpc2387/ldscripts/lpc2387.ld @@ -184,7 +184,7 @@ SECTIONS * collect all initialized .data sections that go into RAM * initial values get placed at the end of .text in flash */ - .data : AT (_etext) + .data : { . = ALIGN(4); /* ensure data is aligned so relocation can use 4-byte operations */ _data = .; /* create a global symbol marking the start of the .data section */ @@ -209,7 +209,7 @@ SECTIONS KEEP(*(SORT(.fini_array.*))) KEEP(*(.fini_array)) PROVIDE_HIDDEN (__fini_array_end = .); - } >ram /* put all the above into RAM (but load the LMA copy into FLASH) */ + } > ram AT> flash /* put all the above into RAM (but load the LMA copy into FLASH) */ . = ALIGN(4); /* ensure data is aligned so relocation can use 4-byte operations */ _edata = .; /* define a global symbol marking the end of the .data section */ From 2339ed35cef8381fbe1aefe813569a5db36c57cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Wed, 9 May 2018 07:52:32 +0200 Subject: [PATCH 19/27] atmega_common: add arch specific XFA ldscript to properly place .roxfa --- cpu/atmega_common/Makefile.include | 1 + cpu/atmega_common/ldscripts/xfa.ld | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 cpu/atmega_common/ldscripts/xfa.ld diff --git a/cpu/atmega_common/Makefile.include b/cpu/atmega_common/Makefile.include index 717ec08ab640..3e8c1a6ca686 100644 --- a/cpu/atmega_common/Makefile.include +++ b/cpu/atmega_common/Makefile.include @@ -8,6 +8,7 @@ export CFLAGS_OPT ?= -Os export CFLAGS += $(CFLAGS_CPU) $(CFLAGS_LINK) $(CFLAGS_DBG) $(CFLAGS_OPT) export ASFLAGS += $(CFLAGS_CPU) $(CFLAGS_DBG) +LINKFLAGS += -L$(RIOTCPU)/atmega_common/ldscripts export LINKFLAGS += $(CFLAGS_CPU) $(CFLAGS_DBG) $(CFLAGS_OPT) -static -lgcc -e reset_handler -Wl,--gc-sections # export the peripheral drivers to be linked into the final binary diff --git a/cpu/atmega_common/ldscripts/xfa.ld b/cpu/atmega_common/ldscripts/xfa.ld new file mode 100644 index 000000000000..29b85699c9a9 --- /dev/null +++ b/cpu/atmega_common/ldscripts/xfa.ld @@ -0,0 +1,16 @@ +SECTIONS +{ + .data : + { + /* Special case for AVR (Harvard architecture) where .rodata is merged + * into .data by the toolchain default ldscripts. */ + KEEP (*(SORT(.roxfa.*))) + KEEP (*(SORT(.xfa.*))) + } + __data_start = ADDR(.data); + __data_load_start = LOADADDR(.data); + __data_end = (__data_start + SIZEOF(.data)); + __data_load_end = (__data_load_start + SIZEOF(.data)); +} + +INSERT AFTER .text; From fc08ca9426ed569d88ecd40148d2c8c22a29bf43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Wed, 9 May 2018 07:53:00 +0200 Subject: [PATCH 20/27] fixup! squash XFA use global ldscript for XFA --- Makefile.include | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile.include b/Makefile.include index 888341469b04..0aa8c48fb2c9 100644 --- a/Makefile.include +++ b/Makefile.include @@ -236,7 +236,7 @@ INCLUDES += -I$(RIOTBASE)/core/include -I$(RIOTBASE)/drivers/include -I$(RIOTBAS # Augmentation ldscript for cross file arrays (XFA) # this argument must come before any other -T options on the command line, # otherwise we get an error message ".text not found for insert" -export LINKFLAGS += -T$(RIOTBASE)/core/ldscripts/xfa.ld +LINKFLAGS += -Txfa.ld # process provided features -include $(RIOTBOARD)/$(BOARD)/Makefile.features @@ -257,6 +257,10 @@ TOOLCHAINS_SUPPORTED ?= gnu # Import all toolchain settings include $(RIOTMAKE)/toolchain/$(TOOLCHAIN).inc.mk +# Append ldscript path after importing CPU and board makefiles to allow +# overriding the core ldscripts +LINKFLAGS += -L$(RIOTBASE)/core/ldscripts + # Tell ccache to pass the original file to the compiler, instead of passing the # preprocessed code. Without this setting, the compilation will fail with # -Wimplicit-fallthrough warnings even when the fall through case is properly From 60c365b908df898e2c0c296aa82d834f283cc048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Wed, 9 May 2018 08:25:50 +0200 Subject: [PATCH 21/27] fixup! squash xfa add const test --- tests/xfa/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/xfa/main.c b/tests/xfa/main.c index 3143bc7a0938..d771850863d8 100644 --- a/tests/xfa/main.c +++ b/tests/xfa/main.c @@ -37,12 +37,14 @@ int main(void) puts("Cross file array test"); unsigned n = XFA_LEN(xfatest_t, xfatest); + printf("xfatest[%u]:\n", n); for (unsigned i = 0; i < n; i++) { - printf("(%u/%u): %u, \"%s\"\n", i, n, xfatest[i].val, xfatest[i].text); + printf("[%u] = %u, \"%s\"\n", i, xfatest[i].val, xfatest[i].text); } n = XFA_LEN(xfatest_t, xfatest_const); + printf("xfatest_const[%u]:\n", n); for (unsigned i = 0; i < n; i++) { - printf("(%u/%u): %u, \"%s\"\n", i, n, xfatest_const[i].val, xfatest_const[i].text); + printf("[%u] = %u, \"%s\"\n", i, xfatest_const[i].val, xfatest_const[i].text); } hack1 = hack2; From 81137b6af0cd1a7fe9dbcb015f2500ac36bf88ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Mon, 14 May 2018 22:27:10 +0200 Subject: [PATCH 22/27] unittests: Add XFA tests --- .../tests-core/tests-core-xfa-data1.c | 32 ++++ .../tests-core/tests-core-xfa-data2.c | 27 ++++ tests/unittests/tests-core/tests-core-xfa.c | 146 ++++++++++++++++++ tests/unittests/tests-core/tests-core-xfa.h | 28 ++++ tests/unittests/tests-core/tests-core.c | 1 + tests/unittests/tests-core/tests-core.h | 7 + 6 files changed, 241 insertions(+) create mode 100644 tests/unittests/tests-core/tests-core-xfa-data1.c create mode 100644 tests/unittests/tests-core/tests-core-xfa-data2.c create mode 100644 tests/unittests/tests-core/tests-core-xfa.c create mode 100644 tests/unittests/tests-core/tests-core-xfa.h diff --git a/tests/unittests/tests-core/tests-core-xfa-data1.c b/tests/unittests/tests-core/tests-core-xfa-data1.c new file mode 100644 index 000000000000..af8af9c07828 --- /dev/null +++ b/tests/unittests/tests-core/tests-core-xfa-data1.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2018 Eistec AB + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @addtogroup unittests + * @{ + * + * @file + * @brief Data elements for the core/xfa unit test + * + * @author Joakim Nohlgård + */ +#include "xfa.h" +#include "tests-core-xfa.h" + +XFA(xfatest, 0) xfatest_t _xfatest1 = { .val = 12345, .text = "xfatest1" }; +XFA_CONST(xfatest_const, 0) xfatest_t _xfatest_const1 = { .val = 0xcafe, .text = "xfatest_const1" }; + +XFA_INIT(xfatest_t, xfatest_use); +XFA_INIT_CONST(xfatest_t, xfatest_use_const); + +XFA(xfatest_use, 0) xfatest_t _xfatest_use1 = { .val = 3333, .text = "xfatest_use1" }; +XFA(xfatest_use, 0) xfatest_t _xfatest_use_again = { .val = 555, .text = "xfatest use again" }; +XFA_CONST(xfatest_use_const, 0) xfatest_t _xfatest_use_const1 = { .val = 4444, .text = "xfatest_use_const1" }; + +int hack1; +/** @} */ diff --git a/tests/unittests/tests-core/tests-core-xfa-data2.c b/tests/unittests/tests-core/tests-core-xfa-data2.c new file mode 100644 index 000000000000..1084cdb82735 --- /dev/null +++ b/tests/unittests/tests-core/tests-core-xfa-data2.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018 Eistec AB + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @addtogroup unittests + * @{ + * + * @file + * @brief Data elements for the core/xfa unit test + * + * @author Joakim Nohlgård + */ +#include "xfa.h" +#include "tests-core-xfa.h" + +XFA(xfatest, 0) xfatest_t _xfatest2 = { .val = 0xbeef, .text = "another test string" }; +XFA_CONST(xfatest_const, 0) xfatest_t _xfatest_const2 = { .val = 32444, .text = "const string xfa 2" }; +XFA(xfatest_use, 0) xfatest_t _xfatest_use2 = { .val = 11111, .text = "xfatest_use2" }; +XFA_CONST(xfatest_use_const, 0) xfatest_t _xfatest_use_const2 = { .val = 22222, .text = "xfatest_use_const2" }; + +int hack2; +/** @} */ diff --git a/tests/unittests/tests-core/tests-core-xfa.c b/tests/unittests/tests-core/tests-core-xfa.c new file mode 100644 index 000000000000..f21afd44627b --- /dev/null +++ b/tests/unittests/tests-core/tests-core-xfa.c @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2018 Eistec AB + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#include +#include "xfa.h" + +#include "embUnit.h" + +#include "tests-core.h" +#include "tests-core-xfa.h" + +extern int hack1; +extern int hack2; + +XFA_INIT(xfatest_t, xfatest); +XFA_INIT_CONST(xfatest_t, xfatest_const); +XFA_USE(xfatest_t, xfatest_use); +XFA_USE_CONST(xfatest_t, xfatest_use_const); + +/* Verifying that cross file array linking is correct by iterating over an external array */ +static void test_xfa_data(void) +{ + hack1 = hack2; + + unsigned n = XFA_LEN(xfatest_t, xfatest); + TEST_ASSERT_EQUAL_INT(2, n); + unsigned found = 0; + for (unsigned k = 0; k < n; ++k) { + /* we do not want to enforce the order of the data elements */ + switch (xfatest[k].val) { + case 12345: + /* tests-core-xfa-data1.c */ + TEST_ASSERT_EQUAL_STRING("xfatest1", xfatest[k].text); + ++found; + break; + case 0xbeef: + /* tests-core-xfa-data2.c */ + TEST_ASSERT_EQUAL_STRING("another test string", xfatest[k].text); + ++found; + break; + default: + break; + } + } + TEST_ASSERT_EQUAL_INT(n, found); +} + +static void test_xfa_const_data(void) +{ + unsigned n = XFA_LEN(xfatest_t, xfatest_const); + TEST_ASSERT_EQUAL_INT(2, n); + unsigned found = 0; + for (unsigned k = 0; k < n; ++k) { + /* we do not want to enforce the order of the data elements */ + switch (xfatest_const[k].val) { + case 0xcafe: + /* tests-core-xfa-data1.c */ + TEST_ASSERT_EQUAL_STRING("xfatest_const1", xfatest_const[k].text); + ++found; + break; + case 32444: + /* tests-core-xfa-data2.c */ + TEST_ASSERT_EQUAL_STRING("const string xfa 2", xfatest_const[k].text); + ++found; + break; + default: + break; + } + } + TEST_ASSERT_EQUAL_INT(n, found); +} + +static void test_xfa_use_data(void) +{ + unsigned n = XFA_LEN(xfatest_t, xfatest_use); + TEST_ASSERT_EQUAL_INT(3, n); + unsigned found = 0; + for (unsigned k = 0; k < n; ++k) { + /* we do not want to enforce the order of the data elements */ + switch (xfatest_use[k].val) { + case 3333: + /* tests-core-xfa-data1.c */ + TEST_ASSERT_EQUAL_STRING("xfatest_use1", xfatest_use[k].text); + ++found; + break; + case 555: + /* tests-core-xfa-data1.c */ + TEST_ASSERT_EQUAL_STRING("xfatest use again", xfatest_use[k].text); + ++found; + break; + case 11111: + /* tests-core-xfa-data2.c */ + TEST_ASSERT_EQUAL_STRING("xfatest_use2", xfatest_use[k].text); + ++found; + break; + default: + break; + } + } + TEST_ASSERT_EQUAL_INT(n, found); +} + +static void test_xfa_use_const_data(void) +{ + unsigned n = XFA_LEN(xfatest_t, xfatest_use_const); + TEST_ASSERT_EQUAL_INT(2, n); + unsigned found = 0; + for (unsigned k = 0; k < n; ++k) { + /* we do not want to enforce the order of the data elements */ + switch (xfatest_use_const[k].val) { + case 4444: + /* tests-core-xfa-data1.c */ + TEST_ASSERT_EQUAL_STRING("xfatest_use_const1", xfatest_use_const[k].text); + ++found; + break; + case 22222: + /* tests-core-xfa-data2.c */ + TEST_ASSERT_EQUAL_STRING("xfatest_use_const2", xfatest_use_const[k].text); + ++found; + break; + default: + break; + } + } + TEST_ASSERT_EQUAL_INT(n, found); +} + +Test *tests_core_xfa_tests(void) +{ + EMB_UNIT_TESTFIXTURES(fixtures) { + new_TestFixture(test_xfa_data), + new_TestFixture(test_xfa_const_data), + new_TestFixture(test_xfa_use_data), + new_TestFixture(test_xfa_use_const_data), + }; + + EMB_UNIT_TESTCALLER(core_xfa_tests, NULL, NULL, + fixtures); + + return (Test *)&core_xfa_tests; +} diff --git a/tests/unittests/tests-core/tests-core-xfa.h b/tests/unittests/tests-core/tests-core-xfa.h new file mode 100644 index 000000000000..dc7b6b4c2354 --- /dev/null +++ b/tests/unittests/tests-core/tests-core-xfa.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 Eistec AB + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @addtogroup unittests + * @{ + * + * @file + * @brief Declarations for the core/xfa unit test + * + * @author Joakim Nohlgård + */ +#ifndef TESTS_CORE_XFA_H +#define TESTS_CORE_XFA_H + +typedef struct { + unsigned val; + const char *text; +} xfatest_t; + +#endif /* TESTS_CORE_XFA_H */ + +/** @} */ diff --git a/tests/unittests/tests-core/tests-core.c b/tests/unittests/tests-core/tests-core.c index 3551286e5d6e..fe7dfe2af539 100644 --- a/tests/unittests/tests-core/tests-core.c +++ b/tests/unittests/tests-core/tests-core.c @@ -19,4 +19,5 @@ void tests_core(void) TESTS_RUN(tests_core_priority_queue_tests()); TESTS_RUN(tests_core_byteorder_tests()); TESTS_RUN(tests_core_ringbuffer_tests()); + TESTS_RUN(tests_core_xfa_tests()); } diff --git a/tests/unittests/tests-core/tests-core.h b/tests/unittests/tests-core/tests-core.h index a22a58e4d8b1..294e888fe0d4 100644 --- a/tests/unittests/tests-core/tests-core.h +++ b/tests/unittests/tests-core/tests-core.h @@ -92,6 +92,13 @@ Test *tests_core_byteorder_tests(void); */ Test *tests_core_ringbuffer_tests(void); +/** + * @brief Generates tests for xfa.h + * + * @return embUnit tests if successful, NULL if not. + */ +Test *tests_core_xfa_tests(void); + #ifdef __cplusplus } #endif From 0bfa9e6717a9aa5255cec785e64a4677501fae2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Mon, 14 May 2018 22:31:53 +0200 Subject: [PATCH 23/27] tests/xfa: Add static check of XFA linking --- tests/xfa/Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/xfa/Makefile b/tests/xfa/Makefile index abe5a68a5500..0c1a5809ae48 100644 --- a/tests/xfa/Makefile +++ b/tests/xfa/Makefile @@ -3,3 +3,12 @@ APPLICATION = xfa include ../Makefile.tests_common include $(RIOTBASE)/Makefile.include + +all: static-test +static-test: $(ELFFILE) + $(Q)TEST_STARTADDR=$$($(OBJDUMP) --syms $< | grep -E '\sxfatest_const$$' | awk '{ printf "0x%s", $$1}'); \ + TEST_ENDADDR=$$($(OBJDUMP) --syms $< | grep -E '\sxfatest_const_end$$' | awk '{ printf "0x%s", $$1}'); \ + if test ! $$((TEST_STARTADDR)) -lt $$((TEST_ENDADDR)); then \ + echo "Error: Static check of XFA linked const array failed, verify linker flags and try again" >&2; \ + exit 1; \ + fi From e209a3194c5132e18cc796ebfdf822f019ad8fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Mon, 14 May 2018 22:32:09 +0200 Subject: [PATCH 24/27] squash xfa.h Fix XFA_USE macros --- core/include/xfa.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/include/xfa.h b/core/include/xfa.h index 0ee9cd86d457..20ce349a5c9d 100644 --- a/core/include/xfa.h +++ b/core/include/xfa.h @@ -84,8 +84,8 @@ * @param[in] name name of the cross-file array */ #define XFA_USE_CONST(type, name) \ - extern const type name [0]; \ - extern const type name ## _end [0]; + extern const type name []; \ + extern const type name ## _end [] /** * @brief Declare an external writable cross-file array @@ -99,8 +99,8 @@ * @param[in] name name of the cross-file array */ #define XFA_USE(type, name) \ - extern type name [0]; \ - extern type name ## _end [0]; + extern type name []; \ + extern type name ## _end [] /** * @brief Define variable in writable cross-file array From 6d09bbd54d5153e44d9b46a058e63a28f4d70903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Mon, 14 May 2018 22:40:59 +0200 Subject: [PATCH 25/27] msp430: Add -Wno-pragmas for XFA in ancient GCC --- cpu/msp430_common/Makefile.include | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cpu/msp430_common/Makefile.include b/cpu/msp430_common/Makefile.include index ab6e0cf8c0d3..b34ce661583b 100644 --- a/cpu/msp430_common/Makefile.include +++ b/cpu/msp430_common/Makefile.include @@ -7,6 +7,9 @@ export CFLAGS += -DCPU_MODEL_$(MODEL) export UNDEF += $(BINDIR)/msp430_common/startup.o export USEMODULE += msp430_common msp430_common_periph periph_common +# Ignore unknown pragmas (for xfa with gcc 4.6.3) +CFLAGS += -Wno-pragmas + DEFAULT_MODULE += oneway_malloc # include the msp430 common Makefile From dbd06a987709c96e74dca25488b9fb5bac19a842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Mon, 14 May 2018 23:01:40 +0200 Subject: [PATCH 26/27] pic32_common: Add CPU specific xfa.ld variant --- cpu/mips_pic32_common/Makefile.include | 2 ++ cpu/mips_pic32_common/ldscripts/xfa.ld | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 cpu/mips_pic32_common/ldscripts/xfa.ld diff --git a/cpu/mips_pic32_common/Makefile.include b/cpu/mips_pic32_common/Makefile.include index e0582db5dd7e..648adce56634 100644 --- a/cpu/mips_pic32_common/Makefile.include +++ b/cpu/mips_pic32_common/Makefile.include @@ -2,6 +2,8 @@ include $(RIOTCPU)/mips32r2_common/Makefile.include export INCLUDES += -I$(RIOTCPU)/mips_pic32_common/include +LINKFLAGS += -L$(RIOTCPU)/mips_pic32_common/ldscripts + USEMODULE += mips_pic32_common USEMODULE += mips_pic32_common_periph diff --git a/cpu/mips_pic32_common/ldscripts/xfa.ld b/cpu/mips_pic32_common/ldscripts/xfa.ld new file mode 100644 index 000000000000..ef5e17a9a41b --- /dev/null +++ b/cpu/mips_pic32_common/ldscripts/xfa.ld @@ -0,0 +1,21 @@ +SECTIONS +{ + .data : + { + KEEP (*(SORT(.xfa.*))) + } + _fdata = ADDR(.data); + _edata = (_fdata + SIZEOF(.data)); +} + +INSERT BEFORE .sbss; + +SECTIONS +{ + .rodata : + { + KEEP (*(SORT(.roxfa.*))) + } +} + +INSERT AFTER .dtors; From 794b8aae7f2c8c4e9af71e89cc65671de3d3ba52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Harter?= Date: Mon, 4 Jun 2018 12:43:15 +0200 Subject: [PATCH 27/27] xfa: add a test script Enable it for CI test --- tests/xfa/Makefile | 4 ++++ tests/xfa/tests/01-run.py | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100755 tests/xfa/tests/01-run.py diff --git a/tests/xfa/Makefile b/tests/xfa/Makefile index 0c1a5809ae48..0252e6d773f1 100644 --- a/tests/xfa/Makefile +++ b/tests/xfa/Makefile @@ -2,6 +2,10 @@ APPLICATION = xfa include ../Makefile.tests_common +TEST_ON_CI_WHITELIST += all +test: + tests/01-run.py + include $(RIOTBASE)/Makefile.include all: static-test diff --git a/tests/xfa/tests/01-run.py b/tests/xfa/tests/01-run.py new file mode 100755 index 000000000000..e19b572a2c24 --- /dev/null +++ b/tests/xfa/tests/01-run.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2018 Gaëtan Harter +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. + +import os +import sys + + +def testfunc(child): + child.expect_exact('Cross file array test') + child.expect_exact('xfatest[2]:') + child.expect_exact('[0] = 1, "xfatest1"') + child.expect_exact('[1] = 2, "xfatest2"') + child.expect_exact('xfatest_const[2]:') + child.expect_exact('[0] = 123, "xfatest_const1"') + child.expect_exact('[1] = 45, "xfatest_const2"') + + +if __name__ == "__main__": + sys.path.append(os.path.join(os.environ['RIOTTOOLS'], 'testrunner')) + from testrunner import run + exit(run(testfunc))