1 /*
2 * Copyright (c) 2019 Alexander Wachter
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <drivers/can.h>
8 #include <kernel.h>
9 #include <sys/util.h>
10
11 #define LOG_LEVEL CONFIG_CAN_LOG_LEVEL
12 #include <logging/log.h>
13 LOG_MODULE_REGISTER(can_driver);
14
15 #define CAN_SYNC_SEG 1
16
17 #define WORK_BUF_COUNT_IS_POWER_OF_2 !(CONFIG_CAN_WORKQ_FRAMES_BUF_CNT & \
18 (CONFIG_CAN_WORKQ_FRAMES_BUF_CNT - 1))
19
20 #define WORK_BUF_MOD_MASK (CONFIG_CAN_WORKQ_FRAMES_BUF_CNT - 1)
21
22 #if WORK_BUF_COUNT_IS_POWER_OF_2
23 #define WORK_BUF_MOD_SIZE(x) ((x) & WORK_BUF_MOD_MASK)
24 #else
25 #define WORK_BUF_MOD_SIZE(x) ((x) % CONFIG_CAN_WORKQ_FRAMES_BUF_CNT)
26 #endif
27
28 #define WORK_BUF_FULL 0xFFFF
29
can_msgq_put(struct zcan_frame * frame,void * arg)30 static void can_msgq_put(struct zcan_frame *frame, void *arg)
31 {
32 struct k_msgq *msgq = (struct k_msgq *)arg;
33 int ret;
34
35 __ASSERT_NO_MSG(msgq);
36
37 ret = k_msgq_put(msgq, frame, K_NO_WAIT);
38 if (ret) {
39 LOG_ERR("Msgq %p overflowed. Frame ID: 0x%x", arg, frame->id);
40 }
41 }
42
z_impl_can_attach_msgq(const struct device * dev,struct k_msgq * msg_q,const struct zcan_filter * filter)43 int z_impl_can_attach_msgq(const struct device *dev, struct k_msgq *msg_q,
44 const struct zcan_filter *filter)
45 {
46 const struct can_driver_api *api = dev->api;
47
48 return api->attach_isr(dev, can_msgq_put, msg_q, filter);
49 }
50
can_work_buffer_init(struct can_frame_buffer * buffer)51 static inline void can_work_buffer_init(struct can_frame_buffer *buffer)
52 {
53 buffer->head = 0;
54 buffer->tail = 0;
55 }
56
can_work_buffer_put(struct zcan_frame * frame,struct can_frame_buffer * buffer)57 static inline int can_work_buffer_put(struct zcan_frame *frame,
58 struct can_frame_buffer *buffer)
59 {
60 uint16_t next_head = WORK_BUF_MOD_SIZE(buffer->head + 1);
61
62 if (buffer->head == WORK_BUF_FULL) {
63 return -1;
64 }
65
66 buffer->buf[buffer->head] = *frame;
67
68 /* Buffer is almost full */
69 if (next_head == buffer->tail) {
70 buffer->head = WORK_BUF_FULL;
71 } else {
72 buffer->head = next_head;
73 }
74
75 return 0;
76 }
77
78 static inline
can_work_buffer_get_next(struct can_frame_buffer * buffer)79 struct zcan_frame *can_work_buffer_get_next(struct can_frame_buffer *buffer)
80 {
81 /* Buffer empty */
82 if (buffer->head == buffer->tail) {
83 return NULL;
84 } else {
85 return &buffer->buf[buffer->tail];
86 }
87 }
88
can_work_buffer_free_next(struct can_frame_buffer * buffer)89 static inline void can_work_buffer_free_next(struct can_frame_buffer *buffer)
90 {
91 uint16_t next_tail = WORK_BUF_MOD_SIZE(buffer->tail + 1);
92
93 if (buffer->head == buffer->tail) {
94 return;
95 }
96
97 if (buffer->head == WORK_BUF_FULL) {
98 buffer->head = buffer->tail;
99 }
100
101 buffer->tail = next_tail;
102 }
103
can_work_handler(struct k_work * work)104 static void can_work_handler(struct k_work *work)
105 {
106 struct zcan_work *can_work = CONTAINER_OF(work, struct zcan_work,
107 work_item);
108 struct zcan_frame *frame;
109
110 while ((frame = can_work_buffer_get_next(&can_work->buf))) {
111 can_work->cb(frame, can_work->cb_arg);
112 can_work_buffer_free_next(&can_work->buf);
113 }
114 }
115
can_work_isr_put(struct zcan_frame * frame,void * arg)116 static void can_work_isr_put(struct zcan_frame *frame, void *arg)
117 {
118 struct zcan_work *work = (struct zcan_work *)arg;
119 int ret;
120
121 ret = can_work_buffer_put(frame, &work->buf);
122 if (ret) {
123 LOG_ERR("Workq buffer overflow. Msg ID: 0x%x", frame->id);
124 return;
125 }
126
127 k_work_submit_to_queue(work->work_queue, &work->work_item);
128 }
129
can_attach_workq(const struct device * dev,struct k_work_q * work_q,struct zcan_work * work,can_rx_callback_t callback,void * callback_arg,const struct zcan_filter * filter)130 int can_attach_workq(const struct device *dev, struct k_work_q *work_q,
131 struct zcan_work *work,
132 can_rx_callback_t callback, void *callback_arg,
133 const struct zcan_filter *filter)
134 {
135 const struct can_driver_api *api = dev->api;
136
137 k_work_init(&work->work_item, can_work_handler);
138 work->work_queue = work_q;
139 work->cb = callback;
140 work->cb_arg = callback_arg;
141 can_work_buffer_init(&work->buf);
142
143 return api->attach_isr(dev, can_work_isr_put, work, filter);
144 }
145
146
update_sampling_pnt(uint32_t ts,uint32_t sp,struct can_timing * res,const struct can_timing * max,const struct can_timing * min)147 static int update_sampling_pnt(uint32_t ts, uint32_t sp, struct can_timing *res,
148 const struct can_timing *max,
149 const struct can_timing *min)
150 {
151 uint16_t ts1_max = max->phase_seg1 + max->prop_seg;
152 uint16_t ts1_min = min->phase_seg1 + min->prop_seg;
153 uint32_t sp_calc;
154 uint16_t ts1, ts2;
155
156 ts2 = ts - (ts * sp) / 1000;
157 ts2 = CLAMP(ts2, min->phase_seg2, max->phase_seg2);
158 ts1 = ts - CAN_SYNC_SEG - ts2;
159
160 if (ts1 > ts1_max) {
161 ts1 = ts1_max;
162 ts2 = ts - CAN_SYNC_SEG - ts1;
163 if (ts2 > max->phase_seg2) {
164 return -1;
165 }
166 } else if (ts1 < ts1_min) {
167 ts1 = ts1_min;
168 ts2 = ts - ts1;
169 if (ts2 < min->phase_seg2) {
170 return -1;
171 }
172 }
173
174 res->prop_seg = CLAMP(ts1 / 2, min->prop_seg, max->prop_seg);
175 res->phase_seg1 = ts1 - res->prop_seg;
176 res->phase_seg2 = ts2;
177
178 sp_calc = (CAN_SYNC_SEG + ts1) * 1000 / ts;
179
180 return sp_calc > sp ? sp_calc - sp : sp - sp_calc;
181 }
182
183 /* 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)184 static int can_calc_timing_int(uint32_t core_clock, struct can_timing *res,
185 const struct can_timing *min,
186 const struct can_timing *max,
187 uint32_t bitrate, uint16_t sp)
188 {
189 uint32_t ts = max->prop_seg + max->phase_seg1 + max->phase_seg2 +
190 CAN_SYNC_SEG;
191 uint16_t sp_err_min = UINT16_MAX;
192 int sp_err;
193 struct can_timing tmp_res;
194
195 if (sp >= 1000 ||
196 (!IS_ENABLED(CONFIG_CAN_FD_MODE) && bitrate > 1000000) ||
197 (IS_ENABLED(CONFIG_CAN_FD_MODE) && bitrate > 8000000)) {
198 return -EINVAL;
199 }
200
201 for (int prescaler = MAX(core_clock / (ts * bitrate), 1);
202 prescaler <= max->prescaler; ++prescaler) {
203 if (core_clock % (prescaler * bitrate)) {
204 /* No integer ts */
205 continue;
206 }
207
208 ts = core_clock / (prescaler * bitrate);
209
210 sp_err = update_sampling_pnt(ts, sp, &tmp_res,
211 max, min);
212 if (sp_err < 0) {
213 /* No prop_seg, seg1, seg2 combination possible */
214 continue;
215 }
216
217 if (sp_err < sp_err_min) {
218 sp_err_min = sp_err;
219 res->prop_seg = tmp_res.prop_seg;
220 res->phase_seg1 = tmp_res.phase_seg1;
221 res->phase_seg2 = tmp_res.phase_seg2;
222 res->prescaler = (uint16_t)prescaler;
223 if (sp_err == 0) {
224 /* No better result than a perfect match*/
225 break;
226 }
227 }
228 }
229
230 if (sp_err_min) {
231 LOG_DBG("SP error: %d 1/1000", sp_err_min);
232 }
233
234 return sp_err_min == UINT16_MAX ? -EINVAL : (int)sp_err_min;
235 }
236
can_calc_timing(const struct device * dev,struct can_timing * res,uint32_t bitrate,uint16_t sample_pnt)237 int can_calc_timing(const struct device *dev, struct can_timing *res,
238 uint32_t bitrate, uint16_t sample_pnt)
239 {
240 const struct can_driver_api *api = dev->api;
241 uint32_t core_clock;
242 int ret;
243
244 ret = can_get_core_clock(dev, &core_clock);
245 if (ret != 0) {
246 return ret;
247 }
248
249 return can_calc_timing_int(core_clock, res, &api->timing_min,
250 &api->timing_max, bitrate, sample_pnt);
251 }
252
253 #ifdef CONFIG_CAN_FD_MODE
can_calc_timing_data(const struct device * dev,struct can_timing * res,uint32_t bitrate,uint16_t sample_pnt)254 int can_calc_timing_data(const struct device *dev, struct can_timing *res,
255 uint32_t bitrate, uint16_t sample_pnt)
256 {
257 const struct can_driver_api *api = dev->api;
258 uint32_t core_clock;
259 int ret;
260
261 ret = can_get_core_clock(dev, &core_clock);
262 if (ret != 0) {
263 return ret;
264 }
265
266 return can_calc_timing_int(core_clock, res, &api->timing_min_data,
267 &api->timing_max_data, bitrate, sample_pnt);
268 }
269 #endif
270
can_calc_prescaler(const struct device * dev,struct can_timing * timing,uint32_t bitrate)271 int can_calc_prescaler(const struct device *dev, struct can_timing *timing,
272 uint32_t bitrate)
273 {
274 uint32_t ts = timing->prop_seg + timing->phase_seg1 + timing->phase_seg2 +
275 CAN_SYNC_SEG;
276 uint32_t core_clock;
277 int ret;
278
279 ret = can_get_core_clock(dev, &core_clock);
280 if (ret != 0) {
281 return ret;
282 }
283
284 timing->prescaler = core_clock / (bitrate * ts);
285
286 return core_clock % (ts * timing->prescaler);
287 }
288