device: provide internal access to static device array

Device objects in Zephyr are currently placed into an array by linker
scripts, making it easy to iterate over all devices if the array
address and size can be obtained.  This has applications in device
power management, but the existing API for this was available only
when that feature was enabled.  It also uses a signed type to hold the
device count.

Provide a new API that is generally available, but marked as internal
since normally applications should not iterate over all devices.  Mark
the PM API approach deprecated.

Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
This commit is contained in:
Peter Bigot 2020-06-22 08:55:37 -05:00 committed by Carles Cufí
commit 219a3ca96d
5 changed files with 26 additions and 15 deletions

View file

@ -299,7 +299,7 @@ Get Device List
.. code-block:: c .. code-block:: c
void device_list_get(struct device **device_list, int *device_count); size_t z_device_get_all_static(struct device **device_list);
The Zephyr RTOS kernel internally maintains a list of all devices in the system. The Zephyr RTOS kernel internally maintains a list of all devices in the system.
The SOC interface uses this API to get the device list. The SOC interface can use the list to The SOC interface uses this API to get the device list. The SOC interface can use the list to

View file

@ -230,6 +230,16 @@ struct device {
*/ */
__syscall struct device *device_get_binding(const char *name); __syscall struct device *device_get_binding(const char *name);
/** @brief Get access to the static array of static devices.
*
* @param devices where to store the pointer to the array of
* statically allocated devices. The array must not be mutated
* through this pointer.
*
* @return the number of statically allocated devices.
*/
size_t z_device_get_all_static(struct device **devices);
/** /**
* @} * @}
*/ */
@ -403,8 +413,13 @@ static inline int device_get_power_state(struct device *device,
* *
* @param device_list Pointer to receive the device list array * @param device_list Pointer to receive the device list array
* @param device_count Pointer to receive the device count * @param device_count Pointer to receive the device count
*
* @deprecated in 2.4 release, replace with z_device_get_all_static()
*/ */
void device_list_get(struct device **device_list, int *device_count); __deprecated static inline void device_list_get(struct device **device_list, int *device_count)
{
*device_count = z_device_get_all_static(device_list);
}
/** /**
* @brief Check if any device is in the middle of a transaction * @brief Check if any device is in the middle of a transaction

View file

@ -117,6 +117,12 @@ static inline struct device *z_vrfy_device_get_binding(const char *name)
#include <syscalls/device_get_binding_mrsh.c> #include <syscalls/device_get_binding_mrsh.c>
#endif /* CONFIG_USERSPACE */ #endif /* CONFIG_USERSPACE */
size_t z_device_get_all_static(struct device **devices)
{
*devices = __device_start;
return __device_end - __device_start;
}
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT #ifdef CONFIG_DEVICE_POWER_MANAGEMENT
int device_pm_control_nop(struct device *unused_device, int device_pm_control_nop(struct device *unused_device,
uint32_t unused_ctrl_command, uint32_t unused_ctrl_command,
@ -127,14 +133,6 @@ int device_pm_control_nop(struct device *unused_device,
return -ENOTSUP; return -ENOTSUP;
} }
void device_list_get(struct device **device_list, int *device_count)
{
*device_list = __device_start;
*device_count = __device_end - __device_start;
}
int device_any_busy_check(void) int device_any_busy_check(void)
{ {
int i = 0; int i = 0;

View file

@ -149,7 +149,7 @@ void sys_pm_resume_devices(void)
void sys_pm_create_device_list(void) void sys_pm_create_device_list(void)
{ {
int count; size_t count = z_device_get_all_static(&all_devices);
device_idx_t pmi; device_idx_t pmi;
/* /*
@ -157,9 +157,8 @@ void sys_pm_create_device_list(void)
* Ordering should be done based on dependencies. Devices * Ordering should be done based on dependencies. Devices
* in the beginning of the list will be resumed first. * in the beginning of the list will be resumed first.
*/ */
device_list_get(&all_devices, &count);
__ASSERT_NO_MSG((0 <= count) && (count <= DEVICE_IDX_MAX)); __ASSERT_NO_MSG(count <= DEVICE_IDX_MAX);
/* Reserve initial slots for core devices. */ /* Reserve initial slots for core devices. */
num_pm = ARRAY_SIZE(core_devices); num_pm = ARRAY_SIZE(core_devices);

View file

@ -177,10 +177,9 @@ void test_pre_kernel_detection(void)
*/ */
static void test_build_suspend_device_list(void) static void test_build_suspend_device_list(void)
{ {
int devcount;
struct device *devices; struct device *devices;
size_t devcount = z_device_get_all_static(&devices);
device_list_get(&devices, &devcount);
zassert_false((devcount == 0), NULL); zassert_false((devcount == 0), NULL);
} }