device: perform dynamic device initialization during system startup
Initialize all device objects in a batch before invoking any code that might try to reference data in them. This eliminates a race condition enabled by the ability to resolve a device structure at build time, and reference it from one device's initialization routine before the device itself has been initialized. While the device is pulled from the sys_init records rather than static devices, all in-tree init_entry records that are associated with devices are produced via Z_DEVICE_DEFINE(), so there should be no static devices that would be missed by instead iterating over the device records. Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
This commit is contained in:
parent
a955c9e1aa
commit
1cadd8b305
3 changed files with 21 additions and 4 deletions
|
@ -31,6 +31,22 @@ extern uint32_t __device_busy_end[];
|
|||
#define DEVICE_BUSY_SIZE (__device_busy_end - __device_busy_start)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize state for all static devices.
|
||||
*
|
||||
* The state object is always zero-initialized, but this may not be
|
||||
* sufficient.
|
||||
*/
|
||||
void z_device_state_init(void)
|
||||
{
|
||||
const struct device *dev = __device_start;
|
||||
|
||||
while (dev < __device_end) {
|
||||
z_object_init(dev);
|
||||
++dev;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Execute all the init entry initialization functions at a given level
|
||||
*
|
||||
|
@ -60,10 +76,6 @@ void z_sys_init_run_level(int32_t level)
|
|||
for (entry = levels[level]; entry < levels[level+1]; entry++) {
|
||||
const struct device *dev = entry->dev;
|
||||
|
||||
if (dev != NULL) {
|
||||
z_object_init(dev);
|
||||
}
|
||||
|
||||
if ((entry->init(dev) != 0) && (dev != NULL)) {
|
||||
/* Initialization failed.
|
||||
* Set the init status bit so device is not declared ready.
|
||||
|
|
|
@ -37,6 +37,8 @@ static inline void z_data_copy(void)
|
|||
#endif
|
||||
FUNC_NORETURN void z_cstart(void);
|
||||
|
||||
void z_device_state_init(void);
|
||||
|
||||
extern FUNC_NORETURN void z_thread_entry(k_thread_entry_t entry,
|
||||
void *p1, void *p2, void *p3);
|
||||
|
||||
|
|
|
@ -386,6 +386,9 @@ FUNC_NORETURN void z_cstart(void)
|
|||
#if defined(CONFIG_MMU) && defined(CONFIG_USERSPACE)
|
||||
z_kernel_map_fixup();
|
||||
#endif
|
||||
/* do any necessary initialization of static devices */
|
||||
z_device_state_init();
|
||||
|
||||
/* perform basic hardware initialization */
|
||||
z_sys_init_run_level(_SYS_INIT_LEVEL_PRE_KERNEL_1);
|
||||
z_sys_init_run_level(_SYS_INIT_LEVEL_PRE_KERNEL_2);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue