2018-05-04 09:41:53 +02:00
|
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.de>
|
|
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
2021-01-05 10:51:24 +01:00
|
|
|
|
* @experimental This API is considered experimental and will probably change
|
|
|
|
|
* without notice!
|
|
|
|
|
*
|
2018-05-04 09:41:53 +02:00
|
|
|
|
* @file
|
|
|
|
|
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef XFA_H
|
|
|
|
|
#define XFA_H
|
|
|
|
|
|
2020-09-10 13:22:44 +02:00
|
|
|
|
/*
|
|
|
|
|
* Unfortunately, current gcc trips over accessing XFA's because of their
|
|
|
|
|
* zero-size start/end array that are used of symbol markers, with an "array
|
|
|
|
|
* index out of bounds" warning. So until a solution for that is found, we
|
|
|
|
|
* need to disable array bounds checks for files using XFAs.
|
|
|
|
|
*/
|
2020-12-08 16:10:44 +01:00
|
|
|
|
#ifndef DOXYGEN
|
2020-09-10 13:22:44 +02:00
|
|
|
|
_Pragma("GCC diagnostic ignored \"-Warray-bounds\"")
|
2020-12-08 16:10:44 +01:00
|
|
|
|
#endif
|
2020-09-10 13:22:44 +02:00
|
|
|
|
|
2018-05-04 09:41:53 +02:00
|
|
|
|
/**
|
|
|
|
|
* @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
|
|
|
|
|
*/
|
2020-12-02 12:24:33 +01:00
|
|
|
|
#define _XFA_CONST(name, \
|
|
|
|
|
prio) __attribute__((used, \
|
|
|
|
|
section(".roxfa." #name "." #prio)))
|
2018-05-04 09:41:53 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @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.
|
|
|
|
|
*
|
2020-12-01 17:02:10 +01:00
|
|
|
|
* The pragmas prevent these errors:
|
|
|
|
|
*
|
|
|
|
|
* error: ISO C forbids empty initializer braces
|
|
|
|
|
* error: ISO C forbids zero-size array ‘xfatest_const_end’
|
|
|
|
|
*
|
2018-05-04 09:41:53 +02:00
|
|
|
|
* @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\"") \
|
2020-12-01 11:14:56 +01:00
|
|
|
|
_XFA_CONST(name, 0_) const volatile type name [0] = {}; \
|
|
|
|
|
_XFA_CONST(name, 9_) const volatile type name ## _end [0] = {}; \
|
2018-05-04 09:41:53 +02:00
|
|
|
|
_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.
|
|
|
|
|
*
|
2020-12-01 17:02:10 +01:00
|
|
|
|
* The pragmas prevent these errors:
|
|
|
|
|
*
|
|
|
|
|
* error: ISO C forbids empty initializer braces
|
|
|
|
|
* error: ISO C forbids zero-size array ‘xfatest_end’
|
|
|
|
|
*
|
2018-05-04 09:41:53 +02:00
|
|
|
|
* @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 };
|
|
|
|
|
*
|
2020-12-08 16:10:44 +01:00
|
|
|
|
* @param[in] xfa_name name of the xfa
|
|
|
|
|
* @param[in] prio priority within the xfa
|
2018-05-04 09:41:53 +02:00
|
|
|
|
*/
|
2020-12-02 12:24:33 +01:00
|
|
|
|
#define XFA(xfa_name, prio) _XFA(xfa_name, 5_ ## prio)
|
2018-05-04 09:41:53 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @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 };
|
|
|
|
|
*
|
2020-12-08 16:10:44 +01:00
|
|
|
|
* @param[in] xfa_name name of the xfa
|
|
|
|
|
* @param[in] prio priority within the xfa
|
2018-05-04 09:41:53 +02:00
|
|
|
|
*/
|
2020-12-02 12:24:33 +01:00
|
|
|
|
#define XFA_CONST(xfa_name, prio) _XFA_CONST(xfa_name, 5_ ## prio)
|
2018-05-04 09:41:53 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Add a pointer to cross-file array
|
|
|
|
|
*
|
|
|
|
|
* Pointers will end up sorted by prio.
|
|
|
|
|
*
|
2021-02-23 11:45:53 +01:00
|
|
|
|
* @note This implementation uses the __typeof__() C extension.
|
|
|
|
|
* It is available both in GCC and LLVM, and both don't complain with
|
|
|
|
|
* plain "-std=c11". If deemed necessary, use of __typeof__ can be removed
|
|
|
|
|
* and the type can be added as parameter, at the cost of much less
|
|
|
|
|
* convenience.
|
|
|
|
|
*
|
2018-05-04 09:41:53 +02:00
|
|
|
|
* @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) \
|
2020-12-02 12:24:33 +01:00
|
|
|
|
_XFA_CONST(xfa_name, 5_ ## prio) \
|
2021-02-23 11:45:53 +01:00
|
|
|
|
const __typeof__(entry) xfa_name ## _ ## prio ## _ ## name = entry
|
2018-05-04 09:41:53 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Calculate number of entries in cross-file array
|
|
|
|
|
*/
|
2020-12-02 12:24:33 +01:00
|
|
|
|
#define XFA_LEN(type, \
|
|
|
|
|
name) (((const char *)name ## _end - (const char *)name) / \
|
|
|
|
|
sizeof(type))
|
2018-05-04 09:41:53 +02:00
|
|
|
|
|
2020-12-02 12:19:31 +01:00
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
extern "C" {
|
|
|
|
|
#endif
|
|
|
|
|
/* making externc happy */
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-05-04 09:41:53 +02:00
|
|
|
|
#endif /* XFA_H */
|
2020-12-08 16:10:44 +01:00
|
|
|
|
/** @} */
|