Skip to content

Commit 21a4bfe

Browse files
committed
device: Add new macros to instanciate device objects
In order to get rid of the manually inserted initialization priority, device object generation need new macros. Until now, 2 set of macros have co-existed because of legacy support. Indeed, devices used to be created fully manually before devicetree introduction. Once devicetree appeared, DT based macros were added. Now is the time to get rid of such difference, and have a unique macro for creating device objects. So instead of DEVICE_DEFINE() and DEVICE_DT_DEFINE() there will be DEVICE_INSTANCE(). Instead of DEVICE_DT_INST_DEFINE() there will be DEVICE_INSTANCE_FROM_DT_INST(). Instead of DEVICE_GET() and DEVICE_DT_GET(), there will be DEVICE_INSTANCE_GET(). Same for DEVICE_INIT_DT_GET() and DEVICE_INIT_GET(), there will be DEVICE_INIT_ENTRY_GET() In the future step of deprecating old macros, these are then identified: - DEVICE_DEFINE - DEVICE_DT_DEFINE - DEVICE_GET - DEVICE_DT_GET - DEVICE_INIT_DT_GET - DEVICE_INIT_GET - DEVICE_NAME_GET() could be replaced by DEVICE_INSTANCE_NAME()) - DEVICE_DT_NAME_GET() could be replaced by DEVICE_INSTANCE_NAME()) - DEVICE_DECLARE() could be replaced as well And probably some more, thus reducing the amount of macros which would help to clean-up the header and have a more concise set. The difference is now that priority parameter is removed, as well as the name parameter (originaly from DEVICE_DEFINE legacy macro). In this case it is just simpler to reuse the "unique token" dev_id. Because of the dependency being fully computed _prior_ to building zephyr, these new macros do not support CONFIG_DEVICE_DEPS anymore. This feature was never really used anywhere and is a legacy thing. So new macros do not accept variable arguments. Signed-off-by: Tomasz Bursztyka <[email protected]>
1 parent 573c457 commit 21a4bfe

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

include/zephyr/device.h

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,24 @@ typedef int16_t device_handle_t;
145145
config, level, prio, api, \
146146
&Z_DEVICE_STATE_NAME(dev_id))
147147

148+
/**
149+
* @brief Return the device id whether it's a devicetree based device or not
150+
*
151+
* @param ident Either a devicetree node identifier or a plain unique token
152+
*/
153+
#define Z_DEVICE_ID(ident) \
154+
COND_CODE_1(DT_NODE_EXISTS(ident), \
155+
(Z_DEVICE_DT_DEV_ID(ident)), (ident))
156+
157+
/**
158+
* @brief Return the device name whether it's a devicetree based device or not
159+
*
160+
* @param ident Either a devicetree node identifier or a plain unique token
161+
*/
162+
#define Z_DEVICE_NAME(ident) \
163+
COND_CODE_1(DT_NODE_EXISTS(ident), \
164+
(DEVICE_DT_NAME(ident)), (STRINGIFY(ident)))
165+
148166
/**
149167
* @brief Return a string name for a devicetree node.
150168
*
@@ -210,6 +228,64 @@ typedef int16_t device_handle_t;
210228
__VA_ARGS__) \
211229
IF_ENABLED(CONFIG_LLEXT_EXPORT_DEVICES, (Z_DEVICE_EXPORT(node_id);))
212230

231+
/**
232+
* @brief Create a device object and set it up for boot time initialization.
233+
*
234+
* @note This macro supports both devicetree based device as well as
235+
* non-devicetree based device (legacy support).
236+
*
237+
* This macro defines a @ref device that is automatically configured by the
238+
* kernel during system initialization. If the given identifier is a plain
239+
* unique token, it will be used in the name of the global device structure
240+
* as a C identifier as well as its @ref device.name.
241+
* If the given identifier is a devicetree node itentifier, the global device
242+
* object's name as a C will be derived from the node's dependency ordinal
243+
* (DT based) and @ref device.name will be set to `DEVICE_DT_NAME(node_id)`.
244+
*
245+
* The device is declared with extern visibility, so a pointer to a global
246+
* device object can be obtained either with `DEVICE_DT_GET(node_id)` in case
247+
* the device is devicetree based, or with `DEVICE_GET(dev_id)` for
248+
* non-devicetree legacy devices. And this from any source file that includes
249+
* `<zephyr/device.h>`. Before using the pointer, the referenced object should
250+
* be checked using device_is_ready().
251+
*
252+
* @param ident Either a devicetree node identifier or a plain unique token
253+
* @param init_fn Pointer to the device's initialization function, which will be
254+
* run by the kernel during system initialization. Can be `NULL`.
255+
* @param pm Pointer to the device's power management resources, a
256+
* @ref pm_device, which will be stored in @ref device.pm. Use `NULL` if the
257+
* device does not use PM.
258+
* @param data Pointer to the device's private mutable data, which will be
259+
* stored in @ref device.data.
260+
* @param config Pointer to the device's private constant data, which will be
261+
* stored in @ref device.config field.
262+
* @param level The device's initialization level (PRE_KERNEL_1, PRE_KERNEL_2 or
263+
* POST_KERNEL).
264+
* @param api Pointer to the device's API structure. Can be `NULL`.
265+
*/
266+
#define DEVICE_INSTANCE(ident, init_fn, pm, data, config, level, api) \
267+
Z_DEVICE_STATE_DEFINE(Z_DEVICE_ID(ident)); \
268+
Z_DEVICE_DEFINE(ident, Z_DEVICE_ID(ident), \
269+
Z_DEVICE_NAME(ident), init_fn, pm, data, config, \
270+
ZINIT_GET_LEVEL(Z_DEVICE_ID(ident), level), \
271+
ZINIT_GET_PRIORITY(ident, Z_DEVICE_ID(ident)), \
272+
api, &Z_DEVICE_STATE_NAME(Z_DEVICE_ID(ident)))
273+
274+
/**
275+
* @brief Like DEVICE_INSTANCE(), but with an extra parameter in order to
276+
* provide an externaly defined device state object.
277+
*
278+
* First parameters are as expected by DEVICE_INSTANCE().
279+
* @param state A pointer on the externally defined device state object
280+
*/
281+
#define DEVICE_INSTANCE_EXTERNAL_STATE(ident, init_fn, pm, data, \
282+
config, level, api, state) \
283+
Z_DEVICE_DEFINE(ident, Z_DEVICE_ID(ident), \
284+
Z_DEVICE_NAME(ident), init_fn, pm, data, config, \
285+
ZINIT_GET_LEVEL(Z_DEVICE_ID(ident), level), \
286+
ZINIT_GET_PRIORITY(ident, Z_DEVICE_ID(ident)), \
287+
api, state)
288+
213289
/**
214290
* @brief Like DEVICE_DT_DEFINE(), but uses an instance of a `DT_DRV_COMPAT`
215291
* compatible instead of a node identifier.
@@ -221,6 +297,17 @@ typedef int16_t device_handle_t;
221297
#define DEVICE_DT_INST_DEFINE(inst, ...) \
222298
DEVICE_DT_DEFINE(DT_DRV_INST(inst), __VA_ARGS__)
223299

300+
/**
301+
* @brief Like DEVICE_INSTANCE, but uses an instance of a `DT_DRV_COMPAT`
302+
* compatible instead of a node identifier.
303+
304+
* @param inst Instance number. The `ident` argument to DEVICE_INSTANCE() is
305+
* set to `DT_DRV_INST(inst)`.
306+
* @param ... Other parameters as expected by DEVICE_INSTANCE().
307+
*/
308+
#define DEVICE_INSTANCE_FROM_DT_INST(inst, init_fn, pm, data, config, level, api) \
309+
DEVICE_INSTANCE(DT_DRV_INST(inst), init_fn, pm, data, config, level, api)
310+
224311
/**
225312
* @brief The name of the global device object for @p node_id
226313
*
@@ -333,6 +420,15 @@ typedef int16_t device_handle_t;
333420
*/
334421
#define DEVICE_GET(dev_id) (&DEVICE_NAME_GET(dev_id))
335422

423+
/**
424+
* @brief Obtain a pointer to a device object
425+
*
426+
* @param ident Either a devicetree node identifier or a plain unique token
427+
*/
428+
#define DEVICE_INSTANCE_GET(ident) \
429+
COND_CODE_1(DT_NODE_EXISTS(ident), \
430+
(&DEVICE_DT_NAME_GET(ident)), (&DEVICE_NAME_GET(ident)))
431+
336432
/**
337433
* @brief Declare a static device object
338434
*
@@ -369,6 +465,16 @@ typedef int16_t device_handle_t;
369465
*/
370466
#define DEVICE_INIT_GET(dev_id) (&Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)))
371467

468+
/**
469+
* @brief Get a @ref init_entry reference from a device
470+
*
471+
* @param ident Either a devicetree node identifier or a plain unique token
472+
*/
473+
#define DEVICE_INIT_ENTRY_GET(ident) \
474+
COND_CODE_1(DT_NODE_EXISTS(ident), \
475+
(&Z_INIT_ENTRY_NAME(DEVICE_DT_NAME_GET(ident))), \
476+
(&Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(ident))))
477+
372478
/**
373479
* @brief Runtime device dynamic structure (in RAM) per driver instance
374480
*

0 commit comments

Comments
 (0)