device: support for mutable devices
Add support for mutable devices. Mutable devices are those which can be modified after declaration, in-place, in kernel mode. In order for a device to be mutable, the following must be true * `CONFIG_DEVICE_MUTABLE` must be y-selected * the Devicetree bindings for the device must include `mutable.yaml` * the Devicetree node must include the `zephyr,mutable` property Signed-off-by: Christopher Friedt <cfriedt@meta.com>
This commit is contained in:
parent
28dccf236b
commit
afc59112a9
6 changed files with 68 additions and 18 deletions
|
@ -128,3 +128,7 @@ if(CONFIG_USB_HOST_STACK)
|
||||||
zephyr_iterable_section(NAME usbh_contex GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4)
|
zephyr_iterable_section(NAME usbh_contex GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4)
|
||||||
zephyr_iterable_section(NAME usbh_class_data GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4)
|
zephyr_iterable_section(NAME usbh_class_data GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_DEVICE_MUTABLE)
|
||||||
|
zephyr_iterable_section(NAME device_mutable GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4)
|
||||||
|
endif()
|
||||||
|
|
13
dts/bindings/base/mutable.yaml
Normal file
13
dts/bindings/base/mutable.yaml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# Copyright (c) 2023, Meta
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
# Properties for Mutable devices
|
||||||
|
|
||||||
|
properties:
|
||||||
|
zephyr,mutable:
|
||||||
|
type: boolean
|
||||||
|
description: |
|
||||||
|
True iff the device structure may be mutated.
|
||||||
|
|
||||||
|
Inherit this binding for devices that are runtime-modifiable, in-place.
|
||||||
|
This places the device structure into SRAM rather than Flash.
|
|
@ -41,6 +41,10 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define Z_DEVICE_DEPS_ENDS INT16_MAX
|
#define Z_DEVICE_DEPS_ENDS INT16_MAX
|
||||||
|
|
||||||
|
/** @brief Determine if a DT node is mutable */
|
||||||
|
#define Z_DEVICE_IS_MUTABLE(node_id) \
|
||||||
|
COND_CODE_1(IS_ENABLED(CONFIG_DEVICE_MUTABLE), (DT_PROP(node_id, zephyr_mutable)), (0))
|
||||||
|
|
||||||
/** @endcond */
|
/** @endcond */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -924,12 +928,13 @@ static inline bool z_impl_device_is_ready(const struct device *dev)
|
||||||
* @param api Reference to device API.
|
* @param api Reference to device API.
|
||||||
* @param ... Optional dependencies, manually specified.
|
* @param ... Optional dependencies, manually specified.
|
||||||
*/
|
*/
|
||||||
#define Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, \
|
#define Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, prio, api, state, \
|
||||||
prio, api, state, deps) \
|
deps) \
|
||||||
COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static)) \
|
COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static)) \
|
||||||
const STRUCT_SECTION_ITERABLE_NAMED(device, \
|
COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (), (const)) \
|
||||||
Z_DEVICE_SECTION_NAME(level, prio), \
|
STRUCT_SECTION_ITERABLE_NAMED_ALTERNATE( \
|
||||||
DEVICE_NAME_GET(dev_id)) = \
|
device, COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (device_mutable), (device)), \
|
||||||
|
Z_DEVICE_SECTION_NAME(level, prio), DEVICE_NAME_GET(dev_id)) = \
|
||||||
Z_DEVICE_INIT(name, pm, data, config, api, state, deps)
|
Z_DEVICE_INIT(name, pm, data, config, api, state, deps)
|
||||||
|
|
||||||
/* deprecated device initialization levels */
|
/* deprecated device initialization levels */
|
||||||
|
@ -961,15 +966,15 @@ static inline bool z_impl_device_is_ready(const struct device *dev)
|
||||||
* @param level Initialization level.
|
* @param level Initialization level.
|
||||||
* @param prio Initialization priority.
|
* @param prio Initialization priority.
|
||||||
*/
|
*/
|
||||||
#define Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, init_fn_, level, prio) \
|
#define Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, init_fn_, level, prio) \
|
||||||
Z_DEVICE_LEVEL_CHECK_DEPRECATED_LEVEL(level) \
|
Z_DEVICE_LEVEL_CHECK_DEPRECATED_LEVEL(level) \
|
||||||
\
|
\
|
||||||
static const Z_DECL_ALIGN(struct init_entry) __used __noasan \
|
static const Z_DECL_ALIGN(struct init_entry) __used __noasan Z_INIT_ENTRY_SECTION( \
|
||||||
Z_INIT_ENTRY_SECTION(level, prio, \
|
level, prio, Z_DEVICE_INIT_SUB_PRIO(node_id)) \
|
||||||
Z_DEVICE_INIT_SUB_PRIO(node_id)) \
|
Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \
|
||||||
Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \
|
.init_fn = {COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (.dev_rw), (.dev)) = \
|
||||||
.init_fn = {.dev = (init_fn_)}, \
|
(init_fn_)}, \
|
||||||
.dev = &DEVICE_NAME_GET(dev_id), \
|
.dev = &DEVICE_NAME_GET(dev_id), \
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1015,8 +1020,9 @@ static inline bool z_impl_device_is_ready(const struct device *dev)
|
||||||
* don't have a corresponding @ref device allocated. There's no way to figure
|
* don't have a corresponding @ref device allocated. There's no way to figure
|
||||||
* that out until after we've built the zephyr image, though.
|
* that out until after we've built the zephyr image, though.
|
||||||
*/
|
*/
|
||||||
#define Z_MAYBE_DEVICE_DECLARE_INTERNAL(node_id) \
|
#define Z_MAYBE_DEVICE_DECLARE_INTERNAL(node_id) \
|
||||||
extern const struct device DEVICE_DT_NAME_GET(node_id);
|
extern COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (), \
|
||||||
|
(const)) struct device DEVICE_DT_NAME_GET(node_id);
|
||||||
|
|
||||||
DT_FOREACH_STATUS_OKAY_NODE(Z_MAYBE_DEVICE_DECLARE_INTERNAL)
|
DT_FOREACH_STATUS_OKAY_NODE(Z_MAYBE_DEVICE_DECLARE_INTERNAL)
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,17 @@ union init_function {
|
||||||
* @retval -errno If device initialization fails.
|
* @retval -errno If device initialization fails.
|
||||||
*/
|
*/
|
||||||
int (*dev)(const struct device *dev);
|
int (*dev)(const struct device *dev);
|
||||||
|
#ifdef CONFIG_DEVICE_MUTABLE
|
||||||
|
/**
|
||||||
|
* Device initialization function (rw).
|
||||||
|
*
|
||||||
|
* @param dev Device instance.
|
||||||
|
*
|
||||||
|
* @retval 0 On success
|
||||||
|
* @retval -errno If device initialization fails.
|
||||||
|
*/
|
||||||
|
int (*dev_rw)(struct device *dev);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,7 +107,12 @@ struct init_entry {
|
||||||
* If the init entry belongs to a device, this fields stores a
|
* If the init entry belongs to a device, this fields stores a
|
||||||
* reference to it, otherwise it is set to NULL.
|
* reference to it, otherwise it is set to NULL.
|
||||||
*/
|
*/
|
||||||
const struct device *dev;
|
union {
|
||||||
|
const struct device *dev;
|
||||||
|
#ifdef CONFIG_DEVICE_MUTABLE
|
||||||
|
struct device *dev_rw;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @cond INTERNAL_HIDDEN */
|
/** @cond INTERNAL_HIDDEN */
|
||||||
|
|
|
@ -137,6 +137,10 @@
|
||||||
ITERABLE_SECTION_RAM(zbus_channel_observation_mask, 1)
|
ITERABLE_SECTION_RAM(zbus_channel_observation_mask, 1)
|
||||||
#endif /* CONFIG_ZBUS */
|
#endif /* CONFIG_ZBUS */
|
||||||
|
|
||||||
|
#if defined(CONFIG_DEVICE_MUTABLE)
|
||||||
|
ITERABLE_SECTION_RAM(device_mutable, 4)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_USERSPACE
|
#ifdef CONFIG_USERSPACE
|
||||||
_static_kernel_objects_end = .;
|
_static_kernel_objects_end = .;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1274,6 +1274,13 @@ config DEVICE_DEPS_DYNAMIC
|
||||||
Option that makes it possible to manipulate device dependencies at
|
Option that makes it possible to manipulate device dependencies at
|
||||||
runtime.
|
runtime.
|
||||||
|
|
||||||
|
config DEVICE_MUTABLE
|
||||||
|
bool "Mutable devices [EXPERIMENTAL]"
|
||||||
|
select EXPERIMENTAL
|
||||||
|
help
|
||||||
|
Support mutable devices. Mutable devices are instantiated in SRAM
|
||||||
|
instead of Flash and are runtime modifiable in kernel mode.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
rsource "Kconfig.vm"
|
rsource "Kconfig.vm"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue