1 /*
2  * Copyright (c) 2015 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_INIT_H_
8 #define ZEPHYR_INCLUDE_INIT_H_
9 
10 #include <stdint.h>
11 #include <stddef.h>
12 
13 #include <zephyr/sys/util.h>
14 #include <zephyr/toolchain.h>
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 /**
21  * @defgroup sys_init System Initialization
22  * @ingroup os_services
23  *
24  * Zephyr offers an infrastructure to call initialization code before `main`.
25  * Such initialization calls can be registered using SYS_INIT() or
26  * SYS_INIT_NAMED() macros. By using a combination of initialization levels and
27  * priorities init sequence can be adjusted as needed. The available
28  * initialization levels are described, in order, below:
29  *
30  * - `EARLY`: Used very early in the boot process, right after entering the C
31  *   domain (``z_cstart()``). This can be used in architectures and SoCs that
32  *   extend or implement architecture code and use drivers or system services
33  *   that have to be initialized before the Kernel calls any architecture
34  *   specific initialization code.
35  * - `PRE_KERNEL_1`: Executed in Kernel's initialization context, which uses
36  *   the interrupt stack. At this point Kernel services are not yet available.
37  * - `PRE_KERNEL_2`: Same as `PRE_KERNEL_1`.
38  * - `POST_KERNEL`: Executed after Kernel is alive. From this point on, Kernel
39  *   primitives can be used.
40  * - `APPLICATION`: Executed just before application code (`main`).
41  * - `SMP`: Only available if @kconfig{CONFIG_SMP} is enabled, specific for
42  *   SMP.
43  *
44  * Initialization priority can take a value in the range of 0 to 99.
45  *
46  * @note The same infrastructure is used by devices.
47  * @{
48  */
49 
50 struct device;
51 
52 /**
53  * @brief Initialization function for init entries.
54  *
55  * Init entries support both the system initialization and the device
56  * APIs. Each API has its own init function signature; hence, we have a
57  * union to cover both.
58  */
59 union init_function {
60 	/**
61 	 * System initialization function.
62 	 *
63 	 * @retval 0 On success
64 	 * @retval -errno If init fails.
65 	 */
66 	int (*sys)(void);
67 	/**
68 	 * Device initialization function.
69 	 *
70 	 * @param dev Device instance.
71 	 *
72 	 * @retval 0 On success
73 	 * @retval -errno If device initialization fails.
74 	 */
75 	int (*dev)(const struct device *dev);
76 #ifdef CONFIG_DEVICE_MUTABLE
77 	/**
78 	 * Device initialization function (rw).
79 	 *
80 	 * @param dev Device instance.
81 	 *
82 	 * @retval 0 On success
83 	 * @retval -errno If device initialization fails.
84 	 */
85 	int (*dev_rw)(struct device *dev);
86 #endif
87 };
88 
89 /**
90  * @brief Structure to store initialization entry information.
91  *
92  * @internal
93  * Init entries need to be defined following these rules:
94  *
95  * - Their name must be set using Z_INIT_ENTRY_NAME().
96  * - They must be placed in a special init section, given by
97  *   Z_INIT_ENTRY_SECTION().
98  * - They must be aligned, e.g. using Z_DECL_ALIGN().
99  *
100  * See SYS_INIT_NAMED() for an example.
101  * @endinternal
102  */
103 struct init_entry {
104 	/** Initialization function. */
105 	union init_function init_fn;
106 	/**
107 	 * If the init entry belongs to a device, this fields stores a
108 	 * reference to it, otherwise it is set to NULL.
109 	 */
110 	union {
111 		const struct device *dev;
112 #ifdef CONFIG_DEVICE_MUTABLE
113 		struct device *dev_rw;
114 #endif
115 	};
116 };
117 
118 /** @cond INTERNAL_HIDDEN */
119 
120 /* Helper definitions to evaluate level equality */
121 #define Z_INIT_EARLY_EARLY		 1
122 #define Z_INIT_PRE_KERNEL_1_PRE_KERNEL_1 1
123 #define Z_INIT_PRE_KERNEL_2_PRE_KERNEL_2 1
124 #define Z_INIT_POST_KERNEL_POST_KERNEL	 1
125 #define Z_INIT_APPLICATION_APPLICATION	 1
126 #define Z_INIT_SMP_SMP			 1
127 
128 /* Init level ordinals */
129 #define Z_INIT_ORD_EARLY	0
130 #define Z_INIT_ORD_PRE_KERNEL_1 1
131 #define Z_INIT_ORD_PRE_KERNEL_2 2
132 #define Z_INIT_ORD_POST_KERNEL	3
133 #define Z_INIT_ORD_APPLICATION	4
134 #define Z_INIT_ORD_SMP		5
135 
136 /**
137  * @brief Obtain init entry name.
138  *
139  * @param init_id Init entry unique identifier.
140  */
141 #define Z_INIT_ENTRY_NAME(init_id) _CONCAT(__init_, init_id)
142 
143 /**
144  * @brief Init entry section.
145  *
146  * Each init entry is placed in a section with a name crafted so that it allows
147  * linker scripts to sort them according to the specified
148  * level/priority/sub-priority.
149  */
150 #define Z_INIT_ENTRY_SECTION(level, prio, sub_prio)                           \
151 	__attribute__((__section__(                                           \
152 		".z_init_" #level STRINGIFY(prio)"_" STRINGIFY(sub_prio)"_")))
153 
154 
155 /* Designated initializers where added to C in C99. There were added to
156  * C++ 20 years later in a much more restricted form. C99 allows many
157  * variations: out of order, mix of designated and not, overlap,
158  * override,... but C++ allows none of these. See differences detailed
159  * in the P0329R0.pdf C++ proposal.
160  * Note __STDC_VERSION__ is undefined when compiling C++.
161  */
162 #if defined(__STDC_VERSION__) && (__STDC_VERSION__) < 201100
163 
164 /* Anonymous unions require C11. Some pre-C11 gcc versions have early
165  * support for anonymous unions but they require these braces when
166  * combined with C99 designated initializers, see longer discussion in
167  * #69411.
168  * These braces are compatible with any C version but not with C++20.
169  */
170 #  define Z_INIT_SYS_INIT_DEV_NULL  { .dev = NULL }
171 
172 #else
173 
174 /* When using -std=c++20 or higher, g++ (v12.2.0) reject braces for
175  * initializing anonymous unions because it is technically a mix of
176  * designated and not designated initializers which is not allowed in
177  * C++. Interestingly, the _same_ g++ version does accept the braces above
178  * when using -std=c++17 or lower!
179  * The tests/lib/cpp/cxx/ added by commit 3d9c428d57bf invoke the C++
180  * compiler with a range of different `-std=...` parameters without needing
181  * any manual configuration.
182  */
183 #  define Z_INIT_SYS_INIT_DEV_NULL    .dev = NULL
184 
185 #endif
186 
187 /** @endcond */
188 
189 /**
190  * @brief Obtain the ordinal for an init level.
191  *
192  * @param level Init level (EARLY, PRE_KERNEL_1, PRE_KERNEL_2, POST_KERNEL,
193  * APPLICATION, SMP).
194  *
195  * @return Init level ordinal.
196  */
197 #define INIT_LEVEL_ORD(level)                                                  \
198 	COND_CODE_1(Z_INIT_EARLY_##level, (Z_INIT_ORD_EARLY),                  \
199 	(COND_CODE_1(Z_INIT_PRE_KERNEL_1_##level, (Z_INIT_ORD_PRE_KERNEL_1),   \
200 	(COND_CODE_1(Z_INIT_PRE_KERNEL_2_##level, (Z_INIT_ORD_PRE_KERNEL_2),   \
201 	(COND_CODE_1(Z_INIT_POST_KERNEL_##level, (Z_INIT_ORD_POST_KERNEL),     \
202 	(COND_CODE_1(Z_INIT_APPLICATION_##level, (Z_INIT_ORD_APPLICATION),     \
203 	(COND_CODE_1(Z_INIT_SMP_##level, (Z_INIT_ORD_SMP),                     \
204 	(ZERO_OR_COMPILE_ERROR(0)))))))))))))
205 
206 /**
207  * @brief Register an initialization function.
208  *
209  * The function will be called during system initialization according to the
210  * given level and priority.
211  *
212  * @param init_fn Initialization function.
213  * @param level Initialization level. Allowed tokens: `EARLY`, `PRE_KERNEL_1`,
214  * `PRE_KERNEL_2`, `POST_KERNEL`, `APPLICATION` and `SMP` if
215  * @kconfig{CONFIG_SMP} is enabled.
216  * @param prio Initialization priority within @p _level. Note that it must be a
217  * decimal integer literal without leading zeroes or sign (e.g. `32`), or an
218  * equivalent symbolic name (e.g. `#define MY_INIT_PRIO 32`); symbolic
219  * expressions are **not** permitted (e.g.
220  * `CONFIG_KERNEL_INIT_PRIORITY_DEFAULT + 5`).
221  */
222 #define SYS_INIT(init_fn, level, prio)                                         \
223 	SYS_INIT_NAMED(init_fn, init_fn, level, prio)
224 
225 /**
226  * @brief Register an initialization function (named).
227  *
228  * @note This macro can be used for cases where the multiple init calls use the
229  * same init function.
230  *
231  * @param name Unique name for SYS_INIT entry.
232  * @param init_fn_ See SYS_INIT().
233  * @param level See SYS_INIT().
234  * @param prio See SYS_INIT().
235  *
236  * @see SYS_INIT()
237  */
238 #define SYS_INIT_NAMED(name, init_fn_, level, prio)                                       \
239 	static const Z_DECL_ALIGN(struct init_entry)                                      \
240 		Z_INIT_ENTRY_SECTION(level, prio, 0) __used __noasan                      \
241 		Z_INIT_ENTRY_NAME(name) = {.init_fn = {.sys = (init_fn_)},                \
242 			Z_INIT_SYS_INIT_DEV_NULL}
243 
244 /** @} */
245 
246 #ifdef __cplusplus
247 }
248 #endif
249 
250 #endif /* ZEPHYR_INCLUDE_INIT_H_ */
251