From 66092f5506207e4ac4cb31bc2d337ca3540e2920 Mon Sep 17 00:00:00 2001 From: Kaspar Schleiser Date: Fri, 4 May 2018 09:41:53 +0200 Subject: [PATCH] core: Introduce cross file arrays (XFA) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Joakim NohlgÄrd --- Makefile.include | 9 +++ core/include/xfa.h | 153 ++++++++++++++++++++++++++++++++++++++++++ core/ldscripts/xfa.ld | 23 +++++++ 3 files changed, 185 insertions(+) create mode 100644 core/include/xfa.h create mode 100644 core/ldscripts/xfa.ld diff --git a/Makefile.include b/Makefile.include index f29184448e..6875e21797 100644 --- a/Makefile.include +++ b/Makefile.include @@ -357,6 +357,11 @@ endif # 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" +LINKFLAGS += -Txfa.ld + # process provided features include $(RIOTBASE)/Makefile.features @@ -416,6 +421,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 diff --git a/core/include/xfa.h b/core/include/xfa.h new file mode 100644 index 0000000000..20ce349a5c --- /dev/null +++ b/core/include/xfa.h @@ -0,0 +1,153 @@ +/* + * 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 helper macro for other XFA_* macros + * + * @internal + */ +#define _XFA_CONST(name, prio) __attribute__((used, section(".roxfa." #name "." #prio))) const + +/** + * @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\"") \ + _XFA_CONST(name, 0_) const type name [0] = {}; \ + _XFA_CONST(name, 9_) const type name ## _end [0] = {}; \ + _Pragma("GCC diagnostic pop") \ + extern const 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. + * + * @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\"") \ + _XFA(name, 0_) type name [0] = {}; \ + _XFA(name, 9_) type name ## _end [0] = {}; \ + _Pragma("GCC diagnostic pop") \ + extern const unsigned __xfa_dummy + +/** + * @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. + * 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_CONST(type, name) \ + extern const type name []; \ + extern const type name ## _end [] + +/** + * @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 []; \ + extern type name ## _end [] + +/** + * @brief Define variable in writable 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 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 + * + * 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_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) (((const char*)name ## _end - (const char*)name) / sizeof(type)) + +/** @} */ +#endif /* XFA_H */ diff --git a/core/ldscripts/xfa.ld b/core/ldscripts/xfa.ld new file mode 100644 index 0000000000..34b7d7635f --- /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;