1 /*
2 * Copyright (c) 2022 Vestas Wind Systems A/S
3 * Copyright (c) 2019 Alexander Wachter
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr/drivers/can.h>
9 #include <zephyr/ztest.h>
10 #include <strings.h>
11
12 /**
13 * @addtogroup t_driver_can
14 * @{
15 * @defgroup t_can_timing test_can_timing
16 * @}
17 */
18
19 /**
20 * @brief Allowed sample point calculation margin in permille.
21 */
22 #define SAMPLE_POINT_MARGIN 50
23
24 /**
25 * @brief Defines a set of CAN timing test values
26 */
27 struct can_timing_test {
28 /** Desired bitrate in bits/s */
29 uint32_t bitrate;
30 /** Desired sample point in permille */
31 uint16_t sp;
32 /** Do these values represent an invalid CAN timing? */
33 bool invalid;
34 };
35
36 /**
37 * @brief List of CAN timing values to test.
38 */
39 static const struct can_timing_test can_timing_tests[] = {
40 /** Standard bitrates. */
41 #ifndef CONFIG_CAN_ESP32_TWAI
42 /* ESP32 TWAI does not support bitrates below 25kbit/s */
43 { 20000, 875, false },
44 #endif /* CONFIG_CAN_ESP32_TWAI */
45 { 50000, 875, false },
46 { 125000, 875, false },
47 { 250000, 875, false },
48 { 500000, 875, false },
49 { 800000, 800, false },
50 { 1000000, 750, false },
51 /** Additional, valid sample points. */
52 { 125000, 900, false },
53 { 125000, 800, false },
54 /** Valid bitrate, invalid sample point. */
55 { 125000, 1000, true },
56 /** Invalid classic/arbitration bitrate, valid sample point. */
57 { 1000000 + 1, 750, true },
58 };
59
60 /**
61 * @brief List of CAN timing values to test for the data phase.
62 */
63 #ifdef CONFIG_CAN_FD_MODE
64 static const struct can_timing_test can_timing_data_tests[] = {
65 /** Standard bitrates. */
66 { 500000, 875, false },
67 { 1000000, 750, false },
68 /** Additional, valid sample points. */
69 { 500000, 900, false },
70 { 500000, 800, false },
71 /** Valid bitrate, invalid sample point. */
72 { 500000, 1000, true },
73 /** Invalid CAN-FD bitrate, valid sample point. */
74 { 8000000 + 1, 750, true },
75 };
76 #endif /* CONFIG_CAN_FD_MODE */
77
78 /**
79 * @brief Assert that a CAN timing struct matches the specified bitrate
80 *
81 * Assert that the values of a CAN timing struct matches the specified bitrate
82 * for a given CAN controller device instance.
83 *
84 * @param dev pointer to the device structure for the driver instance
85 * @param timing pointer to the CAN timing struct
86 * @param bitrate the CAN bitrate in bits/s
87 */
assert_bitrate_correct(const struct device * dev,struct can_timing * timing,uint32_t bitrate)88 static void assert_bitrate_correct(const struct device *dev, struct can_timing *timing,
89 uint32_t bitrate)
90 {
91 const uint32_t ts = 1 + timing->prop_seg + timing->phase_seg1 + timing->phase_seg2;
92 uint32_t core_clock;
93 uint32_t bitrate_calc;
94 int err;
95
96 zassert_not_equal(timing->prescaler, 0, "prescaler is zero");
97
98 err = can_get_core_clock(dev, &core_clock);
99 zassert_equal(err, 0, "failed to get core CAN clock");
100
101 bitrate_calc = core_clock / timing->prescaler / ts;
102 zassert_equal(bitrate, bitrate_calc, "bitrate mismatch");
103 }
104
105 /**
106 * @brief Assert that a CAN timing struct is within the bounds
107 *
108 * Assert that the values of a CAN timing struct are within the bounds for a
109 * given CAN controller device instance.
110 *
111 * @param dev pointer to the device structure for the driver instance
112 * @param timing pointer to the CAN timing struct
113 */
assert_timing_within_bounds(struct can_timing * timing,const struct can_timing * min,const struct can_timing * max)114 static void assert_timing_within_bounds(struct can_timing *timing,
115 const struct can_timing *min,
116 const struct can_timing *max)
117 {
118 zassert_true(timing->sjw <= max->sjw, "sjw exceeds max");
119 zassert_true(timing->prop_seg <= max->prop_seg, "prop_seg exceeds max");
120 zassert_true(timing->phase_seg1 <= max->phase_seg1, "phase_seg1 exceeds max");
121 zassert_true(timing->phase_seg2 <= max->phase_seg2, "phase_seg2 exceeds max");
122 zassert_true(timing->prescaler <= max->prescaler, "prescaler exceeds max");
123
124 zassert_true(timing->sjw >= min->sjw, "sjw lower than min");
125 zassert_true(timing->prop_seg >= min->prop_seg, "prop_seg lower than min");
126 zassert_true(timing->phase_seg1 >= min->phase_seg1, "phase_seg1 lower than min");
127 zassert_true(timing->phase_seg2 >= min->phase_seg2, "phase_seg2 lower than min");
128 zassert_true(timing->prescaler >= min->prescaler, "prescaler lower than min");
129 }
130
131 /**
132 * @brief Assert that a sample point is within a specified margin
133 *
134 * Assert that values of a CAN timing struct results in a specified sample point
135 * within a given margin.
136 *
137 * @param timing pointer to the CAN timing struct
138 * @param sp sample point in permille
139 * @param sp_margin sample point margin in permille
140 */
assert_sp_within_margin(struct can_timing * timing,uint16_t sp,uint16_t sp_margin)141 static void assert_sp_within_margin(struct can_timing *timing, uint16_t sp, uint16_t sp_margin)
142 {
143 const uint32_t ts = 1 + timing->prop_seg + timing->phase_seg1 + timing->phase_seg2;
144 const uint16_t sp_calc = ((1 + timing->prop_seg + timing->phase_seg1) * 1000) / ts;
145
146 zassert_within(sp, sp_calc, sp_margin,
147 "sample point %d not within calculated sample point %d +/- %d",
148 sp, sp_calc, sp_margin);
149 }
150
151 /**
152 * @brief Test a set of CAN timing values
153 *
154 * Test a set of CAN timing values on a specified CAN controller device
155 * instance.
156 *
157 * @param dev pointer to the device structure for the driver instance
158 * @param test pointer to the set of CAN timing values
159 */
test_timing_values(const struct device * dev,const struct can_timing_test * test,bool data_phase)160 static void test_timing_values(const struct device *dev, const struct can_timing_test *test,
161 bool data_phase)
162 {
163 const struct can_timing *max = NULL;
164 const struct can_timing *min = NULL;
165 struct can_timing timing = { 0 };
166 int sp_err;
167 int err;
168
169 printk("testing bitrate %u, sample point %u.%u%% (%s): ",
170 test->bitrate, test->sp / 10, test->sp % 10, test->invalid ? "invalid" : "valid");
171
172 if (data_phase) {
173 if (IS_ENABLED(CONFIG_CAN_FD_MODE)) {
174 min = can_get_timing_data_min(dev);
175 max = can_get_timing_data_max(dev);
176 sp_err = can_calc_timing_data(dev, &timing, test->bitrate, test->sp);
177 } else {
178 zassert_unreachable("data phase timing test without CAN-FD support");
179 }
180 } else {
181 min = can_get_timing_min(dev);
182 max = can_get_timing_max(dev);
183 sp_err = can_calc_timing(dev, &timing, test->bitrate, test->sp);
184 }
185
186 if (test->invalid) {
187 zassert_equal(sp_err, -EINVAL, "err %d, expected -EINVAL", sp_err);
188 printk("OK\n");
189 } else {
190 zassert_true(sp_err >= 0, "unknown error %d", sp_err);
191 zassert_true(sp_err <= SAMPLE_POINT_MARGIN, "sample point error %d too large",
192 sp_err);
193
194 printk("sjw = %u, prop_seg = %u, phase_seg1 = %u, phase_seg2 = %u, prescaler = %u ",
195 timing.sjw, timing.prop_seg, timing.phase_seg1, timing.phase_seg2,
196 timing.prescaler);
197
198 assert_bitrate_correct(dev, &timing, test->bitrate);
199 assert_timing_within_bounds(&timing, min, max);
200 assert_sp_within_margin(&timing, test->sp, SAMPLE_POINT_MARGIN);
201
202 if (IS_ENABLED(CONFIG_CAN_FD_MODE) && data_phase) {
203 err = can_set_timing_data(dev, &timing);
204 } else {
205 err = can_set_timing(dev, &timing);
206 }
207 zassert_equal(err, 0, "failed to set timing (err %d)", err);
208
209 printk("OK, sample point error %d.%d%%\n", sp_err / 10, sp_err % 10);
210 }
211 }
212
213 /**
214 * @brief Test all CAN timing values
215 */
ZTEST_USER(can_timing,test_timing)216 ZTEST_USER(can_timing, test_timing)
217 {
218 const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus));
219 int i;
220
221 for (i = 0; i < ARRAY_SIZE(can_timing_tests); i++) {
222 test_timing_values(dev, &can_timing_tests[i], false);
223 }
224 }
225
226 /**
227 * @brief Test all CAN timing values for the data phase.
228 */
ZTEST_USER(can_timing,test_timing_data)229 ZTEST_USER(can_timing, test_timing_data)
230 {
231 const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus));
232 can_mode_t cap;
233 int err;
234 int i;
235
236 err = can_get_capabilities(dev, &cap);
237 zassert_equal(err, 0, "failed to get CAN controller capabilities (err %d)", err);
238
239 if ((cap & CAN_MODE_FD) == 0) {
240 ztest_test_skip();
241 }
242
243 for (i = 0; i < ARRAY_SIZE(can_timing_data_tests); i++) {
244 test_timing_values(dev, &can_timing_data_tests[i], true);
245 }
246 }
247
248 /**
249 * @brief Test that the minimum timing values can be set.
250 */
ZTEST_USER(can_timing,test_set_timing_min)251 ZTEST_USER(can_timing, test_set_timing_min)
252 {
253 const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus));
254 int err;
255
256 err = can_set_timing(dev, can_get_timing_min(dev));
257 zassert_equal(err, 0, "failed to set minimum timing parameters (err %d)", err);
258 }
259
260 /**
261 * @brief Test that the minimum timing values for the data phase can be set.
262 */
ZTEST_USER(can_timing,test_set_timing_data_min)263 ZTEST_USER(can_timing, test_set_timing_data_min)
264 {
265 const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus));
266 can_mode_t cap;
267 int err;
268
269 err = can_get_capabilities(dev, &cap);
270 zassert_equal(err, 0, "failed to get CAN controller capabilities (err %d)", err);
271
272 if ((cap & CAN_MODE_FD) == 0) {
273 ztest_test_skip();
274 }
275
276 err = can_set_timing_data(dev, can_get_timing_data_min(dev));
277 zassert_equal(err, 0, "failed to set minimum timing data parameters (err %d)", err);
278 }
279
280 /**
281 * @brief Test that the maximum timing values can be set.
282 */
ZTEST_USER(can_timing,test_set_timing_max)283 ZTEST_USER(can_timing, test_set_timing_max)
284 {
285 const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus));
286 int err;
287
288 err = can_set_timing(dev, can_get_timing_max(dev));
289 zassert_equal(err, 0, "failed to set maximum timing parameters (err %d)", err);
290 }
291
292 /**
293 * @brief Test that the maximum timing values for the data phase can be set.
294 */
ZTEST_USER(can_timing,test_set_timing_data_max)295 ZTEST_USER(can_timing, test_set_timing_data_max)
296 {
297 const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus));
298 can_mode_t cap;
299 int err;
300
301 err = can_get_capabilities(dev, &cap);
302 zassert_equal(err, 0, "failed to get CAN controller capabilities (err %d)", err);
303
304 if ((cap & CAN_MODE_FD) == 0) {
305 ztest_test_skip();
306 }
307
308 err = can_set_timing_data(dev, can_get_timing_data_max(dev));
309 zassert_equal(err, 0, "failed to set maximum timing data parameters (err %d)", err);
310 }
311
can_timing_setup(void)312 void *can_timing_setup(void)
313 {
314 const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus));
315 uint32_t core_clock;
316 int err;
317
318 zassert_true(device_is_ready(dev), "CAN device not ready");
319
320 err = can_get_core_clock(dev, &core_clock);
321 zassert_equal(err, 0, "failed to get core CAN clock");
322
323 printk("testing on device %s @ %u Hz\n", dev->name, core_clock);
324
325 k_object_access_grant(dev, k_current_get());
326
327 return NULL;
328 }
329
330 ZTEST_SUITE(can_timing, NULL, can_timing_setup, NULL, NULL, NULL);
331