Zephyr Project API  3.4.0
A Scalable Open Source RTOS
device.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#ifndef ZEPHYR_INCLUDE_DEVICE_H_
8#define ZEPHYR_INCLUDE_DEVICE_H_
9
10#include <stdint.h>
11
12#include <zephyr/devicetree.h>
13#include <zephyr/init.h>
17#include <zephyr/sys/util.h>
18#include <zephyr/toolchain.h>
19
20#ifdef __cplusplus
21extern "C" {
22#endif
23
46
53#define DEVICE_HANDLE_SEP INT16_MIN
54
61#define DEVICE_HANDLE_ENDS INT16_MAX
62
64#define DEVICE_HANDLE_NULL 0
65
85#define DEVICE_NAME_GET(dev_id) _CONCAT(__device_, dev_id)
86
87/* Node paths can exceed the maximum size supported by
88 * device_get_binding() in user mode; this macro synthesizes a unique
89 * dev_id from a devicetree node while staying within this maximum
90 * size.
91 *
92 * The ordinal used in this name can be mapped to the path by
93 * examining zephyr/include/generated/devicetree_generated.h.
94 */
95#define Z_DEVICE_DT_DEV_ID(node_id) _CONCAT(dts_ord_, DT_DEP_ORD(node_id))
96
127#define DEVICE_DEFINE(dev_id, name, init_fn, pm, data, config, level, prio, \
128 api) \
129 Z_DEVICE_STATE_DEFINE(dev_id); \
130 Z_DEVICE_DEFINE(DT_INVALID_NODE, dev_id, name, init_fn, pm, data, \
131 config, level, prio, api, \
132 &Z_DEVICE_STATE_NAME(dev_id))
133
145#define DEVICE_DT_NAME(node_id) \
146 DT_PROP_OR(node_id, label, DT_NODE_FULL_NAME(node_id))
147
177#define DEVICE_DT_DEFINE(node_id, init_fn, pm, data, config, level, prio, api, \
178 ...) \
179 Z_DEVICE_STATE_DEFINE(Z_DEVICE_DT_DEV_ID(node_id)); \
180 Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), \
181 DEVICE_DT_NAME(node_id), init_fn, pm, data, config, \
182 level, prio, api, \
183 &Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_ID(node_id)), \
184 __VA_ARGS__)
185
194#define DEVICE_DT_INST_DEFINE(inst, ...) \
195 DEVICE_DT_DEFINE(DT_DRV_INST(inst), __VA_ARGS__)
196
211#define DEVICE_DT_NAME_GET(node_id) DEVICE_NAME_GET(Z_DEVICE_DT_DEV_ID(node_id))
212
228#define DEVICE_DT_GET(node_id) (&DEVICE_DT_NAME_GET(node_id))
229
239#define DEVICE_DT_INST_GET(inst) DEVICE_DT_GET(DT_DRV_INST(inst))
240
257#define DEVICE_DT_GET_ANY(compat) \
258 COND_CODE_1(DT_HAS_COMPAT_STATUS_OKAY(compat), \
259 (DEVICE_DT_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(compat))), \
260 (NULL))
261
278#define DEVICE_DT_GET_ONE(compat) \
279 COND_CODE_1(DT_HAS_COMPAT_STATUS_OKAY(compat), \
280 (DEVICE_DT_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(compat))), \
281 (ZERO_OR_COMPILE_ERROR(0)))
282
293#define DEVICE_DT_GET_OR_NULL(node_id) \
294 COND_CODE_1(DT_NODE_HAS_STATUS(node_id, okay), \
295 (DEVICE_DT_GET(node_id)), (NULL))
296
307#define DEVICE_GET(dev_id) (&DEVICE_NAME_GET(dev_id))
308
323#define DEVICE_DECLARE(dev_id) \
324 static const struct device DEVICE_NAME_GET(dev_id)
325
333#define DEVICE_INIT_DT_GET(node_id) \
334 (&Z_INIT_ENTRY_NAME(DEVICE_DT_NAME_GET(node_id)))
335
343#define DEVICE_INIT_GET(dev_id) (&Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)))
344
362
366 bool initialized : 1;
367};
368
369struct pm_device;
370
371#ifdef CONFIG_HAS_DYNAMIC_DEVICE_HANDLES
372#define Z_DEVICE_HANDLES_CONST
373#else
374#define Z_DEVICE_HANDLES_CONST const
375#endif
376
380struct device {
382 const char *name;
384 const void *config;
386 const void *api;
390 void *data;
398 Z_DEVICE_HANDLES_CONST device_handle_t *handles;
399
400#if defined(CONFIG_PM_DEVICE) || defined(__DOXYGEN__)
405 struct pm_device *pm;
406#endif
407};
408
417static inline device_handle_t device_handle_get(const struct device *dev)
418{
421
422 /* TODO: If/when devices can be constructed that are not part of the
423 * fixed sequence we'll need another solution.
424 */
425 if (dev != NULL) {
427 }
428
429 return ret;
430}
431
440static inline const struct device *
442{
444 const struct device *dev = NULL;
445 size_t numdev;
446
448
449 if ((dev_handle > 0) && ((size_t)dev_handle <= numdev)) {
450 dev = &STRUCT_SECTION_START(device)[dev_handle - 1];
451 }
452
453 return dev;
454}
455
474typedef int (*device_visitor_callback_t)(const struct device *dev,
475 void *context);
476
495static inline const device_handle_t *
496device_required_handles_get(const struct device *dev, size_t *count)
497{
498 const device_handle_t *rv = dev->handles;
499
500 if (rv != NULL) {
501 size_t i = 0;
502
503 while ((rv[i] != DEVICE_HANDLE_ENDS) &&
504 (rv[i] != DEVICE_HANDLE_SEP)) {
505 ++i;
506 }
507 *count = i;
508 }
509
510 return rv;
511}
512
531static inline const device_handle_t *
532device_injected_handles_get(const struct device *dev, size_t *count)
533{
534 const device_handle_t *rv = dev->handles;
535 size_t region = 0;
536 size_t i = 0;
537
538 if (rv != NULL) {
539 /* Fast forward to injected devices */
540 while (region != 1) {
541 if (*rv == DEVICE_HANDLE_SEP) {
542 region++;
543 }
544 rv++;
545 }
546 while ((rv[i] != DEVICE_HANDLE_ENDS) &&
547 (rv[i] != DEVICE_HANDLE_SEP)) {
548 ++i;
549 }
550 *count = i;
551 }
552
553 return rv;
554}
555
575static inline const device_handle_t *
576device_supported_handles_get(const struct device *dev, size_t *count)
577{
578 const device_handle_t *rv = dev->handles;
579 size_t region = 0;
580 size_t i = 0;
581
582 if (rv != NULL) {
583 /* Fast forward to supporting devices */
584 while (region != 2) {
585 if (*rv == DEVICE_HANDLE_SEP) {
586 region++;
587 }
588 rv++;
589 }
590 /* Count supporting devices.
591 * Trailing NULL's can be injected by gen_handles.py due to
592 * CONFIG_PM_DEVICE_POWER_DOMAIN_DYNAMIC_NUM
593 */
594 while ((rv[i] != DEVICE_HANDLE_ENDS) &&
595 (rv[i] != DEVICE_HANDLE_NULL)) {
596 ++i;
597 }
598 *count = i;
599 }
600
601 return rv;
602}
603
634int device_required_foreach(const struct device *dev,
635 device_visitor_callback_t visitor_cb,
636 void *context);
637
667int device_supported_foreach(const struct device *dev,
668 device_visitor_callback_t visitor_cb,
669 void *context);
670
691__syscall const struct device *device_get_binding(const char *name);
692
701size_t z_device_get_all_static(const struct device **devices);
702
717bool z_device_is_ready(const struct device *dev);
718
735__syscall bool device_is_ready(const struct device *dev);
736
737static inline bool z_impl_device_is_ready(const struct device *dev)
738{
739 return z_device_is_ready(dev);
740}
741
752#define Z_DEVICE_STATE_NAME(dev_id) _CONCAT(__devstate_, dev_id)
753
759#define Z_DEVICE_STATE_DEFINE(dev_id) \
760 static Z_DECL_ALIGN(struct device_state) Z_DEVICE_STATE_NAME(dev_id) \
761 __attribute__((__section__(".z_devstate")))
762
769#define Z_DEVICE_HANDLES_NAME(dev_id) _CONCAT(__devicehdl_, dev_id)
770
776#define Z_DEVICE_EXTRA_HANDLES(...) \
777 FOR_EACH_NONEMPTY_TERM(IDENTITY, (,), __VA_ARGS__)
778
780#define Z_DEVICE_HANDLES_SECTION \
781 __attribute__((__section__(".__device_handles_pass1")))
782
783#ifdef __cplusplus
784#define Z_DEVICE_HANDLES_EXTERN extern
785#else
786#define Z_DEVICE_HANDLES_EXTERN
787#endif
788
824#define Z_DEVICE_HANDLES_DEFINE(node_id, dev_id, ...) \
825 extern Z_DEVICE_HANDLES_CONST device_handle_t Z_DEVICE_HANDLES_NAME( \
826 dev_id)[]; \
827 Z_DEVICE_HANDLES_CONST Z_DECL_ALIGN(device_handle_t) \
828 Z_DEVICE_HANDLES_SECTION Z_DEVICE_HANDLES_EXTERN __weak \
829 Z_DEVICE_HANDLES_NAME(dev_id)[] = { \
830 COND_CODE_1( \
831 DT_NODE_EXISTS(node_id), \
832 (DT_DEP_ORD(node_id), DT_REQUIRES_DEP_ORDS(node_id)), \
833 (DEVICE_HANDLE_NULL,)) \
834 DEVICE_HANDLE_SEP, \
835 Z_DEVICE_EXTRA_HANDLES(__VA_ARGS__) \
836 DEVICE_HANDLE_SEP, \
837 COND_CODE_1(DT_NODE_EXISTS(node_id), \
838 (DT_SUPPORTS_DEP_ORDS(node_id)), ()) \
839 }
840
847#define Z_DEVICE_MAX_NAME_LEN 48
848
854#define Z_DEVICE_NAME_CHECK(name) \
855 BUILD_ASSERT(sizeof(Z_STRINGIFY(name)) <= Z_DEVICE_MAX_NAME_LEN, \
856 Z_STRINGIFY(DEVICE_NAME_GET(name)) " too long")
857
869#define Z_DEVICE_INIT(name_, pm_, data_, config_, api_, state_, handles_) \
870 { \
871 .name = name_, \
872 .config = (config_), \
873 .api = (api_), \
874 .state = (state_), \
875 .data = (data_), \
876 .handles = (handles_), \
877 IF_ENABLED(CONFIG_PM_DEVICE, (.pm = (pm_),)) \
878 }
879
886#define Z_DEVICE_SECTION_NAME(level, prio) \
887 _CONCAT(INIT_LEVEL_ORD(level), _##prio)
888
905#define Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, \
906 prio, api, state, handles) \
907 COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static)) \
908 const STRUCT_SECTION_ITERABLE_NAMED(device, \
909 Z_DEVICE_SECTION_NAME(level, prio), \
910 DEVICE_NAME_GET(dev_id)) = \
911 Z_DEVICE_INIT(name, pm, data, config, api, state, handles)
912
921#define Z_DEVICE_INIT_ENTRY_DEFINE(dev_id, init_fn_, level, prio) \
922 static const Z_DECL_ALIGN(struct init_entry) \
923 Z_INIT_ENTRY_SECTION(level, prio) __used __noasan \
924 Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \
925 .init_fn = {.dev = (init_fn_)}, \
926 .dev = &DEVICE_NAME_GET(dev_id), \
927 }
928
950#define Z_DEVICE_DEFINE(node_id, dev_id, name, init_fn, pm, data, config, \
951 level, prio, api, state, ...) \
952 Z_DEVICE_NAME_CHECK(name); \
953 \
954 Z_DEVICE_HANDLES_DEFINE(node_id, dev_id, __VA_ARGS__); \
955 \
956 Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, \
957 prio, api, state, Z_DEVICE_HANDLES_NAME(dev_id)); \
958 \
959 Z_DEVICE_INIT_ENTRY_DEFINE(dev_id, init_fn, level, prio)
960
961#if defined(CONFIG_HAS_DTS) || defined(__DOXYGEN__)
972#define Z_MAYBE_DEVICE_DECLARE_INTERNAL(node_id) \
973 extern const struct device DEVICE_DT_NAME_GET(node_id);
974
975DT_FOREACH_STATUS_OKAY_NODE(Z_MAYBE_DEVICE_DECLARE_INTERNAL)
976#endif /* CONFIG_HAS_DTS */
977
980#ifdef __cplusplus
981}
982#endif
983
984#include <syscalls/device.h>
985
986#endif /* ZEPHYR_INCLUDE_DEVICE_H_ */
ZTEST_BMEM int count
Definition: main.c:33
Devicetree main header.
DT_FOREACH_STATUS_OKAY_NODE(Z_MAYBE_EMUL_DECLARE_INTERNAL)
volatile int rv
Definition: main.c:45
const struct device * device_get_binding(const char *name)
Get a device reference from its device::name field.
int16_t device_handle_t
Type used to represent a "handle" for a device.
Definition: device.h:45
static const device_handle_t * device_required_handles_get(const struct device *dev, size_t *count)
Get the device handles for devicetree dependencies of this device.
Definition: device.h:496
static const device_handle_t * device_supported_handles_get(const struct device *dev, size_t *count)
Get the set of handles that this device supports.
Definition: device.h:576
static device_handle_t device_handle_get(const struct device *dev)
Get the handle for a given device.
Definition: device.h:417
#define DEVICE_HANDLE_NULL
Flag value used to identify an unknown device.
Definition: device.h:64
#define DEVICE_HANDLE_SEP
Flag value used in lists of device handles to separate distinct groups.
Definition: device.h:53
int device_required_foreach(const struct device *dev, device_visitor_callback_t visitor_cb, void *context)
Visit every device that dev directly requires.
static const struct device * device_from_handle(device_handle_t dev_handle)
Get the device corresponding to a handle.
Definition: device.h:441
int(* device_visitor_callback_t)(const struct device *dev, void *context)
Prototype for functions used when iterating over a set of devices.
Definition: device.h:474
bool device_is_ready(const struct device *dev)
Verify that a device is ready for use.
#define DEVICE_HANDLE_ENDS
Flag value used in lists of device handles to indicate the end of the list.
Definition: device.h:61
static const device_handle_t * device_injected_handles_get(const struct device *dev, size_t *count)
Get the device handles for injected dependencies of this device.
Definition: device.h:532
int device_supported_foreach(const struct device *dev, device_visitor_callback_t visitor_cb, void *context)
Visit every device that dev directly supports.
#define STRUCT_SECTION_START_EXTERN(struct_type)
iterable section extern for start symbol for a struct
Definition: iterable_sections.h:159
#define STRUCT_SECTION_START(struct_type)
iterable section start symbol for a struct type
Definition: iterable_sections.h:149
#define STRUCT_SECTION_COUNT(struct_type, dst)
Count elements in a section.
Definition: iterable_sections.h:281
static ZTEST_BMEM volatile int ret
Definition: k_float_disable.c:29
Definitions of various linker Sections.
__UINT8_TYPE__ uint8_t
Definition: stdint.h:88
__INT16_TYPE__ int16_t
Definition: stdint.h:73
Runtime device dynamic structure (in RAM) per driver instance.
Definition: device.h:353
bool initialized
Definition: device.h:366
uint8_t init_res
Definition: device.h:361
Runtime device structure (in ROM) per driver instance.
Definition: device.h:380
const char * name
Definition: device.h:382
struct pm_device * pm
Definition: device.h:405
void * data
Definition: device.h:390
const device_handle_t * handles
Definition: device.h:398
const void * api
Definition: device.h:386
struct device_state * state
Definition: device.h:388
const void * config
Definition: device.h:384
Device PM info.
Definition: device.h:126
const struct device * dev
Definition: device.h:129
Macros to abstract toolchain specific capabilities.
Misc utilities.