Merge pull request #15002 from kaspar030/pr/xfa_v3
core: introduce crossfile arrays (xfa) v3
This commit is contained in:
commit
15124e4769
@ -416,6 +416,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
|
||||
|
||||
@ -59,6 +59,9 @@ else
|
||||
LINKFLAGS += -ldl
|
||||
endif
|
||||
|
||||
# XFA (cross file array) support
|
||||
LINKFLAGS += -T$(RIOTBASE)/cpu/native/ldscripts/xfa.ld
|
||||
|
||||
# clean up unused functions
|
||||
CFLAGS += -ffunction-sections -fdata-sections
|
||||
ifeq ($(OS),Darwin)
|
||||
|
||||
186
core/include/xfa.h
Normal file
186
core/include/xfa.h
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* @experimental This API is considered experimental and will probably change
|
||||
* without notice!
|
||||
*
|
||||
* @file
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*/
|
||||
|
||||
#ifndef XFA_H
|
||||
#define XFA_H
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef DOXYGEN
|
||||
_Pragma("GCC diagnostic ignored \"-Warray-bounds\"")
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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)))
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
* The pragmas prevent these errors:
|
||||
*
|
||||
* error: ISO C forbids empty initializer braces
|
||||
* error: ISO C forbids zero-size array ‘xfatest_const_end’
|
||||
*
|
||||
* @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 volatile type name [0] = {}; \
|
||||
_XFA_CONST(name, 9_) const volatile 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.
|
||||
*
|
||||
* The pragmas prevent these errors:
|
||||
*
|
||||
* error: ISO C forbids empty initializer braces
|
||||
* error: ISO C forbids zero-size array ‘xfatest_end’
|
||||
*
|
||||
* @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] xfa_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] xfa_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))
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* making externc happy */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* XFA_H */
|
||||
/** @} */
|
||||
16
cpu/atmega_common/ldscripts/xfa.ld
Normal file
16
cpu/atmega_common/ldscripts/xfa.ld
Normal file
@ -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;
|
||||
@ -55,6 +55,7 @@ SECTIONS
|
||||
*(.text .text.* .gnu.linkonce.t.*)
|
||||
*(.glue_7t) *(.glue_7)
|
||||
*(.rodata .rodata* .gnu.linkonce.r.*)
|
||||
KEEP (*(SORT(.roxfa.*)))
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
|
||||
/* Support C constructors, and C destructors in both user code
|
||||
@ -167,6 +168,7 @@ SECTIONS
|
||||
_srelocate = .;
|
||||
*(.ramfunc .ramfunc.*);
|
||||
*(.data .data.*);
|
||||
KEEP (*(SORT(.xfa.*)))
|
||||
KEEP (*(.openocd .openocd.*))
|
||||
. = ALIGN(4);
|
||||
_erelocate = .;
|
||||
|
||||
@ -158,6 +158,7 @@ SECTIONS
|
||||
_data_start = ABSOLUTE(.);
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
KEEP (*(SORT(.xfa.*)))
|
||||
*(.gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
@ -243,6 +244,7 @@ SECTIONS
|
||||
_rodata_start = ABSOLUTE(.);
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
KEEP (*(SORT(.roxfa.*)))
|
||||
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
|
||||
@ -61,9 +61,10 @@ endif
|
||||
|
||||
ARCHIVES += -lgcc -lwpa -lcore -lnet80211 -lphy -lpp -lstdc++
|
||||
|
||||
LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/esp8266.rom.ld
|
||||
LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/esp8266.riot-os.ld
|
||||
LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/esp8266.peripherals.ld
|
||||
LINKFLAGS += -L$(RIOTCPU)/$(CPU)/ld
|
||||
LINKFLAGS += -Tesp8266.rom.ld
|
||||
LINKFLAGS += -Tesp8266.riot-os.ld
|
||||
LINKFLAGS += -Tesp8266.peripherals.ld
|
||||
|
||||
LINKFLAGS += -Wl,-wrap=pp_attach
|
||||
LINKFLAGS += -Wl,-wrap=pm_attach
|
||||
|
||||
@ -105,6 +105,7 @@ SECTIONS
|
||||
*(.sdata2.*)
|
||||
*(.gnu.linkonce.s2.*)
|
||||
*(.jcr)
|
||||
KEEP (*(SORT(.xfa.*)))
|
||||
_data_end = ABSOLUTE(.);
|
||||
} >dram0_0_seg :dram0_0_phdr
|
||||
|
||||
@ -139,6 +140,7 @@ SECTIONS
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
KEEP (*(SORT(.roxfa.*)))
|
||||
/* C++ exception handlers table: */
|
||||
__XT_EXCEPTION_DESCS__ = ABSOLUTE(.);
|
||||
*(.xt_except_desc)
|
||||
|
||||
@ -65,6 +65,7 @@ SECTIONS
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*crtend.o(.dtors))
|
||||
KEEP (*(SORT(.roxfa.*)))
|
||||
|
||||
. = ALIGN(4);
|
||||
_efixed = .; /* End of text section */
|
||||
@ -163,6 +164,7 @@ SECTIONS
|
||||
*(.ramfunc .ramfunc.*);
|
||||
*(.data .data.*);
|
||||
KEEP (*(.openocd .openocd.*))
|
||||
KEEP (*(SORT(.xfa.*)))
|
||||
. = ALIGN(4);
|
||||
_erelocate = .;
|
||||
} > ram AT> rom
|
||||
|
||||
@ -6,7 +6,6 @@ include $(RIOTCPU)/mips32r2_common/Makefile.include
|
||||
CFLAGS += -D_SYS__PTHREADTYPES_H_
|
||||
|
||||
CFLAGS += -DCPU_FAM_$(call uppercase_and_underscore,$(CPU_FAM))
|
||||
|
||||
LINKFLAGS += -L$(RIOTCPU)/mips_pic32_common/ldscripts
|
||||
INCLUDES += -I$(RIOTCPU)/mips_pic32_common/include
|
||||
|
||||
DIRS += $(RIOTCPU)/$(CPU)/$(CPU_MODEL)
|
||||
|
||||
21
cpu/mips_pic32_common/ldscripts/xfa.ld
Normal file
21
cpu/mips_pic32_common/ldscripts/xfa.ld
Normal file
@ -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;
|
||||
24
cpu/msp430_common/ldscripts/xfa.ld
Normal file
24
cpu/msp430_common/ldscripts/xfa.ld
Normal file
@ -0,0 +1,24 @@
|
||||
SECTIONS
|
||||
{
|
||||
.rodata :
|
||||
{
|
||||
KEEP (*(SORT(.roxfa.*)))
|
||||
} > ROM
|
||||
}
|
||||
|
||||
INSERT AFTER .rodata;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.data :
|
||||
{
|
||||
KEEP (*(SORT(.xfa.*)))
|
||||
} > RAM AT> ROM
|
||||
|
||||
. = ALIGN(2);
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
PROVIDE (__dataend = .);
|
||||
}
|
||||
|
||||
INSERT AFTER .data;
|
||||
19
cpu/native/ldscripts/xfa.ld
Normal file
19
cpu/native/ldscripts/xfa.ld
Normal file
@ -0,0 +1,19 @@
|
||||
SECTIONS
|
||||
{
|
||||
.data :
|
||||
{
|
||||
KEEP (*(SORT(.xfa.*)))
|
||||
}
|
||||
}
|
||||
|
||||
INSERT AFTER .text;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.rodata :
|
||||
{
|
||||
KEEP (*(SORT(.roxfa.*)))
|
||||
}
|
||||
}
|
||||
|
||||
INSERT AFTER .text;
|
||||
@ -61,6 +61,7 @@ SECTIONS
|
||||
*(.rdata)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
KEEP (*(SORT(.roxfa.*)))
|
||||
} >flash AT>flash :flash
|
||||
|
||||
. = ALIGN(4);
|
||||
@ -182,6 +183,7 @@ SECTIONS
|
||||
*(.srodata.cst4)
|
||||
*(.srodata.cst2)
|
||||
*(.srodata .srodata.*)
|
||||
KEEP (*(SORT(.xfa.*)))
|
||||
} >ram AT>flash :ram_init
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
@ -9,8 +9,11 @@ CFLAGS_OPT ?= -Os
|
||||
|
||||
CFLAGS += $(CFLAGS_CPU) $(CFLAGS_LINK) $(CFLAGS_DBG) $(CFLAGS_OPT)
|
||||
ASFLAGS += $(CFLAGS_CPU) $(CFLAGS_DBG)
|
||||
|
||||
# needed for xfa support. Order is important.
|
||||
LINKFLAGS += -T$(RIOTCPU)/atmega_common/ldscripts/xfa.ld
|
||||
|
||||
LINKFLAGS += $(CFLAGS_CPU) $(CFLAGS_DBG) $(CFLAGS_OPT) -static -lgcc -e reset_handler -Wl,--gc-sections
|
||||
OFLAGS += -j .text -j .data
|
||||
|
||||
# Use ROM_LEN and RAM_LEN during link
|
||||
$(if $(ROM_LEN),,$(error ROM_LEN is not defined))
|
||||
|
||||
@ -64,6 +64,9 @@ LINKFLAGS += -L$(RIOTCPU)/$(CPU)/ldscripts
|
||||
LINKFLAGS += $(CFLAGS_CPU) $(CFLAGS_DBG) $(CFLAGS_OPT)
|
||||
LINKFLAGS += -Wl,--gc-sections
|
||||
|
||||
# XFA support
|
||||
LINKFLAGS += -T$(RIOTCPU)/mips_pic32_common/ldscripts/xfa.ld
|
||||
|
||||
OPTIONAL_CFLAGS_BLACKLIST += -Wformat-overflow
|
||||
OPTIONAL_CFLAGS_BLACKLIST += -Wformat-truncation
|
||||
OPTIONAL_CFLAGS_BLACKLIST += -gz
|
||||
|
||||
@ -15,6 +15,8 @@ ASFLAGS += $(CFLAGS_CPU) --defsym $(CPU_MODEL)=1 $(CFLAGS_DBG)
|
||||
|
||||
LINKFLAGS += $(CFLAGS_CPU) $(CFLAGS_DBG) $(CFLAGS_OPT)
|
||||
LINKFLAGS += -Wl,--gc-sections -Wl,-L$(MSP430_SUPPORT_FILES)/include
|
||||
LINKFLAGS += -T $(MSP430_SUPPORT_FILES)/include/$(CPU_MODEL).ld
|
||||
LINKFLAGS += $(RIOTCPU)/msp430_common/ldscripts/xfa.ld
|
||||
|
||||
OPTIONAL_CFLAGS_BLACKLIST += -fdiagnostics-color
|
||||
OPTIONAL_CFLAGS_BLACKLIST += -Wformat-overflow
|
||||
|
||||
32
tests/unittests/tests-core/tests-core-xfa-data1.c
Normal file
32
tests/unittests/tests-core/tests-core-xfa-data1.c
Normal file
@ -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 <joakim.nohlgard@eistec.se>
|
||||
*/
|
||||
#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;
|
||||
/** @} */
|
||||
26
tests/unittests/tests-core/tests-core-xfa-data2.c
Normal file
26
tests/unittests/tests-core/tests-core-xfa-data2.c
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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 <joakim.nohlgard@eistec.se>
|
||||
*/
|
||||
#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" };
|
||||
|
||||
/** @} */
|
||||
144
tests/unittests/tests-core/tests-core-xfa.c
Normal file
144
tests/unittests/tests-core/tests-core-xfa.c
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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 <stdint.h>
|
||||
#include "bitarithm.h"
|
||||
#include "xfa.h"
|
||||
|
||||
#include "embUnit.h"
|
||||
|
||||
#include "tests-core.h"
|
||||
#include "tests-core-xfa.h"
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
TEST_ASSERT(!(found & BIT0));
|
||||
found |= BIT0;
|
||||
break;
|
||||
case 0xbeef:
|
||||
/* tests-core-xfa-data2.c */
|
||||
TEST_ASSERT_EQUAL_STRING("another test string", xfatest[k].text);
|
||||
TEST_ASSERT(!(found & BIT1));
|
||||
found |= BIT1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
TEST_ASSERT_EQUAL_INT((1U << n) - 1, 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;
|
||||
}
|
||||
36
tests/unittests/tests-core/tests-core-xfa.h
Normal file
36
tests/unittests/tests-core/tests-core-xfa.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 <joakim.nohlgard@eistec.se>
|
||||
*/
|
||||
#ifndef TESTS_CORE_XFA_H
|
||||
#define TESTS_CORE_XFA_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned val;
|
||||
const char *text;
|
||||
} xfatest_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TESTS_CORE_XFA_H */
|
||||
|
||||
/** @} */
|
||||
@ -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());
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
12
tests/xfa/Makefile
Normal file
12
tests/xfa/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
|
||||
all: static-test
|
||||
static-test: $(ELFFILE)
|
||||
$(Q)TEST_STARTADDR=$$($(OBJDUMP) -t $< | grep -E '\sxfatest_const$$' | awk '{ printf "0x%s", $$1}'); \
|
||||
TEST_ENDADDR=$$($(OBJDUMP) -t $< | 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
|
||||
47
tests/xfa/main.c
Normal file
47
tests/xfa/main.c
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 test
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief cross file array (XFA) test application
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "xfa.h"
|
||||
|
||||
#include "xfatest.h"
|
||||
|
||||
XFA_INIT(xfatest_t, xfatest);
|
||||
XFA_INIT_CONST(xfatest_t, xfatest_const);
|
||||
|
||||
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, \"%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, \"%s\"\n", i, xfatest_const[i].val, xfatest_const[i].text);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
26
tests/xfa/tests/01-run.py
Executable file
26
tests/xfa/tests/01-run.py
Executable file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2021 Freie Universität Berlin
|
||||
# 2021 Inria
|
||||
# 2021 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.
|
||||
|
||||
import sys
|
||||
from testrunner import run
|
||||
|
||||
|
||||
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.exit(run(testfunc))
|
||||
29
tests/xfa/xfatest.h
Normal file
29
tests/xfa/xfatest.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef XFATEST_H
|
||||
#define XFATEST_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef DOXYGEN /* just a test header, please ignore */
|
||||
|
||||
typedef struct {
|
||||
unsigned val;
|
||||
const char *text;
|
||||
} xfatest_t;
|
||||
|
||||
#endif /* DOXYGEN */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* XFATEST_H */
|
||||
5
tests/xfa/xfatest1.c
Normal file
5
tests/xfa/xfatest1.c
Normal file
@ -0,0 +1,5 @@
|
||||
#include "xfa.h"
|
||||
#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" };
|
||||
5
tests/xfa/xfatest2.c
Normal file
5
tests/xfa/xfatest2.c
Normal file
@ -0,0 +1,5 @@
|
||||
#include "xfa.h"
|
||||
#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" };
|
||||
Loading…
x
Reference in New Issue
Block a user