diff --git a/include/device.h b/include/device.h index 3c71f6a0c15..87599d6086d 100644 --- a/include/device.h +++ b/include/device.h @@ -699,6 +699,50 @@ static inline bool device_is_ready(const struct device *dev) Z_DEVICE_STATE_DEFINE(node_id, dev_name) \ Z_DEVICE_DEFINE_PM_SLOT(dev_name) +/* Helper macros needed for CONFIG_DEVICE_HANDLE_PADDING. These should + * be deleted when that option is removed. + * + * This is implemented "by hand" -- rather than using a helper macro + * like UTIL_LISTIFY() -- because we need to allow users to wrap + * DEVICE_DT_DEFINE with UTIL_LISTIFY, like this: + * + * #define DEFINE_FOO_DEVICE(...) DEVICE_DT_DEFINE(...) + * UTIL_LISTIFY(N, DEFINE_FOO_DEVICE) + * + * If Z_DEVICE_HANDLE_PADDING uses UTIL_LISTIFY, this type of code + * would fail, because the UTIL_LISTIFY token within the + * Z_DEVICE_DEFINE_HANDLES expansion would not be expanded again, + * since it appears in a context where UTIL_LISTIFY is already being + * expanded. Standard C does not reexpand macros appearing in their + * own expansion; this would lead to infinite recursions in general. + */ +#define Z_DEVICE_HANDLE_PADDING \ + Z_DEVICE_HANDLE_PADDING_(CONFIG_DEVICE_HANDLE_PADDING) +#define Z_DEVICE_HANDLE_PADDING_(count) \ + Z_DEVICE_HANDLE_PADDING__(count) +#define Z_DEVICE_HANDLE_PADDING__(count) \ + Z_DEVICE_HANDLE_PADDING_ ## count +#define Z_DEVICE_HANDLE_PADDING_10 \ + DEVICE_HANDLE_ENDS, Z_DEVICE_HANDLE_PADDING_9 +#define Z_DEVICE_HANDLE_PADDING_9 \ + DEVICE_HANDLE_ENDS, Z_DEVICE_HANDLE_PADDING_8 +#define Z_DEVICE_HANDLE_PADDING_8 \ + DEVICE_HANDLE_ENDS, Z_DEVICE_HANDLE_PADDING_7 +#define Z_DEVICE_HANDLE_PADDING_7 \ + DEVICE_HANDLE_ENDS, Z_DEVICE_HANDLE_PADDING_6 +#define Z_DEVICE_HANDLE_PADDING_6 \ + DEVICE_HANDLE_ENDS, Z_DEVICE_HANDLE_PADDING_5 +#define Z_DEVICE_HANDLE_PADDING_5 \ + DEVICE_HANDLE_ENDS, Z_DEVICE_HANDLE_PADDING_4 +#define Z_DEVICE_HANDLE_PADDING_4 \ + DEVICE_HANDLE_ENDS, Z_DEVICE_HANDLE_PADDING_3 +#define Z_DEVICE_HANDLE_PADDING_3 \ + DEVICE_HANDLE_ENDS, Z_DEVICE_HANDLE_PADDING_2 +#define Z_DEVICE_HANDLE_PADDING_2 \ + DEVICE_HANDLE_ENDS, Z_DEVICE_HANDLE_PADDING_1 +#define Z_DEVICE_HANDLE_PADDING_1 \ + DEVICE_HANDLE_ENDS, Z_DEVICE_HANDLE_PADDING_0 +#define Z_DEVICE_HANDLE_PADDING_0 EMPTY /* Initial build provides a record that associates the device object * with its devicetree ordinal, and provides the dependency ordinals. @@ -735,6 +779,7 @@ BUILD_ASSERT(sizeof(device_handle_t) == 2, "fix the linker scripts"); )) \ DEVICE_HANDLE_SEP, \ Z_DEVICE_EXTRA_HANDLES(__VA_ARGS__) \ + Z_DEVICE_HANDLE_PADDING \ }; #ifdef CONFIG_PM_DEVICE diff --git a/kernel/Kconfig b/kernel/Kconfig index 9bf3d6d0105..d9480ec44c9 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -303,6 +303,22 @@ config WAITQ_DUMB endchoice # WAITQ_ALGORITHM +config DEVICE_HANDLE_PADDING + int "Number of additional device handles to use for padding" + default 0 + range 0 10 + help + This is a "fudge factor" which works around build system + limitations. It is safe to ignore unless you get a specific + build system error about it. + + The option's value is the number of superfluous device handle + values which are introduced into the array pointed to by each + device's 'handles' member during the first linker pass. + + Each handle uses 2 bytes, so a value of 3 would use an extra + 6 bytes of ROM for every device. + menu "Kernel Debugging and Metrics" config INIT_STACKS diff --git a/scripts/gen_handles.py b/scripts/gen_handles.py index 1d19619d7d1..558ce82c707 100755 --- a/scripts/gen_handles.py +++ b/scripts/gen_handles.py @@ -311,9 +311,15 @@ def main(): # address. We can't allow the size of any object in the # final elf to change. We also must make sure at least one # DEVICE_HANDLE_ENDS is inserted. - assert len(hdls) < len(hs.handles), "%s no DEVICE_HANDLE_ENDS inserted" % (dev.sym.name,) - while len(hdls) < len(hs.handles): + padding = len(hs.handles) - len(hdls) + assert padding > 0, \ + (f"device {dev.sym.name}: " + "linker pass 1 left no room to insert DEVICE_HANDLE_ENDS. " + "To work around, increase CONFIG_DEVICE_HANDLE_PADDING by " + + str(1 + (-padding))) + while padding > 0: hdls.append(DEVICE_HANDLE_ENDS) + padding -= 1 assert len(hdls) == len(hs.handles), "%s handle overflow" % (dev.sym.name,) lines = [