CANopenLinux
CANopenNode on Linux devices
Loading...
Searching...
No Matches
CO_driver_target.h
Go to the documentation of this file.
1
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#define CO_CONFIG_GFC (CO_CONFIG_GFC_ENABLE | CO_CONFIG_GFC_CONSUMER | CO_CONFIG_GFC_PRODUCER)
106
107#define CO_CONFIG_SRDO \
108 (CO_CONFIG_SRDO_ENABLE | CO_CONFIG_SRDO_CHECK_TX | CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE \
109 | CO_CONFIG_GLOBAL_FLAG_TIMERNEXT)
110
111#ifndef CO_CONFIG_GTW
112#define CO_CONFIG_GTW \
113 (CO_CONFIG_GTW_ASCII | CO_CONFIG_GTW_ASCII_SDO | CO_CONFIG_GTW_ASCII_NMT | CO_CONFIG_GTW_ASCII_LSS \
114 | CO_CONFIG_GTW_ASCII_LOG | CO_CONFIG_GTW_ASCII_ERROR_DESC | CO_CONFIG_GTW_ASCII_PRINT_HELP \
115 | CO_CONFIG_GTW_ASCII_PRINT_LEDS)
116#define CO_CONFIG_GTW_BLOCK_DL_LOOP 3
117#define CO_CONFIG_GTWA_COMM_BUF_SIZE 2000
118#define CO_CONFIG_GTWA_LOG_BUF_SIZE 10000
119#endif
120
121#ifndef CO_CONFIG_CRC16
122#define CO_CONFIG_CRC16 (CO_CONFIG_CRC16_ENABLE)
123#endif
124
125#ifndef CO_CONFIG_FIFO
126#define CO_CONFIG_FIFO \
127 (CO_CONFIG_FIFO_ENABLE | CO_CONFIG_FIFO_ALT_READ | CO_CONFIG_FIFO_CRC16_CCITT | CO_CONFIG_FIFO_ASCII_COMMANDS \
128 | CO_CONFIG_FIFO_ASCII_DATATYPES)
129#endif
130
131/* Print debug info from some internal parts of the stack */
132#if (CO_CONFIG_DEBUG) & CO_CONFIG_DEBUG_COMMON
133#include <stdio.h>
134#include <syslog.h>
135#define CO_DEBUG_COMMON(msg) log_printf(LOG_DEBUG, DBG_CO_DEBUG, msg);
136#endif
137
162#ifndef CO_DRIVER_MULTI_INTERFACE
163#define CO_DRIVER_MULTI_INTERFACE 0
164#endif
165
182#ifndef CO_DRIVER_ERROR_REPORTING
183#define CO_DRIVER_ERROR_REPORTING 1
184#endif
185
186/* skip this section for Doxygen, because it is documented in CO_driver.h */
187#ifndef CO_DOXYGEN
188
189/* Basic definitions */
190#ifdef __BYTE_ORDER
191#if __BYTE_ORDER == __LITTLE_ENDIAN
192#define CO_LITTLE_ENDIAN
193#define CO_SWAP_16(x) x
194#define CO_SWAP_32(x) x
195#define CO_SWAP_64(x) x
196#else
197#define CO_BIG_ENDIAN
198#include <byteswap.h>
199#define CO_SWAP_16(x) bswap_16(x)
200#define CO_SWAP_32(x) bswap_32(x)
201#define CO_SWAP_64(x) bswap_64(x)
202#endif
203#endif
204/* NULL is defined in stddef.h */
205/* true and false are defined in stdbool.h */
206/* int8_t to uint64_t are defined in stdint.h */
207typedef uint_fast8_t bool_t;
208typedef float float32_t;
209typedef double float64_t;
210
211/* CAN receive message structure as aligned in socketCAN. */
212typedef struct {
213 uint32_t ident;
214 uint8_t DLC;
215 uint8_t padding[3];
216 uint8_t data[8];
217} CO_CANrxMsg_t;
218
219/* Access to received CAN message */
220static inline uint16_t
221CO_CANrxMsg_readIdent(void* rxMsg) {
222 CO_CANrxMsg_t* rxMsgCasted = (CO_CANrxMsg_t*)rxMsg;
223 return (uint16_t)(rxMsgCasted->ident & CAN_SFF_MASK);
224}
225
226static inline uint8_t
227CO_CANrxMsg_readDLC(void* rxMsg) {
228 CO_CANrxMsg_t* rxMsgCasted = (CO_CANrxMsg_t*)rxMsg;
229 return (uint8_t)(rxMsgCasted->DLC);
230}
231
232static inline uint8_t*
233CO_CANrxMsg_readData(void* rxMsg) {
234 CO_CANrxMsg_t* rxMsgCasted = (CO_CANrxMsg_t*)rxMsg;
235 return (uint8_t*)(rxMsgCasted->data);
236}
237
238/* Received message object */
239typedef struct {
240 uint32_t ident;
241 uint32_t mask;
242 void* object;
243 void (*CANrx_callback)(void* object, void* message);
244 int can_ifindex; /* CAN Interface index from last message */
245 struct timespec timestamp; /* time of reception of last message */
246} CO_CANrx_t;
247
248/* Transmit message object as aligned in socketCAN. */
249typedef struct {
250 uint32_t ident;
251 uint8_t DLC;
252 uint8_t padding[3]; /* ensure alignment */
253 uint8_t data[8];
254 volatile bool_t bufferFull;
255 volatile bool_t syncFlag; /* info about transmit message */
256 int can_ifindex; /* CAN Interface index to use */
257} CO_CANtx_t;
258
259/* Max COB ID for standard frame format */
260#define CO_CAN_MSG_SFF_MAX_COB_ID (1 << CAN_SFF_ID_BITS)
261
262/* CAN interface object (CANptr), passed to CO_CANinit() */
263typedef struct {
264 int can_ifindex; /* CAN Interface index */
265 int epoll_fd; /* File descriptor for epoll, which waits for CAN receive event */
266} CO_CANptrSocketCan_t;
267
268/* socketCAN interface object */
269typedef struct {
270 int can_ifindex; /* CAN Interface index */
271 char ifName[IFNAMSIZ]; /* CAN Interface name */
272 int fd; /* socketCAN file descriptor */
273#if CO_DRIVER_ERROR_REPORTING > 0 || defined CO_DOXYGEN
275#endif
276} CO_CANinterface_t;
277
278/* CAN module object */
279typedef struct {
280 /* List of can interfaces. From CO_CANmodule_init() or one per CO_CANmodule_addInterface() call */
281 CO_CANinterface_t* CANinterfaces;
282 uint32_t CANinterfaceCount; /* interface count */
283 CO_CANrx_t* rxArray;
284 uint16_t rxSize;
285 struct can_filter* rxFilter; /* socketCAN filter list, one per rx buffer */
286 uint32_t rxDropCount; /* messages dropped on rx socket queue */
287 CO_CANtx_t* txArray;
288 uint16_t txSize;
289 uint16_t CANerrorStatus;
290 volatile bool_t CANnormal;
291 volatile uint16_t CANtxCount;
292 int epoll_fd; /* File descriptor for epoll, which waits for CAN receive event */
293#if CO_DRIVER_MULTI_INTERFACE > 0 || defined CO_DOXYGEN
294 /* Lookup tables Cob ID to rx/tx array index. Only feasible for SFF Messages. */
295 uint32_t rxIdentToIndex[CO_CAN_MSG_SFF_MAX_COB_ID];
296 uint32_t txIdentToIndex[CO_CAN_MSG_SFF_MAX_COB_ID];
297#endif
299
300/* Data storage: Maximum file name length including path */
301#ifndef CO_STORAGE_PATH_MAX
302#define CO_STORAGE_PATH_MAX 255
303#endif
304
305/* Data storage object for one entry */
306typedef struct {
307 void* addr;
308 size_t len;
309 uint8_t subIndexOD;
310 uint8_t attr;
311 char filename[CO_STORAGE_PATH_MAX]; /* Name of the file, where data block is stored */
312 uint16_t crc; /* CRC checksum of the data stored previously, for auto storage */
313 FILE* fp; /* Pointer to opened file, for auto storage */
315
316#ifdef CO_SINGLE_THREAD
317#define CO_LOCK_CAN_SEND(CAN_MODULE) \
318 { (void)CAN_MODULE; }
319#define CO_UNLOCK_CAN_SEND(CAN_MODULE) \
320 { (void)CAN_MODULE; }
321#define CO_LOCK_EMCY(CAN_MODULE) \
322 { (void)CAN_MODULE; }
323#define CO_UNLOCK_EMCY(CAN_MODULE) \
324 { (void)CAN_MODULE; }
325#define CO_LOCK_OD(CAN_MODULE) \
326 { (void)CAN_MODULE; }
327#define CO_UNLOCK_OD(CAN_MODULE) \
328 { (void)CAN_MODULE; }
329#define CO_MemoryBarrier()
330#else
331
332/* (un)lock critical section in CO_CANsend() - unused */
333#define CO_LOCK_CAN_SEND(CAN_MODULE)
334#define CO_UNLOCK_CAN_SEND(CAN_MODULE)
335
336/* (un)lock critical section in CO_errorReport() or CO_errorReset() */
337extern pthread_mutex_t CO_EMCY_mutex;
338
339static inline int
340CO_LOCK_EMCY(CO_CANmodule_t* CANmodule) {
341 (void)CANmodule;
342 return pthread_mutex_lock(&CO_EMCY_mutex);
343}
344
345static inline void
346CO_UNLOCK_EMCY(CO_CANmodule_t* CANmodule) {
347 (void)CANmodule;
348 (void)pthread_mutex_unlock(&CO_EMCY_mutex);
349}
350
351/* (un)lock critical section when accessing Object Dictionary */
352extern pthread_mutex_t CO_OD_mutex;
353
354static inline int
355CO_LOCK_OD(CO_CANmodule_t* CANmodule) {
356 (void)CANmodule;
357 return pthread_mutex_lock(&CO_OD_mutex);
358}
359
360static inline void
361CO_UNLOCK_OD(CO_CANmodule_t* CANmodule) {
362 (void)CANmodule;
363 (void)pthread_mutex_unlock(&CO_OD_mutex);
364}
365
366/* Synchronization between CAN receive and message processing threads. */
367#define CO_MemoryBarrier() \
368 { __sync_synchronize(); }
369#endif /* CO_SINGLE_THREAD */
370
371#define CO_FLAG_READ(rxNew) ((rxNew) != NULL)
372#define CO_FLAG_SET(rxNew) \
373 { \
374 CO_MemoryBarrier(); \
375 rxNew = (void*)1L; \
376 }
377#define CO_FLAG_CLEAR(rxNew) \
378 { \
379 CO_MemoryBarrier(); \
380 rxNew = NULL; \
381 }
382
383#endif /* #ifndef CO_DOXYGEN */
384
385#if CO_DRIVER_MULTI_INTERFACE > 0 || defined CO_DOXYGEN
396
411bool_t CO_CANrxBuffer_getInterface(CO_CANmodule_t* CANmodule, uint16_t ident, const void** const CANptrRx,
412 struct timespec* timestamp);
413
429#endif /* CO_DRIVER_MULTI_INTERFACE */
430
452bool_t CO_CANrxFromEpoll(CO_CANmodule_t* CANmodule, struct epoll_event* ev, CO_CANrxMsg_t* buffer, int32_t* msgIndex);
453
456#ifdef __cplusplus
457}
458#endif /* __cplusplus */
459
460#endif /* CO_DRIVER_TARGET_H */
CANopenNode Linux socketCAN Error handling.
#define CO_LOCK_EMCY(CAN_MODULE)
#define CO_UNLOCK_EMCY(CAN_MODULE)
#define CO_UNLOCK_OD(CAN_MODULE)
#define CO_LOCK_OD(CAN_MODULE)
unsigned int uint16_t
unsigned long int uint32_t
float float32_t
uint_fast8_t bool_t
unsigned char uint8_t
double float64_t
signed long int int32_t
CO_ReturnError_t
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