1 /*
2  * Copyright (c) 2019 Vestas Wind Systems A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/drivers/can.h>
9 #include <zephyr/init.h>
10 #include <zephyr/sys/util.h>
11 
12 #include <canopennode.h>
13 
14 #define LOG_LEVEL CONFIG_CANOPEN_LOG_LEVEL
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_REGISTER(canopen_driver);
17 
18 K_KERNEL_STACK_DEFINE(canopen_tx_workq_stack,
19 		      CONFIG_CANOPENNODE_TX_WORKQUEUE_STACK_SIZE);
20 
21 struct k_work_q canopen_tx_workq;
22 
23 struct canopen_tx_work_container {
24 	struct k_work work;
25 	CO_CANmodule_t *CANmodule;
26 };
27 
28 struct canopen_tx_work_container canopen_tx_queue;
29 
30 K_MUTEX_DEFINE(canopen_send_mutex);
31 K_MUTEX_DEFINE(canopen_emcy_mutex);
32 K_MUTEX_DEFINE(canopen_co_mutex);
33 
canopen_send_lock(void)34 inline void canopen_send_lock(void)
35 {
36 	k_mutex_lock(&canopen_send_mutex, K_FOREVER);
37 }
38 
canopen_send_unlock(void)39 inline void canopen_send_unlock(void)
40 {
41 	k_mutex_unlock(&canopen_send_mutex);
42 }
43 
canopen_emcy_lock(void)44 inline void canopen_emcy_lock(void)
45 {
46 	k_mutex_lock(&canopen_emcy_mutex, K_FOREVER);
47 }
48 
canopen_emcy_unlock(void)49 inline void canopen_emcy_unlock(void)
50 {
51 	k_mutex_unlock(&canopen_emcy_mutex);
52 }
53 
canopen_od_lock(void)54 inline void canopen_od_lock(void)
55 {
56 	k_mutex_lock(&canopen_co_mutex, K_FOREVER);
57 }
58 
canopen_od_unlock(void)59 inline void canopen_od_unlock(void)
60 {
61 	k_mutex_unlock(&canopen_co_mutex);
62 }
63 
canopen_detach_all_rx_filters(CO_CANmodule_t * CANmodule)64 static void canopen_detach_all_rx_filters(CO_CANmodule_t *CANmodule)
65 {
66 	uint16_t i;
67 
68 	if (!CANmodule || !CANmodule->rx_array || !CANmodule->configured) {
69 		return;
70 	}
71 
72 	for (i = 0U; i < CANmodule->rx_size; i++) {
73 		if (CANmodule->rx_array[i].filter_id != -ENOSPC) {
74 			can_remove_rx_filter(CANmodule->dev,
75 					     CANmodule->rx_array[i].filter_id);
76 			CANmodule->rx_array[i].filter_id = -ENOSPC;
77 		}
78 	}
79 }
80 
canopen_rx_callback(const struct device * dev,struct can_frame * frame,void * user_data)81 static void canopen_rx_callback(const struct device *dev, struct can_frame *frame, void *user_data)
82 {
83 	CO_CANmodule_t *CANmodule = (CO_CANmodule_t *)user_data;
84 	CO_CANrxMsg_t rxMsg;
85 	CO_CANrx_t *buffer;
86 	int i;
87 
88 	ARG_UNUSED(dev);
89 
90 	/* Loop through registered rx buffers in priority order */
91 	for (i = 0; i < CANmodule->rx_size; i++) {
92 		buffer = &CANmodule->rx_array[i];
93 
94 		if (buffer->filter_id == -ENOSPC || buffer->pFunct == NULL) {
95 			continue;
96 		}
97 
98 		if (((frame->id ^ buffer->ident) & buffer->mask) == 0U) {
99 			rxMsg.ident = frame->id;
100 			rxMsg.DLC = frame->dlc;
101 			memcpy(rxMsg.data, frame->data, frame->dlc);
102 			buffer->pFunct(buffer->object, &rxMsg);
103 			break;
104 		}
105 	}
106 }
107 
canopen_tx_callback(const struct device * dev,int error,void * arg)108 static void canopen_tx_callback(const struct device *dev, int error, void *arg)
109 {
110 	CO_CANmodule_t *CANmodule = arg;
111 
112 	ARG_UNUSED(dev);
113 
114 	if (!CANmodule) {
115 		LOG_ERR("failed to process CAN tx callback");
116 		return;
117 	}
118 
119 	if (error == 0) {
120 		CANmodule->first_tx_msg = false;
121 	}
122 
123 	k_work_submit_to_queue(&canopen_tx_workq, &canopen_tx_queue.work);
124 }
125 
canopen_tx_retry(struct k_work * item)126 static void canopen_tx_retry(struct k_work *item)
127 {
128 	struct canopen_tx_work_container *container =
129 		CONTAINER_OF(item, struct canopen_tx_work_container, work);
130 	CO_CANmodule_t *CANmodule = container->CANmodule;
131 	struct can_frame frame;
132 	CO_CANtx_t *buffer;
133 	int err;
134 	uint16_t i;
135 
136 	memset(&frame, 0, sizeof(frame));
137 
138 	CO_LOCK_CAN_SEND();
139 
140 	for (i = 0; i < CANmodule->tx_size; i++) {
141 		buffer = &CANmodule->tx_array[i];
142 		if (buffer->bufferFull) {
143 			frame.id = buffer->ident;
144 			frame.dlc = buffer->DLC;
145 			frame.flags |= (buffer->rtr ? CAN_FRAME_RTR : 0);
146 			memcpy(frame.data, buffer->data, buffer->DLC);
147 
148 			err = can_send(CANmodule->dev, &frame, K_NO_WAIT,
149 				       canopen_tx_callback, CANmodule);
150 			if (err == -EAGAIN) {
151 				break;
152 			} else if (err != 0) {
153 				LOG_ERR("failed to send CAN frame (err %d)",
154 					err);
155 				CO_errorReport(CANmodule->em,
156 					       CO_EM_GENERIC_SOFTWARE_ERROR,
157 					       CO_EMC_COMMUNICATION, 0);
158 
159 			}
160 
161 			buffer->bufferFull = false;
162 		}
163 	}
164 
165 	CO_UNLOCK_CAN_SEND();
166 }
167 
CO_CANsetConfigurationMode(void * CANdriverState)168 void CO_CANsetConfigurationMode(void *CANdriverState)
169 {
170 	struct canopen_context *ctx = (struct canopen_context *)CANdriverState;
171 	int err;
172 
173 	err = can_stop(ctx->dev);
174 	if (err != 0 && err != -EALREADY) {
175 		LOG_ERR("failed to stop CAN interface (err %d)", err);
176 	}
177 }
178 
CO_CANsetNormalMode(CO_CANmodule_t * CANmodule)179 void CO_CANsetNormalMode(CO_CANmodule_t *CANmodule)
180 {
181 	int err;
182 
183 	err = can_start(CANmodule->dev);
184 	if (err != 0 && err != -EALREADY) {
185 		LOG_ERR("failed to start CAN interface (err %d)", err);
186 		return;
187 	}
188 
189 	CANmodule->CANnormal = true;
190 }
191 
CO_CANmodule_init(CO_CANmodule_t * CANmodule,void * CANdriverState,CO_CANrx_t rxArray[],uint16_t rxSize,CO_CANtx_t txArray[],uint16_t txSize,uint16_t CANbitRate)192 CO_ReturnError_t CO_CANmodule_init(CO_CANmodule_t *CANmodule,
193 				   void *CANdriverState,
194 				   CO_CANrx_t rxArray[], uint16_t rxSize,
195 				   CO_CANtx_t txArray[], uint16_t txSize,
196 				   uint16_t CANbitRate)
197 {
198 	struct canopen_context *ctx = (struct canopen_context *)CANdriverState;
199 	uint16_t i;
200 	int err;
201 	int max_filters;
202 
203 	LOG_DBG("rxSize = %d, txSize = %d", rxSize, txSize);
204 
205 	if (!CANmodule || !rxArray || !txArray || !CANdriverState) {
206 		LOG_ERR("failed to initialize CAN module");
207 		return CO_ERROR_ILLEGAL_ARGUMENT;
208 	}
209 
210 	max_filters = can_get_max_filters(ctx->dev, false);
211 	if (max_filters != -ENOSYS) {
212 		if (max_filters < 0) {
213 			LOG_ERR("unable to determine number of CAN RX filters");
214 			return CO_ERROR_SYSCALL;
215 		}
216 
217 		if (rxSize > max_filters) {
218 			LOG_ERR("insufficient number of concurrent CAN RX filters"
219 				" (needs %d, %d available)", rxSize, max_filters);
220 			return CO_ERROR_OUT_OF_MEMORY;
221 		} else if (rxSize < max_filters) {
222 			LOG_DBG("excessive number of concurrent CAN RX filters enabled"
223 				" (needs %d, %d available)", rxSize, max_filters);
224 		}
225 	}
226 
227 	canopen_detach_all_rx_filters(CANmodule);
228 	canopen_tx_queue.CANmodule = CANmodule;
229 
230 	CANmodule->dev = ctx->dev;
231 	CANmodule->rx_array = rxArray;
232 	CANmodule->rx_size = rxSize;
233 	CANmodule->tx_array = txArray;
234 	CANmodule->tx_size = txSize;
235 	CANmodule->CANnormal = false;
236 	CANmodule->first_tx_msg = true;
237 	CANmodule->errors = 0;
238 	CANmodule->em = NULL;
239 
240 	for (i = 0U; i < rxSize; i++) {
241 		rxArray[i].ident = 0U;
242 		rxArray[i].pFunct = NULL;
243 		rxArray[i].filter_id = -ENOSPC;
244 	}
245 
246 	for (i = 0U; i < txSize; i++) {
247 		txArray[i].bufferFull = false;
248 	}
249 
250 	err = can_set_bitrate(CANmodule->dev, KHZ(CANbitRate));
251 	if (err) {
252 		LOG_ERR("failed to configure CAN bitrate (err %d)", err);
253 		return CO_ERROR_ILLEGAL_ARGUMENT;
254 	}
255 
256 	err = can_set_mode(CANmodule->dev, CAN_MODE_NORMAL);
257 	if (err) {
258 		LOG_ERR("failed to configure CAN interface (err %d)", err);
259 		return CO_ERROR_ILLEGAL_ARGUMENT;
260 	}
261 
262 	CANmodule->configured = true;
263 
264 	return CO_ERROR_NO;
265 }
266 
CO_CANmodule_disable(CO_CANmodule_t * CANmodule)267 void CO_CANmodule_disable(CO_CANmodule_t *CANmodule)
268 {
269 	int err;
270 
271 	if (!CANmodule || !CANmodule->dev) {
272 		return;
273 	}
274 
275 	canopen_detach_all_rx_filters(CANmodule);
276 
277 	err = can_stop(CANmodule->dev);
278 	if (err != 0 && err != -EALREADY) {
279 		LOG_ERR("failed to disable CAN interface (err %d)", err);
280 	}
281 }
282 
CO_CANrxMsg_readIdent(const CO_CANrxMsg_t * rxMsg)283 uint16_t CO_CANrxMsg_readIdent(const CO_CANrxMsg_t *rxMsg)
284 {
285 	return rxMsg->ident;
286 }
287 
CO_CANrxBufferInit(CO_CANmodule_t * CANmodule,uint16_t index,uint16_t ident,uint16_t mask,bool_t rtr,void * object,CO_CANrxBufferCallback_t pFunct)288 CO_ReturnError_t CO_CANrxBufferInit(CO_CANmodule_t *CANmodule, uint16_t index,
289 				uint16_t ident, uint16_t mask, bool_t rtr,
290 				void *object,
291 				CO_CANrxBufferCallback_t pFunct)
292 {
293 	struct can_filter filter;
294 	CO_CANrx_t *buffer;
295 
296 	if (CANmodule == NULL) {
297 		return CO_ERROR_ILLEGAL_ARGUMENT;
298 	}
299 
300 	if (!pFunct || (index >= CANmodule->rx_size)) {
301 		LOG_ERR("failed to initialize CAN rx buffer, illegal argument");
302 		CO_errorReport(CANmodule->em, CO_EM_GENERIC_SOFTWARE_ERROR,
303 			       CO_EMC_SOFTWARE_INTERNAL, 0);
304 		return CO_ERROR_ILLEGAL_ARGUMENT;
305 	}
306 
307 	buffer = &CANmodule->rx_array[index];
308 	buffer->object = object;
309 	buffer->pFunct = pFunct;
310 	buffer->ident = ident;
311 	buffer->mask = mask;
312 
313 	filter.flags = (rtr ? CAN_FILTER_RTR : CAN_FILTER_DATA);
314 	filter.id = ident;
315 	filter.mask = mask;
316 
317 	if (buffer->filter_id != -ENOSPC) {
318 		can_remove_rx_filter(CANmodule->dev, buffer->filter_id);
319 	}
320 
321 	buffer->filter_id = can_add_rx_filter(CANmodule->dev,
322 					      canopen_rx_callback,
323 					      CANmodule, &filter);
324 	if (buffer->filter_id == -ENOSPC) {
325 		LOG_ERR("failed to add CAN rx callback, no free filter");
326 		CO_errorReport(CANmodule->em, CO_EM_MEMORY_ALLOCATION_ERROR,
327 			       CO_EMC_SOFTWARE_INTERNAL, 0);
328 		return CO_ERROR_OUT_OF_MEMORY;
329 	}
330 
331 	return CO_ERROR_NO;
332 }
333 
CO_CANtxBufferInit(CO_CANmodule_t * CANmodule,uint16_t index,uint16_t ident,bool_t rtr,uint8_t noOfBytes,bool_t syncFlag)334 CO_CANtx_t *CO_CANtxBufferInit(CO_CANmodule_t *CANmodule, uint16_t index,
335 			       uint16_t ident, bool_t rtr, uint8_t noOfBytes,
336 			       bool_t syncFlag)
337 {
338 	CO_CANtx_t *buffer;
339 
340 	if (CANmodule == NULL) {
341 		return NULL;
342 	}
343 
344 	if (index >= CANmodule->tx_size) {
345 		LOG_ERR("failed to initialize CAN rx buffer, illegal argument");
346 		CO_errorReport(CANmodule->em, CO_EM_GENERIC_SOFTWARE_ERROR,
347 			       CO_EMC_SOFTWARE_INTERNAL, 0);
348 		return NULL;
349 	}
350 
351 	buffer = &CANmodule->tx_array[index];
352 	buffer->ident = ident;
353 	buffer->rtr = rtr;
354 	buffer->DLC = noOfBytes;
355 	buffer->bufferFull = false;
356 	buffer->syncFlag = syncFlag;
357 
358 	return buffer;
359 }
360 
CO_CANsend(CO_CANmodule_t * CANmodule,CO_CANtx_t * buffer)361 CO_ReturnError_t CO_CANsend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer)
362 {
363 	CO_ReturnError_t ret = CO_ERROR_NO;
364 	struct can_frame frame;
365 	int err;
366 
367 	if (!CANmodule || !CANmodule->dev || !buffer) {
368 		return CO_ERROR_ILLEGAL_ARGUMENT;
369 	}
370 
371 	memset(&frame, 0, sizeof(frame));
372 
373 	CO_LOCK_CAN_SEND();
374 
375 	if (buffer->bufferFull) {
376 		if (!CANmodule->first_tx_msg) {
377 			CO_errorReport(CANmodule->em, CO_EM_CAN_TX_OVERFLOW,
378 				       CO_EMC_CAN_OVERRUN, buffer->ident);
379 		}
380 		buffer->bufferFull = false;
381 		ret = CO_ERROR_TX_OVERFLOW;
382 	}
383 
384 	frame.id = buffer->ident;
385 	frame.dlc = buffer->DLC;
386 	frame.flags = (buffer->rtr ? CAN_FRAME_RTR : 0);
387 	memcpy(frame.data, buffer->data, buffer->DLC);
388 
389 	err = can_send(CANmodule->dev, &frame, K_NO_WAIT, canopen_tx_callback,
390 		       CANmodule);
391 	if (err == -EAGAIN) {
392 		buffer->bufferFull = true;
393 	} else if (err != 0) {
394 		LOG_ERR("failed to send CAN frame (err %d)", err);
395 		CO_errorReport(CANmodule->em, CO_EM_GENERIC_SOFTWARE_ERROR,
396 			       CO_EMC_COMMUNICATION, 0);
397 		ret = CO_ERROR_TX_UNCONFIGURED;
398 	}
399 
400 	CO_UNLOCK_CAN_SEND();
401 
402 	return ret;
403 }
404 
CO_CANclearPendingSyncPDOs(CO_CANmodule_t * CANmodule)405 void CO_CANclearPendingSyncPDOs(CO_CANmodule_t *CANmodule)
406 {
407 	bool_t tpdoDeleted = false;
408 	CO_CANtx_t *buffer;
409 	uint16_t i;
410 
411 	if (!CANmodule) {
412 		return;
413 	}
414 
415 	CO_LOCK_CAN_SEND();
416 
417 	for (i = 0; i < CANmodule->tx_size; i++) {
418 		buffer = &CANmodule->tx_array[i];
419 		if (buffer->bufferFull && buffer->syncFlag) {
420 			buffer->bufferFull = false;
421 			tpdoDeleted = true;
422 		}
423 	}
424 
425 	CO_UNLOCK_CAN_SEND();
426 
427 	if (tpdoDeleted) {
428 		CO_errorReport(CANmodule->em, CO_EM_TPDO_OUTSIDE_WINDOW,
429 			       CO_EMC_COMMUNICATION, 0);
430 	}
431 }
432 
CO_CANverifyErrors(CO_CANmodule_t * CANmodule)433 void CO_CANverifyErrors(CO_CANmodule_t *CANmodule)
434 {
435 	CO_EM_t *em = (CO_EM_t *)CANmodule->em;
436 	struct can_bus_err_cnt err_cnt;
437 	enum can_state state;
438 	uint8_t rx_overflows;
439 	uint32_t errors;
440 	int err;
441 
442 	/*
443 	 * TODO: Zephyr lacks an API for reading the rx mailbox
444 	 * overflow counter.
445 	 */
446 	rx_overflows  = 0;
447 
448 	err = can_get_state(CANmodule->dev, &state, &err_cnt);
449 	if (err != 0) {
450 		LOG_ERR("failed to get CAN controller state (err %d)", err);
451 		return;
452 	}
453 
454 	errors = ((uint32_t)err_cnt.tx_err_cnt << 16) |
455 		 ((uint32_t)err_cnt.rx_err_cnt << 8) |
456 		 rx_overflows;
457 
458 	if (errors != CANmodule->errors) {
459 		CANmodule->errors = errors;
460 
461 		if (state == CAN_STATE_BUS_OFF) {
462 			/* Bus off */
463 			CO_errorReport(em, CO_EM_CAN_TX_BUS_OFF,
464 				       CO_EMC_BUS_OFF_RECOVERED, errors);
465 		} else {
466 			/* Bus not off */
467 			CO_errorReset(em, CO_EM_CAN_TX_BUS_OFF, errors);
468 
469 			if ((err_cnt.rx_err_cnt >= 96U) ||
470 			    (err_cnt.tx_err_cnt >= 96U)) {
471 				/* Bus warning */
472 				CO_errorReport(em, CO_EM_CAN_BUS_WARNING,
473 					       CO_EMC_NO_ERROR, errors);
474 			} else {
475 				/* Bus not warning */
476 				CO_errorReset(em, CO_EM_CAN_BUS_WARNING,
477 					      errors);
478 			}
479 
480 			if (err_cnt.rx_err_cnt >= 128U) {
481 				/* Bus rx passive */
482 				CO_errorReport(em, CO_EM_CAN_RX_BUS_PASSIVE,
483 					       CO_EMC_CAN_PASSIVE, errors);
484 			} else {
485 				/* Bus not rx passive */
486 				CO_errorReset(em, CO_EM_CAN_RX_BUS_PASSIVE,
487 					      errors);
488 			}
489 
490 			if (err_cnt.tx_err_cnt >= 128U &&
491 			    !CANmodule->first_tx_msg) {
492 				/* Bus tx passive */
493 				CO_errorReport(em, CO_EM_CAN_TX_BUS_PASSIVE,
494 					       CO_EMC_CAN_PASSIVE, errors);
495 			} else if (CO_isError(em, CO_EM_CAN_TX_BUS_PASSIVE)) {
496 				/* Bus not tx passive */
497 				CO_errorReset(em, CO_EM_CAN_TX_BUS_PASSIVE,
498 					      errors);
499 				CO_errorReset(em, CO_EM_CAN_TX_OVERFLOW,
500 					      errors);
501 			}
502 		}
503 
504 		/* This code can be activated if we can read the overflows*/
505 		if (false && rx_overflows != 0U) {
506 			CO_errorReport(em, CO_EM_CAN_RXB_OVERFLOW,
507 				       CO_EMC_CAN_OVERRUN, errors);
508 		}
509 	}
510 }
511 
canopen_init(void)512 static int canopen_init(void)
513 {
514 
515 	k_work_queue_start(&canopen_tx_workq, canopen_tx_workq_stack,
516 			   K_KERNEL_STACK_SIZEOF(canopen_tx_workq_stack),
517 			   CONFIG_CANOPENNODE_TX_WORKQUEUE_PRIORITY, NULL);
518 
519 	k_thread_name_set(&canopen_tx_workq.thread, "canopen_tx_workq");
520 
521 	k_work_init(&canopen_tx_queue.work, canopen_tx_retry);
522 
523 	return 0;
524 }
525 
526 SYS_INIT(canopen_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
527