1 /*
2 * Copyright (c) 2023 Google LLC
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <zephyr/device.h>
7 #include <zephyr/drivers/emul_sensor.h>
8 #include <zephyr/drivers/emul.h>
9 #include <zephyr/ztest.h>
10 #include <zephyr/drivers/sensor.h>
11 #include <zephyr/drivers/sensor_data_types.h>
12 #include <zephyr/rtio/rtio.h>
13 #include <zephyr/sys/bitarray.h>
14
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_REGISTER(generic_test);
17
18 /**
19 * A union of all sensor data types.
20 */
21 union sensor_data_union {
22 struct sensor_three_axis_data three_axis;
23 struct sensor_occurrence_data occurrence;
24 struct sensor_q31_data q31;
25 struct sensor_byte_data byte;
26 struct sensor_uint64_data uint64;
27 };
28
29 /*
30 * Set up an RTIO context that can be shared for all sensors
31 */
32
33 static struct sensor_chan_spec iodev_all_channels[SENSOR_CHAN_ALL];
34 static struct sensor_read_config iodev_read_config = {
35 .channels = iodev_all_channels,
36 .max = SENSOR_CHAN_ALL,
37 };
38 RTIO_IODEV_DEFINE(iodev_read, &__sensor_iodev_api, &iodev_read_config);
39
40 /* Create the RTIO context to service the reading */
41 RTIO_DEFINE_WITH_MEMPOOL(sensor_read_rtio_ctx, 1, 1, 1, 64, 4);
42
43 /**
44 * @brief Prepare the RTIO context for next test
45 */
before(void * args)46 static void before(void *args)
47 {
48 ARG_UNUSED(args);
49
50 /* Clear the array of requested channels */
51 memset(iodev_all_channels, 0, sizeof(iodev_all_channels));
52
53 /* Reset the channel count */
54 iodev_read_config.count = 0;
55
56 /* Remove previous sensor pointer */
57 iodev_read_config.sensor = NULL;
58
59 /* Wipe the mempool by marking every block free */
60 zassert_ok(sys_bitarray_clear_region(sensor_read_rtio_ctx.block_pool->bitmap,
61 sensor_read_rtio_ctx.block_pool->info.num_blocks,
62 0));
63
64 /* Flush the SQ and CQ */
65 rtio_sqe_drop_all(&sensor_read_rtio_ctx);
66 while (rtio_cqe_consume(&sensor_read_rtio_ctx)) {
67 ;
68 }
69 }
70
71 /**
72 * @brief Helper function the carries out the generic sensor test for a given sensor device.
73 * Verifies that the device has a suitable emulator that implements the backend API and
74 * skips the test gracefully if not.
75 */
run_generic_test(const struct device * dev)76 static void run_generic_test(const struct device *dev)
77 {
78 zassert_not_null(dev, "Cannot get device pointer. Is this driver properly instantiated?");
79
80 const struct emul *emul = emul_get_binding(dev->name);
81
82 /* Skip this sensor if there is no emulator loaded. */
83 if (!emul) {
84 ztest_test_skip();
85 }
86
87 /* Also skip if this emulator does not implement the backend API. */
88 if (!emul_sensor_backend_is_supported(emul)) {
89 ztest_test_skip();
90 }
91
92 /*
93 * Begin the actual test sequence
94 */
95
96 static struct {
97 bool supported;
98 bool received;
99 q31_t expected_values[CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS];
100 q31_t epsilon;
101 int8_t expected_value_shift;
102 } channel_table[SENSOR_CHAN_ALL];
103
104 memset(channel_table, 0, sizeof(channel_table));
105
106 /* Discover supported channels on this device and fill out our sensor read request */
107 for (enum sensor_channel ch = 0; ch < ARRAY_SIZE(channel_table); ch++) {
108 if (SENSOR_CHANNEL_3_AXIS(ch)) {
109 continue;
110 }
111
112 q31_t lower, upper;
113 int8_t shift;
114 struct sensor_chan_spec ch_spec = {.chan_type = ch, .chan_idx = 0};
115
116 if (emul_sensor_backend_get_sample_range(emul, ch_spec, &lower, &upper,
117 &channel_table[ch].epsilon, &shift) == 0) {
118 /* This channel is supported */
119 channel_table[ch].supported = true;
120
121 LOG_INF("CH %d: lower=%d, upper=%d, eps=%d, shift=%d", ch, lower, upper,
122 channel_table[ch].epsilon, shift);
123
124 /* Add to the list of channels to read */
125 iodev_all_channels[iodev_read_config.count++].chan_type = ch;
126
127 /* Generate a set of CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS test
128 * values.
129 */
130
131 channel_table[ch].expected_value_shift = shift;
132 for (size_t i = 0; i < CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS; i++) {
133 channel_table[ch].expected_values[i] =
134 lower +
135 (i * ((int64_t)upper - lower) /
136 (CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS - 1));
137 LOG_INF("CH %d: Expected value %d/%d: %d", ch, i + 1,
138 CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS,
139 channel_table[ch].expected_values[i]);
140 }
141 }
142 }
143 iodev_read_config.sensor = dev;
144
145 /* Do a read of all channels for quantity CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS
146 * iterations.
147 */
148
149 for (size_t iteration = 0; iteration < CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS;
150 iteration++) {
151 int rv;
152
153 /* Reset received flag */
154 for (size_t i = 0; i < ARRAY_SIZE(channel_table); i++) {
155 channel_table[i].received = false;
156 }
157
158 /* Set this iteration's expected values in emul for every supported channel */
159 for (size_t i = 0; i < iodev_read_config.count; i++) {
160 struct sensor_chan_spec ch_spec = iodev_all_channels[i];
161
162 rv = emul_sensor_backend_set_channel(
163 emul, ch_spec,
164 &channel_table[ch_spec.chan_type].expected_values[iteration],
165 channel_table[ch_spec.chan_type].expected_value_shift);
166 zassert_ok(rv,
167 "Cannot set value 0x%08x on channel (type: %d, index: %d) "
168 "(error %d, iteration %d/%d)",
169 channel_table[i].expected_values[iteration], ch_spec.chan_type,
170 ch_spec.chan_idx, rv, iteration + 1,
171 CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS);
172 }
173
174 /* Perform the actual sensor read */
175 rv = sensor_read_async_mempool(&iodev_read, &sensor_read_rtio_ctx, NULL);
176 zassert_ok(rv, "Could not read sensor (error %d, iteration %d/%d)", rv,
177 iteration + 1, CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS);
178
179 /* Wait for a CQE */
180 struct rtio_cqe *cqe = rtio_cqe_consume_block(&sensor_read_rtio_ctx);
181
182 zassert_ok(cqe->result, "CQE has failed status (error %d, iteration %d/%d)",
183 cqe->result, iteration + 1,
184 CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS);
185
186 uint8_t *buf = NULL;
187 uint32_t buf_len = 0;
188
189 /* Cache the data from the CQE */
190 rtio_cqe_get_mempool_buffer(&sensor_read_rtio_ctx, cqe, &buf, &buf_len);
191
192 /* Release the CQE */
193 rtio_cqe_release(&sensor_read_rtio_ctx, cqe);
194
195 const struct sensor_decoder_api *decoder;
196 union sensor_data_union decoded_data;
197
198 zassert_ok(sensor_get_decoder(dev, &decoder));
199
200 /* Loop through each channel */
201 for (int ch = 0; ch < ARRAY_SIZE(channel_table); ch++) {
202 if (!channel_table[ch].supported) {
203 continue;
204 }
205
206 struct sensor_decode_context ctx =
207 SENSOR_DECODE_CONTEXT_INIT(decoder, buf, ch, 0);
208
209 rv = sensor_decode(&ctx, &decoded_data, 1);
210 zassert_equal(1, rv, "Could not decode (error %d, ch %d, iteration %d/%d)",
211 rv, ch, iteration + 1,
212 CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS);
213
214 channel_table[ch].received = true;
215
216 /* Retrieve the actual value */
217 q31_t q;
218 int8_t shift;
219
220 switch (ch) {
221 /* Special handling to break out triplet samples. */
222 case SENSOR_CHAN_MAGN_X:
223 case SENSOR_CHAN_ACCEL_X:
224 case SENSOR_CHAN_GYRO_X:
225 q = decoded_data.three_axis.readings[0].x;
226 shift = decoded_data.three_axis.shift;
227 break;
228 case SENSOR_CHAN_MAGN_Y:
229 case SENSOR_CHAN_ACCEL_Y:
230 case SENSOR_CHAN_GYRO_Y:
231 q = decoded_data.three_axis.readings[0].y;
232 shift = decoded_data.three_axis.shift;
233 break;
234 case SENSOR_CHAN_MAGN_Z:
235 case SENSOR_CHAN_ACCEL_Z:
236 case SENSOR_CHAN_GYRO_Z:
237 q = decoded_data.three_axis.readings[0].z;
238 shift = decoded_data.three_axis.shift;
239 break;
240
241 /* Default case for single Q31 samples */
242 default:
243 q = decoded_data.q31.readings[0].value;
244 shift = decoded_data.q31.shift;
245 break;
246 }
247
248 /* Align everything to be a 64-bit Q32.32 number for comparison */
249 int64_t expected_shifted =
250 (int64_t)channel_table[ch].expected_values[iteration]
251 << channel_table[ch].expected_value_shift;
252 int64_t actual_shifted = (int64_t)q << shift;
253 int64_t epsilon_shifted = (int64_t)channel_table[ch].epsilon
254 << channel_table[ch].expected_value_shift;
255
256 zassert_within(expected_shifted, actual_shifted, epsilon_shifted,
257 "Expected %lld, got %lld (shift %d, ch %d, iteration %d/%d, "
258 "Error %lld, Epsilon %lld)",
259 expected_shifted, actual_shifted, shift, ch, iteration + 1,
260 CONFIG_GENERIC_SENSOR_TEST_NUM_EXPECTED_VALS,
261 expected_shifted - actual_shifted, epsilon_shifted);
262 }
263
264 /* Release the memory */
265 rtio_release_buffer(&sensor_read_rtio_ctx, buf, buf_len);
266
267 /* Ensure all supported channels were received */
268 int missing_channel_count = 0;
269
270 for (size_t i = 0; i < ARRAY_SIZE(channel_table); i++) {
271 if (channel_table[i].supported && !channel_table[i].received) {
272 missing_channel_count++;
273 }
274 }
275
276 zassert_equal(0, missing_channel_count, "%d channel(s) not received",
277 missing_channel_count);
278 }
279 }
280
281 #define DECLARE_ZTEST_PER_DEVICE(n) \
282 ZTEST(generic, test_##n) \
283 { \
284 run_generic_test(DEVICE_DT_GET(n)); \
285 }
286
287 /* Iterate through each of the emulated buses and create a test for each device. */
288 DT_FOREACH_CHILD_STATUS_OKAY(DT_NODELABEL(test_i2c), DECLARE_ZTEST_PER_DEVICE)
289 DT_FOREACH_CHILD_STATUS_OKAY(DT_NODELABEL(test_i3c), DECLARE_ZTEST_PER_DEVICE)
290 DT_FOREACH_CHILD_STATUS_OKAY(DT_NODELABEL(test_spi), DECLARE_ZTEST_PER_DEVICE)
291
292 ZTEST_SUITE(generic, NULL, NULL, before, NULL, NULL);
293