diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 0db1debff4d16..64f26fe148ef4 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -27,6 +27,7 @@ config SENSOR_ASYNC_API select RTIO_SYS_MEM_BLOCKS select RTIO_CONSUME_SEM select RTIO_WORKQ + default y help Enables the asynchronous sensor API by leveraging the RTIO subsystem. diff --git a/drivers/sensor/default_rtio_sensor.c b/drivers/sensor/default_rtio_sensor.c index 511ad0b6f0020..ac75e67d235f3 100644 --- a/drivers/sensor/default_rtio_sensor.c +++ b/drivers/sensor/default_rtio_sensor.c @@ -10,17 +10,178 @@ #include #include #include +#include #include #include LOG_MODULE_REGISTER(sensor_compat, CONFIG_SENSOR_LOG_LEVEL); +static struct sensor_chan_spec default_channels[16]; +static struct sensor_read_config default_blocking_read_config = { + .channels = default_channels, + .max = ARRAY_SIZE(default_channels), +}; +RTIO_IODEV_DEFINE(default_blocking_read_rtio_dev, &__sensor_iodev_api, + &default_blocking_read_config); +RTIO_DEFINE(default_blocking_rtio, 4, 4); +K_MUTEX_DEFINE(blocking_rtio_mutex); + /* * Ensure that the size of the generic header aligns with the sensor channel specifier . If it * doesn't, then cores that require aligned memory access will fail to read channel[0]. */ BUILD_ASSERT((sizeof(struct sensor_data_generic_header) % sizeof(struct sensor_chan_spec)) == 0); +static void append_q31_value(size_t idx, int8_t *shift, q31_t *values, size_t num_values, + q31_t new_value, int8_t new_shift) +{ + if (idx == 0 || *shift == new_shift) { + *shift = new_shift; + values[idx] = new_value; + return; + } + if (new_shift < *shift) { + /* Need to shift new_value */ + new_value >>= (*shift - new_shift); + values[idx] = new_value; + return; + } + /* Need to shift all the old values */ + for (size_t i = 0; i < idx; ++i) { + values[i] >>= (new_shift - *shift); + } + values[idx] = new_value; + *shift = new_shift; +} + +int sensor_read_and_decode(const struct device *dev, struct sensor_chan_spec *channels, + size_t num_channels, int8_t *shift, q31_t *values, size_t num_values) +{ + static uint8_t read_buffer[128]; + static uint8_t decode_buffer[128 + sizeof(uintptr_t) - 1]; + const struct sensor_decoder_api *decoder; + int rc; + + k_mutex_lock(&blocking_rtio_mutex, K_FOREVER); + + rc = sensor_reconfigure_read_iodev(&default_blocking_read_rtio_dev, dev, channels, + num_channels); + + if (rc != 0) { + LOG_ERR("Failed to reconfigure RTIO device"); + k_mutex_unlock(&blocking_rtio_mutex); + return rc; + } + + rc = sensor_read(&default_blocking_read_rtio_dev, &default_blocking_rtio, read_buffer, + sizeof(read_buffer)); + if (rc != 0) { + LOG_ERR("Failed to read RTIO device"); + k_mutex_unlock(&blocking_rtio_mutex); + return rc; + } + + rc = sensor_get_decoder(dev, &decoder); + if (rc != 0) { + LOG_ERR("Failed to get decoder"); + k_mutex_unlock(&blocking_rtio_mutex); + return rc; + } + + size_t value_idx = 0; + + for (size_t channel_idx = 0; channel_idx < num_channels && value_idx < num_values; + ++channel_idx) { + size_t base_size; + size_t frame_size; + uint16_t frame_count; + uint32_t fit = 0; + + rc = decoder->get_frame_count(read_buffer, channels[channel_idx], &frame_count); + if (rc != 0) { + LOG_ERR("Failed to get frame count"); + k_mutex_unlock(&blocking_rtio_mutex); + return rc; + } + + if (frame_count == 0) { + LOG_ERR("Data missing for channel %d", channels[channel_idx].chan_type); + k_mutex_unlock(&blocking_rtio_mutex); + return -ENODATA; + } + + if (frame_count > 1) { + LOG_WRN("Too much data for a one shot read, some frames will be skipped"); + } + + rc = decoder->get_size_info(channels[channel_idx], &base_size, &frame_size); + if (rc != 0) { + LOG_ERR("Failed to get decode size requirements"); + k_mutex_unlock(&blocking_rtio_mutex); + return rc; + } + + if (base_size + frame_size > sizeof(decode_buffer)) { + LOG_ERR("Decoded size is too big"); + k_mutex_unlock(&blocking_rtio_mutex); + return -ENOMEM; + } + + size_t alignment; + void *aligned_decode_buffer; + + if (SENSOR_CHANNEL_3_AXIS(channels[channel_idx].chan_type)) { + alignment = _Alignof(struct sensor_three_axis_data); + } else { + alignment = _Alignof(struct sensor_q31_data); + } + + aligned_decode_buffer = (void *)ROUND_UP((uintptr_t)decode_buffer, alignment); + + rc = decoder->decode(read_buffer, channels[channel_idx], &fit, 1, + aligned_decode_buffer); + if (rc <= 0) { + LOG_ERR("Failed to decode frame"); + k_mutex_unlock(&blocking_rtio_mutex); + return rc; + } + + switch (channels[channel_idx].chan_type) { + case SENSOR_CHAN_ACCEL_XYZ: + case SENSOR_CHAN_GYRO_XYZ: + case SENSOR_CHAN_MAGN_XYZ: { + struct sensor_three_axis_data *data = + (struct sensor_three_axis_data *)aligned_decode_buffer; + + LOG_DBG("Adding 3 entries for channel %d", channels[channel_idx].chan_type); + append_q31_value(value_idx++, shift, values, num_values, + data->readings[0].values[0], data->shift); + append_q31_value(value_idx++, shift, values, num_values, + data->readings[0].values[1], data->shift); + append_q31_value(value_idx++, shift, values, num_values, + data->readings[0].values[2], data->shift); + break; + } + default: { + struct sensor_q31_data *data = + (struct sensor_q31_data *)aligned_decode_buffer; + + LOG_DBG("Adding 1 entry for channel %d", channels[channel_idx].chan_type); + append_q31_value(value_idx++, shift, values, num_values, + data->readings[0].value, data->shift); + break; + } + } + } + if (value_idx > num_values) { + LOG_ERR("Wrote too many values, %zu / %zu", value_idx, num_values); + k_mutex_unlock(&blocking_rtio_mutex); + return -ENOMEM; + } + k_mutex_unlock(&blocking_rtio_mutex); + return 0; +} + static void sensor_submit_fallback(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); static void sensor_iodev_submit(struct rtio_iodev_sqe *iodev_sqe) @@ -108,12 +269,7 @@ static inline int check_header_contains_channel(const struct sensor_data_generic return -1; } -/** - * @brief Fallback function for retrofiting old drivers to rtio (sync) - * - * @param[in] iodev_sqe The read submission queue event - */ -static void sensor_submit_fallback_sync(struct rtio_iodev_sqe *iodev_sqe) +void z_impl_sensor_submit_fallback_sync(struct rtio_iodev_sqe *iodev_sqe) { const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; const struct device *dev = cfg->sensor; @@ -134,7 +290,7 @@ static void sensor_submit_fallback_sync(struct rtio_iodev_sqe *iodev_sqe) uint8_t *buf; uint32_t buf_len; - rc = sensor_sample_fetch(dev); + rc = z_impl_sensor_sample_fetch(dev); /* Check that the fetch succeeded */ if (rc != 0) { LOG_WRN("Failed to fetch samples"); @@ -142,7 +298,8 @@ static void sensor_submit_fallback_sync(struct rtio_iodev_sqe *iodev_sqe) return; } - /* Get the buffer for the frame, it may be allocated dynamically by the rtio context */ + /* Get the buffer for the frame, it may be allocated dynamically by the rtio context + */ rc = rtio_sqe_rx_buf(iodev_sqe, min_buf_len, min_buf_len, &buf, &buf_len); if (rc != 0) { LOG_WRN("Failed to get a read buffer of size %u bytes", min_buf_len); @@ -159,32 +316,30 @@ static void sensor_submit_fallback_sync(struct rtio_iodev_sqe *iodev_sqe) q31_t *q = (q31_t *)(buf + compute_header_size(num_output_samples)); + if ((uintptr_t)q % 4 != 0) { + printk(" fixing alignment, q: %p\n", q); + q = (q31_t *)(((uintptr_t)q + 4 - 1) & ~(uintptr_t)0x3); + printk(" q: %p\n", q); + } + /* Populate values, update shift, and set channels */ for (size_t i = 0, sample_idx = 0; i < cfg->count; ++i) { struct sensor_value value[3]; const int num_samples = SENSOR_CHANNEL_3_AXIS(channels[i].chan_type) ? 3 : 1; /* Get the current channel requested by the user */ - rc = sensor_channel_get(dev, channels[i].chan_type, value); + rc = z_impl_sensor_channel_get(dev, channels[i].chan_type, value); if (num_samples == 3) { - header->channels[sample_idx++] = (struct sensor_chan_spec) { - rc == 0 ? channels[i].chan_type - 3 : SENSOR_CHAN_MAX, - 0 - }; - header->channels[sample_idx++] = (struct sensor_chan_spec) { - rc == 0 ? channels[i].chan_type - 2 : SENSOR_CHAN_MAX, - 0 - }; - header->channels[sample_idx++] = (struct sensor_chan_spec) { - rc == 0 ? channels[i].chan_type - 1 : SENSOR_CHAN_MAX, - 0 - }; + header->channels[sample_idx++] = (struct sensor_chan_spec){ + rc == 0 ? channels[i].chan_type - 3 : SENSOR_CHAN_MAX, 0}; + header->channels[sample_idx++] = (struct sensor_chan_spec){ + rc == 0 ? channels[i].chan_type - 2 : SENSOR_CHAN_MAX, 0}; + header->channels[sample_idx++] = (struct sensor_chan_spec){ + rc == 0 ? channels[i].chan_type - 1 : SENSOR_CHAN_MAX, 0}; } else { - header->channels[sample_idx++] = (struct sensor_chan_spec) { - rc == 0 ? channels[i].chan_type : SENSOR_CHAN_MAX, - 0 - }; + header->channels[sample_idx++] = (struct sensor_chan_spec){ + rc == 0 ? channels[i].chan_type : SENSOR_CHAN_MAX, 0}; } if (rc != 0) { @@ -193,19 +348,20 @@ static void sensor_submit_fallback_sync(struct rtio_iodev_sqe *iodev_sqe) continue; } - /* Get the largest absolute value reading to set the scale for the channel */ + /* Get the largest absolute value reading to set the scale for the channel + */ uint32_t header_scale = 0; for (int sample = 0; sample < num_samples; ++sample) { /* * The scale is the ceil(abs(sample)). - * Since we are using fractional values, it's easier to assume that .val2 - * is non 0 and convert this to abs(sample.val1) + 1 (removing a branch). - * Since it's possible that val1 (int32_t) is saturated (INT32_MAX) we need - * to upcast it to 64 bit int first, then take the abs() of that 64 bit - * int before we '+ 1'. Once that's done, we can safely cast back down - * to uint32_t because the min value is 0 and max is INT32_MAX + 1 which - * is less than UINT32_MAX. + * Since we are using fractional values, it's easier to assume that + * .val2 is non 0 and convert this to abs(sample.val1) + 1 (removing + * a branch). Since it's possible that val1 (int32_t) is saturated + * (INT32_MAX) we need to upcast it to 64 bit int first, then take + * the abs() of that 64 bit int before we '+ 1'. Once that's done, + * we can safely cast back down to uint32_t because the min value is + * 0 and max is INT32_MAX + 1 which is less than UINT32_MAX. */ uint32_t scale = (uint32_t)llabs((int64_t)value[sample].val1) + 1; @@ -218,9 +374,9 @@ static void sensor_submit_fallback_sync(struct rtio_iodev_sqe *iodev_sqe) sample_idx -= num_samples; if (header->shift < new_shift) { /* - * Shift was updated, need to convert all the existing q values. This could - * be optimized by calling zdsp_scale_q31() but that would force a - * dependency between sensors and the zDSP subsystem. + * Shift was updated, need to convert all the existing q values. + * This could be optimized by calling zdsp_scale_q31() but that + * would force a dependency between sensors and the zDSP subsystem. */ for (int q_idx = 0; q_idx < sample_idx; ++q_idx) { q[q_idx] = q[q_idx] >> (new_shift - header->shift); @@ -230,8 +386,8 @@ static void sensor_submit_fallback_sync(struct rtio_iodev_sqe *iodev_sqe) /* * Spread the q31 values. This is needed because some channels are 3D. If - * the user specified one of those then num_samples will be 3; and we need to - * produce 3 separate readings. + * the user specified one of those then num_samples will be 3; and we need + * to produce 3 separate readings. */ for (int sample = 0; sample < num_samples; ++sample) { /* Check if the channel is already in the buffer */ @@ -251,14 +407,15 @@ static void sensor_submit_fallback_sync(struct rtio_iodev_sqe *iodev_sqe) int64_t value_u = sensor_value_to_micro(&value[sample]); /* Convert to q31 using the shift */ + q[sample_idx + sample] = - ((value_u * ((INT64_C(1) << 31) - 1)) / 1000000) >> header->shift; + ((value_u * ((INT64_C(1) << (31 - header->shift)) - 1)) / 1000000); - LOG_DBG("value[%d]=%s%d.%06d, q[%d]@%p=%d, shift: %d", - sample, value_u < 0 ? "-" : "", - abs((int)value[sample].val1), abs((int)value[sample].val2), - (int)(sample_idx + sample), (void *)&q[sample_idx + sample], - q[sample_idx + sample], header->shift); + LOG_DBG("value[%d]=%s%d.%06d, q[%d]@%p=%d, shift: %d", sample, + value_u < 0 ? "-" : "", abs((int)value[sample].val1), + abs((int)value[sample].val2), (int)(sample_idx + sample), + (void *)&q[sample_idx + sample], q[sample_idx + sample], + header->shift); } sample_idx += num_samples; } @@ -332,8 +489,10 @@ static int get_frame_count(const uint8_t *buffer, struct sensor_chan_spec channe case SENSOR_CHAN_GYRO_XYZ: case SENSOR_CHAN_MAGN_XYZ: case SENSOR_CHAN_POS_DXYZ: - for (size_t i = 0 ; i < header->num_channels; ++i) { - /* For 3-axis channels, we need to verify we have each individual axis */ + for (size_t i = 0; i < header->num_channels; ++i) { + /* For 3-axis channels, we need to verify we have each individual + * axis + */ struct sensor_chan_spec channel_x = { .chan_type = channel.chan_type - 3, .chan_idx = channel.chan_idx, @@ -347,8 +506,8 @@ static int get_frame_count(const uint8_t *buffer, struct sensor_chan_spec channe .chan_idx = channel.chan_idx, }; - /** The three axes don't need to be at the beginning of the header, but - * they should be consecutive. + /* The three axes don't need to be at the beginning of the header, + * but they should be consecutive. */ if (((header->num_channels - i) >= 3) && sensor_chan_spec_eq(header->channels[i], channel_x) && @@ -378,7 +537,7 @@ int sensor_natively_supported_channel_size_info(struct sensor_chan_spec channel, __ASSERT_NO_MSG(base_size != NULL); __ASSERT_NO_MSG(frame_size != NULL); - if (channel.chan_type >= SENSOR_CHAN_ALL) { + if (channel.chan_type >= SENSOR_CHAN_MAX) { return -ENOTSUP; } @@ -480,19 +639,31 @@ static int decode_q31(const struct sensor_data_generic_header *header, const q31 * @return >0 the number of decoded frames * @return <0 on error */ -static int decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, - uint32_t *fit, uint16_t max_count, void *data_out) +static int decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, uint32_t *fit, + uint16_t max_count, void *data_out) { const struct sensor_data_generic_header *header = (const struct sensor_data_generic_header *)buffer; const q31_t *q = (const q31_t *)(buffer + compute_header_size(header->num_channels)); int count = 0; - if (*fit != 0 || max_count < 1) { + if ((uintptr_t)q % 4 != 0) { + printk(" fixing alignment, q: %p\n", q); + q = (const q31_t *)(((uintptr_t)q + 4 - 1) & ~(uintptr_t)0x3); + printk(" q: %p\n", q); + } + + if (*fit != 0) { + LOG_ERR("Frame iterator MUST be 0"); + return -EINVAL; + } + if (max_count < 1) { + LOG_ERR("max_count CANNOT be 0"); return -EINVAL; } - if (chan_spec.chan_type >= SENSOR_CHAN_ALL) { + if (chan_spec.chan_type >= SENSOR_CHAN_MAX) { + LOG_WRN("Channe type too big"); return 0; } diff --git a/drivers/sensor/sensor_handlers.c b/drivers/sensor/sensor_handlers.c index 9e30024e7687b..8f94881825cb3 100644 --- a/drivers/sensor/sensor_handlers.c +++ b/drivers/sensor/sensor_handlers.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "zephyr/rtio/rtio.h" #include #include @@ -79,4 +80,11 @@ static inline int z_vrfy_sensor_reconfigure_read_iodev(const struct rtio_iodev * return z_impl_sensor_reconfigure_read_iodev(iodev, sensor, channels, num_channels); } #include + +static inline void z_vrfy_sensor_submit_fallback_sync(struct rtio_iodev_sqe *iodev_sqe) +{ + K_OOPS(K_SYSCALL_MEMORY_READ(iodev_sqe, sizeof(struct rtio_iodev_sqe))); + z_impl_sensor_submit_fallback_sync(iodev_sqe); +} +#include #endif diff --git a/include/zephyr/drivers/sensor.h b/include/zephyr/drivers/sensor.h index 2e92f100542f4..235a7ba4a3bb9 100644 --- a/include/zephyr/drivers/sensor.h +++ b/include/zephyr/drivers/sensor.h @@ -404,10 +404,8 @@ typedef void (*sensor_trigger_handler_t)(const struct device *dev, * * See sensor_attr_set() for argument description */ -typedef int (*sensor_attr_set_t)(const struct device *dev, - enum sensor_channel chan, - enum sensor_attribute attr, - const struct sensor_value *val); +typedef int (*sensor_attr_set_t)(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val); /** * @typedef sensor_attr_get_t @@ -415,10 +413,8 @@ typedef int (*sensor_attr_set_t)(const struct device *dev, * * See sensor_attr_get() for argument description */ -typedef int (*sensor_attr_get_t)(const struct device *dev, - enum sensor_channel chan, - enum sensor_attribute attr, - struct sensor_value *val); +typedef int (*sensor_attr_get_t)(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val); /** * @typedef sensor_trigger_set_t @@ -426,8 +422,7 @@ typedef int (*sensor_attr_get_t)(const struct device *dev, * * See sensor_trigger_set() for argument description */ -typedef int (*sensor_trigger_set_t)(const struct device *dev, - const struct sensor_trigger *trig, +typedef int (*sensor_trigger_set_t)(const struct device *dev, const struct sensor_trigger *trig, sensor_trigger_handler_t handler); /** * @typedef sensor_sample_fetch_t @@ -435,16 +430,14 @@ typedef int (*sensor_trigger_set_t)(const struct device *dev, * * See sensor_sample_fetch() for argument description */ -typedef int (*sensor_sample_fetch_t)(const struct device *dev, - enum sensor_channel chan); +typedef int (*sensor_sample_fetch_t)(const struct device *dev, enum sensor_channel chan); /** * @typedef sensor_channel_get_t * @brief Callback API for getting a reading from a sensor * * See sensor_channel_get() for argument description */ -typedef int (*sensor_channel_get_t)(const struct device *dev, - enum sensor_channel chan, +typedef int (*sensor_channel_get_t)(const struct device *dev, enum sensor_channel chan, struct sensor_value *val); /** @@ -478,7 +471,7 @@ static inline bool sensor_chan_spec_eq(struct sensor_chan_spec chan_spec0, struct sensor_chan_spec chan_spec1) { return chan_spec0.chan_type == chan_spec1.chan_type && - chan_spec0.chan_idx == chan_spec1.chan_idx; + chan_spec0.chan_idx == chan_spec1.chan_idx; } /** @@ -588,10 +581,8 @@ struct sensor_decode_context { */ #define SENSOR_DECODE_CONTEXT_INIT(decoder_, buffer_, channel_type_, channel_index_) \ { \ - .decoder = (decoder_), \ - .buffer = (buffer_), \ - .channel = {.chan_type = (channel_type_), .chan_idx = (channel_index_)}, \ - .fit = 0, \ + .decoder = (decoder_), .buffer = (buffer_), \ + .channel = {.chan_type = (channel_type_), .chan_idx = (channel_index_)}, .fit = 0, \ } /** @@ -743,18 +734,13 @@ __subsystem struct sensor_driver_api { * * @return 0 if successful, negative errno code if failure. */ -__syscall int sensor_attr_set(const struct device *dev, - enum sensor_channel chan, - enum sensor_attribute attr, - const struct sensor_value *val); +__syscall int sensor_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val); -static inline int z_impl_sensor_attr_set(const struct device *dev, - enum sensor_channel chan, - enum sensor_attribute attr, - const struct sensor_value *val) +static inline int z_impl_sensor_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) { - const struct sensor_driver_api *api = - (const struct sensor_driver_api *)dev->api; + const struct sensor_driver_api *api = (const struct sensor_driver_api *)dev->api; if (api->attr_set == NULL) { return -ENOSYS; @@ -775,18 +761,13 @@ static inline int z_impl_sensor_attr_set(const struct device *dev, * * @return 0 if successful, negative errno code if failure. */ -__syscall int sensor_attr_get(const struct device *dev, - enum sensor_channel chan, - enum sensor_attribute attr, - struct sensor_value *val); +__syscall int sensor_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val); -static inline int z_impl_sensor_attr_get(const struct device *dev, - enum sensor_channel chan, - enum sensor_attribute attr, - struct sensor_value *val) +static inline int z_impl_sensor_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val) { - const struct sensor_driver_api *api = - (const struct sensor_driver_api *)dev->api; + const struct sensor_driver_api *api = (const struct sensor_driver_api *)dev->api; if (api->attr_get == NULL) { return -ENOSYS; @@ -817,12 +798,10 @@ static inline int z_impl_sensor_attr_get(const struct device *dev, * * @return 0 if successful, negative errno code if failure. */ -static inline int sensor_trigger_set(const struct device *dev, - const struct sensor_trigger *trig, +static inline int sensor_trigger_set(const struct device *dev, const struct sensor_trigger *trig, sensor_trigger_handler_t handler) { - const struct sensor_driver_api *api = - (const struct sensor_driver_api *)dev->api; + const struct sensor_driver_api *api = (const struct sensor_driver_api *)dev->api; if (api->trigger_set == NULL) { return -ENOSYS; @@ -848,13 +827,13 @@ static inline int sensor_trigger_set(const struct device *dev, * @param dev Pointer to the sensor device * * @return 0 if successful, negative errno code if failure. + * @deprecated Use sensor_read_and_decode */ __syscall int sensor_sample_fetch(const struct device *dev); static inline int z_impl_sensor_sample_fetch(const struct device *dev) { - const struct sensor_driver_api *api = - (const struct sensor_driver_api *)dev->api; + const struct sensor_driver_api *api = (const struct sensor_driver_api *)dev->api; return api->sample_fetch(dev, SENSOR_CHAN_ALL); } @@ -879,15 +858,14 @@ static inline int z_impl_sensor_sample_fetch(const struct device *dev) * @param type The channel that needs updated * * @return 0 if successful, negative errno code if failure. + * @deprecated Use sensor_read_and_decode */ -__syscall int sensor_sample_fetch_chan(const struct device *dev, - enum sensor_channel type); +__syscall int sensor_sample_fetch_chan(const struct device *dev, enum sensor_channel type); static inline int z_impl_sensor_sample_fetch_chan(const struct device *dev, enum sensor_channel type) { - const struct sensor_driver_api *api = - (const struct sensor_driver_api *)dev->api; + const struct sensor_driver_api *api = (const struct sensor_driver_api *)dev->api; return api->sample_fetch(dev, type); } @@ -912,21 +890,80 @@ static inline int z_impl_sensor_sample_fetch_chan(const struct device *dev, * @param val Where to store the value * * @return 0 if successful, negative errno code if failure. + * @deprecated Use sensor_read_and_decode */ -__syscall int sensor_channel_get(const struct device *dev, - enum sensor_channel chan, +__syscall int sensor_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val); -static inline int z_impl_sensor_channel_get(const struct device *dev, - enum sensor_channel chan, +static inline int z_impl_sensor_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) { - const struct sensor_driver_api *api = - (const struct sensor_driver_api *)dev->api; + const struct sensor_driver_api *api = (const struct sensor_driver_api *)dev->api; return api->channel_get(dev, chan, val); } +/** + * @param[in] dev Pointer to the sensor device + * @param[in] channels Channels to read + * @param[in] num_channels The number of channels in the channel array + * @param[out] shift The shift value for the result(s) + * @param[out] values The read values. Note that some channels produce more than one value, it's + * the caller's responsibility to allocate enough memory. + * @param[in] num_values The number of allocated values. + * @return 0 if successful, negative errno code on failure. + */ +int sensor_read_and_decode(const struct device *dev, struct sensor_chan_spec *channels, + size_t num_channels, int8_t *shift, q31_t *values, size_t num_values); + +/** + * @brief Fallback function for retrofiting old drivers to rtio (sync) + * + * @param[in] iodev_sqe The read submission queue event + */ +__syscall void sensor_submit_fallback_sync(struct rtio_iodev_sqe *iodev_sqe); + +void z_impl_sensor_submit_fallback_sync(struct rtio_iodev_sqe *iodev_sqe); + +/** + * Convert q31 value to legacy sensor_value + * + * @param[in] value The q31 style value + * @param[in] shift The shift component of the value + * @param[out] val The sensor_value struct to update + */ +static inline void q31_to_sensor_value(q31_t value, int8_t shift, struct sensor_value *val) +{ + int64_t shifted = value; + + if (shift > 0) { + shifted <<= shift; + } else if (shift < 0) { + shifted >>= -shift; + } + val->val1 = shifted >> 31; + val->val2 = CLAMP((shifted & 0x7fffffff) * 1000000 / INT32_MAX, -999999, 999999); +} + +/** + * Converst a q31 value to float + * + * @param[in] value The q31 style value + * @param[in] shift The shift component of the value + * @return Float representation of the q31 value + */ +static inline float q31_to_float(q31_t value, int8_t shift) +{ + int64_t shifted = value; + + if (shift > 0) { + shifted >>= shift; + } else if (shift < 0) { + shifted <<= -shift; + } + return (float)shifted / (float)INT32_MAX; +} + #if defined(CONFIG_SENSOR_ASYNC_API) || defined(__DOXYGEN__) /* @@ -973,8 +1010,8 @@ struct __attribute__((__packed__)) sensor_data_generic_header { * @ref SENSOR_CHAN_ACCEL_Y, or @ref SENSOR_CHAN_ACCEL_Z * @retval false otherwise */ -#define SENSOR_CHANNEL_IS_ACCEL(chan) \ - ((chan) == SENSOR_CHAN_ACCEL_XYZ || (chan) == SENSOR_CHAN_ACCEL_X || \ +#define SENSOR_CHANNEL_IS_ACCEL(chan) \ + ((chan) == SENSOR_CHAN_ACCEL_XYZ || (chan) == SENSOR_CHAN_ACCEL_X || \ (chan) == SENSOR_CHAN_ACCEL_Y || (chan) == SENSOR_CHAN_ACCEL_Z) /** @@ -985,8 +1022,8 @@ struct __attribute__((__packed__)) sensor_data_generic_header { * @ref SENSOR_CHAN_GYRO_Y, or @ref SENSOR_CHAN_GYRO_Z * @retval false otherwise */ -#define SENSOR_CHANNEL_IS_GYRO(chan) \ - ((chan) == SENSOR_CHAN_GYRO_XYZ || (chan) == SENSOR_CHAN_GYRO_X || \ +#define SENSOR_CHANNEL_IS_GYRO(chan) \ + ((chan) == SENSOR_CHAN_GYRO_XYZ || (chan) == SENSOR_CHAN_GYRO_X || \ (chan) == SENSOR_CHAN_GYRO_Y || (chan) == SENSOR_CHAN_GYRO_Z) /** @@ -1186,12 +1223,12 @@ void sensor_processing_with_callback(struct rtio *ctx, sensor_processing_callbac /** * @brief The value of gravitational constant in micro m/s^2. */ -#define SENSOR_G 9806650LL +#define SENSOR_G 9806650LL /** * @brief The value of constant PI in micros. */ -#define SENSOR_PI 3141592LL +#define SENSOR_PI 3141592LL /** * @brief Helper function to convert acceleration from m/s^2 to Gs @@ -1405,27 +1442,21 @@ struct sensor_info { const char *friendly_name; }; -#define SENSOR_INFO_INITIALIZER(_dev, _vendor, _model, _friendly_name) \ - { \ - .dev = _dev, \ - .vendor = _vendor, \ - .model = _model, \ - .friendly_name = _friendly_name, \ +#define SENSOR_INFO_INITIALIZER(_dev, _vendor, _model, _friendly_name) \ + { \ + .dev = _dev, .vendor = _vendor, .model = _model, .friendly_name = _friendly_name, \ } -#define SENSOR_INFO_DEFINE(name, ...) \ - static const STRUCT_SECTION_ITERABLE(sensor_info, name) = \ +#define SENSOR_INFO_DEFINE(name, ...) \ + static const STRUCT_SECTION_ITERABLE(sensor_info, name) = \ SENSOR_INFO_INITIALIZER(__VA_ARGS__) -#define SENSOR_INFO_DT_NAME(node_id) \ - _CONCAT(__sensor_info, DEVICE_DT_NAME_GET(node_id)) +#define SENSOR_INFO_DT_NAME(node_id) _CONCAT(__sensor_info, DEVICE_DT_NAME_GET(node_id)) -#define SENSOR_INFO_DT_DEFINE(node_id) \ - SENSOR_INFO_DEFINE(SENSOR_INFO_DT_NAME(node_id), \ - DEVICE_DT_GET(node_id), \ - DT_NODE_VENDOR_OR(node_id, NULL), \ - DT_NODE_MODEL_OR(node_id, NULL), \ - DT_PROP_OR(node_id, friendly_name, NULL)) \ +#define SENSOR_INFO_DT_DEFINE(node_id) \ + SENSOR_INFO_DEFINE(SENSOR_INFO_DT_NAME(node_id), DEVICE_DT_GET(node_id), \ + DT_NODE_VENDOR_OR(node_id, NULL), DT_NODE_MODEL_OR(node_id, NULL), \ + DT_PROP_OR(node_id, friendly_name, NULL)) #else @@ -1461,13 +1492,11 @@ struct sensor_info { * @param api_ptr Provides an initial pointer to the API function struct used * by the driver. Can be NULL. */ -#define SENSOR_DEVICE_DT_DEFINE(node_id, init_fn, pm_device, \ - data_ptr, cfg_ptr, level, prio, \ - api_ptr, ...) \ - DEVICE_DT_DEFINE(node_id, init_fn, pm_device, \ - data_ptr, cfg_ptr, level, prio, \ - api_ptr, __VA_ARGS__); \ - \ +#define SENSOR_DEVICE_DT_DEFINE(node_id, init_fn, pm_device, data_ptr, cfg_ptr, level, prio, \ + api_ptr, ...) \ + DEVICE_DT_DEFINE(node_id, init_fn, pm_device, data_ptr, cfg_ptr, level, prio, api_ptr, \ + __VA_ARGS__); \ + \ SENSOR_INFO_DT_DEFINE(node_id); /** @@ -1479,7 +1508,7 @@ struct sensor_info { * * @param ... other parameters as expected by SENSOR_DEVICE_DT_DEFINE(). */ -#define SENSOR_DEVICE_DT_INST_DEFINE(inst, ...) \ +#define SENSOR_DEVICE_DT_INST_DEFINE(inst, ...) \ SENSOR_DEVICE_DT_DEFINE(DT_DRV_INST(inst), __VA_ARGS__) /** @@ -1536,7 +1565,7 @@ static inline int64_t sensor_value_to_micro(const struct sensor_value *val) static inline int sensor_value_from_milli(struct sensor_value *val, int64_t milli) { if (milli < ((int64_t)INT32_MIN - 1) * 1000LL || - milli > ((int64_t)INT32_MAX + 1) * 1000LL) { + milli > ((int64_t)INT32_MAX + 1) * 1000LL) { return -ERANGE; } @@ -1556,7 +1585,7 @@ static inline int sensor_value_from_milli(struct sensor_value *val, int64_t mill static inline int sensor_value_from_micro(struct sensor_value *val, int64_t micro) { if (micro < ((int64_t)INT32_MIN - 1) * 1000000LL || - micro > ((int64_t)INT32_MAX + 1) * 1000000LL) { + micro > ((int64_t)INT32_MAX + 1) * 1000000LL) { return -ERANGE; } diff --git a/samples/sensor/mpr/src/main.c b/samples/sensor/mpr/src/main.c index d74711ca68c18..7ea50c5259648 100644 --- a/samples/sensor/mpr/src/main.c +++ b/samples/sensor/mpr/src/main.c @@ -21,20 +21,22 @@ int main(void) while (1) { struct sensor_value pressure; - - rc = sensor_sample_fetch(dev); - if (rc != 0) { - printf("sensor_sample_fetch error: %d\n", rc); - break; - } - - rc = sensor_channel_get(dev, SENSOR_CHAN_PRESS, &pressure); + int8_t shift; + q31_t pressure_value; + struct sensor_chan_spec channels[1] = { + {.chan_type = SENSOR_CHAN_PRESS, .chan_idx = 0}, + }; + + rc = sensor_read_and_decode(dev, channels, ARRAY_SIZE(channels), &shift, + &pressure_value, 1); if (rc != 0) { - printf("sensor_channel_get error: %d\n", rc); + printf("sensor_read_and_decode error: %d\n", rc); break; } + printf("pressure (q31): %" PRIq(6) " kPa\n", PRIq_arg(pressure_value, 6, shift)); - printf("pressure: %u.%u kPa\n", pressure.val1, pressure.val2); + q31_to_sensor_value(pressure_value, shift, &pressure); + printf("pressure (sensor_value): %u.%u kPa\n", pressure.val1, pressure.val2); k_sleep(K_SECONDS(1)); } diff --git a/tests/boards/nrf/qdec/src/main.c b/tests/boards/nrf/qdec/src/main.c index 6bc867f8aa9c7..bdd5f0c7ca902 100644 --- a/tests/boards/nrf/qdec/src/main.c +++ b/tests/boards/nrf/qdec/src/main.c @@ -132,6 +132,11 @@ static void qenc_emulate_verify_reading(struct qdec_qenc_loopback *loopback, int32_t expected_steps = emulation_duration_ms / emulator_period_ms; int32_t expected_reading = 360 * expected_steps / loopback->qdec_config_step; int32_t delta = expected_reading / 4; + int8_t rotation_shift; + q31_t rotation_value; + struct sensor_chan_spec channels[1] = { + {.chan_type = SENSOR_CHAN_ROTATION, .chan_idx = 0}, + }; if (!forward) { expected_reading *= -1; @@ -142,7 +147,8 @@ static void qenc_emulate_verify_reading(struct qdec_qenc_loopback *loopback, /* wait for some readings */ k_msleep(emulation_duration_ms); - rc = sensor_sample_fetch(loopback->qdec); + rc = sensor_read_and_decode(loopback->qdec, channels, ARRAY_SIZE(channels), &rotation_shift, + &rotation_value, 1); if (!overflow_expected) { zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); @@ -150,8 +156,7 @@ static void qenc_emulate_verify_reading(struct qdec_qenc_loopback *loopback, zassert_true(rc == -EOVERFLOW, "Failed to detect overflow"); } - rc = sensor_channel_get(loopback->qdec, SENSOR_CHAN_ROTATION, &val); - zassert_true(rc == 0, "Failed to get sample (%d)", rc); + q31_to_sensor_value(rotation_value, rotation_shift, &val); TC_PRINT("Expected reading: %d, actual value: %d, delta: %d\n", expected_reading, val.val1, delta); @@ -165,11 +170,9 @@ static void qenc_emulate_verify_reading(struct qdec_qenc_loopback *loopback, /* wait and get readings to clear state */ k_msleep(100); - rc = sensor_sample_fetch(loopback->qdec); - zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); - - rc = sensor_channel_get(loopback->qdec, SENSOR_CHAN_ROTATION, &val); - zassert_true(rc == 0, "Failed to get sample (%d)", rc); + rc = sensor_read_and_decode(loopback->qdec, channels, ARRAY_SIZE(channels), &rotation_shift, + &rotation_value, 1); + zassert_true(rc == 0, "Failed to read sample (%d)", rc); } static void sensor_trigger_set_and_disable(struct qdec_qenc_loopback *loopback) @@ -247,6 +250,11 @@ ZTEST(qdec_sensor, test_sensor_trigger_set_and_disable) static void sensor_trigger_set_test(struct qdec_qenc_loopback *loopback) { int rc; + int8_t rotation_shift; + q31_t rotation_value; + struct sensor_chan_spec channels[1] = { + {.chan_type = SENSOR_CHAN_ROTATION, .chan_idx = 0}, + }; struct sensor_value val = {0}; if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { @@ -266,11 +274,11 @@ static void sensor_trigger_set_test(struct qdec_qenc_loopback *loopback) rc = k_sem_take(&sem, K_MSEC(200)); zassert_true(rc == 0, "qdec handler should be triggered (%d)", rc); - rc = sensor_sample_fetch(loopback->qdec); - zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); + rc = sensor_read_and_decode(loopback->qdec, channels, ARRAY_SIZE(channels), &rotation_shift, + &rotation_value, 1); + zassert_true(rc == 0, "Failed to read sample (%d)", rc); - rc = sensor_channel_get(loopback->qdec, SENSOR_CHAN_ROTATION, &val); - zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); + q31_to_sensor_value(rotation_value, rotation_shift, &val); TC_PRINT("QDEC reading: %d\n", val.val1); zassert_true(val.val1 != 0, "No readings from QDEC"); @@ -368,6 +376,11 @@ ZTEST(qdec_sensor, test_qdec_readings) static void sensor_channel_get_empty(const struct device *const dev) { int rc; + int8_t rotation_shift; + q31_t rotation_value; + struct sensor_chan_spec channels[1] = { + {.chan_type = SENSOR_CHAN_ROTATION, .chan_idx = 0}, + }; struct sensor_value val = {0}; if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { @@ -377,24 +390,19 @@ static void sensor_channel_get_empty(const struct device *const dev) /* wait for potential new readings */ k_msleep(100); - rc = sensor_sample_fetch(dev); - zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); - - /* get readings but ignore them, as they may include reading from time - * when emulation was still working (i.e. during previous test) - */ - rc = sensor_channel_get(dev, SENSOR_CHAN_ROTATION, &val); - zassert_true(rc == 0, "Failed to get sample (%d)", rc); + rc = sensor_read_and_decode(dev, channels, ARRAY_SIZE(channels), &rotation_shift, + &rotation_value, 1); + zassert_true(rc == 0, "Failed to read sample (%d)", rc); /* wait for potential new readings */ k_msleep(100); - rc = sensor_sample_fetch(dev); + rc = sensor_read_and_decode(dev, channels, ARRAY_SIZE(channels), &rotation_shift, + &rotation_value, 1); zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); /* emulation was not working, expect no readings */ - rc = sensor_channel_get(dev, SENSOR_CHAN_ROTATION, &val); - zassert_true(rc == 0, "Failed to get sample (%d)", rc); + q31_to_sensor_value(rotation_value, rotation_shift, &val); zassert_true(val.val1 == 0, "Expected no readings but got: %d", val.val1); zassert_true(val.val2 == 0, "Expected no readings but got: %d", val.val2); @@ -420,8 +428,12 @@ ZTEST(qdec_sensor, test_sensor_channel_get_empty) static void sensor_channel_get_test(struct qdec_qenc_loopback *loopback) { int rc; - struct sensor_value val_first = {0}; - struct sensor_value val_second = {0}; + int8_t rotation_shift; + q31_t rotation_value; + struct sensor_chan_spec channels[1] = { + {.chan_type = SENSOR_CHAN_ROTATION, .chan_idx = 0}, + }; + struct sensor_value val = {0}; if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { pm_device_runtime_get(loopback->qdec); @@ -432,32 +444,12 @@ static void sensor_channel_get_test(struct qdec_qenc_loopback *loopback) /* wait for some readings*/ k_msleep(100); - rc = sensor_sample_fetch(loopback->qdec); - zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); - - rc = sensor_channel_get(loopback->qdec, SENSOR_CHAN_ROTATION, &val_first); - zassert_true(rc == 0, "Failed to get sample (%d)", rc); - zassert_true(val_first.val1 != 0, "No readings from QDEC"); + rc = sensor_read_and_decode(loopback->qdec, channels, ARRAY_SIZE(channels), &rotation_shift, + &rotation_value, 1); + zassert_true(rc == 0, "Failed to read sample (%d)", rc); - /* wait for more readings*/ - k_msleep(200); - - rc = sensor_channel_get(loopback->qdec, SENSOR_CHAN_ROTATION, &val_second); - zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); - zassert_true(val_second.val1 != 0, "No readings from QDEC"); - - /* subsequent calls of sensor_channel_get without calling sensor_sample_fetch - * should yield the same value - */ - zassert_true(val_first.val1 == val_second.val1, - "Expected the same readings: %d vs %d", - val_first.val1, - val_second.val1); - - zassert_true(val_first.val2 == val_second.val2, - "Expected the same readings: %d vs %d", - val_first.val2, - val_second.val2); + q31_to_sensor_value(rotation_value, rotation_shift, &val); + zassert_true(val.val1 != 0, "No readings from QDEC"); if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { pm_device_runtime_put(loopback->qdec); @@ -481,6 +473,11 @@ ZTEST(qdec_sensor, test_sensor_channel_get) static void sensor_channel_get_negative(struct qdec_qenc_loopback *loopback) { int rc; + int8_t max_shift; + q31_t max_value; + struct sensor_chan_spec channels[1] = { + {.chan_type = SENSOR_CHAN_MAX, .chan_idx = 0}, + }; struct sensor_value val = {0}; if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { @@ -492,11 +489,11 @@ static void sensor_channel_get_negative(struct qdec_qenc_loopback *loopback) /* wait for some readings*/ k_msleep(100); - rc = sensor_sample_fetch(loopback->qdec); - zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); + rc = sensor_read_and_decode(loopback->qdec, channels, ARRAY_SIZE(channels), &max_shift, + &max_value, 1); + zassert_true(rc == 0, "Failed to read sample (%d)", rc); - rc = sensor_channel_get(loopback->qdec, SENSOR_CHAN_MAX, &val); - zassert_true(rc < 0, "Should failed to get sample (%d)", rc); + q31_to_sensor_value(max_value, max_shift, &val); zassert_true(val.val1 == 0, "Some readings from QDEC: %d", val.val1); zassert_true(val.val2 == 0, "Some readings from QDEC: %d", val.val2); @@ -522,18 +519,21 @@ ZTEST(qdec_sensor, test_sensor_channel_get_negative) static void sensor_sample_fetch_test(const struct device *const dev) { int rc; + int8_t shift; + q31_t value; + struct sensor_chan_spec channels[2] = { + {.chan_type = SENSOR_CHAN_ROTATION, .chan_idx = 0}, + {.chan_type = SENSOR_CHAN_MAX, .chan_idx = 0}, + }; if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { pm_device_runtime_get(dev); } - rc = sensor_sample_fetch(dev); - zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); - - rc = sensor_sample_fetch_chan(dev, SENSOR_CHAN_ROTATION); + rc = sensor_read_and_decode(dev, &channels[0], 1, &shift, &value, 1); zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); - rc = sensor_sample_fetch_chan(dev, SENSOR_CHAN_MAX); + rc = sensor_read_and_decode(dev, &channels[1], 1, &shift, &value, 1); zassert_true(rc < 0, "Should fail to fetch sample from invalid channel (%d)", rc); if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { @@ -542,7 +542,7 @@ static void sensor_sample_fetch_test(const struct device *const dev) } /** - * @brief sensor_sample_fetch(_chan) test + * @brief Reading sample test * * Confirm fetching work with QDEC specific channel - rotation * diff --git a/tests/drivers/sensor/generic/prj.conf b/tests/drivers/sensor/generic/prj.conf index 9467c2926896d..893b76426518a 100644 --- a/tests/drivers/sensor/generic/prj.conf +++ b/tests/drivers/sensor/generic/prj.conf @@ -1 +1,3 @@ CONFIG_ZTEST=y +CONFIG_SENSOR=y +CONFIG_SENSOR_LOG_LEVEL_DBG=y diff --git a/tests/drivers/sensor/generic/prj_fpu.conf b/tests/drivers/sensor/generic/prj_fpu.conf index b93a5675d97c8..3d5b440c58c0b 100644 --- a/tests/drivers/sensor/generic/prj_fpu.conf +++ b/tests/drivers/sensor/generic/prj_fpu.conf @@ -1,2 +1,4 @@ CONFIG_ZTEST=y CONFIG_FPU=y +CONFIG_SENSOR=y +CONFIG_SENSOR_LOG_LEVEL_DBG=y diff --git a/tests/drivers/sensor/generic/src/dummy_sensor.c b/tests/drivers/sensor/generic/src/dummy_sensor.c index e1e1208fd27b8..22a45e33f03d9 100644 --- a/tests/drivers/sensor/generic/src/dummy_sensor.c +++ b/tests/drivers/sensor/generic/src/dummy_sensor.c @@ -20,8 +20,7 @@ static const struct dummy_sensor_config dummy_config = { .i2c_address = 123 }; -static int dummy_sensor_sample_fetch(const struct device *dev, - enum sensor_channel chan) +static int dummy_sensor_sample_fetch_impl(const struct device *dev, enum sensor_channel chan) { ARG_UNUSED(dev); ARG_UNUSED(chan); @@ -30,8 +29,7 @@ static int dummy_sensor_sample_fetch(const struct device *dev, return 0; } -static int dummy_sensor_channel_get(const struct device *dev, - enum sensor_channel chan, +static int dummy_sensor_channel_get_impl(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) { struct dummy_sensor_data *data = dev->data; @@ -96,7 +94,7 @@ static int dummy_sensor_init(const struct device *dev) /* initialize the channels value for dummy driver */ for (int i = 0; i < SENSOR_CHANNEL_NUM; i++) { data->val[i].val1 = i; - data->val[i].val2 = i*i; + data->val[i].val2 = i * i * 1000; } return 0; @@ -162,16 +160,16 @@ int dummy_sensor_trigger_set(const struct device *dev, } static DEVICE_API(sensor, dummy_sensor_api) = { - .sample_fetch = &dummy_sensor_sample_fetch, - .channel_get = &dummy_sensor_channel_get, + .sample_fetch = &dummy_sensor_sample_fetch_impl, + .channel_get = &dummy_sensor_channel_get_impl, .attr_set = dummy_sensor_attr_set, .attr_get = dummy_sensor_attr_get, .trigger_set = dummy_sensor_trigger_set, }; static DEVICE_API(sensor, dummy_sensor_no_trig_api) = { - .sample_fetch = &dummy_sensor_sample_fetch, - .channel_get = &dummy_sensor_channel_get, + .sample_fetch = &dummy_sensor_sample_fetch_impl, + .channel_get = &dummy_sensor_channel_get_impl, .attr_set = NULL, .attr_get = NULL, .trigger_set = NULL, diff --git a/tests/drivers/sensor/generic/src/main.c b/tests/drivers/sensor/generic/src/main.c index 76545ca3dacf6..89bdc07989893 100644 --- a/tests/drivers/sensor/generic/src/main.c +++ b/tests/drivers/sensor/generic/src/main.c @@ -28,12 +28,18 @@ struct trigger_sequence { enum sensor_attribute attr; }; -static struct channel_sequence chan_elements[] = { - { SENSOR_CHAN_LIGHT, { 0, 0 } }, - { SENSOR_CHAN_RED, { 1, 1 } }, - { SENSOR_CHAN_GREEN, { 2, 4 } }, - { SENSOR_CHAN_BLUE, { 3, 9 } }, - { SENSOR_CHAN_PROX, { 4, 16 } } +static struct channel_sequence chan_elements[] = {{SENSOR_CHAN_LIGHT, {0, 0}}, + {SENSOR_CHAN_RED, {1, 1000}}, + {SENSOR_CHAN_GREEN, {2, 4000}}, + {SENSOR_CHAN_BLUE, {3, 9000}}, + {SENSOR_CHAN_PROX, {4, 16000}}}; + +static struct sensor_chan_spec channels[] = { + {.chan_type = SENSOR_CHAN_LIGHT, .chan_idx = 0}, + {.chan_type = SENSOR_CHAN_RED, .chan_idx = 0}, + {.chan_type = SENSOR_CHAN_GREEN, .chan_idx = 0}, + {.chan_type = SENSOR_CHAN_BLUE, .chan_idx = 0}, + {.chan_type = SENSOR_CHAN_PROX, .chan_idx = 0}, }; static struct trigger_sequence trigger_elements[] = { @@ -58,10 +64,12 @@ static struct trigger_sequence trigger_elements[] = { { 155, 180 }, SENSOR_ATTR_UPPER_THRESH } }; -#define TOTAL_CHAN_ELEMENTS (sizeof(chan_elements) / \ - sizeof(struct channel_sequence)) -#define TOTAL_TRIG_ELEMENTS (sizeof(trigger_elements) / \ - sizeof(struct trigger_sequence)) +static struct sensor_chan_spec trigger_channels[] = { + {.chan_type = SENSOR_CHAN_PROX, .chan_idx = 0}, +}; + +#define TOTAL_CHAN_ELEMENTS (sizeof(chan_elements) / sizeof(struct channel_sequence)) +#define TOTAL_TRIG_ELEMENTS (sizeof(trigger_elements) / sizeof(struct trigger_sequence)) /** * @brief Test get multiple channels values. @@ -101,43 +109,39 @@ static struct trigger_sequence trigger_elements[] = { * Assumptions and Constraints: * - N/A * - * @see sensor_sample_fetch(), sensor_channel_get() + * @see sensor_read_and_decode() */ ZTEST(sensor_api, test_sensor_get_channels) { const struct device *dev; struct sensor_value data; + int8_t shift; + q31_t values[ARRAY_SIZE(channels)]; dev = device_get_binding(DUMMY_SENSOR_NAME); zassert_not_null(dev, "failed: dev is null"); /* test fetch single channel */ - zassert_equal(sensor_sample_fetch_chan(dev, chan_elements[0].chan), - RETURN_SUCCESS, "fail to fetch sample"); + zassert_equal(sensor_read_and_decode(dev, channels, 1, &shift, values, 1), RETURN_SUCCESS, + "fail to fetch sample"); /* Get and check channel 0 value. */ - zassert_equal(sensor_channel_get(dev, chan_elements[0].chan, - &data), RETURN_SUCCESS, "fail to get channel"); - zassert_equal(data.val1, chan_elements[0].data.val1, - "the data does not match"); - zassert_equal(data.val2, chan_elements[0].data.val2, - "the data does not match"); + q31_to_sensor_value(values[0], shift, &data); + zassert_equal(data.val1, chan_elements[0].data.val1, "the data does not match"); + zassert_equal(data.val2, chan_elements[0].data.val2, "the data does not match"); /* test fetch all channel */ - zassert_equal(sensor_sample_fetch(dev), RETURN_SUCCESS, - "fail to fetch sample"); + zassert_equal(sensor_read_and_decode(dev, channels, ARRAY_SIZE(channels), &shift, values, + ARRAY_SIZE(values)), + RETURN_SUCCESS, "fail to fetch sample"); /* Get and check channels value except for chanel 0. */ for (int i = 1; i < TOTAL_CHAN_ELEMENTS; i++) { - zassert_equal(sensor_channel_get(dev, chan_elements[i].chan, - &data), RETURN_SUCCESS, "fail to get channel"); - zassert_equal(data.val1, chan_elements[i].data.val1, - "the data does not match"); - zassert_equal(data.val2, chan_elements[i].data.val2, - "the data does not match"); + q31_to_sensor_value(values[i], shift, &data); + zassert_within(sensor_value_to_micro(&data), + sensor_value_to_micro(&chan_elements[i].data), 50, + "[%d] the data does not match, got %lld but expected %lld", i, + sensor_value_to_micro(&data), + sensor_value_to_micro(&chan_elements[i].data)); } - - /* Get data with invalid channel. */ - zassert_not_equal(sensor_channel_get(dev, SENSOR_CHAN_DISTANCE, - &data), RETURN_SUCCESS, "should fail for invalid channel"); } static void trigger_handler(const struct device *dev, @@ -194,13 +198,16 @@ ZTEST(sensor_api, test_sensor_handle_triggers) const struct device *dev; const struct device *dev_no_trig; struct sensor_value data; + int8_t shift; + q31_t values[ARRAY_SIZE(channels)]; dev = device_get_binding(DUMMY_SENSOR_NAME); dev_no_trig = device_get_binding(DUMMY_SENSOR_NAME_NO_TRIG); zassert_not_null(dev, "failed: dev is null"); - zassert_equal(sensor_sample_fetch(dev), RETURN_SUCCESS, - "fail to fetch sample"); + zassert_equal(sensor_read_and_decode(dev, channels, ARRAY_SIZE(channels), &shift, values, + ARRAY_SIZE(values)), + RETURN_SUCCESS, "fail to fetch sample"); /* setup multiple triggers */ for (int i = 0; i < TOTAL_TRIG_ELEMENTS; i++) { @@ -230,15 +237,17 @@ ZTEST(sensor_api, test_sensor_handle_triggers) /* get channels value after trigger fired */ k_sem_take(&sem, K_FOREVER); - zassert_equal(sensor_channel_get(dev, - trigger_elements[i].trig.chan, - &data), RETURN_SUCCESS, "fail to get channel"); + zassert_ok(sensor_read_and_decode(dev, trigger_channels, + ARRAY_SIZE(trigger_channels), &shift, values, + ARRAY_SIZE(values))); + q31_to_sensor_value(values[0], shift, &data); /* check the result of the trigger channel */ - zassert_equal(data.val1, trigger_elements[i].data.val1, - "retrieved data does not match"); - zassert_equal(data.val2, trigger_elements[i].data.val2, - "retrieved data does not match"); + zassert_within(sensor_value_to_micro(&data), + sensor_value_to_micro(&trigger_elements[i].data), 50, + "[%d] retrieved data does not match, got %lld but expected %lld", i, + sensor_value_to_micro(&data), + sensor_value_to_micro(&trigger_elements[i].data)); /* set attributes for no trig dev */ zassert_equal(sensor_attr_set(dev_no_trig, diff --git a/tests/drivers/sensor/icm42688/prj.conf b/tests/drivers/sensor/icm42688/prj.conf index e62f65fa930fb..7272ad3e90e49 100644 --- a/tests/drivers/sensor/icm42688/prj.conf +++ b/tests/drivers/sensor/icm42688/prj.conf @@ -8,6 +8,7 @@ CONFIG_GPIO=y # Enable sensors CONFIG_SENSOR=y +CONFIG_SENSOR_LOG_LEVEL_DBG=y # Enable emulation CONFIG_EMUL=y diff --git a/tests/drivers/sensor/icm42688/src/main.c b/tests/drivers/sensor/icm42688/src/main.c index bc945cb2db70d..3205f0cb15f66 100644 --- a/tests/drivers/sensor/icm42688/src/main.c +++ b/tests/drivers/sensor/icm42688/src/main.c @@ -41,9 +41,14 @@ ZTEST_SUITE(icm42688, NULL, icm42688_setup, NULL, NULL, NULL); ZTEST_F(icm42688, test_fetch_fail_no_ready_data) { uint8_t status = 0; + int8_t shift; + q31_t value; + struct sensor_chan_spec channels[1] = { + {.chan_type = SENSOR_CHAN_ACCEL_X, .chan_idx = 0}, + }; icm4268x_emul_set_reg(fixture->target, REG_INT_STATUS, &status, 1); - zassert_equal(-EBUSY, sensor_sample_fetch(fixture->dev)); + zassert_equal(-EBUSY, sensor_read_and_decode(fixture->dev, channels, 1, &shift, &value, 1)); } static void test_fetch_temp_mc(const struct icm42688_fixture *fixture, int16_t temperature_mc) @@ -53,6 +58,11 @@ static void test_fetch_temp_mc(const struct icm42688_fixture *fixture, int16_t t int64_t actual_uc; int16_t temperature_reg; uint8_t buffer[2]; + int8_t shift; + q31_t q_value; + struct sensor_chan_spec channels[1] = { + {.chan_type = SENSOR_CHAN_DIE_TEMP, .chan_idx = 0}, + }; /* Set the INT_STATUS register to show we have data */ buffer[0] = BIT_DATA_RDY_INT; @@ -68,8 +78,8 @@ static void test_fetch_temp_mc(const struct icm42688_fixture *fixture, int16_t t icm4268x_emul_set_reg(fixture->target, REG_TEMP_DATA1, buffer, 2); /* Fetch the data */ - zassert_ok(sensor_sample_fetch(fixture->dev)); - zassert_ok(sensor_channel_get(fixture->dev, SENSOR_CHAN_DIE_TEMP, &value)); + zassert_ok(sensor_read_and_decode(fixture->dev, channels, 1, &shift, &q_value, 1)); + q31_to_sensor_value(q_value, shift, &value); /* Assert data is within 5 milli-C of the tested temperature */ expected_uc = temperature_mc * INT64_C(1000); @@ -93,6 +103,11 @@ static void test_fetch_accel_with_range(const struct icm42688_fixture *fixture, int32_t expect_ug; int32_t actual_ug; uint8_t register_buffer[6]; + int8_t shift; + q31_t q_values[3]; + struct sensor_chan_spec channels[] = { + {.chan_type = SENSOR_CHAN_ACCEL_XYZ, .chan_idx = 0}, + }; /* Se the INT_STATUS register to show we have data */ register_buffer[0] = BIT_DATA_RDY_INT; @@ -111,8 +126,10 @@ static void test_fetch_accel_with_range(const struct icm42688_fixture *fixture, icm4268x_emul_set_reg(fixture->target, REG_ACCEL_DATA_X1, register_buffer, 6); /* Fetch the data */ - zassert_ok(sensor_sample_fetch(fixture->dev)); - zassert_ok(sensor_channel_get(fixture->dev, SENSOR_CHAN_ACCEL_XYZ, values)); + zassert_ok(sensor_read_and_decode(fixture->dev, channels, 1, &shift, q_values, 3)); + q31_to_sensor_value(q_values[0], shift, &values[0]); + q31_to_sensor_value(q_values[1], shift, &values[1]); + q31_to_sensor_value(q_values[2], shift, &values[2]); /* Assert the data is within 0.005g (0.05m/s2) */ actual_ug = sensor_ms2_to_ug(&values[0]); @@ -155,6 +172,11 @@ static void test_fetch_gyro_with_range(const struct icm42688_fixture *fixture, i int32_t expect_10udps; int32_t actual_10udps; uint8_t register_buffer[6]; + int8_t shift; + q31_t q_values[3]; + struct sensor_chan_spec channels[] = { + {.chan_type = SENSOR_CHAN_GYRO_XYZ, .chan_idx = 0}, + }; /* Se the INT_STATUS register to show we have data */ register_buffer[0] = BIT_DATA_RDY_INT; @@ -173,8 +195,10 @@ static void test_fetch_gyro_with_range(const struct icm42688_fixture *fixture, i icm4268x_emul_set_reg(fixture->target, REG_GYRO_DATA_X1, register_buffer, 6); /* Fetch the data */ - zassert_ok(sensor_sample_fetch(fixture->dev)); - zassert_ok(sensor_channel_get(fixture->dev, SENSOR_CHAN_GYRO_XYZ, values)); + zassert_ok(sensor_read_and_decode(fixture->dev, channels, 1, &shift, q_values, 3)); + q31_to_sensor_value(q_values[0], shift, &values[0]); + q31_to_sensor_value(q_values[1], shift, &values[1]); + q31_to_sensor_value(q_values[2], shift, &values[2]); /* Assert the data is within 0.5 d/s (0.001 rad/s) */ actual_10udps = sensor_rad_to_10udegrees(&values[0]); diff --git a/tests/drivers/sensor/ina228/src/ina228_test.c b/tests/drivers/sensor/ina228/src/ina228_test.c index 458607df63859..6d33033d60fa3 100644 --- a/tests/drivers/sensor/ina228/src/ina228_test.c +++ b/tests/drivers/sensor/ina228/src/ina228_test.c @@ -132,6 +132,18 @@ ZTEST_F(ina228, test_example_from_data_sheet) struct sensor_value sensor_val; double reading; + int8_t shift[7]; + q31_t value[7]; + struct sensor_chan_spec channels[7] = { + {.chan_type = SENSOR_CHAN_VOLTAGE, .chan_idx = 0}, + {.chan_type = SENSOR_CHAN_CURRENT, .chan_idx = 0}, + {.chan_type = SENSOR_CHAN_POWER, .chan_idx = 0}, + {.chan_type = SENSOR_CHAN_INA2XX_CHARGE, .chan_idx = 0}, + {.chan_type = SENSOR_CHAN_INA2XX_ENERGY, .chan_idx = 0}, + {.chan_type = SENSOR_CHAN_DIE_TEMP, .chan_idx = 0}, + {.chan_type = SENSOR_CHAN_VSHUNT, .chan_idx = 0}, + }; + ina228_emul_get_reg_16(fixture->target_basic, INA237_REG_CONFIG, &resulting_registervalue); /* * RST 0 0... .... .... .... @@ -191,38 +203,37 @@ ZTEST_F(ina228, test_example_from_data_sheet) /* Datasheet value 3200 decimal */ ina228_emul_set_reg_16(fixture->target_basic, INA237_REG_DIETEMP, 0x0C80); - zassert_ok(sensor_sample_fetch(fixture->dev_basic)); + zassert_ok(sensor_read_and_decode(fixture->dev_basic, channels, ARRAY_SIZE(channels), shift, + value, 7)); - zassert_ok(sensor_channel_get(fixture->dev_basic, SENSOR_CHAN_VOLTAGE, &sensor_val)); + q31_to_sensor_value(value[0], shift[0], &sensor_val); reading = sensor_value_to_double(&sensor_val); zexpect_within(48.0, reading, 1.0e-3, "Got %.6f V", reading); - zassert_ok(sensor_channel_get(fixture->dev_basic, SENSOR_CHAN_CURRENT, &sensor_val)); + q31_to_sensor_value(value[1], shift[0], &sensor_val); reading = sensor_value_to_double(&sensor_val); zexpect_within(6.0, reading, 0.1, "Got %.6f A", reading); - zassert_ok(sensor_channel_get(fixture->dev_basic, SENSOR_CHAN_POWER, &sensor_val)); + q31_to_sensor_value(value[2], shift[0], &sensor_val); reading = sensor_value_to_double(&sensor_val); /* Some difference due to limited resolution in devicetree LSB setting */ zexpect_within(287, reading, 1, "Got %.6f W", reading); - zassert_ok(sensor_channel_get(fixture->dev_basic, - (enum sensor_channel)SENSOR_CHAN_INA2XX_CHARGE, &sensor_val)); + q31_to_sensor_value(value[3], shift[0], &sensor_val); reading = sensor_value_to_double(&sensor_val); /* Some difference due to limited resolution in devicetree LSB setting */ zexpect_within(21500, reading, 20, "Got %.6f C", reading); - zassert_ok(sensor_channel_get(fixture->dev_basic, - (enum sensor_channel)SENSOR_CHAN_INA2XX_ENERGY, &sensor_val)); + q31_to_sensor_value(value[4], shift[0], &sensor_val); reading = sensor_value_to_double(&sensor_val); /* Some difference due to limited resolution in devicetree LSB setting */ - zexpect_within(1032800, reading, 50, "Got %.6f J", reading); + zexpect_within(1032800, reading, 500, "Got %.6f J", reading); - zassert_ok(sensor_channel_get(fixture->dev_basic, SENSOR_CHAN_DIE_TEMP, &sensor_val)); + q31_to_sensor_value(value[5], shift[0], &sensor_val); reading = sensor_value_to_double(&sensor_val); - zexpect_within(25, reading, 1.0e-3, "Got %.3f deg C", reading); + zexpect_within(25, reading, 1.0e-1, "Got %.3f deg C", reading); - zassert_ok(sensor_channel_get(fixture->dev_basic, SENSOR_CHAN_VSHUNT, &sensor_val)); + q31_to_sensor_value(value[6], shift[0], &sensor_val); reading = sensor_value_to_double(&sensor_val); zexpect_within(0.0972, reading, 1.0e-3, "Got %.6f V", reading); } @@ -235,6 +246,15 @@ ZTEST_F(ina228, test_negative_values) struct sensor_value sensor_val; double reading; + int8_t shift; + q31_t value[4]; + struct sensor_chan_spec channels[4] = { + {.chan_type = SENSOR_CHAN_CURRENT, .chan_idx = 0}, + {.chan_type = SENSOR_CHAN_INA2XX_CHARGE, .chan_idx = 0}, + {.chan_type = SENSOR_CHAN_DIE_TEMP, .chan_idx = 0}, + {.chan_type = SENSOR_CHAN_VSHUNT, .chan_idx = 0}, + }; + /* Current LSB = 19000 nA according to devicetree settings. * -100 = 0xFFF9C in 20 bit two's complement * This corresponds to -1.9 mA @@ -263,22 +283,22 @@ ZTEST_F(ina228, test_negative_values) ina228_emul_set_reg_24(fixture->target_basic, INA237_REG_POWER, 0x000000); ina228_emul_set_reg_40(fixture->target_basic, INA228_REG_ENERGY, 0x0000000000); - zassert_ok(sensor_sample_fetch(fixture->dev_basic)); + zassert_ok(sensor_read_and_decode(fixture->dev_basic, channels, ARRAY_SIZE(channels), + &shift, value, 4)); - zassert_ok(sensor_channel_get(fixture->dev_basic, SENSOR_CHAN_CURRENT, &sensor_val)); + q31_to_sensor_value(value[0], shift, &sensor_val); reading = sensor_value_to_double(&sensor_val); zexpect_within(-1.907e-3, reading, 1.0e-5, "Got %.6f A", reading); - zassert_ok(sensor_channel_get(fixture->dev_basic, - (enum sensor_channel)SENSOR_CHAN_INA2XX_CHARGE, &sensor_val)); + q31_to_sensor_value(value[1], shift, &sensor_val); reading = sensor_value_to_double(&sensor_val); zexpect_within(-1.907e-3, reading, 1.0e-5, "Got %.6f C", reading); - zassert_ok(sensor_channel_get(fixture->dev_basic, SENSOR_CHAN_DIE_TEMP, &sensor_val)); + q31_to_sensor_value(value[2], shift, &sensor_val); reading = sensor_value_to_double(&sensor_val); zexpect_within(-0.78125, reading, 1.0e-3, "Got %.3f deg C", reading); - zassert_ok(sensor_channel_get(fixture->dev_basic, SENSOR_CHAN_VSHUNT, &sensor_val)); + q31_to_sensor_value(value[3], shift, &sensor_val); reading = sensor_value_to_double(&sensor_val); zexpect_within(-3.155e-5, reading, 1.0e-6, "Got %.6f V", reading); } @@ -288,7 +308,11 @@ ZTEST_F(ina228, test_negative_values) */ ZTEST_F(ina228, test_invalid_channel) { - struct sensor_value sensor_val; + int8_t shift; + q31_t value; + struct sensor_chan_spec channels[1] = { + {.chan_type = SENSOR_CHAN_ALTITUDE, .chan_idx = 0}, + }; ina228_emul_set_reg_24(fixture->target_basic, INA237_REG_CURRENT, 0x0000); ina228_emul_set_reg_40(fixture->target_basic, INA228_REG_CHARGE, 0x0000000000); @@ -298,7 +322,5 @@ ZTEST_F(ina228, test_invalid_channel) ina228_emul_set_reg_24(fixture->target_basic, INA237_REG_POWER, 0x000000); ina228_emul_set_reg_40(fixture->target_basic, INA228_REG_ENERGY, 0x0000000000); - zassert_ok(sensor_sample_fetch(fixture->dev_basic)); - - zassert_not_ok(sensor_channel_get(fixture->dev_basic, SENSOR_CHAN_ALTITUDE, &sensor_val)); + zassert_not_ok(sensor_read_and_decode(fixture->dev_basic, channels, 1, &shift, &value, 1)); } diff --git a/tests/drivers/sensor/temp_sensor/src/main.c b/tests/drivers/sensor/temp_sensor/src/main.c index 9d8c15ae6b6e7..92f2cb571c7f5 100644 --- a/tests/drivers/sensor/temp_sensor/src/main.c +++ b/tests/drivers/sensor/temp_sensor/src/main.c @@ -18,18 +18,19 @@ ZTEST(temp_sensor, test_polling) int rc; int cnt; struct sensor_value val; + int8_t shift; + q31_t value; + struct sensor_chan_spec channels; cnt = 0; while (1) { int32_t temp_val; - rc = sensor_sample_fetch_chan(temp_dev, chan_to_use); + channels.chan_type = chan_to_use; + rc = sensor_read_and_decode(temp_dev, &channels, 1, &shift, &value, 1); zassert_ok(rc, "Cannot fetch chan sample: %d.", rc); - rc = sensor_channel_get(temp_dev, chan_to_use, &val); - zassert_ok(rc, "Cannot read from channel %d: %d.", - chan_to_use, rc); - + q31_to_sensor_value(value, shift, &val); temp_val = (val.val1 * 100) + (val.val2 / 10000); TC_PRINT("Temperature: %d.%02u\n", temp_val/100, abs(temp_val) % 100); @@ -59,8 +60,10 @@ ZTEST(temp_sensor, test_trigger) { int rc; struct sensor_value val; - struct sensor_trigger trig = { .type = SENSOR_TRIG_THRESHOLD, - .chan = chan_to_use }; + struct sensor_trigger trig = {.type = SENSOR_TRIG_THRESHOLD, .chan = chan_to_use}; + int8_t shift; + q31_t value; + struct sensor_chan_spec channel = {.chan_type = chan_to_use, .chan_idx = 0}; /* Check if the sensor allows setting a threshold trigger. * If not, skip the test. @@ -71,10 +74,10 @@ ZTEST(temp_sensor, test_trigger) ztest_test_skip(); } - rc = sensor_channel_get(temp_dev, chan_to_use, &val); - zassert_ok(rc, "Cannot read from channel %d: %d.", - chan_to_use, rc); + rc = sensor_read_and_decode(temp_dev, &channel, 1, &shift, &value, 1); + zassert_ok(rc, "Cannot read from channel %d: %d.", chan_to_use, rc); + q31_to_sensor_value(value, shift, &val); /* Set the upper threshold somewhat below the temperature read above. */ val.val1 -= 5; rc = sensor_attr_set(temp_dev, chan_to_use, @@ -115,39 +118,37 @@ static void before(void *fixture) { ARG_UNUSED(fixture); - int rc; - int cnt; - struct sensor_value val; + int rc = 0; + int cnt = 0; + int8_t shift; + q31_t value; + struct sensor_chan_spec channels[] = { + {.chan_type = SENSOR_CHAN_DIE_TEMP, .chan_idx = 0}, + {.chan_type = SENSOR_CHAN_AMBIENT_TEMP, .chan_idx = 0}, + }; zassert_true(device_is_ready(temp_dev), "Device %s is not ready.", temp_dev->name); - cnt = 0; - /* Try to fetch a sample to check if the sensor is ready to work. - * Try several times if it appears to be needing a while for some - * initialization of communication etc. - */ - while (1) { - rc = sensor_sample_fetch(temp_dev); - if (rc != -EAGAIN && rc != -ENOTCONN) { - break; + for (int i = 0; i < 2; ++i) { + /* Try to fetch a sample to check if the sensor is ready to work. + * Try several times if it appears to be needing a while for some + * initialization of communication etc. + */ + while (cnt < (i + 1) * 3) { + rc = sensor_read_and_decode(temp_dev, &channels[i], 1, &shift, &value, 1); + if (rc != -EAGAIN && rc != -ENOTCONN) { + chan_to_use = channels[i].chan_type; + break; + } + + ++cnt; + + k_sleep(K_MSEC(1000)); } - - ++cnt; - zassert_false(cnt >= 3, "Cannot fetch a sample: %d.", rc); - - k_sleep(K_MSEC(1000)); } + zassert_false(cnt > 6, "Cannot fetch a sample: %d.", rc); zassert_ok(rc, "Cannot fetch a sample: %d.", rc); - - /* Check if the sensor provides the die temperature. - * If not, switch to the ambient one. - */ - chan_to_use = SENSOR_CHAN_DIE_TEMP; - rc = sensor_channel_get(temp_dev, chan_to_use, &val); - if (rc == -ENOTSUP) { - chan_to_use = SENSOR_CHAN_AMBIENT_TEMP; - } } ZTEST_SUITE(temp_sensor, NULL, NULL, before, NULL, NULL);