Lely core libraries 2.3.2
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
40struct __co_sync {
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
74static void co_sync_update(co_sync_t *sync);
75
82static co_unsigned32_t co_1005_dn_ind(
83 co_sub_t *sub, struct co_sdo_req *req, void *data);
84
91static co_unsigned32_t co_1006_dn_ind(
92 co_sub_t *sub, struct co_sdo_req *req, void *data);
93
100static co_unsigned32_t co_1019_dn_ind(
101 co_sub_t *sub, struct co_sdo_req *req, void *data);
102
108static int co_sync_recv(const struct can_msg *msg, void *data);
109
115static int co_sync_timer(const struct timespec *tp, void *data);
116
117void *
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
128void
129__co_sync_free(void *ptr)
130{
131 free(ptr);
132}
133
134struct __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 }
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);
188error_start:
190error_create_timer:
191 can_recv_destroy(sync->recv);
192error_create_recv:
193 co_obj_set_dn_ind(obj_1005, NULL, NULL);
194error_obj_1005:
195 set_errc(errc);
196 return NULL;
197}
198
199void
200__co_sync_fini(struct __co_sync *sync)
201{
202 assert(sync);
203
204 co_sync_stop(sync);
205
207 can_recv_destroy(sync->recv);
208}
209
210co_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
230error_init_sync:
231 __co_sync_free(sync);
232error_alloc_sync:
233 set_errc(errc);
234 return NULL;
235}
236
237void
239{
240 if (sync) {
241 trace("destroying SYNC service");
242 __co_sync_fini(sync);
243 __co_sync_free(sync);
244 }
245}
246
247int
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
284void
286{
287 assert(sync);
288
289 if (sync->stopped)
290 return;
291
292 // Remove the download indication function for the synchronous counter
293 // overflow value object.
294 co_obj_t *obj_1019 = co_dev_find_obj(sync->dev, 0x1019);
295 if (obj_1019)
296 co_obj_set_dn_ind(obj_1019, NULL, NULL);
297
298 // Remove the download indication function for the communication cycle
299 // period object.
300 co_obj_t *obj_1006 = co_dev_find_obj(sync->dev, 0x1006);
301 if (obj_1006)
302 co_obj_set_dn_ind(obj_1006, NULL, NULL);
303
304 // Remove the download indication function for the SYNC COB-ID object.
305 co_obj_t *obj_1005 = co_dev_find_obj(sync->dev, 0x1005);
306 assert(obj_1005);
307 co_obj_set_dn_ind(obj_1005, NULL, NULL);
308
309 sync->stopped = 1;
310}
311
312int
314{
315 assert(sync);
316
317 return sync->stopped;
318}
319
320can_net_t *
322{
323 assert(sync);
324
325 return sync->net;
326}
327
328co_dev_t *
330{
331 assert(sync);
332
333 return sync->dev;
334}
335
336void
337co_sync_get_ind(const co_sync_t *sync, co_sync_ind_t **pind, void **pdata)
338{
339 assert(sync);
340
341 if (pind)
342 *pind = sync->ind;
343 if (pdata)
344 *pdata = sync->ind_data;
345}
346
347void
349{
350 assert(sync);
351
352 sync->ind = ind;
353 sync->ind_data = data;
354}
355
356void
357co_sync_get_err(const co_sync_t *sync, co_sync_err_t **perr, void **pdata)
358{
359 assert(sync);
360
361 if (perr)
362 *perr = sync->err;
363 if (pdata)
364 *pdata = sync->err_data;
365}
366
367void
369{
370 assert(sync);
371
372 sync->err = err;
373 sync->err_data = data;
374}
375
376static void
378{
379 assert(sync);
380
381 if (!(sync->cobid & CO_SYNC_COBID_PRODUCER)) {
382 // Register the receiver under the specified CAN-ID.
383 uint_least32_t id = sync->cobid;
384 uint_least8_t flags = 0;
385 if (id & CO_SYNC_COBID_FRAME) {
386 id &= CAN_MASK_EID;
387 flags |= CAN_FLAG_IDE;
388 } else {
389 id &= CAN_MASK_BID;
390 }
391 can_recv_start(sync->recv, sync->net, id, flags);
392 } else {
393 // Stop the receiver if we are a producer, to prevent receiving
394 // our own SYNC messages.
395 can_recv_stop(sync->recv);
396 }
397
398 if ((sync->cobid & CO_SYNC_COBID_PRODUCER) && sync->us) {
399 // Start SYNC transmission at the next multiple of the SYNC
400 // period.
401 struct timespec start = { 0, 0 };
402 can_net_get_time(sync->net, &start);
403 int_least64_t nsec = start.tv_sec * INT64_C(1000000000)
404 + start.tv_nsec;
405 nsec %= (uint_least64_t)sync->us * 1000;
406 timespec_sub_nsec(&start, nsec);
407 timespec_add_usec(&start, sync->us);
408 struct timespec interval = { 0, 0 };
409 timespec_add_usec(&interval, sync->us);
410 can_timer_start(sync->timer, sync->net, &start, &interval);
411 } else {
412 // Stop the SYNC timer unless we are an active SYNC producer
413 // (with a non-zero communication cycle period).
414 can_timer_stop(sync->timer);
415 }
416
417 sync->cnt = 1;
418}
419
420static co_unsigned32_t
421co_1005_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
422{
423 assert(sub);
424 assert(co_obj_get_idx(co_sub_get_obj(sub)) == 0x1005);
425 assert(req);
426 co_sync_t *sync = data;
427 assert(sync);
428
429 co_unsigned16_t type = co_sub_get_type(sub);
430 assert(!co_type_is_array(type));
431
432 union co_val val;
433 co_unsigned32_t ac = 0;
434 if (co_sdo_req_dn_val(req, type, &val, &ac) == -1)
435 return ac;
436
437 if (co_sub_get_subidx(sub))
438 return CO_SDO_AC_NO_SUB;
439
440 assert(type == CO_DEFTYPE_UNSIGNED32);
441 co_unsigned32_t cobid = val.u32;
442 co_unsigned32_t cobid_old = co_sub_get_val_u32(sub);
443 if (cobid == cobid_old)
444 return 0;
445
446 // The CAN-ID cannot be changed while the producer is and remains
447 // active.
448 int active = cobid & CO_SYNC_COBID_PRODUCER;
449 int active_old = cobid_old & CO_SYNC_COBID_PRODUCER;
450 uint_least32_t canid = cobid & CAN_MASK_EID;
451 uint_least32_t canid_old = cobid_old & CAN_MASK_EID;
452 if (active && active_old && canid != canid_old)
453 return CO_SDO_AC_PARAM_VAL;
454
455 // A 29-bit CAN-ID is only valid if the frame bit is set.
456 if (!(cobid & CO_SYNC_COBID_FRAME)
457 && (cobid & (CAN_MASK_EID ^ CAN_MASK_BID)))
458 return CO_SDO_AC_PARAM_VAL;
459
460 sync->cobid = cobid;
461
462 co_sub_dn(sub, &val);
463
464 co_sync_update(sync);
465 return 0;
466}
467
468static co_unsigned32_t
469co_1006_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
470{
471 assert(sub);
472 assert(co_obj_get_idx(co_sub_get_obj(sub)) == 0x1006);
473 assert(req);
474 co_sync_t *sync = data;
475 assert(sync);
476
477 co_unsigned16_t type = co_sub_get_type(sub);
478 assert(!co_type_is_array(type));
479
480 union co_val val;
481 co_unsigned32_t ac = 0;
482 if (co_sdo_req_dn_val(req, type, &val, &ac) == -1)
483 return ac;
484
485 if (co_sub_get_subidx(sub))
486 return CO_SDO_AC_NO_SUB;
487
488 assert(type == CO_DEFTYPE_UNSIGNED32);
489 co_unsigned32_t us = val.u32;
490 co_unsigned32_t us_old = co_sub_get_val_u32(sub);
491 if (us == us_old)
492 return 0;
493
494 sync->us = us;
495
496 co_sub_dn(sub, &val);
497
498 co_sync_update(sync);
499 return 0;
500}
501
502static co_unsigned32_t
503co_1019_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
504{
505 assert(sub);
506 assert(co_obj_get_idx(co_sub_get_obj(sub)) == 0x1019);
507 assert(req);
508 co_sync_t *sync = data;
509 assert(sync);
510
511 co_unsigned16_t type = co_sub_get_type(sub);
512 assert(!co_type_is_array(type));
513
514 union co_val val;
515 co_unsigned32_t ac = 0;
516 if (co_sdo_req_dn_val(req, type, &val, &ac) == -1)
517 return ac;
518
519 if (co_sub_get_subidx(sub))
520 return CO_SDO_AC_NO_SUB;
521
522 assert(type == CO_DEFTYPE_UNSIGNED8);
523 co_unsigned8_t max_cnt = val.u8;
524 co_unsigned8_t max_cnt_old = co_sub_get_val_u8(sub);
525 if (max_cnt == max_cnt_old)
526 return 0;
527
528 // The synchronous counter overflow value cannot be changed while the
529 // communication cycle period is non-zero.
530 if (sync->us)
531 return CO_SDO_AC_DATA_DEV;
532
533 if (max_cnt == 1 || max_cnt > 240)
534 return CO_SDO_AC_PARAM_VAL;
535
536 sync->max_cnt = max_cnt;
537
538 co_sub_dn(sub, &val);
539
540 co_sync_update(sync);
541 return 0;
542}
543
544static int
545co_sync_recv(const struct can_msg *msg, void *data)
546{
547 assert(msg);
548 assert(!(msg->flags & CAN_FLAG_RTR));
549#if !LELY_NO_CANFD
550 assert(!(msg->flags & CAN_FLAG_EDL));
551#endif
552 co_sync_t *sync = data;
553 assert(sync);
554
555 co_unsigned8_t len = sync->max_cnt ? 1 : 0;
556 if (msg->len != len && sync->err)
557 sync->err(sync, 0x8240, 0x10, sync->err_data);
558
559 co_unsigned8_t cnt = len && msg->len == len ? msg->data[0] : 0;
560 if (sync->ind)
561 sync->ind(sync, cnt, sync->ind_data);
562
563 return 0;
564}
565
566static int
567co_sync_timer(const struct timespec *tp, void *data)
568{
569 (void)tp;
570 co_sync_t *sync = data;
571 assert(sync);
572
573 struct can_msg msg = CAN_MSG_INIT;
574 msg.id = sync->cobid;
575 if (sync->cobid & CO_SYNC_COBID_FRAME) {
576 msg.id &= CAN_MASK_EID;
577 msg.flags |= CAN_FLAG_IDE;
578 } else {
579 msg.id &= CAN_MASK_BID;
580 }
581 if (sync->max_cnt) {
582 msg.len = 1;
583 msg.data[0] = sync->cnt;
584 sync->cnt = sync->cnt < sync->max_cnt ? sync->cnt + 1 : 1;
585 }
586 can_net_send(sync->net, &msg);
587
588 co_unsigned8_t cnt = msg.len ? msg.data[0] : 0;
589 if (sync->ind)
590 sync->ind(sync, cnt, sync->ind_data);
591
592 return 0;
593}
594
595#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
can_timer_t * can_timer_create(void)
Creates a new CAN timer.
Definition: net.c:376
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
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
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
can_recv_t * can_recv_create(void)
Creates a new CAN frame receiver.
Definition: net.c:533
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
A time type with nanosecond resolution.
Definition: time.h:88
long tv_nsec
Nanoseconds [0, 999999999].
Definition: time.h:92
time_t tv_sec
Whole seconds (>= 0).
Definition: time.h:90
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:357
static void co_sync_update(co_sync_t *sync)
Updates and (de)activates a SYNC producer/consumer service.
Definition: sync.c:377
void co_sync_destroy(co_sync_t *sync)
Destroys a CANopen SYNC producer/consumer service.
Definition: sync.c:238
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:329
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:368
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:348
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:503
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:421
static int co_sync_timer(const struct timespec *tp, void *data)
The CAN timer callback function for a SYNC producer service.
Definition: sync.c:567
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:545
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:337
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:313
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:321
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:469
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.