Lely core libraries  1.9.2
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 
35 #include <assert.h>
36 #include <stdlib.h>
37 
39 struct __co_sync {
45  uint32_t cobid;
47  co_unsigned32_t us;
49  co_unsigned8_t max_cnt;
55  co_unsigned8_t cnt;
59  void *ind_data;
63  void *err_data;
64 };
65 
73 static int co_sync_update(co_sync_t *sync);
74 
81 static co_unsigned32_t co_1005_dn_ind(
82  co_sub_t *sub, struct co_sdo_req *req, void *data);
83 
90 static co_unsigned32_t co_1006_dn_ind(
91  co_sub_t *sub, struct co_sdo_req *req, void *data);
92 
99 static co_unsigned32_t co_1019_dn_ind(
100  co_sub_t *sub, struct co_sdo_req *req, void *data);
101 
107 static int co_sync_recv(const struct can_msg *msg, void *data);
108 
114 static int co_sync_timer(const struct timespec *tp, void *data);
115 
116 void *
117 __co_sync_alloc(void)
118 {
119  void *ptr = malloc(sizeof(struct __co_sync));
120  if (__unlikely(!ptr))
121  set_errc(errno2c(errno));
122  return ptr;
123 }
124 
125 void
126 __co_sync_free(void *ptr)
127 {
128  free(ptr);
129 }
130 
131 struct __co_sync *
132 __co_sync_init(struct __co_sync *sync, can_net_t *net, co_dev_t *dev)
133 {
134  assert(sync);
135  assert(net);
136  assert(dev);
137 
138  int errc = 0;
139 
140  sync->net = net;
141  sync->dev = dev;
142 
143  // Retrieve the SYNC COB-ID.
144  co_obj_t *obj_1005 = co_dev_find_obj(sync->dev, 0x1005);
145  if (__unlikely(!obj_1005)) {
146  errc = errnum2c(ERRNUM_NOSYS);
147  goto error_obj_1005;
148  }
149 
150  sync->cobid = co_obj_get_val_u32(obj_1005, 0x00);
151 
152  // Retrieve the communication cycle period (in microseconds).
153  co_obj_t *obj_1006 = co_dev_find_obj(sync->dev, 0x1006);
154  sync->us = co_obj_get_val_u32(obj_1006, 0x00);
155 
156  // Retrieve the synchronous counter overflow value.
157  co_obj_t *obj_1019 = co_dev_find_obj(sync->dev, 0x1019);
158  sync->max_cnt = co_obj_get_val_u8(obj_1019, 0x00);
159 
160  sync->recv = NULL;
161  sync->timer = NULL;
162 
163  sync->cnt = 1;
164 
165  sync->ind = NULL;
166  sync->ind_data = NULL;
167  sync->err = NULL;
168  sync->err_data = NULL;
169 
170  // Set the download indication function for the SYNC COB-ID object.
171  co_obj_set_dn_ind(obj_1005, &co_1005_dn_ind, sync);
172 
173  // Set the download indication function for the communication cycle
174  // period object.
175  if (obj_1006)
176  co_obj_set_dn_ind(obj_1006, &co_1006_dn_ind, sync);
177 
178  // Set the download indication function for the synchronous counter
179  // overflow value object.
180  if (obj_1019)
181  co_obj_set_dn_ind(obj_1019, &co_1019_dn_ind, sync);
182 
183  if (__unlikely(co_sync_update(sync) == -1)) {
184  errc = get_errc();
185  goto error_update;
186  }
187 
188  return sync;
189 
190 error_update:
191  if (obj_1019)
192  co_obj_set_dn_ind(obj_1019, NULL, NULL);
193  if (obj_1006)
194  co_obj_set_dn_ind(obj_1006, NULL, NULL);
195  co_obj_set_dn_ind(obj_1005, NULL, NULL);
196 error_obj_1005:
197  set_errc(errc);
198  return NULL;
199 }
200 
201 void
202 __co_sync_fini(struct __co_sync *sync)
203 {
204  assert(sync);
205 
206  // Remove the download indication function for the synchronous counter
207  // overflow value object.
208  co_obj_t *obj_1019 = co_dev_find_obj(sync->dev, 0x1019);
209  if (obj_1019)
210  co_obj_set_dn_ind(obj_1019, NULL, NULL);
211 
212  // Remove the download indication function for the communication cycle
213  // period object.
214  co_obj_t *obj_1006 = co_dev_find_obj(sync->dev, 0x1006);
215  if (obj_1006)
216  co_obj_set_dn_ind(obj_1006, NULL, NULL);
217 
218  // Remove the download indication function for the SYNC COB-ID object.
219  co_obj_t *obj_1005 = co_dev_find_obj(sync->dev, 0x1005);
220  assert(obj_1005);
221  co_obj_set_dn_ind(obj_1005, NULL, NULL);
222 
223  can_timer_destroy(sync->timer);
224 
225  can_recv_destroy(sync->recv);
226 }
227 
228 co_sync_t *
230 {
231  trace("creating SYNC service");
232 
233  int errc = 0;
234 
235  co_sync_t *sync = __co_sync_alloc();
236  if (__unlikely(!sync)) {
237  errc = get_errc();
238  goto error_alloc_sync;
239  }
240 
241  if (__unlikely(!__co_sync_init(sync, net, dev))) {
242  errc = get_errc();
243  goto error_init_sync;
244  }
245 
246  return sync;
247 
248 error_init_sync:
249  __co_sync_free(sync);
250 error_alloc_sync:
251  set_errc(errc);
252  return NULL;
253 }
254 
255 void
257 {
258  if (sync) {
259  trace("destroying SYNC service");
260  __co_sync_fini(sync);
261  __co_sync_free(sync);
262  }
263 }
264 
265 can_net_t *
267 {
268  assert(sync);
269 
270  return sync->net;
271 }
272 
273 co_dev_t *
275 {
276  assert(sync);
277 
278  return sync->dev;
279 }
280 
281 void
282 co_sync_get_ind(const co_sync_t *sync, co_sync_ind_t **pind, void **pdata)
283 {
284  assert(sync);
285 
286  if (pind)
287  *pind = sync->ind;
288  if (pdata)
289  *pdata = sync->ind_data;
290 }
291 
292 void
294 {
295  assert(sync);
296 
297  sync->ind = ind;
298  sync->ind_data = data;
299 }
300 
301 void
302 co_sync_get_err(const co_sync_t *sync, co_sync_err_t **perr, void **pdata)
303 {
304  assert(sync);
305 
306  if (perr)
307  *perr = sync->err;
308  if (pdata)
309  *pdata = sync->err_data;
310 }
311 
312 void
314 {
315  assert(sync);
316 
317  sync->err = err;
318  sync->err_data = data;
319 }
320 
321 static int
323 {
324  assert(sync);
325 
326  if (!(sync->cobid & CO_SYNC_COBID_PRODUCER)) {
327  if (!sync->recv) {
328  sync->recv = can_recv_create();
329  if (__unlikely(!sync->recv))
330  return -1;
331  can_recv_set_func(sync->recv, &co_sync_recv, sync);
332  }
333  // Register the receiver under the specified CAN-ID.
334  uint32_t id = sync->cobid;
335  uint8_t flags = 0;
336  if (id & CO_SYNC_COBID_FRAME) {
337  id &= CAN_MASK_EID;
338  flags |= CAN_FLAG_IDE;
339  } else {
340  id &= CAN_MASK_BID;
341  }
342  can_recv_start(sync->recv, sync->net, id, flags);
343  } else if (sync->recv) {
344  // Destroy the receiver if we are a producer, to prevent
345  // receiving our own SYNC messages.
346  can_recv_destroy(sync->recv);
347  sync->recv = NULL;
348  }
349 
350  if ((sync->cobid & CO_SYNC_COBID_PRODUCER) && sync->us) {
351  if (!sync->timer) {
352  sync->timer = can_timer_create();
353  if (__unlikely(!sync->timer))
354  return -1;
355  can_timer_set_func(sync->timer, co_sync_timer, sync);
356  }
357  // Start SYNC transmission at the next multiple of the SYNC
358  // period.
359  struct timespec start = { 0, 0 };
360  can_net_get_time(sync->net, &start);
361  intmax_t us = start.tv_sec * INTMAX_C(1000000)
362  + start.tv_nsec / 1000;
363  us = us - (us % sync->us) + sync->us;
364  start.tv_sec = us / 1000000l;
365  start.tv_nsec = (us % 1000000l) * 1000;
366  struct timespec interval = { 0, 1000 * sync->us };
367  can_timer_start(sync->timer, sync->net, &start, &interval);
368  } else if (sync->timer) {
369  // Destroy the SYNC timer unless we are an active SYNC producer
370  // (with a non-zero communication cycle period).
371  can_timer_destroy(sync->timer);
372  sync->timer = NULL;
373  }
374 
375  sync->cnt = 1;
376 
377  return 0;
378 }
379 
380 static co_unsigned32_t
381 co_1005_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
382 {
383  assert(sub);
384  assert(co_obj_get_idx(co_sub_get_obj(sub)) == 0x1005);
385  assert(req);
386  co_sync_t *sync = data;
387  assert(sync);
388 
389  co_unsigned32_t ac = 0;
390 
391  co_unsigned16_t type = co_sub_get_type(sub);
392  union co_val val;
393  if (__unlikely(co_sdo_req_dn_val(req, type, &val, &ac) == -1))
394  return ac;
395 
396  if (__unlikely(co_sub_get_subidx(sub))) {
397  ac = CO_SDO_AC_NO_SUB;
398  goto error;
399  }
400 
401  assert(type == CO_DEFTYPE_UNSIGNED32);
402  co_unsigned32_t cobid = val.u32;
403  co_unsigned32_t cobid_old = co_sub_get_val_u32(sub);
404  if (cobid == cobid_old)
405  goto error;
406 
407  // The CAN-ID cannot be changed while the producer is and remains
408  // active.
409  int active = cobid & CO_SYNC_COBID_PRODUCER;
410  int active_old = cobid_old & CO_SYNC_COBID_PRODUCER;
411  uint32_t canid = cobid & CAN_MASK_EID;
412  uint32_t canid_old = cobid_old & CAN_MASK_EID;
413  if (active && active_old && canid != canid_old) {
414  ac = CO_SDO_AC_PARAM_VAL;
415  goto error;
416  }
417 
418  // A 29-bit CAN-ID is only valid if the frame bit is set.
419  // clang-format off
420  if (__unlikely(!(cobid & CO_SYNC_COBID_FRAME)
421  && (cobid & (CAN_MASK_EID ^ CAN_MASK_BID)))) {
422  // clang-format on
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 (__unlikely(co_sdo_req_dn_val(req, type, &val, &ac) == -1))
454  return ac;
455 
456  if (__unlikely(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 (__unlikely(co_sdo_req_dn_val(req, type, &val, &ac) == -1))
494  return ac;
495 
496  if (__unlikely(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 (__unlikely(sync->us)) {
510  ac = CO_SDO_AC_DATA_DEV;
511  goto error;
512  }
513 
514  if (__unlikely(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 (__unlikely(msg->flags & CAN_FLAG_RTR))
541  return 0;
542 
543 #ifndef LELY_NO_CANFD
544  // Ignore CAN FD format frames.
545  if (__unlikely(msg->flags & CAN_FLAG_EDL))
546  return 0;
547 #endif
548 
549  uint8_t len = sync->max_cnt ? 1 : 0;
550  if (__unlikely(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:88
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:53
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:336
uint_least32_t id
The identifier (11 or 29 bits, depending on the CAN_FLAG_IDE flag).
Definition: msg.h:90
can_recv_t * recv
A pointer to the CAN frame receiver.
Definition: sync.c:51
A CAN network interface.
Definition: net.c:37
#define CAN_MASK_EID
The mask used to extract the 29-bit Extended Identifier from a CAN frame.
Definition: msg.h:34
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:101
A CANopen sub-object.
Definition: obj.h:54
co_dev_t * dev
A pointer to a CANopen device.
Definition: sync.c:43
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:266
#define CAN_MSG_INIT
The static initializer for can_msg.
Definition: msg.h:114
#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:49
#define CAN_MASK_BID
The mask used to extract the 11-bit Base Identifier from a CAN frame.
Definition: msg.h:31
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:59
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:322
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:47
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
uint_least8_t data[CAN_MSG_MAX_LEN]
The frame payload (in case of a data frame).
Definition: msg.h:103
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:313
#define CAN_FLAG_IDE
The Identifier Extension (IDE) flag.
Definition: msg.h:41
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:381
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:282
#define CAN_FLAG_EDL
The Extended Data Length (EDL) flag.
Definition: msg.h:55
void can_recv_destroy(can_recv_t *recv)
Destroys a CAN frame receiver.
Definition: net.c:562
This is the internal header file of the CANopen library.
co_sync_ind_t * ind
A pointer to the indication function.
Definition: sync.c:57
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:832
#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:229
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition: errnum.c:43
#define __unlikely(x)
Indicates to the compiler that the expression is most-likely false.
Definition: features.h:286
can_net_t * net
A pointer to a CAN network interface.
Definition: sync.c:41
void * err_data
A pointer to user-specified data for err.
Definition: sync.c:63
A CANopen device.
Definition: dev.c:38
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_EDL, CAN_FLAG_BRS and CAN_FLAG_ESI...
Definition: msg.h:95
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:458
can_timer_t * can_timer_create(void)
Creates a new CAN timer.
Definition: net.c:382
This header file is part of the CANopen library; it contains the device description declarations...
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.
Definition: val.c:273
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:55
#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:61
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
void co_sync_destroy(co_sync_t *sync)
Destroys a CANopen SYNC producer/consumer service.
Definition: sync.c:256
#define CAN_FLAG_RTR
The Remote Transmission Request (RTR) flag (unavailable in CAN FD format frames). ...
Definition: msg.h:47
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:274
#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:466
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib.h> and defines any missing functionality.
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:279
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:508
A CANopen SYNC producer/consumer service.
Definition: sync.c:39
co_unsigned16_t co_obj_get_idx(const co_obj_t *obj)
Returns the index of a CANopen object.
Definition: obj.c:136
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:293
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:302
A CANopen object.
Definition: obj.h:32
This header file is part of the CANopen library; it contains the object dictionary declarations...
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
Function not supported.
Definition: errnum.h:181
uint32_t cobid
The SYNC COB-ID.
Definition: sync.c:45
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