Lely core libraries  2.2.5
sync.c
Go to the documentation of this file.
1 
24 #include "co.h"
25 
26 #ifndef LELY_NO_CO_SYNC
27 
28 #include <lely/co/dev.h>
29 #include <lely/co/obj.h>
30 #include <lely/co/sdo.h>
31 #include <lely/co/sync.h>
32 #include <lely/co/val.h>
33 #include <lely/util/errnum.h>
34 #include <lely/util/time.h>
35 
36 #include <assert.h>
37 #include <stdlib.h>
38 
40 struct __co_sync {
46  co_unsigned32_t cobid;
48  co_unsigned32_t us;
50  co_unsigned8_t max_cnt;
56  co_unsigned8_t cnt;
60  void *ind_data;
64  void *err_data;
65 };
66 
74 static int co_sync_update(co_sync_t *sync);
75 
82 static co_unsigned32_t co_1005_dn_ind(
83  co_sub_t *sub, struct co_sdo_req *req, void *data);
84 
91 static co_unsigned32_t co_1006_dn_ind(
92  co_sub_t *sub, struct co_sdo_req *req, void *data);
93 
100 static co_unsigned32_t co_1019_dn_ind(
101  co_sub_t *sub, struct co_sdo_req *req, void *data);
102 
108 static int co_sync_recv(const struct can_msg *msg, void *data);
109 
115 static int co_sync_timer(const struct timespec *tp, void *data);
116 
117 void *
118 __co_sync_alloc(void)
119 {
120  void *ptr = malloc(sizeof(struct __co_sync));
121  if (!ptr)
122  set_errc(errno2c(errno));
123  return ptr;
124 }
125 
126 void
127 __co_sync_free(void *ptr)
128 {
129  free(ptr);
130 }
131 
132 struct __co_sync *
133 __co_sync_init(struct __co_sync *sync, can_net_t *net, co_dev_t *dev)
134 {
135  assert(sync);
136  assert(net);
137  assert(dev);
138 
139  int errc = 0;
140 
141  sync->net = net;
142  sync->dev = dev;
143 
144  // Retrieve the SYNC COB-ID.
145  co_obj_t *obj_1005 = co_dev_find_obj(sync->dev, 0x1005);
146  if (!obj_1005) {
147  errc = errnum2c(ERRNUM_NOSYS);
148  goto error_obj_1005;
149  }
150 
151  sync->cobid = co_obj_get_val_u32(obj_1005, 0x00);
152 
153  // Retrieve the communication cycle period (in microseconds).
154  co_obj_t *obj_1006 = co_dev_find_obj(sync->dev, 0x1006);
155  sync->us = co_obj_get_val_u32(obj_1006, 0x00);
156 
157  // Retrieve the synchronous counter overflow value.
158  co_obj_t *obj_1019 = co_dev_find_obj(sync->dev, 0x1019);
159  sync->max_cnt = co_obj_get_val_u8(obj_1019, 0x00);
160 
161  sync->recv = NULL;
162  sync->timer = NULL;
163 
164  sync->cnt = 1;
165 
166  sync->ind = NULL;
167  sync->ind_data = NULL;
168  sync->err = NULL;
169  sync->err_data = NULL;
170 
171  // Set the download indication function for the SYNC COB-ID object.
172  co_obj_set_dn_ind(obj_1005, &co_1005_dn_ind, sync);
173 
174  // Set the download indication function for the communication cycle
175  // period object.
176  if (obj_1006)
177  co_obj_set_dn_ind(obj_1006, &co_1006_dn_ind, sync);
178 
179  // Set the download indication function for the synchronous counter
180  // overflow value object.
181  if (obj_1019)
182  co_obj_set_dn_ind(obj_1019, &co_1019_dn_ind, sync);
183 
184  if (co_sync_update(sync) == -1) {
185  errc = get_errc();
186  goto error_update;
187  }
188 
189  return sync;
190 
191 error_update:
192  if (obj_1019)
193  co_obj_set_dn_ind(obj_1019, NULL, NULL);
194  if (obj_1006)
195  co_obj_set_dn_ind(obj_1006, NULL, NULL);
196  co_obj_set_dn_ind(obj_1005, NULL, NULL);
197 error_obj_1005:
198  set_errc(errc);
199  return NULL;
200 }
201 
202 void
203 __co_sync_fini(struct __co_sync *sync)
204 {
205  assert(sync);
206 
207  // Remove the download indication function for the synchronous counter
208  // overflow value object.
209  co_obj_t *obj_1019 = co_dev_find_obj(sync->dev, 0x1019);
210  if (obj_1019)
211  co_obj_set_dn_ind(obj_1019, NULL, NULL);
212 
213  // Remove the download indication function for the communication cycle
214  // period object.
215  co_obj_t *obj_1006 = co_dev_find_obj(sync->dev, 0x1006);
216  if (obj_1006)
217  co_obj_set_dn_ind(obj_1006, NULL, NULL);
218 
219  // Remove the download indication function for the SYNC COB-ID object.
220  co_obj_t *obj_1005 = co_dev_find_obj(sync->dev, 0x1005);
221  assert(obj_1005);
222  co_obj_set_dn_ind(obj_1005, NULL, NULL);
223 
224  can_timer_destroy(sync->timer);
225 
226  can_recv_destroy(sync->recv);
227 }
228 
229 co_sync_t *
231 {
232  trace("creating SYNC service");
233 
234  int errc = 0;
235 
236  co_sync_t *sync = __co_sync_alloc();
237  if (!sync) {
238  errc = get_errc();
239  goto error_alloc_sync;
240  }
241 
242  if (!__co_sync_init(sync, net, dev)) {
243  errc = get_errc();
244  goto error_init_sync;
245  }
246 
247  return sync;
248 
249 error_init_sync:
250  __co_sync_free(sync);
251 error_alloc_sync:
252  set_errc(errc);
253  return NULL;
254 }
255 
256 void
258 {
259  if (sync) {
260  trace("destroying SYNC service");
261  __co_sync_fini(sync);
262  __co_sync_free(sync);
263  }
264 }
265 
266 can_net_t *
268 {
269  assert(sync);
270 
271  return sync->net;
272 }
273 
274 co_dev_t *
276 {
277  assert(sync);
278 
279  return sync->dev;
280 }
281 
282 void
283 co_sync_get_ind(const co_sync_t *sync, co_sync_ind_t **pind, void **pdata)
284 {
285  assert(sync);
286 
287  if (pind)
288  *pind = sync->ind;
289  if (pdata)
290  *pdata = sync->ind_data;
291 }
292 
293 void
295 {
296  assert(sync);
297 
298  sync->ind = ind;
299  sync->ind_data = data;
300 }
301 
302 void
303 co_sync_get_err(const co_sync_t *sync, co_sync_err_t **perr, void **pdata)
304 {
305  assert(sync);
306 
307  if (perr)
308  *perr = sync->err;
309  if (pdata)
310  *pdata = sync->err_data;
311 }
312 
313 void
315 {
316  assert(sync);
317 
318  sync->err = err;
319  sync->err_data = data;
320 }
321 
322 static int
324 {
325  assert(sync);
326 
327  if (!(sync->cobid & CO_SYNC_COBID_PRODUCER)) {
328  if (!sync->recv) {
329  sync->recv = can_recv_create();
330  if (!sync->recv)
331  return -1;
332  can_recv_set_func(sync->recv, &co_sync_recv, sync);
333  }
334  // Register the receiver under the specified CAN-ID.
335  uint_least32_t id = sync->cobid;
336  uint_least8_t flags = 0;
337  if (id & CO_SYNC_COBID_FRAME) {
338  id &= CAN_MASK_EID;
339  flags |= CAN_FLAG_IDE;
340  } else {
341  id &= CAN_MASK_BID;
342  }
343  can_recv_start(sync->recv, sync->net, id, flags);
344  } else if (sync->recv) {
345  // Destroy the receiver if we are a producer, to prevent
346  // receiving our own SYNC messages.
347  can_recv_destroy(sync->recv);
348  sync->recv = NULL;
349  }
350 
351  if ((sync->cobid & CO_SYNC_COBID_PRODUCER) && sync->us) {
352  if (!sync->timer) {
353  sync->timer = can_timer_create();
354  if (!sync->timer)
355  return -1;
356  can_timer_set_func(sync->timer, co_sync_timer, sync);
357  }
358  // Start SYNC transmission at the next multiple of the SYNC
359  // period.
360  struct timespec start = { 0, 0 };
361  can_net_get_time(sync->net, &start);
362  int_least64_t nsec = start.tv_sec * INT64_C(1000000000)
363  + start.tv_nsec;
364  nsec %= (uint_least64_t)sync->us * 1000;
365  timespec_sub_nsec(&start, nsec);
366  timespec_add_usec(&start, sync->us);
367  struct timespec interval = { 0, 0 };
368  timespec_add_usec(&interval, sync->us);
369  can_timer_start(sync->timer, sync->net, &start, &interval);
370  } else if (sync->timer) {
371  // Destroy the SYNC timer unless we are an active SYNC producer
372  // (with a non-zero communication cycle period).
373  can_timer_destroy(sync->timer);
374  sync->timer = NULL;
375  }
376 
377  sync->cnt = 1;
378 
379  return 0;
380 }
381 
382 static co_unsigned32_t
383 co_1005_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
384 {
385  assert(sub);
386  assert(co_obj_get_idx(co_sub_get_obj(sub)) == 0x1005);
387  assert(req);
388  co_sync_t *sync = data;
389  assert(sync);
390 
391  co_unsigned32_t ac = 0;
392 
393  co_unsigned16_t type = co_sub_get_type(sub);
394  union co_val val;
395  if (co_sdo_req_dn_val(req, type, &val, &ac) == -1)
396  return ac;
397 
398  if (co_sub_get_subidx(sub)) {
399  ac = CO_SDO_AC_NO_SUB;
400  goto error;
401  }
402 
403  assert(type == CO_DEFTYPE_UNSIGNED32);
404  co_unsigned32_t cobid = val.u32;
405  co_unsigned32_t cobid_old = co_sub_get_val_u32(sub);
406  if (cobid == cobid_old)
407  goto error;
408 
409  // The CAN-ID cannot be changed while the producer is and remains
410  // active.
411  int active = cobid & CO_SYNC_COBID_PRODUCER;
412  int active_old = cobid_old & CO_SYNC_COBID_PRODUCER;
413  uint_least32_t canid = cobid & CAN_MASK_EID;
414  uint_least32_t canid_old = cobid_old & CAN_MASK_EID;
415  if (active && active_old && canid != canid_old) {
416  ac = CO_SDO_AC_PARAM_VAL;
417  goto error;
418  }
419 
420  // A 29-bit CAN-ID is only valid if the frame bit is set.
421  if (!(cobid & CO_SYNC_COBID_FRAME)
422  && (cobid & (CAN_MASK_EID ^ CAN_MASK_BID))) {
423  ac = CO_SDO_AC_PARAM_VAL;
424  goto error;
425  }
426 
427  sync->cobid = cobid;
428 
429  co_sub_dn(sub, &val);
430  co_val_fini(type, &val);
431 
432  co_sync_update(sync);
433  return 0;
434 
435 error:
436  co_val_fini(type, &val);
437  return ac;
438 }
439 
440 static co_unsigned32_t
441 co_1006_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
442 {
443  assert(sub);
444  assert(co_obj_get_idx(co_sub_get_obj(sub)) == 0x1006);
445  assert(req);
446  co_sync_t *sync = data;
447  assert(sync);
448 
449  co_unsigned32_t ac = 0;
450 
451  co_unsigned16_t type = co_sub_get_type(sub);
452  union co_val val;
453  if (co_sdo_req_dn_val(req, type, &val, &ac) == -1)
454  return ac;
455 
456  if (co_sub_get_subidx(sub)) {
457  ac = CO_SDO_AC_NO_SUB;
458  goto error;
459  }
460 
461  assert(type == CO_DEFTYPE_UNSIGNED32);
462  co_unsigned32_t us = val.u32;
463  co_unsigned32_t us_old = co_sub_get_val_u32(sub);
464  if (us == us_old)
465  goto error;
466 
467  sync->us = us;
468 
469  co_sub_dn(sub, &val);
470  co_val_fini(type, &val);
471 
472  co_sync_update(sync);
473  return 0;
474 
475 error:
476  co_val_fini(type, &val);
477  return ac;
478 }
479 
480 static co_unsigned32_t
481 co_1019_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
482 {
483  assert(sub);
484  assert(co_obj_get_idx(co_sub_get_obj(sub)) == 0x1019);
485  assert(req);
486  co_sync_t *sync = data;
487  assert(sync);
488 
489  co_unsigned32_t ac = 0;
490 
491  co_unsigned16_t type = co_sub_get_type(sub);
492  union co_val val;
493  if (co_sdo_req_dn_val(req, type, &val, &ac) == -1)
494  return ac;
495 
496  if (co_sub_get_subidx(sub)) {
497  ac = CO_SDO_AC_NO_SUB;
498  goto error;
499  }
500 
501  assert(type == CO_DEFTYPE_UNSIGNED8);
502  co_unsigned8_t max_cnt = val.u8;
503  co_unsigned8_t max_cnt_old = co_sub_get_val_u8(sub);
504  if (max_cnt == max_cnt_old)
505  goto error;
506 
507  // The synchronous counter overflow value cannot be changed while the
508  // communication cycle period is non-zero.
509  if (sync->us) {
510  ac = CO_SDO_AC_DATA_DEV;
511  goto error;
512  }
513 
514  if (max_cnt == 1 || max_cnt > 240) {
515  ac = CO_SDO_AC_PARAM_VAL;
516  goto error;
517  }
518 
519  sync->max_cnt = max_cnt;
520 
521  co_sub_dn(sub, &val);
522  co_val_fini(type, &val);
523 
524  co_sync_update(sync);
525  return 0;
526 
527 error:
528  co_val_fini(type, &val);
529  return ac;
530 }
531 
532 static int
533 co_sync_recv(const struct can_msg *msg, void *data)
534 {
535  assert(msg);
536  co_sync_t *sync = data;
537  assert(sync);
538 
539  // Ignore remote frames.
540  if (msg->flags & CAN_FLAG_RTR)
541  return 0;
542 
543 #ifndef LELY_NO_CANFD
544  // Ignore CAN FD format frames.
545  if (msg->flags & CAN_FLAG_EDL)
546  return 0;
547 #endif
548 
549  co_unsigned8_t len = sync->max_cnt ? 1 : 0;
550  if (msg->len != len && sync->err)
551  sync->err(sync, 0x8240, 0x10, sync->err_data);
552 
553  co_unsigned8_t cnt = len && msg->len == len ? msg->data[0] : 0;
554  if (sync->ind)
555  sync->ind(sync, cnt, sync->ind_data);
556 
557  return 0;
558 }
559 
560 static int
561 co_sync_timer(const struct timespec *tp, void *data)
562 {
563  (void)tp;
564  co_sync_t *sync = data;
565  assert(sync);
566 
567  struct can_msg msg = CAN_MSG_INIT;
568  msg.id = sync->cobid;
569  if (sync->cobid & CO_SYNC_COBID_FRAME) {
570  msg.id &= CAN_MASK_EID;
571  msg.flags |= CAN_FLAG_IDE;
572  } else {
573  msg.id &= CAN_MASK_BID;
574  }
575  if (sync->max_cnt) {
576  msg.len = 1;
577  msg.data[0] = sync->cnt;
578  sync->cnt = sync->cnt < sync->max_cnt ? sync->cnt + 1 : 1;
579  }
580  can_net_send(sync->net, &msg);
581 
582  co_unsigned8_t cnt = msg.len ? msg.data[0] : 0;
583  if (sync->ind)
584  sync->ind(sync, cnt, sync->ind_data);
585 
586  return 0;
587 }
588 
589 #endif // !LELY_NO_CO_SYNC
A CANopen SDO upload/download request.
Definition: sdo.h:178
A CAN or CAN FD format frame.
Definition: msg.h:87
static int co_sync_timer(const struct timespec *tp, void *data)
The CAN timer callback function for a SYNC producer service.
Definition: sync.c:561
can_timer_t * timer
A pointer to the CAN timer.
Definition: sync.c:54
void co_obj_set_dn_ind(co_obj_t *obj, co_sub_dn_ind_t *ind, void *data)
Sets the download indication function for a CANopen object.
Definition: obj.c:372
uint_least32_t id
The identifier (11 or 29 bits, depending on the CAN_FLAG_IDE flag).
Definition: msg.h:89
can_recv_t * recv
A pointer to the CAN frame receiver.
Definition: sync.c:52
A CAN network interface.
Definition: net.c:37
static co_unsigned32_t co_1019_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
The download indication function for (all sub-objects of) CANopen object 1019 (Synchronous counter ov...
Definition: sync.c:481
uint_least8_t len
The number of bytes in data (or the requested number of bytes in case of a remote frame)...
Definition: msg.h:100
A CANopen sub-object.
Definition: obj.h:54
co_dev_t * dev
A pointer to a CANopen device.
Definition: sync.c:44
int errnum2c(errnum_t errnum)
Transforms a platform-independent error number to a native error code.
Definition: errnum.c:825
can_net_t * co_sync_get_net(const co_sync_t *sync)
Returns a pointer to the CAN network of a SYNC producer/consumer service.
Definition: sync.c:267
#define CO_SDO_AC_PARAM_VAL
SDO abort code: Invalid value for parameter (download only).
Definition: sdo.h:135
A union of the CANopen static data types.
Definition: val.h:163
void can_net_get_time(const can_net_t *net, struct timespec *tp)
Retrieves the current time of a CAN network interface.
Definition: net.c:204
co_unsigned8_t max_cnt
The synchronous counter overflow value.
Definition: sync.c:50
void can_timer_start(can_timer_t *timer, can_net_t *net, const struct timespec *start, const struct timespec *interval)
Starts a CAN timer and registers it with a network interface.
Definition: net.c:437
void * ind_data
A pointer to user-specified data for ind.
Definition: sync.c:60
#define CAN_MASK_BID
The mask used to extract the 11-bit Base Identifier from a CAN frame.
Definition: msg.h:31
This header file is part of the CANopen library; it contains the Service Data Object (SDO) declaratio...
This header file is part of the CANopen library; it contains the CANopen value declarations.
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:957
static int co_sync_update(co_sync_t *sync)
Updates and (de)activates a SYNC producer/consumer service.
Definition: sync.c:323
static co_unsigned32_t co_1006_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
The download indication function for (all sub-objects of) CANopen object 1006 (Communication cycle pe...
Definition: sync.c:441
void can_timer_set_func(can_timer_t *timer, can_timer_func_t *func, void *data)
Sets the callback function invoked when a CAN timer is triggered.
Definition: net.c:428
co_unsigned32_t us
The communication cycle period (in microseconds).
Definition: sync.c:48
can_recv_t * can_recv_create(void)
Creates a new CAN frame receiver.
Definition: net.c:537
#define CO_DEFTYPE_UNSIGNED32
The data type (and object index) of a 32-bit unsigned integer.
Definition: type.h:50
void timespec_add_usec(struct timespec *tp, uint_least64_t usec)
Adds usec microseconds to the time at tp.
Definition: time.h:143
uint_least8_t data[CAN_MSG_MAX_LEN]
The frame payload (in case of a data frame).
Definition: msg.h:102
This header file is part of the utilities library; it contains the native and platform-independent er...
void co_sync_set_err(co_sync_t *sync, co_sync_err_t *err, void *data)
Sets the error handling function of a SYNC consumer service.
Definition: sync.c:314
This header file is part of the utilities library; it contains the time function declarations.
static co_unsigned32_t co_1005_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
The download indication function for (all sub-objects of) CANopen object 1005 (COB-ID SYNC message)...
Definition: sync.c:383
void co_sync_get_ind(const co_sync_t *sync, co_sync_ind_t **pind, void **pdata)
Retrieves the indication function invoked after a CANopen SYNC message is received or transmitted...
Definition: sync.c:283
void can_recv_destroy(can_recv_t *recv)
Destroys a CAN frame receiver.
Definition: net.c:562
The Remote Transmission Request (RTR) flag (unavailable in CAN FD format frames). ...
Definition: msg.h:48
This is the internal header file of the CANopen library.
co_sync_ind_t * ind
A pointer to the indication function.
Definition: sync.c:58
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function...
Definition: errnum.c:947
A CAN timer.
Definition: net.c:63
void can_timer_destroy(can_timer_t *timer)
Destroys a CAN timer.
Definition: net.c:407
int co_sub_dn(co_sub_t *sub, void *val)
Downloads (moves) a value into a CANopen sub-object if the refuse-write-on-download flag (CO_OBJ_FLAG...
Definition: obj.c:954
#define CO_DEFTYPE_UNSIGNED8
The data type (and object index) of an 8-bit unsigned integer.
Definition: type.h:44
#define CO_SYNC_COBID_PRODUCER
The bit in the SYNC COB-ID specifying whether the device is a producer.
Definition: sync.h:29
co_sync_t * co_sync_create(can_net_t *net, co_dev_t *dev)
Creates a new CANopen SYNC producer/consumer service.
Definition: sync.c:230
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition: errnum.c:43
can_net_t * net
A pointer to a CAN network interface.
Definition: sync.c:42
void * err_data
A pointer to user-specified data for err.
Definition: sync.c:64
A CANopen device.
Definition: dev.c:41
void can_recv_set_func(can_recv_t *recv, can_recv_func_t *func, void *data)
Sets the callback function used to process CAN frames with a receiver.
Definition: net.c:582
uint_least8_t flags
The flags (any combination of CAN_FLAG_IDE, CAN_FLAG_RTR, CAN_FLAG_FDF, CAN_FLAG_BRS and CAN_FLAG_ESI...
Definition: msg.h:94
co_obj_t * co_sub_get_obj(const co_sub_t *sub)
Returns the a pointer to the CANopen object containing the specified sub-object.
Definition: obj.c:520
The Identifier Extension (IDE) flag.
Definition: msg.h:43
can_timer_t * can_timer_create(void)
Creates a new CAN timer.
Definition: net.c:382
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.
Definition: val.c:275
int can_net_send(can_net_t *net, const struct can_msg *msg)
Sends a CAN frame from a network interface.
Definition: net.c:308
void co_sync_ind_t(co_sync_t *sync, co_unsigned8_t cnt, void *data)
The type of a CANopen SYNC indication function, invoked after a SYNC message is received or transmitt...
Definition: sync.h:49
co_unsigned8_t cnt
The counter value.
Definition: sync.c:56
#define CO_SDO_AC_NO_SUB
SDO abort code: Sub-index does not exist.
Definition: sdo.h:132
static int co_sync_recv(const struct can_msg *msg, void *data)
The CAN receive callback function for a SYNC consumer service.
Definition: sync.c:533
co_sync_err_t * err
A pointer to the error handling function.
Definition: sync.c:62
This header file is part of the CANopen library; it contains the synchronization (SYNC) object declar...
int co_sdo_req_dn_val(struct co_sdo_req *req, co_unsigned16_t type, void *val, co_unsigned32_t *pac)
Copies the next segment of the specified CANopen SDO download request to the internal buffer and...
Definition: sdo.c:165
#define CO_SYNC_COBID_FRAME
The bit in the SYNC COB-ID specifying whether to use an 11-bit (0) or 29-bit (1) CAN-ID.
Definition: sync.h:35
This header file is part of the CANopen library; it contains the device description declarations...
void co_sync_destroy(co_sync_t *sync)
Destroys a CANopen SYNC producer/consumer service.
Definition: sync.c:257
co_unsigned32_t cobid
The SYNC COB-ID.
Definition: sync.c:46
co_dev_t * co_sync_get_dev(const co_sync_t *sync)
Returns a pointer to the CANopen device of a SYNC producer/consumer service.
Definition: sync.c:275
#define CO_SDO_AC_DATA_DEV
SDO abort code: Data cannot be transferred or stored to the application because of the present device...
Definition: sdo.h:165
co_unsigned8_t co_sub_get_subidx(const co_sub_t *sub)
Returns the sub-index of a CANopen sub-object.
Definition: obj.c:528
void timespec_sub_nsec(struct timespec *tp, uint_least64_t nsec)
Subtracts nsec nanoseconds from the time at tp.
Definition: time.h:193
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib.h> and defines any missing functionality.
A CAN frame receiver.
Definition: net.c:99
co_unsigned16_t co_sub_get_type(const co_sub_t *sub)
Returns the data type of a CANopen sub-object.
Definition: obj.c:570
A CANopen SYNC producer/consumer service.
Definition: sync.c:40
co_unsigned16_t co_obj_get_idx(const co_obj_t *obj)
Returns the index of a CANopen object.
Definition: obj.c:154
void co_sync_set_ind(co_sync_t *sync, co_sync_ind_t *ind, void *data)
Sets the indication function invoked after a CANopen SYNC message is received or transmitted.
Definition: sync.c:294
void co_sync_get_err(const co_sync_t *sync, co_sync_err_t **perr, void **pdata)
Retrieves the error handling function of a SYNC consumer service.
Definition: sync.c:303
A CANopen object.
Definition: obj.h:32
This header file is part of the CANopen library; it contains the object dictionary declarations...
#define CAN_MSG_INIT
The static initializer for can_msg.
Definition: msg.h:113
void can_recv_start(can_recv_t *recv, can_net_t *net, uint_least32_t id, uint_least8_t flags)
Registers a CAN frame receiver with a network interface and starts processing frames.
Definition: net.c:591
co_obj_t * co_dev_find_obj(const co_dev_t *dev, co_unsigned16_t idx)
Finds an object in the object dictionary of a CANopen device.
Definition: dev.c:288
Function not supported.
Definition: errnum.h:181
#define CAN_MASK_EID
The mask used to extract the 29-bit Extended Identifier from a CAN frame.
Definition: msg.h:34
void co_sync_err_t(co_sync_t *sync, co_unsigned16_t eec, co_unsigned8_t er, void *data)
The type of a CANopen SYNC error handling function, invoked when the SYNC data length does not match...
Definition: sync.h:60