diff --git a/drivers/flash/flash_shell.c b/drivers/flash/flash_shell.c index f1f948a9439..7cd821dc6e9 100644 --- a/drivers/flash/flash_shell.c +++ b/drivers/flash/flash_shell.c @@ -17,8 +17,8 @@ #define BUF_ARRAY_CNT 16 #define TEST_ARR_SIZE 0x1000 -extern struct device __device_init_start[]; -extern struct device __device_init_end[]; +extern struct device __device_start[]; +extern struct device __device_end[]; static u8_t test_arr[TEST_ARR_SIZE]; @@ -229,7 +229,7 @@ static void device_name_get(size_t idx, struct shell_static_entry *entry) entry->help = NULL; entry->subcmd = &dsub_device_name; - for (dev = __device_init_start; dev != __device_init_end; dev++) { + for (dev = __device_start; dev != __device_end; dev++) { if ((dev->driver_api != NULL) && strcmp(dev->config->name, "") && (dev->config->name != NULL)) { if (idx == device_idx) { diff --git a/drivers/i2c/i2c_shell.c b/drivers/i2c/i2c_shell.c index 3946659844f..686e83515ef 100644 --- a/drivers/i2c/i2c_shell.c +++ b/drivers/i2c/i2c_shell.c @@ -15,8 +15,8 @@ LOG_MODULE_REGISTER(i2c_shell, CONFIG_LOG_DEFAULT_LEVEL); #define I2C_DEVICE_PREFIX "I2C_" -extern struct device __device_init_start[]; -extern struct device __device_init_end[]; +extern struct device __device_start[]; +extern struct device __device_end[]; static int cmd_i2c_scan(const struct shell *shell, size_t argc, char **argv) @@ -80,7 +80,7 @@ static void device_name_get(size_t idx, struct shell_static_entry *entry) entry->help = NULL; entry->subcmd = &dsub_device_name; - for (dev = __device_init_start; dev != __device_init_end; dev++) { + for (dev = __device_start; dev != __device_end; dev++) { if ((dev->driver_api != NULL) && strstr(dev->config->name, I2C_DEVICE_PREFIX) != NULL && strcmp(dev->config->name, "") && (dev->config->name != NULL)) { diff --git a/drivers/sensor/sensor_shell.c b/drivers/sensor/sensor_shell.c index 4e341cbced1..e200459b689 100644 --- a/drivers/sensor/sensor_shell.c +++ b/drivers/sensor/sensor_shell.c @@ -16,8 +16,8 @@ "when no channels are provided. Syntax:\n" \ " .. " -extern struct device __device_init_start[]; -extern struct device __device_init_end[]; +extern struct device __device_start[]; +extern struct device __device_end[]; const char *sensor_channel_name[SENSOR_CHAN_ALL] = { [SENSOR_CHAN_ACCEL_X] = "accel_x", @@ -170,7 +170,7 @@ static void device_name_get(size_t idx, struct shell_static_entry *entry) entry->help = NULL; entry->subcmd = &dsub_channel_name; - for (dev = __device_init_start; dev != __device_init_end; dev++) { + for (dev = __device_start; dev != __device_end; dev++) { if ((dev->driver_api != NULL) && strcmp(dev->config->name, "") && (dev->config->name != NULL)) { if (idx == device_idx) { diff --git a/include/device.h b/include/device.h index eaae09149ff..047adcf4d22 100644 --- a/include/device.h +++ b/include/device.h @@ -7,8 +7,6 @@ #ifndef ZEPHYR_INCLUDE_DEVICE_H_ #define ZEPHYR_INCLUDE_DEVICE_H_ -#include - /** * @brief Device Driver APIs * @defgroup io_interfaces Device Driver APIs @@ -21,7 +19,7 @@ * @{ */ -#include +#include #ifdef __cplusplus extern "C" { @@ -29,6 +27,27 @@ extern "C" { #define Z_DEVICE_MAX_NAME_LEN 48 + +/** + * @def SYS_DEVICE_DEFINE + * + * @brief Run an initialization function at boot at specified priority, + * and define device PM control function. + * + * @details This macro lets you run a function at system boot. + * + * @param drv_name Name of this system device + * @param init_fn Pointer to the boot function to run + * @param pm_control_fn Pointer to device_pm_control function. + * Can be empty function (device_pm_control_nop) if not implemented. + * @param level The initialization level, See Z_INIT_ENTRY_DEFINE for details. + * @param prio Priority within the selected initialization level. See + * Z_INIT_ENTRY_DEFINE for details. + */ +#define SYS_DEVICE_DEFINE(drv_name, init_fn, pm_control_fn, level, prio) \ + DEVICE_DEFINE(Z_SYS_NAME(init_fn), drv_name, init_fn, pm_control_fn, \ + NULL, NULL, level, prio, NULL) + /** * @def DEVICE_INIT * @@ -53,36 +72,10 @@ extern "C" { * @param cfg_info The address to the structure containing the * configuration information for this instance of the driver. * - * @param level The initialization level at which configuration occurs. - * Must be one of the following symbols, which are listed in the order - * they are performed by the kernel: - * \n - * \li PRE_KERNEL_1: Used for devices that have no dependencies, such as those - * that rely solely on hardware present in the processor/SOC. These devices - * cannot use any kernel services during configuration, since they are not - * yet available. - * \n - * \li PRE_KERNEL_2: Used for devices that rely on the initialization of devices - * initialized as part of the PRE_KERNEL_1 level. These devices cannot use any - * kernel services during configuration, since they are not yet available. - * \n - * \li POST_KERNEL: Used for devices that require kernel services during - * configuration. - * \n - * \li POST_KERNEL_SMP: Used for devices that require kernel services during - * configuration after SMP initialization. - * \n - * \li APPLICATION: Used for application components (i.e. non-kernel components) - * that need automatic configuration. These devices can use all services - * provided by the kernel during configuration. + * @param level The initialization level, See Z_INIT_ENTRY_DEFINE for details. * - * @param prio The initialization priority of the device, relative to - * other devices of the same initialization level. Specified as an integer - * value in the range 0 to 99; lower values indicate earlier initialization. - * Must be a decimal integer literal without leading zeroes or sign (e.g. 32), - * or an equivalent symbolic name (e.g. \#define MY_INIT_PRIO 32); symbolic - * expressions are *not* permitted - * (e.g. CONFIG_KERNEL_INIT_PRIORITY_DEFAULT + 5). + * @param prio Priority within the selected initialization level. See + * Z_INIT_ENTRY_DEFINE for details. */ #define DEVICE_INIT(dev_name, drv_name, init_fn, data, cfg_info, level, prio) \ DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, \ @@ -102,19 +95,18 @@ extern "C" { * during initialization. */ #ifndef CONFIG_DEVICE_POWER_MANAGEMENT -#define DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, data, cfg_info, \ - level, prio, api) \ - static const struct device_config _CONCAT(__config_, dev_name) __used \ - __attribute__((__section__(".devconfig.init"))) = { \ - .name = drv_name, .init = (init_fn), \ - .config_info = (cfg_info) \ - }; \ - static Z_DECL_ALIGN(struct device) _CONCAT(__device_, dev_name) __used \ - __attribute__((__section__(".init_" #level STRINGIFY(prio)))) = { \ - .config = &_CONCAT(__config_, dev_name), \ - .driver_api = api, \ - .driver_data = data \ - } +#define DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, data, cfg_info, \ + level, prio, api) \ + static Z_DECL_ALIGN(struct device) \ + _CONCAT(__device_, dev_name) __used \ + __attribute__((__section__(".device_" #level STRINGIFY(prio)))) = { \ + .name = drv_name, \ + .config_info = (cfg_info), \ + .driver_api = (api), \ + .driver_data = (data), \ + }; \ + Z_INIT_ENTRY_DEFINE(_CONCAT(__device_, dev_name), init_fn, \ + (&_CONCAT(__device_, dev_name)), level, prio) #else /* * Use the default device_pm_control for devices that do not call the @@ -146,32 +138,32 @@ extern "C" { DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, data, cfg_info, \ level, prio, api) #else -#define DEVICE_DEFINE(dev_name, drv_name, init_fn, pm_control_fn, \ - data, cfg_info, level, prio, api) \ - static struct device_pm _CONCAT(__pm_, dev_name) __used \ - = { \ - .usage = ATOMIC_INIT(0), \ - .lock = Z_SEM_INITIALIZER( \ - _CONCAT(__pm_, dev_name).lock, 1, 1), \ - .signal = K_POLL_SIGNAL_INITIALIZER( \ - _CONCAT(__pm_, dev_name).signal), \ - .event = K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, \ - K_POLL_MODE_NOTIFY_ONLY, \ - &_CONCAT(__pm_, dev_name).signal), \ - }; \ - static struct device_config _CONCAT(__config_, dev_name) __used \ - __attribute__((__section__(".devconfig.init"))) = { \ - .name = drv_name, .init = (init_fn), \ - .device_pm_control = (pm_control_fn), \ - .pm = &_CONCAT(__pm_, dev_name), \ - .config_info = (cfg_info) \ - }; \ - static Z_DECL_ALIGN(struct device) _CONCAT(__device_, dev_name) __used \ - __attribute__((__section__(".init_" #level STRINGIFY(prio)))) = { \ - .config = &_CONCAT(__config_, dev_name), \ - .driver_api = api, \ - .driver_data = data, \ - } +#define DEVICE_DEFINE(dev_name, drv_name, init_fn, pm_control_fn, \ + data, cfg_info, level, prio, api) \ + static struct device_pm _CONCAT(__pm_, dev_name) __used = { \ + .usage = ATOMIC_INIT(0), \ + .lock = Z_SEM_INITIALIZER( \ + _CONCAT(__pm_, dev_name).lock, 1, 1), \ + .signal = K_POLL_SIGNAL_INITIALIZER( \ + _CONCAT(__pm_, dev_name).signal), \ + .event = K_POLL_EVENT_INITIALIZER( \ + K_POLL_TYPE_SIGNAL, \ + K_POLL_MODE_NOTIFY_ONLY, \ + &_CONCAT(__pm_, dev_name).signal), \ + }; \ + static Z_DECL_ALIGN(struct device) \ + _CONCAT(__device_, dev_name) __used \ + __attribute__((__section__(".device_" #level STRINGIFY(prio)))) = { \ + .name = drv_name, \ + .config_info = (cfg_info), \ + .driver_api = (api), \ + .driver_data = (data), \ + .device_pm_control = (pm_control_fn), \ + .pm = &_CONCAT(__pm_, dev_name), \ + }; \ + Z_INIT_ENTRY_DEFINE(_CONCAT(__device_, dev_name), init_fn, \ + (&_CONCAT(__device_, dev_name)), level, prio) + #endif /** @@ -222,8 +214,6 @@ extern "C" { */ #define DEVICE_DECLARE(name) static struct device DEVICE_NAME_GET(name) -struct device; - typedef void (*device_pm_cb)(struct device *dev, int status, void *context, void *arg); @@ -250,38 +240,28 @@ struct device_pm { }; /** - * @brief Static device information (In ROM) Per driver instance + * @brief Runtime device structure (in memory) per driver instance * * @param name name of the device * @param init init function for the driver * @param config_info address of driver instance config information - */ -struct device_config { - const char *name; - int (*init)(struct device *device); -#ifdef CONFIG_DEVICE_POWER_MANAGEMENT - int (*device_pm_control)(struct device *device, u32_t command, - void *context, device_pm_cb cb, void *arg); - struct device_pm *pm; -#endif - const void *config_info; -}; - -/** - * @brief Runtime device structure (In memory) Per driver instance * @param device_config Build time config information * @param driver_api pointer to structure containing the API functions for - * the device type. This pointer is filled in by the driver at init time. + * the device type. * @param driver_data driver instance data. For driver use only */ struct device { - const struct device_config *config; + const char *name; + const void *config_info; const void *driver_api; - void *driver_data; + void * const driver_data; +#ifdef CONFIG_DEVICE_POWER_MANAGEMENT + int (*device_pm_control)(struct device *device, u32_t command, + void *context, device_pm_cb cb, void *arg); + struct device_pm * const pm; +#endif }; -void z_sys_device_do_config_level(s32_t level); - /** * @brief Retrieve the device structure for a driver by name * @@ -432,9 +412,9 @@ static inline int device_set_power_state(struct device *device, u32_t device_power_state, device_pm_cb cb, void *arg) { - return device->config->device_pm_control(device, - DEVICE_PM_SET_POWER_STATE, - &device_power_state, cb, arg); + return device->device_pm_control(device, + DEVICE_PM_SET_POWER_STATE, + &device_power_state, cb, arg); } /** @@ -453,10 +433,10 @@ static inline int device_set_power_state(struct device *device, static inline int device_get_power_state(struct device *device, u32_t *device_power_state) { - return device->config->device_pm_control(device, - DEVICE_PM_GET_POWER_STATE, - device_power_state, - NULL, NULL); + return device->device_pm_control(device, + DEVICE_PM_GET_POWER_STATE, + device_power_state, + NULL, NULL); } /** diff --git a/include/init.h b/include/init.h index bb1af145aa7..e1977e87588 100644 --- a/include/init.h +++ b/include/init.h @@ -7,8 +7,9 @@ #ifndef ZEPHYR_INCLUDE_INIT_H_ #define ZEPHYR_INCLUDE_INIT_H_ -#include #include +#include +#include #ifdef __cplusplus extern "C" { @@ -29,11 +30,85 @@ extern "C" { #define _SYS_INIT_LEVEL_SMP 4 #endif +struct device; + +/** + * @brief Static init entry structure for each device driver or services + * + * @param init init function for the init entry which will take the dev + * attribute as parameter. See below. + * @param dev pointer to a device driver instance structure. Can be NULL + * if the init entry is not used for a device driver but a service. + */ +struct init_entry { + int (*init)(struct device *dev); + struct device *dev; +}; + +void z_sys_init_run_level(s32_t level); + /* A counter is used to avoid issues when two or more system devices * are declared in the same C file with the same init function. */ #define Z_SYS_NAME(init_fn) _CONCAT(_CONCAT(sys_init_, init_fn), __COUNTER__) +/** + * @def Z_INIT_ENTRY_DEFINE + * + * @brief Create an init entry object and set it up for boot time initialization + * + * @details This macro defines an init entry object that will be automatically + * configured by the kernel during system initialization. Note that + * init entries will not be accessible from user mode. Also this macro should + * not be used directly, use relevant macro such as SYS_INIT() or + * DEVICE_AND_API_INIT() instead. + * + * @param entry_name Init entry name. It is the name this instance exposes to + * the system. + * + * @param init_fn Address to the init function of the entry. + * + * @param device A device driver instance pointer or NULL + * + * @param level The initialization level at which configuration occurs. + * Must be one of the following symbols, which are listed in the order + * they are performed by the kernel: + * \n + * \li PRE_KERNEL_1: Used for initialization objects that have no dependencies, + * such as those that rely solely on hardware present in the processor/SOC. + * These objects cannot use any kernel services during configuration, since + * they are not yet available. + * \n + * \li PRE_KERNEL_2: Used for initialization objects that rely on objects + * initialized as part of the PRE_KERNEL_1 level. These objects cannot use any + * kernel services during configuration, since they are not yet available. + * \n + * \li POST_KERNEL: Used for initialization objects that require kernel services + * during configuration. + * \n + * \li POST_KERNEL_SMP: Used for initialization objects that require kernel + * services during configuration after SMP initialization. + * \n + * \li APPLICATION: Used for application components (i.e. non-kernel components) + * that need automatic configuration. These objects can use all services + * provided by the kernel during configuration. + * + * @param prio The initialization priority of the object, relative to + * other objects of the same initialization level. Specified as an integer + * value in the range 0 to 99; lower values indicate earlier initialization. + * Must be a decimal integer literal without leading zeroes or sign (e.g. 32), + * or an equivalent symbolic name (e.g. \#define MY_INIT_PRIO 32); symbolic + * expressions are *not* permitted + * (e.g. CONFIG_KERNEL_INIT_PRIORITY_DEFAULT + 5). + */ +#define Z_INIT_ENTRY_DEFINE(entry_name, init_fn, device, level, prio) \ + static const Z_DECL_ALIGN(struct init_entry) \ + _CONCAT(__init_, entry_name) __used \ + __attribute__((__section__(".init_" #level STRINGIFY(prio)))) = { \ + .init = (init_fn), \ + .dev = (device), \ + } + /** * @def SYS_INIT * @@ -43,35 +118,13 @@ extern "C" { * * @param init_fn Pointer to the boot function to run * - * @param level The initialization level, See DEVICE_AND_API_INIT for details. + * @param level The initialization level, See Z_INIT_ENTRY_DEFINE for details. * * @param prio Priority within the selected initialization level. See - * DEVICE_AND_API_INIT for details. + * Z_INIT_ENTRY_DEFINE for details. */ #define SYS_INIT(init_fn, level, prio) \ - DEVICE_AND_API_INIT(Z_SYS_NAME(init_fn), "", init_fn, \ - NULL, NULL, level, prio, NULL) - -/** - * @def SYS_DEVICE_DEFINE - * - * @brief Run an initialization function at boot at specified priority, - * and define device PM control function. - * - * @details This macro lets you run a function at system boot. - * - * @param drv_name Name of this system device - * @param init_fn Pointer to the boot function to run - * @param pm_control_fn Pointer to device_pm_control function. - * Can be empty function (device_pm_control_nop) if not - * implemented. - * @param level The initialization level, See DEVICE_INIT for details. - * @param prio Priority within the selected initialization level. See - * DEVICE_INIT for details. - */ -#define SYS_DEVICE_DEFINE(drv_name, init_fn, pm_control_fn, level, prio) \ - DEVICE_DEFINE(Z_SYS_NAME(init_fn), drv_name, init_fn, pm_control_fn, \ - NULL, NULL, level, prio, NULL) + Z_INIT_ENTRY_DEFINE(Z_SYS_NAME(init_fn), init_fn, NULL, level, prio) #ifdef __cplusplus } diff --git a/include/linker/common-ram.ld b/include/linker/common-ram.ld index 3ebfbc21b9e..b0af076c051 100644 --- a/include/linker/common-ram.ld +++ b/include/linker/common-ram.ld @@ -1,10 +1,5 @@ /* SPDX-License-Identifier: Apache-2.0 */ - SECTION_DATA_PROLOGUE(initlevel,,) - { - DEVICE_INIT_SECTIONS() - } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) - #if defined(CONFIG_GEN_SW_ISR_TABLE) && defined(CONFIG_DYNAMIC_INTERRUPTS) SECTION_DATA_PROLOGUE(sw_isr_table,,) { @@ -18,12 +13,10 @@ } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) #endif - /* verify we don't have rogue .init_ initlevel sections */ - SECTION_DATA_PROLOGUE(initlevel_error,,) + SECTION_DATA_PROLOGUE(devices,,) { - DEVICE_INIT_UNDEFINED_SECTION() - } - ASSERT(SIZEOF(initlevel_error) == 0, "Undefined initialization levels used.") + DEVICE_SECTIONS() + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) SECTION_DATA_PROLOGUE(initshell,,) { diff --git a/include/linker/common-rom.ld b/include/linker/common-rom.ld index c16774758e8..963ee810f1a 100644 --- a/include/linker/common-rom.ld +++ b/include/linker/common-rom.ld @@ -1,5 +1,10 @@ /* SPDX-License-Identifier: Apache-2.0 */ + SECTION_PROLOGUE(initlevel,,) + { + INIT_SECTIONS() + } GROUP_LINK_IN(ROMABLE_REGION) + #if defined(CONFIG_GEN_SW_ISR_TABLE) && !defined(CONFIG_DYNAMIC_INTERRUPTS) SECTION_PROLOGUE(sw_isr_table,,) { @@ -12,6 +17,14 @@ *(_SW_ISR_TABLE_SECTION_NAME) } GROUP_LINK_IN(ROMABLE_REGION) #endif + + /* verify we don't have rogue .init_ initlevel sections */ + SECTION_PROLOGUE(initlevel_error,,) + { + INIT_UNDEFINED_SECTION() + } + ASSERT(SIZEOF(initlevel_error) == 0, "Undefined initialization levels used.") + #ifdef CONFIG_CPLUSPLUS SECTION_PROLOGUE(_CTOR_SECTION_NAME,,) { @@ -66,14 +79,6 @@ __app_shmem_regions_end = .; } GROUP_LINK_IN(ROMABLE_REGION) - SECTION_PROLOGUE (devconfig,,) - { - __devconfig_start = .; - *(".devconfig.*") - KEEP(*(SORT_BY_NAME(".devconfig*"))) - __devconfig_end = .; - } GROUP_LINK_IN(ROMABLE_REGION) - SECTION_PROLOGUE(net_l2,,) { __net_l2_start = .; diff --git a/include/linker/linker-defs.h b/include/linker/linker-defs.h index 73109986b5e..cf32ef7d5eb 100644 --- a/include/linker/linker-defs.h +++ b/include/linker/linker-defs.h @@ -45,7 +45,7 @@ */ #ifdef CONFIG_DEVICE_POWER_MANAGEMENT #define DEVICE_COUNT \ - ((__device_init_end - __device_init_start) / _DEVICE_STRUCT_SIZEOF) + ((__device_end - __device_start) / _DEVICE_STRUCT_SIZEOF) #define DEV_BUSY_SZ (((DEVICE_COUNT + 31) / 32) * 4) #define DEVICE_BUSY_BITFIELD() \ FILL(0x00) ; \ @@ -57,37 +57,53 @@ #endif /* - * generate a symbol to mark the start of the device initialization objects for - * the specified level, then link all of those objects (sorted by priority); - * ensure the objects aren't discarded if there is no direct reference to them + * generate a symbol to mark the start of the objects array for + * the specified object and level, then link all of those objects + * (sorted by priority). Ensure the objects aren't discarded if there is + * no direct reference to them */ - -#define DEVICE_INIT_LEVEL(level) \ - __device_##level##_start = .; \ - KEEP(*(SORT(.init_##level[0-9]))); \ - KEEP(*(SORT(.init_##level[1-9][0-9]))); \ +#define CREATE_OBJ_LEVEL(object, level) \ + __##object##_##level##_start = .; \ + KEEP(*(SORT(.##object##_##level[0-9]))); \ + KEEP(*(SORT(.##object##_##level[1-9][0-9]))); \ /* - * link in device initialization objects for all devices that are automatically + * link in initialization objects for all objects that are automatically * initialized by the kernel; the objects are sorted in the order they will be * initialized (i.e. ordered by level, sorted by priority within a level) */ -#define DEVICE_INIT_SECTIONS() \ - __device_init_start = .; \ - DEVICE_INIT_LEVEL(PRE_KERNEL_1) \ - DEVICE_INIT_LEVEL(PRE_KERNEL_2) \ - DEVICE_INIT_LEVEL(POST_KERNEL) \ - DEVICE_INIT_LEVEL(APPLICATION) \ - DEVICE_INIT_LEVEL(SMP) \ - __device_init_end = .; \ - DEVICE_BUSY_BITFIELD() \ +#define INIT_SECTIONS() \ + __init_start = .; \ + CREATE_OBJ_LEVEL(init, PRE_KERNEL_1) \ + CREATE_OBJ_LEVEL(init, PRE_KERNEL_2) \ + CREATE_OBJ_LEVEL(init, POST_KERNEL) \ + CREATE_OBJ_LEVEL(init, APPLICATION) \ + CREATE_OBJ_LEVEL(init, SMP) \ + __init_end = .; \ /* define a section for undefined device initialization levels */ -#define DEVICE_INIT_UNDEFINED_SECTION() \ +#define INIT_UNDEFINED_SECTION() \ KEEP(*(SORT(.init_[_A-Z0-9]*))) \ + +/* + * link in devices objects, which are tied to the init ones; + * the objects are thus sorted the same way as their init object parent + * see include/device.h + */ +#define DEVICE_SECTIONS() \ + __device_start = .; \ + CREATE_OBJ_LEVEL(device, PRE_KERNEL_1) \ + CREATE_OBJ_LEVEL(device, PRE_KERNEL_2) \ + CREATE_OBJ_LEVEL(device, POST_KERNEL) \ + CREATE_OBJ_LEVEL(device, APPLICATION) \ + CREATE_OBJ_LEVEL(device, SMP) \ + __device_end = .; \ + DEVICE_BUSY_BITFIELD() \ + + /* * link in shell initialization objects for all modules that use shell and * their shell commands are automatically initialized by the kernel. diff --git a/kernel/device.c b/kernel/device.c index d9361b0c829..5dd4e5b7900 100644 --- a/kernel/device.c +++ b/kernel/device.c @@ -9,17 +9,20 @@ #include #include -extern struct device __device_init_start[]; -extern struct device __device_PRE_KERNEL_1_start[]; -extern struct device __device_PRE_KERNEL_2_start[]; -extern struct device __device_POST_KERNEL_start[]; -extern struct device __device_APPLICATION_start[]; -extern struct device __device_init_end[]; +extern const struct init_entry __init_start[]; +extern const struct init_entry __init_PRE_KERNEL_1_start[]; +extern const struct init_entry __init_PRE_KERNEL_2_start[]; +extern const struct init_entry __init_POST_KERNEL_start[]; +extern const struct init_entry __init_APPLICATION_start[]; +extern const struct init_entry __init_end[]; #ifdef CONFIG_SMP -extern struct device __device_SMP_start[]; +extern const struct init_entry __init_SMP_start[]; #endif +extern struct device __device_start[]; +extern struct device __device_end[]; + #ifdef CONFIG_DEVICE_POWER_MANAGEMENT extern u32_t __device_busy_start[]; extern u32_t __device_busy_end[]; @@ -27,71 +30,72 @@ extern u32_t __device_busy_end[]; #endif /** - * @brief Execute all the device initialization functions at a given level + * @brief Execute all the init entry initialization functions at a given level * - * @details Invokes the initialization routine for each device object - * created by the DEVICE_INIT() macro using the specified level. - * The linker script places the device objects in memory in the order + * @details Invokes the initialization routine for each init entry object + * created by the INIT_ENTRY_DEFINE() macro using the specified level. + * The linker script places the init entry objects in memory in the order * they need to be invoked, with symbols indicating where one level leaves * off and the next one begins. * * @param level init level to run. */ -void z_sys_device_do_config_level(s32_t level) +void z_sys_init_run_level(s32_t level) { - struct device *info; - static struct device *config_levels[] = { - __device_PRE_KERNEL_1_start, - __device_PRE_KERNEL_2_start, - __device_POST_KERNEL_start, - __device_APPLICATION_start, + static const struct init_entry *levels[] = { + __init_PRE_KERNEL_1_start, + __init_PRE_KERNEL_2_start, + __init_POST_KERNEL_start, + __init_APPLICATION_start, #ifdef CONFIG_SMP - __device_SMP_start, + __init_SMP_start, #endif /* End marker */ - __device_init_end, + __init_end, }; + const struct init_entry *entry; - for (info = config_levels[level]; info < config_levels[level+1]; - info++) { + for (entry = levels[level]; entry < levels[level+1]; entry++) { + struct device *dev = entry->dev; int retval; - const struct device_config *device_conf = info->config; - retval = device_conf->init(info); + if (dev != NULL) { + z_object_init(dev); + } + + retval = entry->init(dev); if (retval != 0) { - /* Initialization failed. Clear the API struct so that - * device_get_binding() will not succeed for it. - */ - info->driver_api = NULL; - } else { - z_object_init(info); + if (dev) { + /* Initialization failed. Clear the API struct + * so that device_get_binding() will not succeed + * for it. + */ + dev->driver_api = NULL; + } } } } struct device *z_impl_device_get_binding(const char *name) { - struct device *info; + struct device *dev; /* Split the search into two loops: in the common scenario, where * device names are stored in ROM (and are referenced by the user * with CONFIG_* macros), only cheap pointer comparisons will be - * performed. Reserve string comparisons for a fallback. + * performed. Reserve string comparisons for a fallback. */ - for (info = __device_init_start; info != __device_init_end; info++) { - if ((info->driver_api != NULL) && - (info->config->name == name)) { - return info; + for (dev = __device_start; dev != __device_end; dev++) { + if ((dev->driver_api != NULL) && + (dev->name == name)) { + return dev; } } - for (info = __device_init_start; info != __device_init_end; info++) { - if (info->driver_api == NULL) { - continue; - } - - if (strcmp(name, info->config->name) == 0) { - return info; + for (dev = __device_start; dev != __device_end; dev++) { + if ((dev->driver_api != NULL) && + (strcmp(name, dev->name) == 0)) { + return dev; } } @@ -126,8 +130,8 @@ int device_pm_control_nop(struct device *unused_device, void device_list_get(struct device **device_list, int *device_count) { - *device_list = __device_init_start; - *device_count = __device_init_end - __device_init_start; + *device_list = __device_start; + *device_count = __device_end - __device_start; } @@ -146,7 +150,7 @@ int device_any_busy_check(void) int device_busy_check(struct device *chk_dev) { if (atomic_test_bit((const atomic_t *)__device_busy_start, - (chk_dev - __device_init_start))) { + (chk_dev - __device_start))) { return -EBUSY; } return 0; @@ -158,7 +162,7 @@ void device_busy_set(struct device *busy_dev) { #ifdef CONFIG_DEVICE_POWER_MANAGEMENT atomic_set_bit((atomic_t *) __device_busy_start, - (busy_dev - __device_init_start)); + (busy_dev - __device_start)); #else ARG_UNUSED(busy_dev); #endif @@ -168,7 +172,7 @@ void device_busy_clear(struct device *busy_dev) { #ifdef CONFIG_DEVICE_POWER_MANAGEMENT atomic_clear_bit((atomic_t *) __device_busy_start, - (busy_dev - __device_init_start)); + (busy_dev - __device_start)); #else ARG_UNUSED(busy_dev); #endif diff --git a/kernel/init.c b/kernel/init.c index 8ae3df128fa..c8e042441f0 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -213,7 +213,7 @@ static void bg_thread_main(void *unused1, void *unused2, void *unused3) z_sys_post_kernel = true; - z_sys_device_do_config_level(_SYS_INIT_LEVEL_POST_KERNEL); + z_sys_init_run_level(_SYS_INIT_LEVEL_POST_KERNEL); #if CONFIG_STACK_POINTER_RANDOM z_stack_adjust_initialized = 1; #endif @@ -234,7 +234,7 @@ static void bg_thread_main(void *unused1, void *unused2, void *unused3) #endif /* Final init level before app starts */ - z_sys_device_do_config_level(_SYS_INIT_LEVEL_APPLICATION); + z_sys_init_run_level(_SYS_INIT_LEVEL_APPLICATION); #ifdef CONFIG_CPLUSPLUS /* Process the .ctors and .init_array sections */ @@ -248,7 +248,7 @@ static void bg_thread_main(void *unused1, void *unused2, void *unused3) #ifdef CONFIG_SMP z_smp_init(); - z_sys_device_do_config_level(_SYS_INIT_LEVEL_SMP); + z_sys_init_run_level(_SYS_INIT_LEVEL_SMP); #endif #ifdef CONFIG_BOOT_TIME_MEASUREMENT @@ -488,8 +488,8 @@ FUNC_NORETURN void z_cstart(void) #endif /* perform basic hardware initialization */ - z_sys_device_do_config_level(_SYS_INIT_LEVEL_PRE_KERNEL_1); - z_sys_device_do_config_level(_SYS_INIT_LEVEL_PRE_KERNEL_2); + z_sys_init_run_level(_SYS_INIT_LEVEL_PRE_KERNEL_1); + z_sys_init_run_level(_SYS_INIT_LEVEL_PRE_KERNEL_2); #ifdef CONFIG_STACK_CANARIES z_early_boot_rand_get((u8_t *)&stack_guard, sizeof(stack_guard)); diff --git a/subsys/shell/modules/device_service.c b/subsys/shell/modules/device_service.c index 4d6f799275d..3b02611ef2d 100644 --- a/subsys/shell/modules/device_service.c +++ b/subsys/shell/modules/device_service.c @@ -10,18 +10,18 @@ #include #include -extern struct device __device_init_start[]; +extern struct device __device_start[]; extern struct device __device_PRE_KERNEL_1_start[]; extern struct device __device_PRE_KERNEL_2_start[]; extern struct device __device_POST_KERNEL_start[]; extern struct device __device_APPLICATION_start[]; -extern struct device __device_init_end[]; +extern struct device __device_end[]; #ifdef CONFIG_SMP extern struct device __device_SMP_start[]; #endif -static struct device *config_levels[] = { +static struct device *levels[] = { __device_PRE_KERNEL_1_start, __device_PRE_KERNEL_2_start, __device_POST_KERNEL_start, @@ -30,20 +30,20 @@ static struct device *config_levels[] = { __device_SMP_start, #endif /* End marker */ - __device_init_end, + __device_end, }; static bool device_get_config_level(const struct shell *shell, int level) { - struct device *info; + struct device *dev; bool devices = false; - for (info = config_levels[level]; info < config_levels[level+1]; - info++) { - if (info->driver_api != NULL) { + for (dev = levels[level]; dev < levels[level+1]; dev++) { + if (dev->driver_api != NULL) { devices = true; + shell_fprintf(shell, SHELL_NORMAL, "- %s\n", - info->config->name); + dev->config->name); } } return devices; @@ -86,27 +86,30 @@ static int cmd_device_levels(const struct shell *shell, static int cmd_device_list(const struct shell *shell, size_t argc, char **argv) { - struct device *info; + struct device *dev; ARG_UNUSED(argc); ARG_UNUSED(argv); shell_fprintf(shell, SHELL_NORMAL, "devices:\n"); - for (info = __device_init_start; info != __device_init_end; info++) { - if (info->driver_api != NULL) { - shell_fprintf(shell, SHELL_NORMAL, "- %s", - info->config->name); -#ifdef CONFIG_DEVICE_POWER_MANAGEMENT - u32_t state = DEVICE_PM_ACTIVE_STATE; - int err; - err = device_get_power_state(info, &state); - if (!err) { - shell_fprintf(shell, SHELL_NORMAL, " (%s)", - device_pm_state_str(state)); - } -#endif /* CONFIG_DEVICE_POWER_MANAGEMENT */ - shell_fprintf(shell, SHELL_NORMAL, "\n"); + for (dev = __device_start; dev != __device_end; dev++) { + if (dev->driver_api == NULL) { + continue; } + + shell_fprintf(shell, SHELL_NORMAL, "- %s", dev->config->name); + +#ifdef CONFIG_DEVICE_POWER_MANAGEMENT + u32_t state = DEVICE_PM_ACTIVE_STATE; + int err; + + err = device_get_power_state(dev, &state); + if (!err) { + shell_fprintf(shell, SHELL_NORMAL, " (%s)", + device_pm_state_str(state)); + } +#endif /* CONFIG_DEVICE_POWER_MANAGEMENT */ + shell_fprintf(shell, SHELL_NORMAL, "\n"); } return 0;