CANopenLinux
CANopenNode on Linux devices
Loading...
Searching...
No Matches
CO_driver_target.h
Go to the documentation of this file.
1
22
23#ifndef CO_DRIVER_TARGET_H
24#define CO_DRIVER_TARGET_H
25
26/* This file contains device and application specific definitions. It is included from CO_driver.h, which contains
27 * documentation for common definitions below. */
28
29#include <stddef.h>
30#include <stdbool.h>
31#include <stdint.h>
32#include <stdio.h>
33#include <endian.h>
34#ifndef CO_SINGLE_THREAD
35#include <pthread.h>
36#endif
37#include <linux/can.h>
38#include <net/if.h>
39#include <sys/epoll.h>
40
41#ifdef CO_DRIVER_CUSTOM
42#include "CO_driver_custom.h"
43#endif
44#include "CO_error.h"
45
46#ifdef __cplusplus
47extern "C" {
48#endif
49
50/* Stack configuration override default values. For more information see file CO_config.h. */
51#ifdef CO_SINGLE_THREAD
52#define CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE 0
53#else
54#define CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE CO_CONFIG_FLAG_CALLBACK_PRE
55#endif
56#define CO_CONFIG_GLOBAL_FLAG_TIMERNEXT CO_CONFIG_FLAG_TIMERNEXT
57
58#ifndef CO_CONFIG_NMT
59#define CO_CONFIG_NMT \
60 (CO_CONFIG_NMT_CALLBACK_CHANGE | CO_CONFIG_NMT_MASTER | CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE \
61 | CO_CONFIG_GLOBAL_FLAG_TIMERNEXT)
62#endif
63
64#ifndef CO_CONFIG_HB_CONS
65#define CO_CONFIG_HB_CONS \
66 (CO_CONFIG_HB_CONS_ENABLE | CO_CONFIG_HB_CONS_CALLBACK_CHANGE | CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE \
67 | CO_CONFIG_GLOBAL_FLAG_TIMERNEXT | CO_CONFIG_GLOBAL_FLAG_OD_DYNAMIC)
68#endif
69
70#ifndef CO_CONFIG_EM
71#define CO_CONFIG_EM \
72 (CO_CONFIG_EM_PRODUCER | CO_CONFIG_EM_PROD_CONFIGURABLE | CO_CONFIG_EM_PROD_INHIBIT | CO_CONFIG_EM_HISTORY \
73 | CO_CONFIG_EM_STATUS_BITS | CO_CONFIG_EM_CONSUMER | CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE \
74 | CO_CONFIG_GLOBAL_FLAG_TIMERNEXT)
75#endif
76
77#ifndef CO_CONFIG_SDO_SRV
78#define CO_CONFIG_SDO_SRV \
79 (CO_CONFIG_SDO_SRV_SEGMENTED | CO_CONFIG_SDO_SRV_BLOCK | CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE \
80 | CO_CONFIG_GLOBAL_FLAG_TIMERNEXT | CO_CONFIG_GLOBAL_FLAG_OD_DYNAMIC)
81#endif
82
83#ifndef CO_CONFIG_SDO_SRV_BUFFER_SIZE
84#define CO_CONFIG_SDO_SRV_BUFFER_SIZE 900
85#endif
86
87#ifndef CO_CONFIG_SDO_CLI
88#define CO_CONFIG_SDO_CLI \
89 (CO_CONFIG_SDO_CLI_ENABLE | CO_CONFIG_SDO_CLI_SEGMENTED | CO_CONFIG_SDO_CLI_BLOCK | CO_CONFIG_SDO_CLI_LOCAL \
90 | CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | CO_CONFIG_GLOBAL_FLAG_TIMERNEXT | CO_CONFIG_GLOBAL_FLAG_OD_DYNAMIC)
91#endif
92
93#ifndef CO_CONFIG_TIME
94#define CO_CONFIG_TIME \
95 (CO_CONFIG_TIME_ENABLE | CO_CONFIG_TIME_PRODUCER | CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE \
96 | CO_CONFIG_GLOBAL_FLAG_OD_DYNAMIC)
97#endif
98
99#ifndef CO_CONFIG_LSS
100#define CO_CONFIG_LSS \
101 (CO_CONFIG_LSS_SLAVE | CO_CONFIG_LSS_SLAVE_FASTSCAN_DIRECT_RESPOND | CO_CONFIG_LSS_MASTER \
102 | CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE)
103#endif
104
105#ifndef CO_CONFIG_GFC
106#define CO_CONFIG_GFC (CO_CONFIG_GFC_ENABLE | CO_CONFIG_GFC_CONSUMER | CO_CONFIG_GFC_PRODUCER)
107#endif
108
109#ifndef CO_CONFIG_SRDO
110#define CO_CONFIG_SRDO \
111 (CO_CONFIG_SRDO_ENABLE | CO_CONFIG_SRDO_CHECK_TX | CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE \
112 | CO_CONFIG_GLOBAL_FLAG_TIMERNEXT)
113#endif
114
115#ifndef CO_CONFIG_GTW
116#define CO_CONFIG_GTW \
117 (CO_CONFIG_GTW_ASCII | CO_CONFIG_GTW_ASCII_SDO | CO_CONFIG_GTW_ASCII_NMT | CO_CONFIG_GTW_ASCII_LSS \
118 | CO_CONFIG_GTW_ASCII_LOG | CO_CONFIG_GTW_ASCII_ERROR_DESC | CO_CONFIG_GTW_ASCII_PRINT_HELP \
119 | CO_CONFIG_GTW_ASCII_PRINT_LEDS)
120#define CO_CONFIG_GTW_BLOCK_DL_LOOP 3
121#define CO_CONFIG_GTWA_COMM_BUF_SIZE 2000
122#define CO_CONFIG_GTWA_LOG_BUF_SIZE 10000
123#endif
124
125#ifndef CO_CONFIG_CRC16
126#define CO_CONFIG_CRC16 (CO_CONFIG_CRC16_ENABLE)
127#endif
128
129#ifndef CO_CONFIG_FIFO
130#define CO_CONFIG_FIFO \
131 (CO_CONFIG_FIFO_ENABLE | CO_CONFIG_FIFO_ALT_READ | CO_CONFIG_FIFO_CRC16_CCITT | CO_CONFIG_FIFO_ASCII_COMMANDS \
132 | CO_CONFIG_FIFO_ASCII_DATATYPES)
133#endif
134
135/* Print debug info from some internal parts of the stack */
136#if (CO_CONFIG_DEBUG) & CO_CONFIG_DEBUG_COMMON
137#include <stdio.h>
138#include <syslog.h>
139#define CO_DEBUG_COMMON(msg) log_printf(LOG_DEBUG, DBG_CO_DEBUG, msg);
140#endif
141
149
166#ifndef CO_DRIVER_MULTI_INTERFACE
167#define CO_DRIVER_MULTI_INTERFACE 0
168#endif
169
186#ifndef CO_DRIVER_ERROR_REPORTING
187#define CO_DRIVER_ERROR_REPORTING 1
188#endif
189
190/* skip this section for Doxygen, because it is documented in CO_driver.h */
191#ifndef CO_DOXYGEN
192
193/* Basic definitions */
194#ifdef __BYTE_ORDER
195#if __BYTE_ORDER == __LITTLE_ENDIAN
196#define CO_LITTLE_ENDIAN
197#define CO_SWAP_16(x) x
198#define CO_SWAP_32(x) x
199#define CO_SWAP_64(x) x
200#else
201#define CO_BIG_ENDIAN
202#include <byteswap.h>
203#define CO_SWAP_16(x) bswap_16(x)
204#define CO_SWAP_32(x) bswap_32(x)
205#define CO_SWAP_64(x) bswap_64(x)
206#endif
207#endif
208/* NULL is defined in stddef.h */
209/* true and false are defined in stdbool.h */
210/* int8_t to uint64_t are defined in stdint.h */
211typedef uint_fast8_t bool_t;
212typedef float float32_t;
213typedef double float64_t;
214
215/* CAN receive message structure as aligned in socketCAN. */
216typedef struct {
217 uint32_t ident;
218 uint8_t DLC;
219 uint8_t padding[3];
220 uint8_t data[8];
221} CO_CANrxMsg_t;
222
223/* Access to received CAN message */
224static inline uint16_t
225CO_CANrxMsg_readIdent(void* rxMsg) {
226 CO_CANrxMsg_t* rxMsgCasted = (CO_CANrxMsg_t*)rxMsg;
227 return (uint16_t)(rxMsgCasted->ident & CAN_SFF_MASK);
228}
229
230static inline uint8_t
231CO_CANrxMsg_readDLC(void* rxMsg) {
232 CO_CANrxMsg_t* rxMsgCasted = (CO_CANrxMsg_t*)rxMsg;
233 return (uint8_t)(rxMsgCasted->DLC);
234}
235
236static inline uint8_t*
237CO_CANrxMsg_readData(void* rxMsg) {
238 CO_CANrxMsg_t* rxMsgCasted = (CO_CANrxMsg_t*)rxMsg;
239 return (uint8_t*)(rxMsgCasted->data);
240}
241
242/* Received message object */
243typedef struct {
244 uint32_t ident;
245 uint32_t mask;
246 void* object;
247 void (*CANrx_callback)(void* object, void* message);
248 int can_ifindex; /* CAN Interface index from last message */
249 struct timespec timestamp; /* time of reception of last message */
250} CO_CANrx_t;
251
252/* Transmit message object as aligned in socketCAN. */
253typedef struct {
254 uint32_t ident;
255 uint8_t DLC;
256 uint8_t padding[3]; /* ensure alignment */
257 uint8_t data[8];
258 volatile bool_t bufferFull;
259 volatile bool_t syncFlag; /* info about transmit message */
260 int can_ifindex; /* CAN Interface index to use */
261} CO_CANtx_t;
262
263/* Max COB ID for standard frame format */
264#define CO_CAN_MSG_SFF_MAX_COB_ID (1 << CAN_SFF_ID_BITS)
265
266/* CAN interface object (CANptr), passed to CO_CANinit() */
267typedef struct {
268 int can_ifindex; /* CAN Interface index */
269 int epoll_fd; /* File descriptor for epoll, which waits for CAN receive event */
270} CO_CANptrSocketCan_t;
271
272/* socketCAN interface object */
273typedef struct {
274 int can_ifindex; /* CAN Interface index */
275 char ifName[IFNAMSIZ]; /* CAN Interface name */
276 int fd; /* socketCAN file descriptor */
277#if CO_DRIVER_ERROR_REPORTING > 0 || defined CO_DOXYGEN
279#endif
280} CO_CANinterface_t;
281
282/* CAN module object */
283typedef struct {
284 /* List of can interfaces. From CO_CANmodule_init() or one per CO_CANmodule_addInterface() call */
285 CO_CANinterface_t* CANinterfaces;
286 uint32_t CANinterfaceCount; /* interface count */
287 CO_CANrx_t* rxArray;
288 uint16_t rxSize;
289 struct can_filter* rxFilter; /* socketCAN filter list, one per rx buffer */
290 uint32_t rxDropCount; /* messages dropped on rx socket queue */
291 CO_CANtx_t* txArray;
292 uint16_t txSize;
293 uint16_t CANerrorStatus;
294 volatile bool_t CANnormal;
295 volatile uint16_t CANtxCount;
296 int epoll_fd; /* File descriptor for epoll, which waits for CAN receive event */
297#if CO_DRIVER_MULTI_INTERFACE > 0 || defined CO_DOXYGEN
298 /* Lookup tables Cob ID to rx/tx array index. Only feasible for SFF Messages. */
299 uint32_t rxIdentToIndex[CO_CAN_MSG_SFF_MAX_COB_ID];
300 uint32_t txIdentToIndex[CO_CAN_MSG_SFF_MAX_COB_ID];
301#endif
302} CO_CANmodule_t;
303
304/* Data storage: Maximum file name length including path */
305#ifndef CO_STORAGE_PATH_MAX
306#define CO_STORAGE_PATH_MAX 255
307#endif
308
309/* Data storage object for one entry */
310typedef struct {
311 void* addr;
312 size_t len;
313 uint8_t subIndexOD;
314 uint8_t attr;
315 char filename[CO_STORAGE_PATH_MAX]; /* Name of the file, where data block is stored */
316 uint16_t crc; /* CRC checksum of the data stored previously, for auto storage */
317 FILE* fp; /* Pointer to opened file, for auto storage */
318} CO_storage_entry_t;
319
320#ifdef CO_SINGLE_THREAD
321#define CO_LOCK_CAN_SEND(CAN_MODULE) \
322 { (void)CAN_MODULE; }
323#define CO_UNLOCK_CAN_SEND(CAN_MODULE) \
324 { (void)CAN_MODULE; }
325#define CO_LOCK_EMCY(CAN_MODULE) \
326 { (void)CAN_MODULE; }
327#define CO_UNLOCK_EMCY(CAN_MODULE) \
328 { (void)CAN_MODULE; }
329#define CO_LOCK_OD(CAN_MODULE) \
330 { (void)CAN_MODULE; }
331#define CO_UNLOCK_OD(CAN_MODULE) \
332 { (void)CAN_MODULE; }
333#define CO_MemoryBarrier()
334#else
335
336/* (un)lock critical section in CO_CANsend() - unused */
337#define CO_LOCK_CAN_SEND(CAN_MODULE)
338#define CO_UNLOCK_CAN_SEND(CAN_MODULE)
339
340/* (un)lock critical section in CO_errorReport() or CO_errorReset() */
341extern pthread_mutex_t CO_EMCY_mutex;
342
343static inline int
344CO_LOCK_EMCY(CO_CANmodule_t* CANmodule) {
345 (void)CANmodule;
346 return pthread_mutex_lock(&CO_EMCY_mutex);
347}
348
349static inline void
350CO_UNLOCK_EMCY(CO_CANmodule_t* CANmodule) {
351 (void)CANmodule;
352 (void)pthread_mutex_unlock(&CO_EMCY_mutex);
353}
354
355/* (un)lock critical section when accessing Object Dictionary */
356extern pthread_mutex_t CO_OD_mutex;
357
358static inline int
359CO_LOCK_OD(CO_CANmodule_t* CANmodule) {
360 (void)CANmodule;
361 return pthread_mutex_lock(&CO_OD_mutex);
362}
363
364static inline void
365CO_UNLOCK_OD(CO_CANmodule_t* CANmodule) {
366 (void)CANmodule;
367 (void)pthread_mutex_unlock(&CO_OD_mutex);
368}
369
370/* Synchronization between CAN receive and message processing threads. */
371#define CO_MemoryBarrier() \
372 { __sync_synchronize(); }
373#endif /* CO_SINGLE_THREAD */
374
375#define CO_FLAG_READ(rxNew) ((rxNew) != NULL)
376#define CO_FLAG_SET(rxNew) \
377 { \
378 CO_MemoryBarrier(); \
379 rxNew = (void*)1L; \
380 }
381#define CO_FLAG_CLEAR(rxNew) \
382 { \
383 CO_MemoryBarrier(); \
384 rxNew = NULL; \
385 }
386
387#endif /* #ifndef CO_DOXYGEN */
388
389#if CO_DRIVER_MULTI_INTERFACE > 0 || defined CO_DOXYGEN
399CO_ReturnError_t CO_CANmodule_addInterface(CO_CANmodule_t* CANmodule, int can_ifindex);
400
415bool_t CO_CANrxBuffer_getInterface(CO_CANmodule_t* CANmodule, uint16_t ident, const void** const CANptrRx,
416 struct timespec* timestamp);
417
432CO_ReturnError_t CO_CANtxBuffer_setInterface(CO_CANmodule_t* CANmodule, uint16_t ident, const void* CANptrTx);
433#endif /* CO_DRIVER_MULTI_INTERFACE */
434
456bool_t CO_CANrxFromEpoll(CO_CANmodule_t* CANmodule, struct epoll_event* ev, CO_CANrxMsg_t* buffer, int32_t* msgIndex);
457
459
460#ifdef __cplusplus
461}
462#endif /* __cplusplus */
463
464#endif /* CO_DRIVER_TARGET_H */
CANopenNode Linux socketCAN Error handling.
bool_t CO_CANrxFromEpoll(CO_CANmodule_t *CANmodule, struct epoll_event *ev, CO_CANrxMsg_t *buffer, int32_t *msgIndex)
Receives CAN messages from matching epoll event.
Definition CO_driver.c:823
CO_ReturnError_t CO_CANtxBuffer_setInterface(CO_CANmodule_t *CANmodule, uint16_t ident, const void *CANptrTx)
Set which interface should be used for message buffer transmission.
CO_ReturnError_t CO_CANmodule_addInterface(CO_CANmodule_t *CANmodule, int can_ifindex)
Add socketCAN interface to can driver.
bool_t CO_CANrxBuffer_getInterface(CO_CANmodule_t *CANmodule, uint16_t ident, const void **const CANptrRx, struct timespec *timestamp)
Check on which interface the last message for one message buffer was received.
socketCAN interface error handling
Definition CO_error.h:98