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