device: make device dependencies optional
Device dependencies are not always required, so make them optional via CONFIG_DEVICE_DEPS. When enabled, the gen_device_deps script will run so that dependencies are collected and part of the final image. Related APIs will be also made available. Since device dependencies are used in just a few places (power domains), disable the feature by default. When not enabled, a second linking pass will not be required. Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
This commit is contained in:
parent
b6d5d246b7
commit
48b201cc53
|
@ -54,7 +54,7 @@ set(CMAKE_EXECUTABLE_SUFFIX .elf)
|
||||||
# into the `zephyr_final` target.
|
# into the `zephyr_final` target.
|
||||||
#
|
#
|
||||||
# Multiple linking stages are required in the following cases:
|
# Multiple linking stages are required in the following cases:
|
||||||
# - device handles structs must be generated (CONFIG_HAS_DTS=y)
|
# - device dependencies structs must be generated (CONFIG_DEVICE_DEPS=y)
|
||||||
# - ISR tables must be generated (CONFIG_GEN_ISR_TABLES=y)
|
# - ISR tables must be generated (CONFIG_GEN_ISR_TABLES=y)
|
||||||
# - Kernel objects hash tables (CONFIG_USERSPACE=y)
|
# - Kernel objects hash tables (CONFIG_USERSPACE=y)
|
||||||
# - Application memory partitions (CONFIG_USERSPACE=y)
|
# - Application memory partitions (CONFIG_USERSPACE=y)
|
||||||
|
@ -75,7 +75,7 @@ set(ZEPHYR_LINK_STAGE_EXECUTABLE zephyr_pre${ZEPHYR_CURRENT_LINKER_PASS})
|
||||||
# existing variable to allow slowly cleanup of linking stage handling.
|
# existing variable to allow slowly cleanup of linking stage handling.
|
||||||
# Three stage linking active: pre0 -> pre1 -> final, this will correspond to `pre1`
|
# Three stage linking active: pre0 -> pre1 -> final, this will correspond to `pre1`
|
||||||
# Two stage linking active: pre0 -> final, this will correspond to `pre0`
|
# Two stage linking active: pre0 -> final, this will correspond to `pre0`
|
||||||
if(CONFIG_USERSPACE OR CONFIG_HAS_DTS)
|
if(CONFIG_USERSPACE OR CONFIG_DEVICE_DEPS)
|
||||||
set(ZEPHYR_PREBUILT_EXECUTABLE zephyr_pre1)
|
set(ZEPHYR_PREBUILT_EXECUTABLE zephyr_pre1)
|
||||||
else()
|
else()
|
||||||
set(ZEPHYR_PREBUILT_EXECUTABLE zephyr_pre0)
|
set(ZEPHYR_PREBUILT_EXECUTABLE zephyr_pre0)
|
||||||
|
@ -912,7 +912,7 @@ zephyr_get_include_directories_for_lang(C
|
||||||
STRIP_PREFIX # Don't use a -I prefix
|
STRIP_PREFIX # Don't use a -I prefix
|
||||||
)
|
)
|
||||||
|
|
||||||
if(CONFIG_HAS_DTS)
|
if(CONFIG_DEVICE_DEPS)
|
||||||
if(CONFIG_DEVICE_DEPS_DYNAMIC)
|
if(CONFIG_DEVICE_DEPS_DYNAMIC)
|
||||||
set(dynamic_deps --dynamic-deps)
|
set(dynamic_deps --dynamic-deps)
|
||||||
endif()
|
endif()
|
||||||
|
@ -1177,7 +1177,7 @@ if(CONFIG_USERSPACE)
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_USERSPACE OR CONFIG_HAS_DTS)
|
if(CONFIG_USERSPACE OR CONFIG_DEVICE_DEPS)
|
||||||
configure_linker_script(
|
configure_linker_script(
|
||||||
${ZEPHYR_CURRENT_LINKER_CMD}
|
${ZEPHYR_CURRENT_LINKER_CMD}
|
||||||
"${LINKER_PASS_${ZEPHYR_CURRENT_LINKER_PASS}_DEFINE}"
|
"${LINKER_PASS_${ZEPHYR_CURRENT_LINKER_PASS}_DEFINE}"
|
||||||
|
|
|
@ -185,9 +185,11 @@ zephyr_iterable_section(NAME tracing_backend KVMA RAM_REGION GROUP RODATA_REGION
|
||||||
zephyr_linker_section(NAME zephyr_dbg_info KVMA RAM_REGION GROUP RODATA_REGION NOINPUT ${XIP_ALIGN_WITH_INPUT})
|
zephyr_linker_section(NAME zephyr_dbg_info KVMA RAM_REGION GROUP RODATA_REGION NOINPUT ${XIP_ALIGN_WITH_INPUT})
|
||||||
zephyr_linker_section_configure(SECTION zephyr_dbg_info INPUT ".zephyr_dbg_info" KEEP)
|
zephyr_linker_section_configure(SECTION zephyr_dbg_info INPUT ".zephyr_dbg_info" KEEP)
|
||||||
|
|
||||||
zephyr_linker_section(NAME device_deps KVMA RAM_REGION GROUP RODATA_REGION NOINPUT ${XIP_ALIGN_WITH_INPUT} ENDALIGN 16)
|
if (CONFIG_DEVICE_DEPS)
|
||||||
zephyr_linker_section_configure(SECTION device_deps INPUT .__device_deps_pass1* KEEP SORT NAME PASS LINKER_DEVICE_DEPS_PASS1)
|
zephyr_linker_section(NAME device_deps KVMA RAM_REGION GROUP RODATA_REGION NOINPUT ${XIP_ALIGN_WITH_INPUT} ENDALIGN 16)
|
||||||
zephyr_linker_section_configure(SECTION device_deps INPUT .__device_deps_pass2* KEEP SORT NAME PASS NOT LINKER_DEVICE_DEPS_PASS1)
|
zephyr_linker_section_configure(SECTION device_deps INPUT .__device_deps_pass1* KEEP SORT NAME PASS LINKER_DEVICE_DEPS_PASS1)
|
||||||
|
zephyr_linker_section_configure(SECTION device_deps INPUT .__device_deps_pass2* KEEP SORT NAME PASS NOT LINKER_DEVICE_DEPS_PASS1)
|
||||||
|
endif()
|
||||||
|
|
||||||
zephyr_iterable_section(NAME _static_thread_data KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4)
|
zephyr_iterable_section(NAME _static_thread_data KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4)
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,13 @@ config POWER_DOMAIN_GPIO
|
||||||
depends on DT_HAS_POWER_DOMAIN_GPIO_ENABLED
|
depends on DT_HAS_POWER_DOMAIN_GPIO_ENABLED
|
||||||
depends on GPIO
|
depends on GPIO
|
||||||
depends on TIMEOUT_64BIT
|
depends on TIMEOUT_64BIT
|
||||||
|
select DEVICE_DEPS
|
||||||
|
|
||||||
config POWER_DOMAIN_INTEL_ADSP
|
config POWER_DOMAIN_INTEL_ADSP
|
||||||
bool "Use Intel ADSP power gating mechanisms"
|
bool "Use Intel ADSP power gating mechanisms"
|
||||||
default y
|
default y
|
||||||
depends on DT_HAS_INTEL_ADSP_POWER_DOMAIN_ENABLED
|
depends on DT_HAS_INTEL_ADSP_POWER_DOMAIN_ENABLED
|
||||||
|
select DEVICE_DEPS
|
||||||
help
|
help
|
||||||
Include Intel ADSP power domain control mechanisms
|
Include Intel ADSP power domain control mechanisms
|
||||||
|
|
||||||
|
|
|
@ -388,15 +388,17 @@ struct device {
|
||||||
struct device_state *state;
|
struct device_state *state;
|
||||||
/** Address of the device instance private data */
|
/** Address of the device instance private data */
|
||||||
void *data;
|
void *data;
|
||||||
|
#if defined(CONFIG_DEVICE_DEPS) || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
* Optional pointer to dependencies associated with the device.
|
* Optional pointer to dependencies associated with the device.
|
||||||
*
|
*
|
||||||
* This encodes a sequence of sets of device handles that have some
|
* This encodes a sequence of sets of device handles that have some
|
||||||
* relationship to this node. The individual sets are extracted with
|
* relationship to this node. The individual sets are extracted with
|
||||||
* dedicated API, such as device_required_handles_get().
|
* dedicated API, such as device_required_handles_get(). Only available
|
||||||
|
* if @kconfig{CONFIG_DEVICE_DEPS} is enabled.
|
||||||
*/
|
*/
|
||||||
Z_DEVICE_DEPS_CONST device_handle_t *deps;
|
Z_DEVICE_DEPS_CONST device_handle_t *deps;
|
||||||
|
#endif /* CONFIG_DEVICE_DEPS */
|
||||||
#if defined(CONFIG_PM_DEVICE) || defined(__DOXYGEN__)
|
#if defined(CONFIG_PM_DEVICE) || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
* Reference to the device PM resources (only available if
|
* Reference to the device PM resources (only available if
|
||||||
|
@ -453,6 +455,8 @@ device_from_handle(device_handle_t dev_handle)
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_DEVICE_DEPS) || defined(__DOXYGEN__)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Prototype for functions used when iterating over a set of devices.
|
* @brief Prototype for functions used when iterating over a set of devices.
|
||||||
*
|
*
|
||||||
|
@ -668,6 +672,8 @@ int device_supported_foreach(const struct device *dev,
|
||||||
device_visitor_callback_t visitor_cb,
|
device_visitor_callback_t visitor_cb,
|
||||||
void *context);
|
void *context);
|
||||||
|
|
||||||
|
#endif /* CONFIG_DEVICE_DEPS */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get a @ref device reference from its @ref device.name field.
|
* @brief Get a @ref device reference from its @ref device.name field.
|
||||||
*
|
*
|
||||||
|
@ -760,6 +766,8 @@ static inline bool z_impl_device_is_ready(const struct device *dev)
|
||||||
static Z_DECL_ALIGN(struct device_state) Z_DEVICE_STATE_NAME(dev_id) \
|
static Z_DECL_ALIGN(struct device_state) Z_DEVICE_STATE_NAME(dev_id) \
|
||||||
__attribute__((__section__(".z_devstate")))
|
__attribute__((__section__(".z_devstate")))
|
||||||
|
|
||||||
|
#if defined(CONFIG_DEVICE_DEPS) || defined(__DOXYGEN__)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Synthesize the name of the object that holds device ordinal and
|
* @brief Synthesize the name of the object that holds device ordinal and
|
||||||
* dependency data.
|
* dependency data.
|
||||||
|
@ -838,6 +846,8 @@ static inline bool z_impl_device_is_ready(const struct device *dev)
|
||||||
(DT_SUPPORTS_DEP_ORDS(node_id)), ()) /**/ \
|
(DT_SUPPORTS_DEP_ORDS(node_id)), ()) /**/ \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_DEVICE_DEPS */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Maximum device name length.
|
* @brief Maximum device name length.
|
||||||
*
|
*
|
||||||
|
@ -873,7 +883,7 @@ static inline bool z_impl_device_is_ready(const struct device *dev)
|
||||||
.api = (api_), \
|
.api = (api_), \
|
||||||
.state = (state_), \
|
.state = (state_), \
|
||||||
.data = (data_), \
|
.data = (data_), \
|
||||||
.deps = (deps_), \
|
IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \
|
||||||
IF_ENABLED(CONFIG_PM_DEVICE, (.pm = (pm_),)) /**/ \
|
IF_ENABLED(CONFIG_PM_DEVICE, (.pm = (pm_),)) /**/ \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -951,7 +961,8 @@ static inline bool z_impl_device_is_ready(const struct device *dev)
|
||||||
level, prio, api, state, ...) \
|
level, prio, api, state, ...) \
|
||||||
Z_DEVICE_NAME_CHECK(name); \
|
Z_DEVICE_NAME_CHECK(name); \
|
||||||
\
|
\
|
||||||
Z_DEVICE_DEPS_DEFINE(node_id, dev_id, __VA_ARGS__); \
|
IF_ENABLED(CONFIG_DEVICE_DEPS, \
|
||||||
|
(Z_DEVICE_DEPS_DEFINE(node_id, dev_id, __VA_ARGS__);)) \
|
||||||
\
|
\
|
||||||
Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, \
|
Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, \
|
||||||
prio, api, state, Z_DEVICE_DEPS_NAME(dev_id)); \
|
prio, api, state, Z_DEVICE_DEPS_NAME(dev_id)); \
|
||||||
|
|
|
@ -969,8 +969,17 @@ endmenu
|
||||||
|
|
||||||
menu "Device Options"
|
menu "Device Options"
|
||||||
|
|
||||||
|
config DEVICE_DEPS
|
||||||
|
bool "Store device dependencies"
|
||||||
|
help
|
||||||
|
When enabled, device dependencies will be stored so that they can be
|
||||||
|
queried at runtime. Device dependencies are typically inferred from
|
||||||
|
devicetree. Enabling this option will increase ROM usage (or RAM if
|
||||||
|
dynamic device dependencies are enabled).
|
||||||
|
|
||||||
config DEVICE_DEPS_DYNAMIC
|
config DEVICE_DEPS_DYNAMIC
|
||||||
bool "Dynamic device dependencies"
|
bool "Dynamic device dependencies"
|
||||||
|
depends on DEVICE_DEPS
|
||||||
help
|
help
|
||||||
Option that makes it possible to manipulate device dependencies at
|
Option that makes it possible to manipulate device dependencies at
|
||||||
runtime.
|
runtime.
|
||||||
|
|
|
@ -100,6 +100,8 @@ bool z_device_is_ready(const struct device *dev)
|
||||||
return dev->state->initialized && (dev->state->init_res == 0U);
|
return dev->state->initialized && (dev->state->init_res == 0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEVICE_DEPS
|
||||||
|
|
||||||
static int device_visitor(const device_handle_t *handles,
|
static int device_visitor(const device_handle_t *handles,
|
||||||
size_t handle_count,
|
size_t handle_count,
|
||||||
device_visitor_callback_t visitor_cb,
|
device_visitor_callback_t visitor_cb,
|
||||||
|
@ -138,3 +140,5 @@ int device_supported_foreach(const struct device *dev,
|
||||||
|
|
||||||
return device_visitor(handles, handle_count, visitor_cb, context);
|
return device_visitor(handles, handle_count, visitor_cb, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_DEVICE_DEPS */
|
||||||
|
|
|
@ -73,8 +73,10 @@ GEN_OFFSET_SYM(_thread_t, tls);
|
||||||
GEN_ABSOLUTE_SYM(__z_interrupt_stack_SIZEOF, sizeof(z_interrupt_stacks[0]));
|
GEN_ABSOLUTE_SYM(__z_interrupt_stack_SIZEOF, sizeof(z_interrupt_stacks[0]));
|
||||||
|
|
||||||
/* member offsets in the device structure. Used in image post-processing */
|
/* member offsets in the device structure. Used in image post-processing */
|
||||||
|
#ifdef CONFIG_DEVICE_DEPS
|
||||||
GEN_ABSOLUTE_SYM(_DEVICE_STRUCT_HANDLES_OFFSET,
|
GEN_ABSOLUTE_SYM(_DEVICE_STRUCT_HANDLES_OFFSET,
|
||||||
offsetof(struct device, deps));
|
offsetof(struct device, deps));
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PM_DEVICE
|
#ifdef CONFIG_PM_DEVICE
|
||||||
GEN_ABSOLUTE_SYM(_DEVICE_STRUCT_PM_OFFSET,
|
GEN_ABSOLUTE_SYM(_DEVICE_STRUCT_PM_OFFSET,
|
||||||
|
|
|
@ -174,6 +174,7 @@ int pm_device_power_domain_add(const struct device *dev,
|
||||||
return power_domain_add_or_remove(dev, domain, true);
|
return power_domain_add_or_remove(dev, domain, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEVICE_DEPS
|
||||||
struct pm_visitor_context {
|
struct pm_visitor_context {
|
||||||
pm_device_action_failed_cb_t failure_cb;
|
pm_device_action_failed_cb_t failure_cb;
|
||||||
enum pm_device_action action;
|
enum pm_device_action action;
|
||||||
|
@ -205,6 +206,7 @@ void pm_device_children_action_run(const struct device *dev,
|
||||||
|
|
||||||
(void)device_supported_foreach(dev, pm_device_children_visitor, &visitor_context);
|
(void)device_supported_foreach(dev, pm_device_children_visitor, &visitor_context);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int pm_device_state_get(const struct device *dev,
|
int pm_device_state_get(const struct device *dev,
|
||||||
enum pm_device_state *state)
|
enum pm_device_state *state)
|
||||||
|
|
|
@ -27,6 +27,8 @@ static const char *get_device_name(const struct device *dev,
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEVICE_DEPS
|
||||||
struct cmd_device_list_visitor_context {
|
struct cmd_device_list_visitor_context {
|
||||||
const struct shell *sh;
|
const struct shell *sh;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
@ -43,6 +45,7 @@ static int cmd_device_list_visitor(const struct device *dev,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_DEVICE_DEPS */
|
||||||
|
|
||||||
static int cmd_device_list(const struct shell *sh,
|
static int cmd_device_list(const struct shell *sh,
|
||||||
size_t argc, char **argv)
|
size_t argc, char **argv)
|
||||||
|
@ -77,6 +80,7 @@ static int cmd_device_list(const struct shell *sh,
|
||||||
}
|
}
|
||||||
|
|
||||||
shell_fprintf(sh, SHELL_NORMAL, " (%s)\n", state);
|
shell_fprintf(sh, SHELL_NORMAL, " (%s)\n", state);
|
||||||
|
#ifdef CONFIG_DEVICE_DEPS
|
||||||
if (!k_is_user_context()) {
|
if (!k_is_user_context()) {
|
||||||
struct cmd_device_list_visitor_context ctx = {
|
struct cmd_device_list_visitor_context ctx = {
|
||||||
.sh = sh,
|
.sh = sh,
|
||||||
|
@ -86,6 +90,7 @@ static int cmd_device_list(const struct shell *sh,
|
||||||
|
|
||||||
(void)device_required_foreach(dev, cmd_device_list_visitor, &ctx);
|
(void)device_required_foreach(dev, cmd_device_list_visitor, &ctx);
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_DEVICE_DEPS */
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
CONFIG_ZTEST=y
|
CONFIG_ZTEST=y
|
||||||
CONFIG_I2C=n
|
CONFIG_I2C=n
|
||||||
CONFIG_ZTEST_NEW_API=y
|
CONFIG_ZTEST_NEW_API=y
|
||||||
|
CONFIG_DEVICE_DEPS=y
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
CONFIG_ZTEST=y
|
CONFIG_ZTEST=y
|
||||||
|
CONFIG_DEVICE_DEPS=y
|
||||||
CONFIG_DEVICE_DEPS_DYNAMIC=y
|
CONFIG_DEVICE_DEPS_DYNAMIC=y
|
||||||
CONFIG_PM=y
|
CONFIG_PM=y
|
||||||
CONFIG_PM_DEVICE=y
|
CONFIG_PM_DEVICE=y
|
||||||
|
|
Loading…
Reference in a new issue