1 /*
2 * Copyright (c) 2022-2024 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 /** Bitrate in bit/s */
29 uint32_t bitrate;
30 /** Desired sample point in permille */
31 uint16_t sp;
32 };
33
34 /**
35 * @brief List of CAN timing values to test.
36 */
37 static const struct can_timing_test can_timing_tests[] = {
38 /* CiA 301 recommended bitrates */
39 #ifdef CONFIG_TEST_ALL_BITRATES
40 { 10000, 875 },
41 #endif /* CONFIG_TEST_ALL_BITRATES */
42 { 20000, 875 },
43 { 50000, 875 },
44 { 125000, 875 },
45 { 250000, 875 },
46 { 500000, 875 },
47 { 800000, 800 },
48 { 1000000, 750 },
49 };
50
51 /**
52 * @brief List of CAN FD data phase timing values to test.
53 */
54 static const struct can_timing_test can_timing_data_tests[] = {
55 /* CiA 601-2 recommended data phase bitrates */
56 { 1000000, 750 },
57 #ifdef CONFIG_TEST_ALL_BITRATES
58 { 2000000, 750 },
59 { 4000000, 750 },
60 { 5000000, 750 },
61 { 8000000, 750 },
62 #endif /* CONFIG_TEST_ALL_BITRATES */
63 };
64
65 /**
66 * @brief Assert that a CAN timing struct matches the specified bitrate
67 *
68 * Assert that the values of a CAN timing struct matches the specified bitrate
69 * for a given CAN controller device instance.
70 *
71 * @param dev pointer to the device structure for the driver instance
72 * @param timing pointer to the CAN timing struct
73 * @param bitrate the CAN bitrate in bit/s
74 */
assert_bitrate_correct(const struct device * dev,struct can_timing * timing,uint32_t bitrate)75 static void assert_bitrate_correct(const struct device *dev, struct can_timing *timing,
76 uint32_t bitrate)
77 {
78 const uint32_t ts = 1 + timing->prop_seg + timing->phase_seg1 + timing->phase_seg2;
79 uint32_t core_clock;
80 uint32_t bitrate_calc;
81 int err;
82
83 zassert_not_equal(timing->prescaler, 0, "prescaler is zero");
84
85 err = can_get_core_clock(dev, &core_clock);
86 zassert_equal(err, 0, "failed to get core CAN clock");
87
88 bitrate_calc = core_clock / timing->prescaler / ts;
89 zassert_equal(bitrate, bitrate_calc, "bitrate mismatch");
90 }
91
92 /**
93 * @brief Assert that a CAN timing struct is within the bounds
94 *
95 * Assert that the values of a CAN timing struct are within the bounds for a
96 * given CAN controller device instance.
97 *
98 * @param dev pointer to the device structure for the driver instance
99 * @param timing pointer to the CAN timing struct
100 */
assert_timing_within_bounds(struct can_timing * timing,const struct can_timing * min,const struct can_timing * max)101 static void assert_timing_within_bounds(struct can_timing *timing,
102 const struct can_timing *min,
103 const struct can_timing *max)
104 {
105 zassert_true(timing->sjw <= max->sjw, "sjw exceeds max");
106 zassert_true(timing->prop_seg <= max->prop_seg, "prop_seg exceeds max");
107 zassert_true(timing->phase_seg1 <= max->phase_seg1, "phase_seg1 exceeds max");
108 zassert_true(timing->phase_seg2 <= max->phase_seg2, "phase_seg2 exceeds max");
109 zassert_true(timing->prescaler <= max->prescaler, "prescaler exceeds max");
110
111 zassert_true(timing->sjw >= min->sjw, "sjw lower than min");
112 zassert_true(timing->prop_seg >= min->prop_seg, "prop_seg lower than min");
113 zassert_true(timing->phase_seg1 >= min->phase_seg1, "phase_seg1 lower than min");
114 zassert_true(timing->phase_seg2 >= min->phase_seg2, "phase_seg2 lower than min");
115 zassert_true(timing->prescaler >= min->prescaler, "prescaler lower than min");
116 }
117
118 /**
119 * @brief Assert that a sample point is within a specified margin
120 *
121 * Assert that values of a CAN timing struct results in a specified sample point
122 * within a given margin.
123 *
124 * @param timing pointer to the CAN timing struct
125 * @param sp sample point in permille
126 * @param sp_margin sample point margin in permille
127 */
assert_sp_within_margin(struct can_timing * timing,uint16_t sp,uint16_t sp_margin)128 static void assert_sp_within_margin(struct can_timing *timing, uint16_t sp, uint16_t sp_margin)
129 {
130 const uint32_t ts = 1 + timing->prop_seg + timing->phase_seg1 + timing->phase_seg2;
131 const uint16_t sp_calc = ((1 + timing->prop_seg + timing->phase_seg1) * 1000) / ts;
132
133 zassert_within(sp, sp_calc, sp_margin,
134 "sample point %d not within calculated sample point %d +/- %d",
135 sp, sp_calc, sp_margin);
136 }
137
138 /**
139 * @brief Test a set of CAN timing values
140 *
141 * Test a set of CAN timing values on a specified CAN controller device
142 * instance.
143 *
144 * @param dev pointer to the device structure for the driver instance
145 * @param test pointer to the set of CAN timing values
146 * returns true if bitrate was supported, false otherwise
147 */
test_timing_values(const struct device * dev,const struct can_timing_test * test,bool data_phase)148 static bool test_timing_values(const struct device *dev, const struct can_timing_test *test,
149 bool data_phase)
150 {
151 const struct can_timing *max = NULL;
152 const struct can_timing *min = NULL;
153 struct can_timing timing = { 0 };
154 int sp_err = -EINVAL;
155 int err;
156
157 printk("testing bitrate %u, sample point %u.%u%%: ",
158 test->bitrate, test->sp / 10, test->sp % 10);
159
160 if (data_phase) {
161 if (IS_ENABLED(CONFIG_CAN_FD_MODE)) {
162 min = can_get_timing_data_min(dev);
163 max = can_get_timing_data_max(dev);
164 sp_err = can_calc_timing_data(dev, &timing, test->bitrate, test->sp);
165 } else {
166 zassert_unreachable("data phase timing test without CAN FD support");
167 }
168 } else {
169 min = can_get_timing_min(dev);
170 max = can_get_timing_max(dev);
171 sp_err = can_calc_timing(dev, &timing, test->bitrate, test->sp);
172 }
173
174 if (sp_err == -ENOTSUP) {
175 printk("bitrate not supported\n");
176 return false;
177 } else {
178 zassert_true(sp_err >= 0, "unknown error %d", sp_err);
179 zassert_true(sp_err <= SAMPLE_POINT_MARGIN, "sample point error %d too large",
180 sp_err);
181
182 printk("sjw = %u, prop_seg = %u, phase_seg1 = %u, phase_seg2 = %u, prescaler = %u ",
183 timing.sjw, timing.prop_seg, timing.phase_seg1, timing.phase_seg2,
184 timing.prescaler);
185
186 assert_bitrate_correct(dev, &timing, test->bitrate);
187 assert_timing_within_bounds(&timing, min, max);
188 assert_sp_within_margin(&timing, test->sp, SAMPLE_POINT_MARGIN);
189
190 if (IS_ENABLED(CONFIG_CAN_FD_MODE) && data_phase) {
191 err = can_set_timing_data(dev, &timing);
192 } else {
193 err = can_set_timing(dev, &timing);
194 }
195 zassert_equal(err, 0, "failed to set timing (err %d)", err);
196
197 printk("OK, sample point error %d.%d%%\n", sp_err / 10, sp_err % 10);
198 }
199
200 return true;
201 }
202
203 /**
204 * @brief Test all CAN timing values
205 */
ZTEST_USER(can_timing,test_timing)206 ZTEST_USER(can_timing, test_timing)
207 {
208 const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus));
209 int count = 0;
210 int i;
211
212 for (i = 0; i < ARRAY_SIZE(can_timing_tests); i++) {
213 if (test_timing_values(dev, &can_timing_tests[i], false)) {
214 count++;
215 }
216 }
217
218 zassert_true(count > 0, "no bitrates supported");
219 }
220
221 /**
222 * @brief Test all CAN timing values for the data phase.
223 */
ZTEST_USER(can_timing,test_timing_data)224 ZTEST_USER(can_timing, test_timing_data)
225 {
226 const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus));
227 can_mode_t cap;
228 int count = 0;
229 int err;
230 int i;
231
232 err = can_get_capabilities(dev, &cap);
233 zassert_equal(err, 0, "failed to get CAN controller capabilities (err %d)", err);
234
235 if ((cap & CAN_MODE_FD) == 0) {
236 ztest_test_skip();
237 }
238
239 for (i = 0; i < ARRAY_SIZE(can_timing_data_tests); i++) {
240 if (test_timing_values(dev, &can_timing_data_tests[i], true)) {
241 count++;
242 }
243 }
244
245 zassert_true(count > 0, "no data phase bitrates supported");
246 }
247
can_timing_setup(void)248 void *can_timing_setup(void)
249 {
250 const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus));
251 uint32_t core_clock;
252 int err;
253
254 zassert_true(device_is_ready(dev), "CAN device not ready");
255 k_object_access_grant(dev, k_current_get());
256
257 err = can_get_core_clock(dev, &core_clock);
258 zassert_equal(err, 0, "failed to get core CAN clock");
259
260 printk("testing on device %s @ %u Hz\n", dev->name, core_clock);
261
262 if (IS_ENABLED(CONFIG_CAN_FD_MODE)) {
263 can_mode_t cap;
264
265 err = can_get_capabilities(dev, &cap);
266 zassert_equal(err, 0, "failed to get CAN controller capabilities (err %d)", err);
267
268 if ((cap & CAN_MODE_FD) != 0) {
269 switch (core_clock) {
270 case MHZ(20):
271 break;
272 case MHZ(40):
273 break;
274 case MHZ(80):
275 break;
276 default:
277 TC_PRINT("Warning: CiA 601-3 recommends a CAN FD core clock of "
278 "20, 40, or 80 MHz for good node interoperability\n");
279 break;
280 }
281 }
282 }
283
284 if (!IS_ENABLED(CONFIG_TEST_ALL_BITRATES)) {
285 TC_PRINT("Warning: Testing limited selection of bitrates "
286 "(CONFIG_TEST_ALL_BITRATES=n)\n");
287 }
288
289 return NULL;
290 }
291
292 ZTEST_SUITE(can_timing, NULL, can_timing_setup, NULL, NULL, NULL);
293