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