diff --git a/apps/data_logger/src/main.c b/apps/data_logger/src/main.c index 0b4235a95..c4c5bc13a 100644 --- a/apps/data_logger/src/main.c +++ b/apps/data_logger/src/main.c @@ -161,7 +161,8 @@ TASK_SCHEDULE_STATES_DEFINE(states, schedules); TASK_RUNNER_TASKS_DEFINE(app_tasks, app_tasks_data, (TDF_LOGGER_TASK, custom_tdf_logger), (IMU_TASK, DEVICE_DT_GET(DT_ALIAS(imu0))), GNSS_TASK_DEFINE, (BATTERY_TASK, DEVICE_DT_GET(DT_ALIAS(fuel_gauge0))), - (ENVIRONMENTAL_TASK, DEVICE_DT_GET(DT_ALIAS(environmental0)))); + (ENVIRONMENTAL_TASK, DEVICE_DT_GET(DT_ALIAS(environmental0)), + DEVICE_DT_GET_OR_NULL(DT_ALIAS(environmental1)))); static void custom_tdf_logger(uint8_t tdf_loggers, uint64_t timestamp) { diff --git a/apps/gateway_lte/src/main.c b/apps/gateway_lte/src/main.c index 6258396a7..f380af63a 100644 --- a/apps/gateway_lte/src/main.c +++ b/apps/gateway_lte/src/main.c @@ -111,7 +111,9 @@ static const struct task_schedule schedules[] = { }; #if DT_NODE_EXISTS(DT_ALIAS(environmental0)) -#define ENV_TASK_DEFINE (ENVIRONMENTAL_TASK, DEVICE_DT_GET(DT_ALIAS(environmental0))) +#define ENV_TASK_DEFINE \ + (ENVIRONMENTAL_TASK, DEVICE_DT_GET(DT_ALIAS(environmental0)), \ + DEVICE_DT_GET_OR_NULL(DT_ALIAS(environmental1))) #else #define ENV_TASK_DEFINE #endif diff --git a/apps/lte_tracker/src/main.c b/apps/lte_tracker/src/main.c index 2a82bb5ef..d277dc016 100644 --- a/apps/lte_tracker/src/main.c +++ b/apps/lte_tracker/src/main.c @@ -125,7 +125,9 @@ static const struct task_schedule schedules[] = { }; #if DT_NODE_EXISTS(DT_ALIAS(environmental0)) -#define ENV_TASK_DEFINE (ENVIRONMENTAL_TASK, DEVICE_DT_GET(DT_ALIAS(environmental0))) +#define ENV_TASK_DEFINE \ + (ENVIRONMENTAL_TASK, DEVICE_DT_GET(DT_ALIAS(environmental0)), \ + DEVICE_DT_GET_OR_NULL(DT_ALIAS(environmental1))) #else #define ENV_TASK_DEFINE #endif diff --git a/boards/embeint/auroch/auroch_nrf9151_common.dtsi b/boards/embeint/auroch/auroch_nrf9151_common.dtsi index b1a2bf9b3..9cb2f456b 100644 --- a/boards/embeint/auroch/auroch_nrf9151_common.dtsi +++ b/boards/embeint/auroch/auroch_nrf9151_common.dtsi @@ -57,6 +57,7 @@ gnss = &max_m10; watchdog0 = &wdt0; environmental0 = &sht4x; + environmental1 = &lps22hh; }; }; diff --git a/boards/embeint/kudu/kudu_cpuapp_common.dtsi b/boards/embeint/kudu/kudu_cpuapp_common.dtsi index 38d1f96f2..dd5352f1c 100644 --- a/boards/embeint/kudu/kudu_cpuapp_common.dtsi +++ b/boards/embeint/kudu/kudu_cpuapp_common.dtsi @@ -54,6 +54,7 @@ watchdog0 = &wdt31; fuel-gauge0 = &fuel_gauge; environmental0 = &sht4x; + environmental1 = &lps22hh; imu0 = &lsm6dsv; modem = &telit_le910c1; }; diff --git a/drivers/sensor/generic_sim.c b/drivers/sensor/generic_sim.c index e9197d04a..1f5ba6655 100644 --- a/drivers/sensor/generic_sim.c +++ b/drivers/sensor/generic_sim.c @@ -13,12 +13,16 @@ #include #include #include +#include #include struct generic_sim_data { struct sensor_value channel_values[SENSOR_CHAN_ALL]; ATOMIC_DEFINE(channels_set, SENSOR_CHAN_ALL); + int resume_rc; + int suspend_rc; + int fetch_rc; }; struct generic_sim_cfg { @@ -27,11 +31,25 @@ struct generic_sim_cfg { LOG_MODULE_DECLARE(GENERIC_SIM, CONFIG_SENSOR_LOG_LEVEL); -void generic_sim_reset(const struct device *dev) +void generic_sim_reset(const struct device *dev, bool reset_rc) { struct generic_sim_data *data = dev->data; memset(data->channels_set, 0, sizeof(data->channels_set)); + if (reset_rc) { + data->resume_rc = 0; + data->suspend_rc = 0; + data->fetch_rc = 0; + } +} + +void generic_sim_func_rc(const struct device *dev, int resume_rc, int suspend_rc, int fetch_rc) +{ + struct generic_sim_data *data = dev->data; + + data->resume_rc = resume_rc; + data->suspend_rc = suspend_rc; + data->fetch_rc = fetch_rc; } int generic_sim_channel_set(const struct device *dev, enum sensor_channel chan, @@ -50,7 +68,13 @@ int generic_sim_channel_set(const struct device *dev, enum sensor_channel chan, static int generic_sim_sample_fetch(const struct device *dev, enum sensor_channel chan) { - return 0; + struct generic_sim_data *data = dev->data; + + if (chan > SENSOR_CHAN_ALL) { + return -ENOTSUP; + } + + return data->fetch_rc; } static int generic_sim_channel_get(const struct device *dev, enum sensor_channel chan, @@ -71,6 +95,26 @@ static int generic_sim_channel_get(const struct device *dev, enum sensor_channel return 0; } +#ifdef CONFIG_PM_DEVICE +static int generic_sim_pm_control(const struct device *dev, enum pm_device_action action) +{ + struct generic_sim_data *data = dev->data; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + return data->suspend_rc; + case PM_DEVICE_ACTION_RESUME: + return data->resume_rc; + case PM_DEVICE_ACTION_TURN_OFF: + return 0; + case PM_DEVICE_ACTION_TURN_ON: + return 0; + default: + return -ENOTSUP; + } +} +#endif /* CONFIG_PM_DEVICE */ + static const struct sensor_driver_api generic_sim_driver_api = { .sample_fetch = generic_sim_sample_fetch, .channel_get = generic_sim_channel_get, @@ -88,8 +132,10 @@ int generic_sim_init(const struct device *dev) .init_rc = -DT_INST_PROP(inst, negated_init_rc), \ }; \ static struct generic_sim_data generic_sim_data_##inst; \ - SENSOR_DEVICE_DT_INST_DEFINE(inst, generic_sim_init, NULL, &generic_sim_data_##inst, \ - &generic_sim_cfg_##inst, POST_KERNEL, \ - CONFIG_SENSOR_INIT_PRIORITY, &generic_sim_driver_api); + PM_DEVICE_DT_INST_DEFINE(inst, generic_sim_pm_control); \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, generic_sim_init, PM_DEVICE_DT_INST_GET(inst), \ + &generic_sim_data_##inst, &generic_sim_cfg_##inst, \ + POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ + &generic_sim_driver_api); DT_INST_FOREACH_STATUS_OKAY(GENERIC_SIM_DEFINE) diff --git a/dts/bindings/sensor/zephyr,generic-sim-sensor.yaml b/dts/bindings/sensor/zephyr,generic-sim-sensor.yaml index ee1d4647b..1d9d9bc49 100644 --- a/dts/bindings/sensor/zephyr,generic-sim-sensor.yaml +++ b/dts/bindings/sensor/zephyr,generic-sim-sensor.yaml @@ -6,6 +6,8 @@ description: | compatible: "zephyr,generic-sim-sensor" +include: [sensor-device.yaml] + properties: negated-init-rc: type: int diff --git a/include/infuse/drivers/sensor/generic_sim.h b/include/infuse/drivers/sensor/generic_sim.h index 86b4aa06e..047e10cb7 100644 --- a/include/infuse/drivers/sensor/generic_sim.h +++ b/include/infuse/drivers/sensor/generic_sim.h @@ -21,8 +21,19 @@ extern "C" { * @brief Reset all channels back to unconfigured * * @param dev Generic simulator sensor device to reset + * @param reset_rc Reset the return codes */ -void generic_sim_reset(const struct device *dev); +void generic_sim_reset(const struct device *dev, bool reset_rc); + +/** + * @brief Configure return value for generic sensor device + * + * @param dev Generic simulator sensor device to reset + * @param resume_rc Return code for @a PM_DEVICE_ACTION_RESUME + * @param suspend_rc Return code for @a PM_DEVICE_ACTION_SUSPEND + * @param fetch_rc Return code for @a sensor_sample_fetch + */ +void generic_sim_func_rc(const struct device *dev, int resume_rc, int suspend_rc, int fetch_rc); /** * @brief Set the value to be returned for a given channel diff --git a/include/infuse/task_runner/tasks/environmental.h b/include/infuse/task_runner/tasks/environmental.h index e3dbbdd9c..ac724715e 100644 --- a/include/infuse/task_runner/tasks/environmental.h +++ b/include/infuse/task_runner/tasks/environmental.h @@ -21,6 +21,14 @@ extern "C" { #endif +/** Configuration struct to hold multiple devices */ +struct task_environmental_devices { + /** Primary environmental sensor, used in preference to @a secondary */ + const struct device *primary; + /** Secondary environmental sensor, used if a channel doesn't exist on @a primary */ + const struct device *secondary; +}; + /** * @brief Environmental task function * @@ -33,14 +41,18 @@ void environmental_task_fn(struct k_work *work); * * @param define_mem Define memory * @param define_config Define task - * @param env_ptr Environmental sensing device bound to task + * @param env_primary Environmental sensing device bound to task (Primary) + * @param env_secondary Environmental sensing device bound to task (Seconday, optional) */ -#define ENVIRONMENTAL_TASK(define_mem, define_config, env_ptr) \ +#define ENVIRONMENTAL_TASK(define_mem, define_config, env_primary, env_secondary) \ + IF_ENABLED(define_mem, (const struct task_environmental_devices _env_task_devices = { \ + .primary = env_primary, \ + .secondary = env_secondary, \ + })) \ IF_ENABLED(define_config, ({.name = "env", \ .task_id = TASK_ID_ENVIRONMENTAL, \ .exec_type = TASK_EXECUTOR_WORKQUEUE, \ - .flags = TASK_FLAG_ARG_IS_DEVICE, \ - .task_arg.dev = env_ptr, \ + .task_arg.const_arg = &_env_task_devices, \ .executor.workqueue = { \ .worker_fn = environmental_task_fn, \ }})) diff --git a/samples/validation/src/main.c b/samples/validation/src/main.c index 4dc4afc77..619cbb9ea 100644 --- a/samples/validation/src/main.c +++ b/samples/validation/src/main.c @@ -61,16 +61,24 @@ K_THREAD_DEFINE(imu_thread, 2048, imu_validator, NULL, NULL, NULL, 5, 0, 0); #endif /* DT_NODE_EXISTS(DT_ALIAS(imu0)) */ #if DT_NODE_EXISTS(DT_ALIAS(environmental0)) -static int env_validator(void *a, void *b, void *c) + +static void env_validation_run(const struct device *dev) { atomic_inc(&validators_registered); - if (infuse_validation_env(DEVICE_DT_GET(DT_ALIAS(environmental0)), VALIDATION_ENV_DRIVER) == - 0) { + if (infuse_validation_env(dev, VALIDATION_ENV_DRIVER) == 0) { atomic_inc(&validators_passed); } else { atomic_inc(&validators_failed); } atomic_inc(&validators_complete); +} + +static int env_validator(void *a, void *b, void *c) +{ + env_validation_run(DEVICE_DT_GET(DT_ALIAS(environmental0))); +#if DT_NODE_EXISTS(DT_ALIAS(environmental1)) + env_validation_run(DEVICE_DT_GET(DT_ALIAS(environmental1))); +#endif /* DT_NODE_EXISTS(DT_ALIAS(environmental1)) */ k_sem_give(&task_complete); return 0; } diff --git a/subsys/data_logger/data_logger.c b/subsys/data_logger/data_logger.c index 525512c55..6ddae8bb3 100644 --- a/subsys/data_logger/data_logger.c +++ b/subsys/data_logger/data_logger.c @@ -502,7 +502,7 @@ int data_logger_block_read(const struct device *dev, uint32_t block_idx, uint16_ LOG_ERR("%s failed to read from backend", dev->name); } /* Read data remaining after wrap */ - if (second_read) { + if (second_read && (rc == 0)) { block = (uint8_t *)block + block_len; LOG_DBG("%s reading remaining %d bytes", dev->name, second_read); rc = api->read(dev, 0, 0, block, second_read); diff --git a/subsys/task_runner/tasks/task_environmental.c b/subsys/task_runner/tasks/task_environmental.c index d5f961a37..e21721e4e 100644 --- a/subsys/task_runner/tasks/task_environmental.c +++ b/subsys/task_runner/tasks/task_environmental.c @@ -22,48 +22,106 @@ LOG_MODULE_REGISTER(task_env, CONFIG_TASK_ENVIRONMENTAL_LOG_LEVEL); INFUSE_ZBUS_CHAN_DEFINE(INFUSE_ZBUS_CHAN_AMBIENT_ENV); #define ZBUS_CHAN INFUSE_ZBUS_CHAN_GET(INFUSE_ZBUS_CHAN_AMBIENT_ENV) -void environmental_task_fn(struct k_work *work) +static int env_fetch(const struct device *dev) { - struct task_data *task = task_data_from_work(work); - const struct task_schedule *sch = task_schedule_from_data(task); - const struct device *env = task->executor.workqueue.task_arg.const_arg; - struct tdf_ambient_temp_pres_hum tdf_tph; - struct tdf_ambient_temperature tdf_temp; - struct sensor_value value; - bool has_pressure; - bool has_humidity; int rc; + /* Validate existence and init state */ + if (dev == NULL) { + return -ENODEV; + } + if (!device_is_ready(dev)) { + LOG_WRN_ONCE("%s not ready", dev->name); + return -ENODEV; + } /* Request sensor to be powered */ - rc = pm_device_runtime_get(env); + rc = pm_device_runtime_get(dev); if (rc < 0) { - LOG_ERR("Terminating due to %s", "PM failure"); - return; + return rc; } /* Trigger the sample */ - rc = sensor_sample_fetch(env); + rc = sensor_sample_fetch(dev); if (rc < 0) { - LOG_ERR("Terminating due to %s", "fetch failure"); - return; + /* Release PM constraint */ + (void)pm_device_runtime_put(dev); + return rc; } + return 0; +} - /* Populate the output TDFs */ - rc = sensor_channel_get(env, SENSOR_CHAN_AMBIENT_TEMP, &value); - tdf_tph.temperature = sensor_value_to_milli(&value); - tdf_temp.temperature = tdf_tph.temperature; - rc = sensor_channel_get(env, SENSOR_CHAN_PRESS, &value); - has_pressure = rc == 0; - tdf_tph.pressure = has_pressure ? sensor_value_to_milli(&value) : 0; - rc = sensor_channel_get(env, SENSOR_CHAN_HUMIDITY, &value); - has_humidity = rc == 0; - tdf_tph.humidity = has_humidity ? sensor_value_to_centi(&value) : 0; - - /* Release power requirement */ - rc = pm_device_runtime_put(env); +static void env_release(const struct device *dev, bool sampled) +{ + int rc; + + if (!sampled) { + return; + } + rc = pm_device_runtime_put(dev); if (rc < 0) { LOG_ERR("PM put failure"); } +} + +void environmental_task_fn(struct k_work *work) +{ + struct task_data *task = task_data_from_work(work); + const struct task_schedule *sch = task_schedule_from_data(task); + const struct task_environmental_devices *devices = + task->executor.workqueue.task_arg.const_arg; + const struct device *primary = devices->primary; + const struct device *secondary = devices->secondary; + struct tdf_ambient_temp_pres_hum tdf_tph = {0}; + struct tdf_ambient_temperature tdf_temp = {0}; + struct sensor_value value; + bool primary_sampled = false; + bool secondary_sampled = false; + bool has_pressure = false; + bool has_humidity = false; + int rc; + + /* Sample from provided sensors */ + rc = env_fetch(primary); + if (rc == 0) { + primary_sampled = true; + } + rc = env_fetch(secondary); + if (rc == 0) { + secondary_sampled = true; + } + + if (!primary_sampled && !secondary_sampled) { + LOG_ERR("Terminating due to no samples"); + return; + } + + LOG_DBG("Sources: %d %d", primary_sampled, secondary_sampled); + + /* Populate the output TDFs */ + if ((primary_sampled && + (sensor_channel_get(primary, SENSOR_CHAN_AMBIENT_TEMP, &value) == 0)) || + ((secondary_sampled && + (sensor_channel_get(secondary, SENSOR_CHAN_AMBIENT_TEMP, &value) == 0)))) { + tdf_tph.temperature = sensor_value_to_milli(&value); + tdf_temp.temperature = tdf_tph.temperature; + } + + if ((primary_sampled && (sensor_channel_get(primary, SENSOR_CHAN_PRESS, &value) == 0)) || + ((secondary_sampled && + (sensor_channel_get(secondary, SENSOR_CHAN_PRESS, &value) == 0)))) { + tdf_tph.pressure = sensor_value_to_milli(&value); + has_pressure = true; + } + if ((primary_sampled && (sensor_channel_get(primary, SENSOR_CHAN_HUMIDITY, &value) == 0)) || + ((secondary_sampled && + (sensor_channel_get(secondary, SENSOR_CHAN_HUMIDITY, &value) == 0)))) { + tdf_tph.humidity = sensor_value_to_centi(&value); + has_humidity = true; + } + + /* Release power requirements */ + env_release(primary, primary_sampled); + env_release(secondary, secondary_sampled); /* Log output TDFs */ TASK_SCHEDULE_TDF_LOG(sch, TASK_ENVIRONMENTAL_LOG_TPH, TDF_AMBIENT_TEMP_PRES_HUM, @@ -75,6 +133,6 @@ void environmental_task_fn(struct k_work *work) zbus_chan_pub(ZBUS_CHAN, &tdf_tph, K_FOREVER); /* Print the measured values */ - LOG_INF("%s: T=%6d mDeg P=%6d Pa H=%3d %%", env->name, tdf_tph.temperature, + LOG_INF("T=%6d mDeg P=%6d Pa H=%3d %%", tdf_tph.temperature, has_pressure ? tdf_tph.pressure : -1, has_humidity ? tdf_tph.humidity / 100 : -1); } diff --git a/tests/drivers/sensor/generic_sim/app.overlay b/tests/drivers/sensor/generic_sim/app.overlay index ea58e9adb..a570707cd 100644 --- a/tests/drivers/sensor/generic_sim/app.overlay +++ b/tests/drivers/sensor/generic_sim/app.overlay @@ -15,4 +15,10 @@ status = "okay"; negated-init-rc = <2>; }; + + test_sensor_pm: test_sensor_pm { + compatible = "zephyr,generic-sim-sensor"; + status = "okay"; + zephyr,pm-device-runtime-auto; + }; }; diff --git a/tests/drivers/sensor/generic_sim/src/main.c b/tests/drivers/sensor/generic_sim/src/main.c index 39d56be1e..9298f201b 100644 --- a/tests/drivers/sensor/generic_sim/src/main.c +++ b/tests/drivers/sensor/generic_sim/src/main.c @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -22,8 +23,10 @@ ZTEST(drivers_sensor_generic_sim, test_init_fail) ZTEST(drivers_sensor_generic_sim, test_init_pass) { const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(test_sensor)); + const struct device *dev_pm = DEVICE_DT_GET(DT_NODELABEL(test_sensor_pm)); zassert_true(device_is_ready(dev)); + zassert_true(device_is_ready(dev_pm)); } ZTEST(drivers_sensor_generic_sim, test_invalid_set_get) @@ -35,6 +38,39 @@ ZTEST(drivers_sensor_generic_sim, test_invalid_set_get) zassert_equal(-EINVAL, generic_sim_channel_set(dev, SENSOR_CHAN_ALL + 1, val)); zassert_equal(-ENOTSUP, sensor_channel_get(dev, SENSOR_CHAN_ALL, &val)); zassert_equal(-ENOTSUP, sensor_channel_get(dev, SENSOR_CHAN_ALL + 1, &val)); + + zassert_equal(-ENOTSUP, sensor_sample_fetch_chan(dev, SENSOR_CHAN_ALL + 1)); +} + +ZTEST(drivers_sensor_generic_sim, test_fetch_rc) +{ + const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(test_sensor)); + + zassert_equal(0, sensor_sample_fetch(dev)); + generic_sim_func_rc(dev, 0, 0, -EIO); + zassert_equal(-EIO, sensor_sample_fetch(dev)); + generic_sim_reset(dev, false); + zassert_equal(-EIO, sensor_sample_fetch(dev)); + generic_sim_reset(dev, true); + zassert_equal(0, sensor_sample_fetch(dev)); +} + +ZTEST(drivers_sensor_generic_sim, test_pm) +{ + const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(test_sensor_pm)); + + if (!IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + ztest_test_skip(); + return; + } + + generic_sim_func_rc(dev, -EIO, 0, 0); + zassert_equal(-EIO, pm_device_runtime_get(dev)); + generic_sim_func_rc(dev, 0, -EIO, 0); + zassert_equal(0, pm_device_runtime_get(dev)); + zassert_equal(-EIO, pm_device_runtime_put(dev)); + generic_sim_func_rc(dev, 0, 0, 0); + zassert_equal(0, pm_device_runtime_put(dev)); } ZTEST(drivers_sensor_generic_sim, test_value_echo) @@ -58,7 +94,7 @@ ZTEST(drivers_sensor_generic_sim, test_value_echo) } /* Reset clears all channels */ - generic_sim_reset(dev); + generic_sim_reset(dev, true); for (int i = 0; i < SENSOR_CHAN_ALL; i++) { zassert_equal(-ENOTSUP, sensor_channel_get(dev, i, &val_read)); } @@ -68,7 +104,7 @@ static void before_fn(void *unused) { const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(test_sensor)); - generic_sim_reset(dev); + generic_sim_reset(dev, true); } ZTEST_SUITE(drivers_sensor_generic_sim, NULL, NULL, before_fn, NULL, NULL); diff --git a/tests/drivers/sensor/generic_sim/testcase.yaml b/tests/drivers/sensor/generic_sim/testcase.yaml index 9a5ae5296..f8d763d30 100644 --- a/tests/drivers/sensor/generic_sim/testcase.yaml +++ b/tests/drivers/sensor/generic_sim/testcase.yaml @@ -2,8 +2,13 @@ sample: description: Generic simulated sensor name: Generic simulated sensor +common: + sysbuild: true + integration_platforms: + - native_sim tests: - sensor.generic_sim: - sysbuild: true - integration_platforms: - - native_sim + sensor.generic_sim: {} + sensor.generic_sim.pm: + extra_configs: + - CONFIG_PM_DEVICE=y + - CONFIG_PM_DEVICE_RUNTIME=y diff --git a/tests/subsys/task_runner/tasks/environmental/app.overlay b/tests/subsys/task_runner/tasks/environmental/app.overlay index 83e696a87..16b0ab8d5 100644 --- a/tests/subsys/task_runner/tasks/environmental/app.overlay +++ b/tests/subsys/task_runner/tasks/environmental/app.overlay @@ -13,8 +13,15 @@ zephyr,pm-device-runtime-auto; }; - generic_sim_sensor: generic_sim_sensor { + sim_env0: generic_sim_env0{ compatible = "zephyr,generic-sim-sensor"; status = "okay"; + zephyr,pm-device-runtime-auto; + }; + + sim_env1: generic_sim_env1 { + compatible = "zephyr,generic-sim-sensor"; + status = "okay"; + zephyr,pm-device-runtime-auto; }; }; diff --git a/tests/subsys/task_runner/tasks/environmental/prj.conf b/tests/subsys/task_runner/tasks/environmental/prj.conf index 6471d508e..1e0f72b55 100644 --- a/tests/subsys/task_runner/tasks/environmental/prj.conf +++ b/tests/subsys/task_runner/tasks/environmental/prj.conf @@ -9,3 +9,6 @@ CONFIG_TDF_DATA_LOGGER_SERIAL_DUMMY_BACKEND=y CONFIG_TASK_RUNNER=y CONFIG_TASK_RUNNER_TASK_ENVIRONMENTAL=y CONFIG_TASK_ENVIRONMENTAL_LOG_LEVEL_DBG=y + +CONFIG_PM_DEVICE=y +CONFIG_PM_DEVICE_RUNTIME=y diff --git a/tests/subsys/task_runner/tasks/environmental/src/main.c b/tests/subsys/task_runner/tasks/environmental/src/main.c index 80a9d9606..f7cd51c79 100644 --- a/tests/subsys/task_runner/tasks/environmental/src/main.c +++ b/tests/subsys/task_runner/tasks/environmental/src/main.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -25,13 +26,46 @@ #include #include -#define DEV DEVICE_DT_GET_ANY(zephyr_generic_sim_sensor) -ENVIRONMENTAL_TASK(1, 0, DEV); -struct task_config config = ENVIRONMENTAL_TASK(0, 1, DEV); +#define ENV0 DEVICE_DT_GET(DT_NODELABEL(sim_env0)) +#define ENV1 DEVICE_DT_GET(DT_NODELABEL(sim_env1)) +ENVIRONMENTAL_TASK(1, 0, ENV0, NULL); +struct task_config config = ENVIRONMENTAL_TASK(0, 1, ENV0, NULL); +const struct task_environmental_devices env_task_devices_dual = { + .primary = ENV0, + .secondary = ENV1, +}; +struct task_config config_dual = { + .name = "env", + .task_id = TASK_ID_ENVIRONMENTAL, + .exec_type = TASK_EXECUTOR_WORKQUEUE, + .task_arg.const_arg = &env_task_devices_dual, + .executor.workqueue = + { + .worker_fn = environmental_task_fn, + }, +}; struct task_data data; struct task_schedule schedule; struct task_schedule_state state; +struct test_configuration { + struct { + int32_t temperature; + uint32_t pressure; + uint32_t humidity; + } primary; + struct { + int32_t temperature; + uint32_t pressure; + uint32_t humidity; + } secondary; + struct { + int32_t temperature; + uint32_t pressure; + uint32_t humidity; + } output; +}; + static K_SEM_DEFINE(env_published, 0, 1); static void env_new_data_cb(const struct zbus_channel *chan); @@ -41,6 +75,14 @@ ZBUS_LISTENER_DEFINE(env_listener, env_new_data_cb); ZBUS_CHAN_ADD_OBS(INFUSE_ZBUS_NAME(INFUSE_ZBUS_CHAN_AMBIENT_ENV), env_listener, 5); #define ZBUS_CHAN INFUSE_ZBUS_CHAN_GET(INFUSE_ZBUS_CHAN_AMBIENT_ENV) +static void expected_pm_state(const struct device *dev, enum pm_device_state expected) +{ + enum pm_device_state state; + + zassert_equal(0, pm_device_state_get(dev, &state)); + zassert_equal(expected, state); +} + static void env_new_data_cb(const struct zbus_channel *chan) { k_sem_give(&env_published); @@ -55,7 +97,7 @@ static void task_schedule(struct task_data *data) } static void expect_logging(uint8_t log_mask, int32_t temperature, uint32_t pressure, - uint16_t humidity) + uint32_t humidity) { struct k_fifo *tx_queue = epacket_dummmy_transmit_fifo_get(); struct tdf_parsed tdf; @@ -101,26 +143,42 @@ static void expect_logging(uint8_t log_mask, int32_t temperature, uint32_t press net_buf_unref(pkt); } -static void test_env(int32_t temperature, uint32_t pressure, uint16_t humidity, uint8_t log_mask) +static void test_env(const struct test_configuration *config, uint8_t log_mask) { INFUSE_ZBUS_TYPE(INFUSE_ZBUS_CHAN_AMBIENT_ENV) env_reading; struct sensor_value value; uint32_t pub_count; + /* Reset all channel info */ + generic_sim_reset(ENV0, false); + generic_sim_reset(ENV1, false); + schedule.task_logging[0].tdf_mask = log_mask; schedule.task_logging[0].loggers = TDF_DATA_LOGGER_SERIAL; - if (temperature != 0) { - sensor_value_from_milli(&value, temperature); - generic_sim_channel_set(DEV, SENSOR_CHAN_AMBIENT_TEMP, value); + if (config->primary.temperature != 0) { + sensor_value_from_milli(&value, config->primary.temperature); + generic_sim_channel_set(ENV0, SENSOR_CHAN_AMBIENT_TEMP, value); + } + if (config->primary.pressure != 0) { + sensor_value_from_milli(&value, config->primary.pressure); + generic_sim_channel_set(ENV0, SENSOR_CHAN_PRESS, value); + } + if (config->primary.humidity != 0) { + sensor_value_from_milli(&value, config->primary.humidity); + generic_sim_channel_set(ENV0, SENSOR_CHAN_HUMIDITY, value); + } + if (config->secondary.temperature != 0) { + sensor_value_from_milli(&value, config->secondary.temperature); + generic_sim_channel_set(ENV1, SENSOR_CHAN_AMBIENT_TEMP, value); } - if (pressure != 0) { - sensor_value_from_milli(&value, pressure); - generic_sim_channel_set(DEV, SENSOR_CHAN_PRESS, value); + if (config->secondary.pressure != 0) { + sensor_value_from_milli(&value, config->secondary.pressure); + generic_sim_channel_set(ENV1, SENSOR_CHAN_PRESS, value); } - if (humidity != 0) { - sensor_value_from_milli(&value, humidity); - generic_sim_channel_set(DEV, SENSOR_CHAN_HUMIDITY, value); + if (config->secondary.humidity != 0) { + sensor_value_from_milli(&value, config->secondary.humidity); + generic_sim_channel_set(ENV1, SENSOR_CHAN_HUMIDITY, value); } /* Clear state */ @@ -136,15 +194,27 @@ static void test_env(int32_t temperature, uint32_t pressure, uint16_t humidity, zassert_equal(0, k_work_delayable_busy_get(&data.executor.workqueue.work)); zassert_equal(pub_count + 1, zbus_chan_pub_stats_count(ZBUS_CHAN)); zbus_chan_read(ZBUS_CHAN, &env_reading, K_FOREVER); - zassert_equal(temperature, env_reading.temperature); - zassert_equal(pressure, env_reading.pressure); - zassert_equal(humidity / 10, env_reading.humidity); + zassert_equal(config->output.temperature, env_reading.temperature); + zassert_equal(config->output.pressure, env_reading.pressure); + zassert_equal(config->output.humidity / 10, env_reading.humidity); - expect_logging(log_mask, temperature, pressure, humidity); + expect_logging(log_mask, config->output.temperature, config->output.pressure, + config->output.humidity); } -ZTEST(task_bat, test_only_temperature) +static void test_cfg(const struct test_configuration *config) { + uint8_t log_all = TASK_ENVIRONMENTAL_LOG_TPH | TASK_ENVIRONMENTAL_LOG_T; + + test_env(config, 0); + test_env(config, TASK_ENVIRONMENTAL_LOG_T); + test_env(config, TASK_ENVIRONMENTAL_LOG_TPH); + test_env(config, log_all); +} + +ZTEST(task_env, test_all_errors) +{ + const struct test_configuration c1 = {0}; schedule = (struct task_schedule){ .task_id = TASK_ID_ENVIRONMENTAL, @@ -155,11 +225,19 @@ ZTEST(task_bat, test_only_temperature) task_runner_init(&schedule, &state, 1, &config, &data, 1); /* No channels configured, every reading should fallback to its error state */ - test_env(27123, 0, 0, 0); + test_cfg(&c1); } -ZTEST(task_bat, test_no_log) +ZTEST(task_env, test_temperature_single) { + const struct test_configuration c1 = { + .primary = {.temperature = 27123}, + .output = {.temperature = 27123}, + }; + const struct test_configuration c2 = { + .secondary = {.temperature = 27123}, + }; + schedule = (struct task_schedule){ .task_id = TASK_ID_ENVIRONMENTAL, .validity = TASK_VALID_ALWAYS, @@ -168,13 +246,50 @@ ZTEST(task_bat, test_no_log) /* Setup links between task config and data */ task_runner_init(&schedule, &state, 1, &config, &data, 1); - test_env(-15000, 100567, 56000, 0); - test_env(21795, 100567, 43250, 0); + /* Only temperature, one source */ + test_cfg(&c1); + test_cfg(&c2); } -ZTEST(task_bat, test_log) +ZTEST(task_env, test_temperature_dual) { - uint8_t log_all = TASK_ENVIRONMENTAL_LOG_TPH | TASK_ENVIRONMENTAL_LOG_T; + const struct test_configuration c1 = { + .primary = {.temperature = 27123}, + .output = {.temperature = 27123}, + }; + const struct test_configuration c2 = { + .secondary = {.temperature = 26123}, + .output = {.temperature = 26123}, + }; + const struct test_configuration c3 = { + .primary = {.temperature = 28123}, + .secondary = {.temperature = 26123}, + .output = {.temperature = 28123}, + }; + + schedule = (struct task_schedule){ + .task_id = TASK_ID_ENVIRONMENTAL, + .validity = TASK_VALID_ALWAYS, + }; + + /* Setup links between task config and data */ + task_runner_init(&schedule, &state, 1, &config_dual, &data, 1); + + /* Only temperature, dual source */ + test_cfg(&c1); + test_cfg(&c2); + test_cfg(&c3); +} + +ZTEST(task_env, test_all_single) +{ + const struct test_configuration c1 = { + .primary = {.temperature = 27123, .pressure = 100567, .humidity = 56000}, + .output = {.temperature = 27123, .pressure = 100567, .humidity = 56000}, + }; + const struct test_configuration c2 = { + .secondary = {.temperature = 27123, .pressure = 100567, .humidity = 43250}, + }; schedule = (struct task_schedule){ .task_id = TASK_ID_ENVIRONMENTAL, @@ -184,14 +299,103 @@ ZTEST(task_bat, test_log) /* Setup links between task config and data */ task_runner_init(&schedule, &state, 1, &config, &data, 1); - test_env(37000, 101000, 12568, TASK_ENVIRONMENTAL_LOG_TPH); - test_env(35010, 101222, 12568, TASK_ENVIRONMENTAL_LOG_TPH); + /* All channels, one source */ + test_cfg(&c1); + test_cfg(&c2); +} + +ZTEST(task_env, test_all_dual) +{ + const struct test_configuration c1 = { + .secondary = {.temperature = 8542, .pressure = 101764, .humidity = 28337}, + .output = {.temperature = 8542, .pressure = 101764, .humidity = 28337}, + }; + const struct test_configuration c2 = { + .secondary = {.temperature = -15672, .pressure = 101567, .humidity = 73250}, + .output = {.temperature = -15672, .pressure = 101567, .humidity = 73250}, + }; + const struct test_configuration c3 = { + .primary = {.temperature = 37173, .pressure = 99754, .humidity = 12000}, + .secondary = {.temperature = 27123, .pressure = 106567, .humidity = 18000}, + .output = {.temperature = 37173, .pressure = 99754, .humidity = 12000}, + }; + + schedule = (struct task_schedule){ + .task_id = TASK_ID_ENVIRONMENTAL, + .validity = TASK_VALID_ALWAYS, + }; + + /* Setup links between task config and data */ + task_runner_init(&schedule, &state, 1, &config_dual, &data, 1); + + /* All channels, dual source */ + test_cfg(&c1); + test_cfg(&c2); + test_cfg(&c3); +} + +ZTEST(task_env, test_failures) +{ + const struct test_configuration c1 = { + .primary = {.temperature = 37173, .pressure = 99754, .humidity = 12000}, + .secondary = {.temperature = 27123, .pressure = 106567, .humidity = 18000}, + .output = {.temperature = 27123, .pressure = 106567, .humidity = 18000}, + }; + const struct test_configuration c2 = { + .primary = {.temperature = 47333}, + .secondary = {.temperature = 27123, .pressure = 106567, .humidity = 18000}, + .output = {.temperature = 47333}, + }; + const struct test_configuration c3 = { + .primary = {.pressure = 99758}, + .secondary = {.temperature = 27123, .pressure = 106567, .humidity = 18000}, + .output = {.pressure = 99758}, + }; + uint32_t pub_count; - test_env(12000, 99999, 58123, TASK_ENVIRONMENTAL_LOG_T); - test_env(12010, 100001, 57234, TASK_ENVIRONMENTAL_LOG_T); + schedule = (struct task_schedule){ + .task_id = TASK_ID_ENVIRONMENTAL, + .validity = TASK_VALID_ALWAYS, + }; - test_env(-11571, 105123, 2000, log_all); - test_env(-45002, 102009, 3123, log_all); + /* Setup links between task config and data */ + task_runner_init(&schedule, &state, 1, &config_dual, &data, 1); + + /* Primary device fails for any reason, falls back to secondary */ + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + generic_sim_func_rc(ENV0, -EIO, 0, 0); + test_cfg(&c1); + expected_pm_state(ENV0, PM_DEVICE_STATE_SUSPENDED); + } + generic_sim_func_rc(ENV0, 0, 0, -EIO); + test_cfg(&c1); + expected_pm_state(ENV0, PM_DEVICE_STATE_SUSPENDED); + generic_sim_func_rc(ENV0, 0, 0, 0); + + /* Secondary device fails for any reason */ + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + generic_sim_func_rc(ENV1, -EIO, 0, 0); + test_cfg(&c2); + test_cfg(&c3); + expected_pm_state(ENV1, PM_DEVICE_STATE_SUSPENDED); + } + generic_sim_func_rc(ENV1, 0, 0, -EIO); + test_cfg(&c2); + test_cfg(&c3); + expected_pm_state(ENV1, PM_DEVICE_STATE_SUSPENDED); + generic_sim_func_rc(ENV1, 0, 0, 0); + + /* Both sensors fail, no logging or publishing */ + generic_sim_func_rc(ENV0, 0, 0, -EIO); + generic_sim_func_rc(ENV1, 0, 0, -EIO); + schedule.task_logging[0].tdf_mask = TASK_ENVIRONMENTAL_LOG_TPH | TASK_ENVIRONMENTAL_LOG_T; + schedule.task_logging[0].loggers = TDF_DATA_LOGGER_SERIAL; + + pub_count = zbus_chan_pub_stats_count(ZBUS_CHAN); + task_schedule(&data); + k_sleep(K_MSEC(500)); + zassert_equal(pub_count, zbus_chan_pub_stats_count(ZBUS_CHAN)); + expect_logging(0, 0, 0, 0); } static void logger_before(void *fixture) @@ -199,13 +403,14 @@ static void logger_before(void *fixture) struct k_fifo *tx_queue = epacket_dummmy_transmit_fifo_get(); struct net_buf *pkt; + generic_sim_reset(ENV0, true); + generic_sim_reset(ENV1, true); tdf_data_logger_flush(TDF_DATA_LOGGER_SERIAL); pkt = k_fifo_get(tx_queue, K_MSEC(10)); if (pkt) { net_buf_unref(pkt); } - generic_sim_reset(DEV); k_sem_reset(&env_published); } -ZTEST_SUITE(task_bat, NULL, NULL, logger_before, NULL, NULL); +ZTEST_SUITE(task_env, NULL, NULL, logger_before, NULL, NULL); diff --git a/tests/subsys/task_runner/tasks/environmental/testcase.yaml b/tests/subsys/task_runner/tasks/environmental/testcase.yaml index 1ce3bb3bf..baed17e97 100644 --- a/tests/subsys/task_runner/tasks/environmental/testcase.yaml +++ b/tests/subsys/task_runner/tasks/environmental/testcase.yaml @@ -2,11 +2,16 @@ common: tags: env min_flash: 64 min_ram: 32 + required_snippets: + - infuse + platform_allow: + - mps2/an385 + integration_platforms: + - mps2/an385 + tests: - task_runner.tasks.env: - required_snippets: - - infuse - platform_allow: - - mps2/an385 - integration_platforms: - - mps2/an385 + task_runner.tasks.env: {} + task_runner.tasks.env.pm: + extra_configs: + - CONFIG_PM_DEVICE=y + - CONFIG_PM_DEVICE_RUNTIME=y diff --git a/west.yml b/west.yml index 3fe28a463..a93afd1a2 100644 --- a/west.yml +++ b/west.yml @@ -12,13 +12,14 @@ manifest: projects: - name: zephyr - revision: ceebd3c5b7fd52ee4305fd928054eacb19365884 + revision: 0d3f625a5a7b7bb7cc2628f4efb8a6135cf27927 # Limit imported repositories to reduce clone time import: name-allowlist: - cmsis-dsp - cmsis_6 - hal_nordic + - hal_st - hal_stm32 - hostap - libmetal