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