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_class_data GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4)
|
||||
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
|
||||
|
||||
/** @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 */
|
||||
|
||||
/**
|
||||
|
@ -924,12 +928,13 @@ static inline bool z_impl_device_is_ready(const struct device *dev)
|
|||
* @param api Reference to device API.
|
||||
* @param ... Optional dependencies, manually specified.
|
||||
*/
|
||||
#define Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, \
|
||||
prio, api, state, deps) \
|
||||
#define Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, prio, api, state, \
|
||||
deps) \
|
||||
COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static)) \
|
||||
const STRUCT_SECTION_ITERABLE_NAMED(device, \
|
||||
Z_DEVICE_SECTION_NAME(level, prio), \
|
||||
DEVICE_NAME_GET(dev_id)) = \
|
||||
COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (), (const)) \
|
||||
STRUCT_SECTION_ITERABLE_NAMED_ALTERNATE( \
|
||||
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)
|
||||
|
||||
/* deprecated device initialization levels */
|
||||
|
@ -964,11 +969,11 @@ static inline bool z_impl_device_is_ready(const struct device *dev)
|
|||
#define Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, init_fn_, level, prio) \
|
||||
Z_DEVICE_LEVEL_CHECK_DEPRECATED_LEVEL(level) \
|
||||
\
|
||||
static const Z_DECL_ALIGN(struct init_entry) __used __noasan \
|
||||
Z_INIT_ENTRY_SECTION(level, prio, \
|
||||
Z_DEVICE_INIT_SUB_PRIO(node_id)) \
|
||||
static const Z_DECL_ALIGN(struct init_entry) __used __noasan Z_INIT_ENTRY_SECTION( \
|
||||
level, prio, Z_DEVICE_INIT_SUB_PRIO(node_id)) \
|
||||
Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \
|
||||
.init_fn = {.dev = (init_fn_)}, \
|
||||
.init_fn = {COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (.dev_rw), (.dev)) = \
|
||||
(init_fn_)}, \
|
||||
.dev = &DEVICE_NAME_GET(dev_id), \
|
||||
}
|
||||
|
||||
|
@ -1016,7 +1021,8 @@ static inline bool z_impl_device_is_ready(const struct device *dev)
|
|||
* that out until after we've built the zephyr image, though.
|
||||
*/
|
||||
#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)
|
||||
|
||||
|
|
|
@ -73,6 +73,17 @@ union init_function {
|
|||
* @retval -errno If device initialization fails.
|
||||
*/
|
||||
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
|
||||
* reference to it, otherwise it is set to NULL.
|
||||
*/
|
||||
union {
|
||||
const struct device *dev;
|
||||
#ifdef CONFIG_DEVICE_MUTABLE
|
||||
struct device *dev_rw;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
/** @cond INTERNAL_HIDDEN */
|
||||
|
|
|
@ -137,6 +137,10 @@
|
|||
ITERABLE_SECTION_RAM(zbus_channel_observation_mask, 1)
|
||||
#endif /* CONFIG_ZBUS */
|
||||
|
||||
#if defined(CONFIG_DEVICE_MUTABLE)
|
||||
ITERABLE_SECTION_RAM(device_mutable, 4)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
_static_kernel_objects_end = .;
|
||||
#endif
|
||||
|
|
|
@ -1274,6 +1274,13 @@ config DEVICE_DEPS_DYNAMIC
|
|||
Option that makes it possible to manipulate device dependencies at
|
||||
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
|
||||
|
||||
rsource "Kconfig.vm"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue