device: store initialization status in the state structure

Separate the state indicator of whether the initialization function
has been invoked from the success or failure of the initialization.
This allows precise confirmation that the device is ready (i.e. it has
been initialized, and that initialization succeeded).

Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
This commit is contained in:
Peter Bigot 2021-02-02 10:23:55 -06:00 committed by Anas Nashif
commit 65eee5cb47
3 changed files with 29 additions and 16 deletions

View file

@ -293,6 +293,20 @@ struct device_pm {
* before they are accessed.
*/
struct device_state {
/** Non-negative result of initializing the device.
*
* The absolute value returned when the device initialization
* function was invoked, or `UINT8_MAX` if the value exceeds
* an 8-bit integer. If initialized is also set, a zero value
* indicates initialization succeeded.
*/
unsigned int init_res : 8;
/** Indicates the device initialization function has been
* invoked.
*/
bool initialized : 1;
#ifdef CONFIG_PM_DEVICE
/* Power management data */
struct device_pm pm;

View file

@ -24,12 +24,6 @@
((__device_end - __device_start) / _DEVICE_STRUCT_SIZEOF)
#define DEVICE_BITFIELD_SIZE (((DEVICE_COUNT + 31) / 32) * 4)
#define DEVICE_INIT_STATUS_BITFIELD() \
FILL(0x00); \
__device_init_status_start = .; \
. = . + DEVICE_BITFIELD_SIZE; \
__device_init_status_end = .;
#ifdef CONFIG_PM_DEVICE
#define DEVICE_BUSY_BITFIELD() \
FILL(0x00); \
@ -53,7 +47,6 @@
CREATE_OBJ_LEVEL(device, APPLICATION)
CREATE_OBJ_LEVEL(device, SMP)
__device_end = .;
DEVICE_INIT_STATUS_BITFIELD()
DEVICE_BUSY_BITFIELD()
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

View file

@ -91,14 +91,22 @@ void z_sys_init_run_level(int32_t level)
for (entry = levels[level]; entry < levels[level+1]; entry++) {
const struct device *dev = entry->dev;
int rc = entry->init(dev);
if ((entry->init(dev) != 0) && (dev != NULL)) {
/* Initialization failed.
* Set the init status bit so device is not declared ready.
if (dev != NULL) {
/* Mark device initialized. If initialization
* failed, record the error condition.
*/
sys_bitfield_set_bit(
(mem_addr_t) __device_init_status_start,
(dev - __device_start));
if (rc != 0) {
if (rc < 0) {
rc = -rc;
}
if (rc > UINT8_MAX) {
rc = UINT8_MAX;
}
dev->state->init_res = rc;
}
dev->state->initialized = true;
}
}
}
@ -157,9 +165,7 @@ size_t z_device_get_all_static(struct device const **devices)
bool z_device_ready(const struct device *dev)
{
/* Set bit indicates device failed initialization */
return !(sys_bitfield_test_bit((mem_addr_t)__device_init_status_start,
(dev - __device_start)));
return dev->state->initialized && (dev->state->init_res == 0);
}
#ifdef CONFIG_PM_DEVICE