LCOV - code coverage report
Current view: top level - zephyr - init.h Hit Total Coverage
Test: new.info Lines: 9 11 81.8 %
Date: 2024-12-22 00:14:23

          Line data    Source code
       1           0 : /*
       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           1 : union init_function {
      60             :         /**
      61             :          * System initialization function.
      62             :          *
      63             :          * @retval 0 On success
      64             :          * @retval -errno If init fails.
      65             :          */
      66           1 :         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           1 :         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           1 : struct init_entry {
     104             :         /** Initialization function. */
     105           1 :         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           0 :                 const struct device *dev;
     112             : #ifdef CONFIG_DEVICE_MUTABLE
     113             :                 struct device *dev_rw;
     114             : #endif
     115           1 :         };
     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           1 : #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           1 : #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           1 : #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_ */

Generated by: LCOV version 1.14