1 /*
2 * Copyright (c) 2019 Alexander Wachter
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/drivers/can.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/sys/check.h>
10 #include <zephyr/sys/util.h>
11 #include <zephyr/logging/log.h>
12
13 LOG_MODULE_REGISTER(can_common, CONFIG_CAN_LOG_LEVEL);
14
15 /* Maximum acceptable deviation in sample point location (permille) */
16 #define SAMPLE_POINT_MARGIN 50
17
18 /* CAN sync segment is always one time quantum */
19 #define CAN_SYNC_SEG 1
20
21 struct can_tx_default_cb_ctx {
22 struct k_sem done;
23 int status;
24 };
25
can_tx_default_cb(const struct device * dev,int error,void * user_data)26 static void can_tx_default_cb(const struct device *dev, int error, void *user_data)
27 {
28 struct can_tx_default_cb_ctx *ctx = user_data;
29
30 ctx->status = error;
31 k_sem_give(&ctx->done);
32 }
33
z_impl_can_send(const struct device * dev,const struct can_frame * frame,k_timeout_t timeout,can_tx_callback_t callback,void * user_data)34 int z_impl_can_send(const struct device *dev, const struct can_frame *frame,
35 k_timeout_t timeout, can_tx_callback_t callback,
36 void *user_data)
37 {
38 const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
39 uint32_t id_mask;
40
41 CHECKIF(frame == NULL) {
42 return -EINVAL;
43 }
44
45 if ((frame->flags & CAN_FRAME_IDE) != 0U) {
46 id_mask = CAN_EXT_ID_MASK;
47 } else {
48 id_mask = CAN_STD_ID_MASK;
49 }
50
51 CHECKIF((frame->id & ~(id_mask)) != 0U) {
52 LOG_ERR("invalid frame with %s (%d-bit) CAN ID 0x%0*x",
53 (frame->flags & CAN_FRAME_IDE) != 0 ? "extended" : "standard",
54 (frame->flags & CAN_FRAME_IDE) != 0 ? 29 : 11,
55 (frame->flags & CAN_FRAME_IDE) != 0 ? 8 : 3, frame->id);
56 return -EINVAL;
57 }
58
59 if (callback == NULL) {
60 struct can_tx_default_cb_ctx ctx;
61 int err;
62
63 k_sem_init(&ctx.done, 0, 1);
64
65 err = api->send(dev, frame, timeout, can_tx_default_cb, &ctx);
66 if (err != 0) {
67 return err;
68 }
69
70 k_sem_take(&ctx.done, K_FOREVER);
71
72 return ctx.status;
73 }
74
75 return api->send(dev, frame, timeout, callback, user_data);
76 }
77
can_add_rx_filter(const struct device * dev,can_rx_callback_t callback,void * user_data,const struct can_filter * filter)78 int can_add_rx_filter(const struct device *dev, can_rx_callback_t callback,
79 void *user_data, const struct can_filter *filter)
80 {
81 const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
82 uint32_t id_mask;
83
84 CHECKIF(callback == NULL || filter == NULL) {
85 return -EINVAL;
86 }
87
88 if ((filter->flags & CAN_FILTER_IDE) != 0U) {
89 id_mask = CAN_EXT_ID_MASK;
90 } else {
91 id_mask = CAN_STD_ID_MASK;
92 }
93
94 CHECKIF(((filter->id & ~(id_mask)) != 0U) || ((filter->mask & ~(id_mask)) != 0U)) {
95 LOG_ERR("invalid filter with %s (%d-bit) CAN ID 0x%0*x, CAN ID mask 0x%0*x",
96 (filter->flags & CAN_FILTER_IDE) != 0 ? "extended" : "standard",
97 (filter->flags & CAN_FILTER_IDE) != 0 ? 29 : 11,
98 (filter->flags & CAN_FILTER_IDE) != 0 ? 8 : 3, filter->id,
99 (filter->flags & CAN_FILTER_IDE) != 0 ? 8 : 3, filter->mask);
100 return -EINVAL;
101 }
102
103 return api->add_rx_filter(dev, callback, user_data, filter);
104 }
105
can_msgq_put(const struct device * dev,struct can_frame * frame,void * user_data)106 static void can_msgq_put(const struct device *dev, struct can_frame *frame, void *user_data)
107 {
108 struct k_msgq *msgq = (struct k_msgq *)user_data;
109 int ret;
110
111 ARG_UNUSED(dev);
112
113 __ASSERT_NO_MSG(msgq);
114
115 ret = k_msgq_put(msgq, frame, K_NO_WAIT);
116 if (ret) {
117 LOG_ERR("Msgq %p overflowed. Frame ID: 0x%x", msgq, frame->id);
118 }
119 }
120
z_impl_can_add_rx_filter_msgq(const struct device * dev,struct k_msgq * msgq,const struct can_filter * filter)121 int z_impl_can_add_rx_filter_msgq(const struct device *dev, struct k_msgq *msgq,
122 const struct can_filter *filter)
123 {
124 const struct can_driver_api *api = dev->api;
125
126 return api->add_rx_filter(dev, can_msgq_put, msgq, filter);
127 }
128
129 /**
130 * @brief Update the timing given a total number of time quanta and a sample point.
131 *
132 * @code{.text}
133 *
134 * +---------------------------------------------------+
135 * | Nominal bit time in time quanta (total_tq) |
136 * +--------------+----------+------------+------------+
137 * | sync_seg | prop_seg | phase_seg1 | phase_seg2 |
138 * +--------------+----------+------------+------------+
139 * | CAN_SYNG_SEG | tseg1 | tseg2 |
140 * +--------------+-----------------------+------------+
141 * ^
142 * sample_pnt
143 * @endcode
144 *
145 * @see @a can_timing
146 *
147 * @param total_tq Total number of time quanta.
148 * @param sample_pnt Sample point in permille of the entire bit time.
149 * @param[out] res Result is written into the @a can_timing struct provided.
150 * @param min Pointer to the minimum supported timing parameter values.
151 * @param max Pointer to the maximum supported timing parameter values.
152 * @retval 0 or positive sample point error on success.
153 * @retval -ENOTSUP if the requested sample point cannot be met.
154 */
update_sample_pnt(uint32_t total_tq,uint32_t sample_pnt,struct can_timing * res,const struct can_timing * min,const struct can_timing * max)155 static int update_sample_pnt(uint32_t total_tq, uint32_t sample_pnt, struct can_timing *res,
156 const struct can_timing *min, const struct can_timing *max)
157 {
158 uint16_t tseg1_max = max->phase_seg1 + max->prop_seg;
159 uint16_t tseg1_min = min->phase_seg1 + min->prop_seg;
160 uint32_t sample_pnt_res;
161 uint16_t tseg1, tseg2;
162
163 /* Calculate number of time quanta in tseg2 for given sample point */
164 tseg2 = total_tq - (total_tq * sample_pnt) / 1000;
165 tseg2 = CLAMP(tseg2, min->phase_seg2, max->phase_seg2);
166
167 /* Calculate number of time quanta in tseg1 */
168 tseg1 = total_tq - CAN_SYNC_SEG - tseg2;
169 if (tseg1 > tseg1_max) {
170 /* Sample point location must be decreased */
171 tseg1 = tseg1_max;
172 tseg2 = total_tq - CAN_SYNC_SEG - tseg1;
173
174 if (tseg2 > max->phase_seg2) {
175 return -ENOTSUP;
176 }
177 } else if (tseg1 < tseg1_min) {
178 /* Sample point location must be increased */
179 tseg1 = tseg1_min;
180 tseg2 = total_tq - CAN_SYNC_SEG - tseg1;
181
182 if (tseg2 < min->phase_seg2) {
183 return -ENOTSUP;
184 }
185 }
186
187 res->phase_seg2 = tseg2;
188
189 /* Attempt to distribute tseg1 evenly between prop_seq and phase_seg1 */
190 res->prop_seg = CLAMP(tseg1 / 2, min->prop_seg, max->prop_seg);
191 res->phase_seg1 = tseg1 - res->prop_seg;
192
193 if (res->phase_seg1 > max->phase_seg1) {
194 /* Even tseg1 distribution not possible, decrease phase_seg1 */
195 res->phase_seg1 = max->phase_seg1;
196 res->prop_seg = tseg1 - res->phase_seg1;
197 } else if (res->phase_seg1 < min->phase_seg1) {
198 /* Even tseg1 distribution not possible, increase phase_seg1 */
199 res->phase_seg1 = min->phase_seg1;
200 res->prop_seg = tseg1 - res->phase_seg1;
201 }
202
203 /* Calculate the resulting sample point */
204 sample_pnt_res = (CAN_SYNC_SEG + tseg1) * 1000 / total_tq;
205
206 /* Return the absolute sample point error */
207 return sample_pnt_res > sample_pnt ?
208 sample_pnt_res - sample_pnt :
209 sample_pnt - sample_pnt_res;
210 }
211
212 /**
213 * @brief Get the sample point location for a given bitrate
214 *
215 * @param bitrate The bitrate in bits/second.
216 * @return The sample point in permille.
217 */
sample_point_for_bitrate(uint32_t bitrate)218 static uint16_t sample_point_for_bitrate(uint32_t bitrate)
219 {
220 uint16_t sample_pnt;
221
222 if (bitrate > 800000) {
223 /* 75.0% */
224 sample_pnt = 750;
225 } else if (bitrate > 500000) {
226 /* 80.0% */
227 sample_pnt = 800;
228 } else {
229 /* 87.5% */
230 sample_pnt = 875;
231 }
232
233 return sample_pnt;
234 }
235
236 /**
237 * @brief Internal function for calculating CAN timing parameters.
238 *
239 * @param dev Pointer to the device structure for the driver instance.
240 * @param[out] res Result is written into the @a can_timing struct provided.
241 * @param min Pointer to the minimum supported timing parameter values.
242 * @param max Pointer to the maximum supported timing parameter values.
243 * @param bitrate Target bitrate in bits/s.
244 * @param sample_pnt Sample point in permille of the entire bit time.
245 *
246 * @retval 0 or positive sample point error on success.
247 * @retval -EINVAL if the requested bitrate or sample point is out of range.
248 * @retval -ENOTSUP if the requested bitrate is not supported.
249 * @retval -EIO if @a can_get_core_clock() is not available.
250 */
can_calc_timing_internal(const struct device * dev,struct can_timing * res,const struct can_timing * min,const struct can_timing * max,uint32_t bitrate,uint16_t sample_pnt)251 static int can_calc_timing_internal(const struct device *dev, struct can_timing *res,
252 const struct can_timing *min, const struct can_timing *max,
253 uint32_t bitrate, uint16_t sample_pnt)
254 {
255 uint32_t total_tq = CAN_SYNC_SEG + max->prop_seg + max->phase_seg1 + max->phase_seg2;
256 struct can_timing tmp_res = { 0 };
257 int err_min = INT_MAX;
258 uint32_t core_clock;
259 int prescaler;
260 int err;
261
262 if (bitrate == 0 || sample_pnt >= 1000) {
263 return -EINVAL;
264 }
265
266 err = can_get_core_clock(dev, &core_clock);
267 if (err != 0) {
268 return -EIO;
269 }
270
271 if (sample_pnt == 0U) {
272 sample_pnt = sample_point_for_bitrate(bitrate);
273 }
274
275 for (prescaler = MAX(core_clock / (total_tq * bitrate), min->prescaler);
276 prescaler <= max->prescaler;
277 prescaler++) {
278
279 if (core_clock % (prescaler * bitrate)) {
280 /* No integer total_tq for this prescaler setting */
281 continue;
282 }
283
284 total_tq = core_clock / (prescaler * bitrate);
285
286 err = update_sample_pnt(total_tq, sample_pnt, &tmp_res, min, max);
287 if (err < 0) {
288 /* Sample point cannot be met for this prescaler setting */
289 continue;
290 }
291
292 if (err < err_min) {
293 /* Improved sample point match */
294 err_min = err;
295 res->prop_seg = tmp_res.prop_seg;
296 res->phase_seg1 = tmp_res.phase_seg1;
297 res->phase_seg2 = tmp_res.phase_seg2;
298 res->prescaler = (uint16_t)prescaler;
299
300 if (err == 0) {
301 /* Perfect sample point match */
302 break;
303 }
304 }
305 }
306
307 if (err_min != 0U) {
308 LOG_DBG("Sample point error: %d 1/1000", err_min);
309 }
310
311 /* Calculate default sjw as phase_seg2 / 2 and clamp the result */
312 res->sjw = MIN(res->phase_seg1, res->phase_seg2 / 2);
313 res->sjw = CLAMP(res->sjw, min->sjw, max->sjw);
314
315 return err_min == INT_MAX ? -ENOTSUP : err_min;
316 }
317
z_impl_can_calc_timing(const struct device * dev,struct can_timing * res,uint32_t bitrate,uint16_t sample_pnt)318 int z_impl_can_calc_timing(const struct device *dev, struct can_timing *res,
319 uint32_t bitrate, uint16_t sample_pnt)
320 {
321 const struct can_timing *min = can_get_timing_min(dev);
322 const struct can_timing *max = can_get_timing_max(dev);
323
324 if (bitrate > 1000000) {
325 return -EINVAL;
326 }
327
328 return can_calc_timing_internal(dev, res, min, max, bitrate, sample_pnt);
329 }
330
331 #ifdef CONFIG_CAN_FD_MODE
z_impl_can_calc_timing_data(const struct device * dev,struct can_timing * res,uint32_t bitrate,uint16_t sample_pnt)332 int z_impl_can_calc_timing_data(const struct device *dev, struct can_timing *res,
333 uint32_t bitrate, uint16_t sample_pnt)
334 {
335 const struct can_timing *min = can_get_timing_data_min(dev);
336 const struct can_timing *max = can_get_timing_data_max(dev);
337
338 if (bitrate > 8000000) {
339 return -EINVAL;
340 }
341
342 return can_calc_timing_internal(dev, res, min, max, bitrate, sample_pnt);
343 }
344 #endif /* CONFIG_CAN_FD_MODE */
345
can_calc_prescaler(const struct device * dev,struct can_timing * timing,uint32_t bitrate)346 int can_calc_prescaler(const struct device *dev, struct can_timing *timing,
347 uint32_t bitrate)
348 {
349 uint32_t ts = timing->prop_seg + timing->phase_seg1 + timing->phase_seg2 +
350 CAN_SYNC_SEG;
351 uint32_t core_clock;
352 int ret;
353
354 ret = can_get_core_clock(dev, &core_clock);
355 if (ret != 0) {
356 return ret;
357 }
358
359 timing->prescaler = core_clock / (bitrate * ts);
360
361 return core_clock % (ts * timing->prescaler);
362 }
363
check_timing_in_range(const struct can_timing * timing,const struct can_timing * min,const struct can_timing * max)364 static int check_timing_in_range(const struct can_timing *timing,
365 const struct can_timing *min,
366 const struct can_timing *max)
367 {
368 if (!IN_RANGE(timing->sjw, min->sjw, max->sjw) ||
369 !IN_RANGE(timing->prop_seg, min->prop_seg, max->prop_seg) ||
370 !IN_RANGE(timing->phase_seg1, min->phase_seg1, max->phase_seg1) ||
371 !IN_RANGE(timing->phase_seg2, min->phase_seg2, max->phase_seg2) ||
372 !IN_RANGE(timing->prescaler, min->prescaler, max->prescaler)) {
373 return -ENOTSUP;
374 }
375
376 if ((timing->sjw > timing->phase_seg1) || (timing->sjw > timing->phase_seg2)) {
377 return -ENOTSUP;
378 }
379
380 return 0;
381 }
382
z_impl_can_set_timing(const struct device * dev,const struct can_timing * timing)383 int z_impl_can_set_timing(const struct device *dev,
384 const struct can_timing *timing)
385 {
386 const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
387 const struct can_timing *min = can_get_timing_min(dev);
388 const struct can_timing *max = can_get_timing_max(dev);
389 int err;
390
391 err = check_timing_in_range(timing, min, max);
392 if (err != 0) {
393 return err;
394 }
395
396 return api->set_timing(dev, timing);
397 }
398
z_impl_can_set_bitrate(const struct device * dev,uint32_t bitrate)399 int z_impl_can_set_bitrate(const struct device *dev, uint32_t bitrate)
400 {
401 struct can_timing timing = { 0 };
402 uint32_t min = can_get_bitrate_min(dev);
403 uint32_t max = can_get_bitrate_max(dev);
404 uint16_t sample_pnt;
405 int ret;
406
407 if ((bitrate < min) || (bitrate > max)) {
408 return -ENOTSUP;
409 }
410
411 sample_pnt = sample_point_for_bitrate(bitrate);
412 ret = can_calc_timing(dev, &timing, bitrate, sample_pnt);
413 if (ret < 0) {
414 return ret;
415 }
416
417 if (ret > SAMPLE_POINT_MARGIN) {
418 return -ERANGE;
419 }
420
421 return can_set_timing(dev, &timing);
422 }
423
424 #ifdef CONFIG_CAN_FD_MODE
z_impl_can_set_timing_data(const struct device * dev,const struct can_timing * timing_data)425 int z_impl_can_set_timing_data(const struct device *dev,
426 const struct can_timing *timing_data)
427 {
428 const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
429 const struct can_timing *min = can_get_timing_data_min(dev);
430 const struct can_timing *max = can_get_timing_data_max(dev);
431 int err;
432
433 if (api->set_timing_data == NULL) {
434 return -ENOSYS;
435 }
436
437 err = check_timing_in_range(timing_data, min, max);
438 if (err != 0) {
439 return err;
440 }
441
442 return api->set_timing_data(dev, timing_data);
443 }
444
z_impl_can_set_bitrate_data(const struct device * dev,uint32_t bitrate_data)445 int z_impl_can_set_bitrate_data(const struct device *dev, uint32_t bitrate_data)
446 {
447 struct can_timing timing_data = { 0 };
448 uint32_t min = can_get_bitrate_min(dev);
449 uint32_t max = can_get_bitrate_max(dev);
450 uint16_t sample_pnt;
451 int ret;
452
453 if ((bitrate_data < min) || (bitrate_data > max)) {
454 return -ENOTSUP;
455 }
456
457 sample_pnt = sample_point_for_bitrate(bitrate_data);
458 ret = can_calc_timing_data(dev, &timing_data, bitrate_data, sample_pnt);
459 if (ret < 0) {
460 return ret;
461 }
462
463 if (ret > SAMPLE_POINT_MARGIN) {
464 return -ERANGE;
465 }
466
467 return can_set_timing_data(dev, &timing_data);
468 }
469 #endif /* CONFIG_CAN_FD_MODE */
470