Lely core libraries 1.9.2
rpdo.c
Go to the documentation of this file.
1
24#include "co.h"
25
26#ifndef LELY_NO_CO_RPDO
27
28#include <lely/co/dev.h>
29#include <lely/co/obj.h>
30#include <lely/co/rpdo.h>
31#include <lely/co/sdo.h>
32#include <lely/co/val.h>
33#include <lely/util/errnum.h>
34
35#include <assert.h>
36#include <inttypes.h>
37#include <stdlib.h>
38
40struct __co_rpdo {
46 co_unsigned16_t num;
58 unsigned int sync : 1;
60 unsigned int swnd : 1;
62 struct can_msg msg;
68 void *ind_data;
72 void *err_data;
73};
74
82static int co_rpdo_init_recv(co_rpdo_t *pdo);
83
90static int co_rpdo_init_timer_event(co_rpdo_t *pdo);
91
99static int co_rpdo_init_timer_swnd(co_rpdo_t *pdo);
100
107static co_unsigned32_t co_1400_dn_ind(
108 co_sub_t *sub, struct co_sdo_req *req, void *data);
109
116static co_unsigned32_t co_1600_dn_ind(
117 co_sub_t *sub, struct co_sdo_req *req, void *data);
118
124static int co_rpdo_recv(const struct can_msg *msg, void *data);
125
132static int co_rpdo_timer_event(const struct timespec *tp, void *data);
133
140static int co_rpdo_timer_swnd(const struct timespec *tp, void *data);
141
151static co_unsigned32_t co_rpdo_read_frame(
152 co_rpdo_t *pdo, const struct can_msg *msg);
153
154void *
155__co_rpdo_alloc(void)
156{
157 void *ptr = malloc(sizeof(struct __co_rpdo));
158 if (__unlikely(!ptr))
159 set_errc(errno2c(errno));
160 return ptr;
161}
162
163void
164__co_rpdo_free(void *ptr)
165{
166 free(ptr);
167}
168
169struct __co_rpdo *
170__co_rpdo_init(struct __co_rpdo *pdo, can_net_t *net, co_dev_t *dev,
171 co_unsigned16_t num)
172{
173 assert(pdo);
174 assert(net);
175 assert(dev);
176
177 int errc = 0;
178
179 if (__unlikely(!num || num > 512)) {
180 errc = errnum2c(ERRNUM_INVAL);
181 goto error_param;
182 }
183
184 // Find the PDO parameters in the object dictionary.
185 co_obj_t *obj_1400 = co_dev_find_obj(dev, 0x1400 + num - 1);
186 co_obj_t *obj_1600 = co_dev_find_obj(dev, 0x1600 + num - 1);
187 if (__unlikely(!obj_1400 || !obj_1600)) {
188 errc = errnum2c(ERRNUM_INVAL);
189 goto error_param;
190 }
191
192 pdo->net = net;
193 pdo->dev = dev;
194 pdo->num = num;
195
196 // Copy the PDO communication parameter record.
197 memset(&pdo->comm, 0, sizeof(pdo->comm));
198 memcpy(&pdo->comm, co_obj_addressof_val(obj_1400),
199 MIN(co_obj_sizeof_val(obj_1400), sizeof(pdo->comm)));
200
201 // Copy the PDO mapping parameter record.
202 memset(&pdo->map, 0, sizeof(pdo->map));
203 memcpy(&pdo->map, co_obj_addressof_val(obj_1600),
204 MIN(co_obj_sizeof_val(obj_1600), sizeof(pdo->map)));
205
206 pdo->recv = NULL;
207
208 pdo->timer_event = NULL;
209 pdo->timer_swnd = NULL;
210
211 pdo->sync = 0;
212 pdo->swnd = 0;
213 pdo->msg = (struct can_msg)CAN_MSG_INIT;
214
215 co_sdo_req_init(&pdo->req);
216
217 pdo->ind = NULL;
218 pdo->ind_data = NULL;
219 pdo->err = NULL;
220 pdo->err_data = NULL;
221
222 // Set the download indication functions PDO communication parameter
223 // record.
224 co_obj_set_dn_ind(obj_1400, &co_1400_dn_ind, pdo);
225
226 // Set the download indication functions PDO mapping parameter record.
227 co_obj_set_dn_ind(obj_1600, &co_1600_dn_ind, pdo);
228
229 if (__unlikely(co_rpdo_init_recv(pdo) == -1)) {
230 errc = get_errc();
231 goto error_init_recv;
232 }
233
234 if (__unlikely(co_rpdo_init_timer_swnd(pdo) == -1)) {
235 errc = get_errc();
236 goto error_init_timer_swnd;
237 }
238
239 return pdo;
240
241error_init_timer_swnd:
243error_init_recv:
244 co_obj_set_dn_ind(obj_1600, NULL, NULL);
245 co_obj_set_dn_ind(obj_1400, NULL, NULL);
246error_param:
247 set_errc(errc);
248 return NULL;
249}
250
251void
252__co_rpdo_fini(struct __co_rpdo *pdo)
253{
254 assert(pdo);
255 assert(pdo->num >= 1 && pdo->num <= 512);
256
257 // Remove the download indication functions PDO mapping parameter
258 // record.
259 co_obj_t *obj_1600 = co_dev_find_obj(pdo->dev, 0x1600 + pdo->num - 1);
260 assert(obj_1600);
261 co_obj_set_dn_ind(obj_1600, NULL, NULL);
262
263 // Remove the download indication functions PDO communication parameter
264 // record.
265 co_obj_t *obj_1400 = co_dev_find_obj(pdo->dev, 0x1400 + pdo->num - 1);
266 assert(obj_1400);
267 co_obj_set_dn_ind(obj_1400, NULL, NULL);
268
269 co_sdo_req_fini(&pdo->req);
270
273
275}
276
277co_rpdo_t *
278co_rpdo_create(can_net_t *net, co_dev_t *dev, co_unsigned16_t num)
279{
280 trace("creating Receive-PDO %d", num);
281
282 int errc = 0;
283
284 co_rpdo_t *pdo = __co_rpdo_alloc();
285 if (__unlikely(!pdo)) {
286 errc = get_errc();
287 goto error_alloc_pdo;
288 }
289
290 if (__unlikely(!__co_rpdo_init(pdo, net, dev, num))) {
291 errc = get_errc();
292 goto error_init_pdo;
293 }
294
295 return pdo;
296
297error_init_pdo:
298 __co_rpdo_free(pdo);
299error_alloc_pdo:
300 set_errc(errc);
301 return NULL;
302}
303
304void
306{
307 if (rpdo) {
308 trace("destroying Receive-PDO %d", rpdo->num);
309 __co_rpdo_fini(rpdo);
310 __co_rpdo_free(rpdo);
311 }
312}
313
314can_net_t *
316{
317 assert(pdo);
318
319 return pdo->net;
320}
321
322co_dev_t *
324{
325 assert(pdo);
326
327 return pdo->dev;
328}
329
330co_unsigned16_t
332{
333 assert(pdo);
334
335 return pdo->num;
336}
337
338const struct co_pdo_comm_par *
340{
341 assert(pdo);
342
343 return &pdo->comm;
344}
345
346const struct co_pdo_map_par *
348{
349 assert(pdo);
350
351 return &pdo->map;
352}
353
354void
355co_rpdo_get_ind(const co_rpdo_t *pdo, co_rpdo_ind_t **pind, void **pdata)
356{
357 assert(pdo);
358
359 if (pind)
360 *pind = pdo->ind;
361 if (pdata)
362 *pdata = pdo->ind_data;
363}
364
365void
367{
368 assert(pdo);
369
370 pdo->ind = ind;
371 pdo->ind_data = data;
372}
373
374void
375co_rpdo_get_err(const co_rpdo_t *pdo, co_rpdo_err_t **perr, void **pdata)
376{
377 assert(pdo);
378
379 if (perr)
380 *perr = pdo->err;
381 if (pdata)
382 *pdata = pdo->err_data;
383}
384
385void
387{
388 assert(pdo);
389
390 pdo->err = err;
391 pdo->err_data = data;
392}
393
394int
396{
397 assert(pdo);
398
399 // Check whether the PDO exists and is valid.
400 if (pdo->comm.cobid & CO_PDO_COBID_VALID)
401 return 0;
402
403 struct can_msg msg = CAN_MSG_INIT;
404 msg.id = pdo->comm.cobid;
405 if (pdo->comm.cobid & CO_PDO_COBID_FRAME) {
406 msg.id &= CAN_MASK_EID;
407 msg.flags |= CAN_FLAG_IDE;
408 } else {
409 msg.id &= CAN_MASK_BID;
410 }
411 msg.flags |= CAN_FLAG_RTR;
412 return can_net_send(pdo->net, &msg);
413}
414
415int
416co_rpdo_sync(co_rpdo_t *pdo, co_unsigned8_t cnt)
417{
418 assert(pdo);
419
420 if (__unlikely(cnt > 240)) {
422 return -1;
423 }
424
425 // Ignore SYNC objects if the transmission type is not synchronous.
426 if (pdo->comm.trans > 0xf0)
427 return 0;
428
429 // Reset the time window for synchronous PDOs.
430 pdo->swnd = 0;
432
433 // Check if we have a CAN frame waiting for a SYNC object.
434 if (!pdo->sync)
435 return 0;
436 pdo->sync = 0;
437
438 return co_rpdo_read_frame(pdo, &pdo->msg) ? -1 : 0;
439}
440
441static int
443{
444 assert(pdo);
445
446 if (!(pdo->comm.cobid & CO_PDO_COBID_VALID)) {
447 if (!pdo->recv) {
448 pdo->recv = can_recv_create();
449 if (__unlikely(!pdo->recv))
450 return -1;
452 }
453 // Register the receiver under the specified CAN-ID.
454 uint32_t id = pdo->comm.cobid;
455 uint8_t flags = 0;
456 if (id & CO_PDO_COBID_FRAME) {
457 id &= CAN_MASK_EID;
459 } else {
460 id &= CAN_MASK_BID;
461 }
462 can_recv_start(pdo->recv, pdo->net, id, flags);
463 } else if (pdo->recv) {
465 pdo->recv = NULL;
466 }
467
468 return 0;
469}
470
471static int
473{
474 assert(pdo);
475
476 if (!(pdo->comm.cobid & CO_PDO_COBID_VALID) && pdo->comm.event) {
477 if (!pdo->timer_event) {
479 if (__unlikely(!pdo->timer_event))
480 return -1;
483 }
484 can_timer_timeout(pdo->timer_event, pdo->net, pdo->comm.event);
485 } else if (pdo->timer_event) {
487 pdo->timer_event = NULL;
488 }
489
490 return 0;
491}
492
493static int
495{
496 assert(pdo);
497
498 // Ignore the synchronous window length unless the RPDO is valid and
499 // synchronous.
500 co_unsigned32_t swnd = co_dev_get_val_u32(pdo->dev, 0x1007, 0x00);
501 if (!(pdo->comm.cobid & CO_PDO_COBID_VALID) && pdo->comm.trans <= 0xf0
502 && swnd) {
503 if (!pdo->timer_swnd) {
505 if (__unlikely(!pdo->timer_swnd))
506 return -1;
508 pdo);
509 }
510 can_timer_timeout(pdo->timer_swnd, pdo->net, swnd);
511 } else if (pdo->timer_swnd) {
513 pdo->timer_swnd = NULL;
514 }
515
516 return 0;
517}
518
519static co_unsigned32_t
520co_1400_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
521{
522 assert(sub);
523 assert(req);
524 co_rpdo_t *pdo = data;
525 assert(pdo);
526 assert(co_obj_get_idx(co_sub_get_obj(sub)) == 0x1400 + pdo->num - 1);
527
528 co_unsigned32_t ac = 0;
529
530 co_unsigned16_t type = co_sub_get_type(sub);
531 union co_val val;
532 if (__unlikely(co_sdo_req_dn_val(req, type, &val, &ac) == -1))
533 return ac;
534
535 switch (co_sub_get_subidx(sub)) {
536 case 0: ac = CO_SDO_AC_NO_WRITE; goto error;
537 case 1: {
538 assert(type == CO_DEFTYPE_UNSIGNED32);
539 co_unsigned32_t cobid = val.u32;
540 co_unsigned32_t cobid_old = co_sub_get_val_u32(sub);
541 if (cobid == cobid_old)
542 goto error;
543
544 // The CAN-ID cannot be changed when the PDO is and remains
545 // valid.
546 int valid = !(cobid & CO_PDO_COBID_VALID);
547 int valid_old = !(cobid_old & CO_PDO_COBID_VALID);
548 uint32_t canid = cobid & CAN_MASK_EID;
549 uint32_t canid_old = cobid_old & CAN_MASK_EID;
550 if (__unlikely(valid && valid_old && canid != canid_old)) {
552 goto error;
553 }
554
555 // A 29-bit CAN-ID is only valid if the frame bit is set.
556 // clang-format off
557 if (__unlikely(!(cobid & CO_PDO_COBID_FRAME)
558 && (cobid & (CAN_MASK_EID ^ CAN_MASK_BID)))) {
559 // clang-format on
561 goto error;
562 }
563
564 pdo->comm.cobid = cobid;
565
566 pdo->sync = 0;
567 pdo->swnd = 0;
568
571 break;
572 }
573 case 2: {
574 assert(type == CO_DEFTYPE_UNSIGNED8);
575 co_unsigned8_t trans = val.u8;
576 co_unsigned8_t trans_old = co_sub_get_val_u8(sub);
577 if (trans == trans_old)
578 goto error;
579
580 // Transmission types 0xF1..0xFD are reserved.
581 if (__unlikely(trans > 0xf0 && trans < 0xfe)) {
583 goto error;
584 }
585
586 pdo->comm.trans = trans;
587
588 pdo->swnd = 0;
589
591 break;
592 }
593 case 3: {
594 assert(type == CO_DEFTYPE_UNSIGNED16);
595 co_unsigned16_t inhibit = val.u16;
596 co_unsigned16_t inhibit_old = co_sub_get_val_u16(sub);
597 if (inhibit == inhibit_old)
598 goto error;
599
600 // The inhibit time cannot be changed while the PDO exists and
601 // is valid.
602 if (__unlikely(!(pdo->comm.cobid & CO_PDO_COBID_VALID))) {
604 goto error;
605 }
606
607 pdo->comm.inhibit = inhibit;
608 break;
609 }
610 case 5: {
611 assert(type == CO_DEFTYPE_UNSIGNED16);
612 co_unsigned16_t event = val.u16;
613 co_unsigned16_t event_old = co_sub_get_val_u16(sub);
614 if (event == event_old)
615 goto error;
616
617 pdo->comm.event = event;
618 break;
619 }
620 default: ac = CO_SDO_AC_NO_SUB; goto error;
621 }
622
623 co_sub_dn(sub, &val);
624error:
625 co_val_fini(type, &val);
626 return ac;
627}
628
629static co_unsigned32_t
630co_1600_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
631{
632 assert(sub);
633 assert(req);
634 co_rpdo_t *pdo = data;
635 assert(pdo);
636 assert(co_obj_get_idx(co_sub_get_obj(sub)) == 0x1600 + pdo->num - 1);
637
638 co_unsigned32_t ac = 0;
639
640 co_unsigned16_t type = co_sub_get_type(sub);
641 union co_val val;
642 if (__unlikely(co_sdo_req_dn_val(req, type, &val, &ac) == -1))
643 return ac;
644
645 int valid = !(pdo->comm.cobid & CO_PDO_COBID_VALID);
646
647 if (!co_sub_get_subidx(sub)) {
648 assert(type == CO_DEFTYPE_UNSIGNED8);
649 co_unsigned8_t n = val.u8;
650 co_unsigned8_t n_old = co_sub_get_val_u8(sub);
651 if (n == n_old)
652 goto error;
653
654 // The PDO mapping cannot be changed when the PDO is valid.
655 if (__unlikely(valid || n > 0x40)) {
657 goto error;
658 }
659
660 size_t bits = 0;
661 for (size_t i = 1; i <= n; i++) {
662 co_unsigned32_t map = pdo->map.map[i - 1];
663 co_unsigned16_t idx = (map >> 16) & 0xffff;
664 co_unsigned8_t subidx = (map >> 8) & 0xff;
665 co_unsigned8_t len = map & 0xff;
666
667 // Check the PDO length.
668 if (__unlikely((bits += len) > CAN_MAX_LEN * 8)) {
670 goto error;
671 }
672
673 // Check whether the sub-object exists and can be mapped
674 // into a PDO (or is a valid dummy entry).
675 ac = co_dev_chk_rpdo(pdo->dev, idx, subidx);
676 if (__unlikely(ac))
677 goto error;
678 }
679
680 pdo->map.n = n;
681 } else {
682 assert(type == CO_DEFTYPE_UNSIGNED32);
683 co_unsigned32_t map = val.u32;
684 co_unsigned32_t map_old = co_sub_get_val_u32(sub);
685 if (map == map_old)
686 goto error;
687
688 // The PDO mapping cannot be changed when the PDO is valid or
689 // sub-index 0x00 is non-zero.
690 if (__unlikely(valid || pdo->map.n)) {
692 goto error;
693 }
694
695 co_unsigned16_t idx = (map >> 16) & 0xffff;
696 co_unsigned8_t subidx = (map >> 8) & 0xff;
697 // Check whether the sub-object exists and can be mapped into a
698 // PDO (or is a valid dummy entry).
699 ac = co_dev_chk_rpdo(pdo->dev, idx, subidx);
700 if (__unlikely(ac))
701 goto error;
702
703 pdo->map.map[co_sub_get_subidx(sub) - 1] = map;
704 }
705
706 co_sub_dn(sub, &val);
707error:
708 co_val_fini(type, &val);
709 return ac;
710}
711
712static int
713co_rpdo_recv(const struct can_msg *msg, void *data)
714{
715 assert(msg);
716 co_rpdo_t *pdo = data;
717 assert(pdo);
718
719 // Ignore remote frames.
720 if (__unlikely(msg->flags & CAN_FLAG_RTR))
721 return 0;
722
723#ifndef LELY_NO_CANFD
724 // Ignore CAN FD format frames.
725 if (__unlikely(msg->flags & CAN_FLAG_EDL))
726 return 0;
727#endif
728
729 // Reset the event timer.
731
732 if (pdo->comm.trans <= 0xf0) {
733 // In case of a synchronous RPDO, save the frame to be processed
734 // after the next SYNC object.
735 if (!pdo->swnd) {
736 pdo->sync = 1;
737 pdo->msg = *msg;
738 }
739 } else if (pdo->comm.trans >= 0xfe) {
740 // In case of an event-driven RPDO, process the frame directly.
741 co_rpdo_read_frame(pdo, msg);
742 }
743
744 return 0;
745}
746
747static int
748co_rpdo_timer_event(const struct timespec *tp, void *data)
749{
750 (void)tp;
751 co_rpdo_t *pdo = data;
752 assert(pdo);
753
754 trace("RPDO %d: no PDO received in synchronous window", pdo->num);
755
756 // Generate an error if an RPDO timeout occurred.
757 if (pdo->err)
758 pdo->err(pdo, 0x8250, 0x10, pdo->err_data);
759
760 return 0;
761}
762
763static int
764co_rpdo_timer_swnd(const struct timespec *tp, void *data)
765{
766 (void)tp;
767 co_rpdo_t *pdo = data;
768 assert(pdo);
769
770 // The synchronous time window has expired.
771 pdo->swnd = 1;
772
773 return 0;
774}
775
776static co_unsigned32_t
777co_rpdo_read_frame(co_rpdo_t *pdo, const struct can_msg *msg)
778{
779 assert(pdo);
780 assert(msg);
781
782 size_t n = MIN(msg->len, CAN_MAX_LEN);
783 co_unsigned32_t ac =
784 co_pdo_dn(&pdo->map, pdo->dev, &pdo->req, msg->data, n);
785
786#ifndef NDEBUG
787 if (ac)
788 trace("RPDO %d: PDO error %08" PRIX32 " (%s)", pdo->num, ac,
789 co_sdo_ac2str(ac));
790#endif
791
792 // Invoke the user-defined callback function.
793 if (pdo->ind)
794 pdo->ind(pdo, ac, msg->data, n, pdo->ind_data);
795
796 if (pdo->err) {
797 if (ac == CO_SDO_AC_PDO_LEN) {
798 // Generate an error message if the PDO was not
799 // processed because too few bytes were available.
800 pdo->err(pdo, 0x8210, 0x10, pdo->err_data);
801 } else if (!ac) {
802 size_t offset = 0;
803 for (size_t i = 0; i < MIN(pdo->map.n, 0x40u); i++)
804 offset += (pdo->map.map[i]) & 0xff;
805 if (__unlikely((offset + 7) / 8 < n))
806 // Generate an error message if the PDO length
807 // exceeds the mapping.
808 pdo->err(pdo, 0x8220, 0x10, pdo->err_data);
809 }
810 }
811
812 return ac;
813}
814
815#endif // !LELY_NO_CO_RPDO
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:825
@ ERRNUM_INVAL
Invalid argument.
Definition: errnum.h:129
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition: errnum.c:947
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:957
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition: errnum.c:43
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Definition: errnum.h:375
#define __unlikely(x)
Indicates to the compiler that the expression is most-likely false.
Definition: features.h:286
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:466
void * co_obj_addressof_val(const co_obj_t *obj)
Returns the address of the value of a CANopen object.
Definition: obj.c:275
co_unsigned16_t co_obj_get_idx(const co_obj_t *obj)
Returns the index of a CANopen object.
Definition: obj.c:136
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
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
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
size_t co_obj_sizeof_val(const co_obj_t *obj)
Returns size (in bytes) of the value of a CANopen object.
Definition: obj.c:281
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
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:165
void co_sdo_req_fini(struct co_sdo_req *req)
Finalizes a CANopen SDO upload/download request.
Definition: sdo.c:121
const char * co_sdo_ac2str(co_unsigned32_t ac)
Returns a string describing an SDO abort code.
Definition: sdo.c:57
#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
#define CO_SDO_AC_PDO_LEN
SDO abort code: The number and length of the objects to be mapped would exceed the PDO length.
Definition: sdo.h:102
void co_sdo_req_init(struct co_sdo_req *req)
Initializes a CANopen SDO upload/download request.
Definition: sdo.c:109
#define CO_SDO_AC_NO_WRITE
SDO abort code: Attempt to write a read only object.
Definition: sdo.h:90
#define MIN(a, b)
Returns the minimum of a and b.
Definition: util.h:57
#define CAN_MASK_EID
The mask used to extract the 29-bit Extended Identifier from a CAN frame.
Definition: msg.h:34
#define CAN_FLAG_RTR
The Remote Transmission Request (RTR) flag (unavailable in CAN FD format frames).
Definition: msg.h:47
#define CAN_MAX_LEN
The maximum number of bytes in the payload of a CAN format frame.
Definition: msg.h:73
#define CAN_FLAG_IDE
The Identifier Extension (IDE) flag.
Definition: msg.h:41
#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:114
#define CAN_FLAG_EDL
The Extended Data Length (EDL) flag.
Definition: msg.h:55
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
can_timer_t * can_timer_create(void)
Creates a new CAN timer.
Definition: net.c:382
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
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
void can_recv_destroy(can_recv_t *recv)
Destroys a CAN frame receiver.
Definition: net.c:562
void can_timer_timeout(can_timer_t *timer, can_net_t *net, int timeout)
Starts a CAN timer and registers it with a network interface.
Definition: net.c:484
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
can_recv_t * can_recv_create(void)
Creates a new CAN frame receiver.
Definition: net.c:537
void can_timer_destroy(can_timer_t *timer)
Destroys a CAN timer.
Definition: net.c:407
co_unsigned32_t co_dev_chk_rpdo(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
Checks if the specified object is valid and can be mapped into a Receive-PDO.
Definition: pdo.c:42
#define CO_PDO_COBID_FRAME
The bit in the PDO COB-ID specifying whether to use an 11-bit (0) or 29-bit (1) CAN-ID.
Definition: pdo.h:37
#define CO_PDO_COBID_VALID
The bit in the PDO COB-ID specifying whether the PDO exists and is valid.
Definition: pdo.h:28
co_unsigned32_t co_pdo_dn(const struct co_pdo_map_par *par, co_dev_t *dev, struct co_sdo_req *req, const uint8_t *buf, size_t n)
Writes mapped PDO values to the object dictionary through a local SDO download request.
Definition: pdo.c:254
void co_rpdo_get_err(const co_rpdo_t *pdo, co_rpdo_err_t **perr, void **pdata)
Retrieves the error handling function of a Receive-PDO service.
Definition: rpdo.c:375
int co_rpdo_rtr(co_rpdo_t *pdo)
Requests the transmission of a PDO.
Definition: rpdo.c:395
static int co_rpdo_timer_event(const struct timespec *tp, void *data)
The CAN timer callback function for deadline monitoring of a Receive-PDO service.
Definition: rpdo.c:748
static int co_rpdo_timer_swnd(const struct timespec *tp, void *data)
The CAN timer callback function for the synchronous time window of a Receive-PDO service.
Definition: rpdo.c:764
co_dev_t * co_rpdo_get_dev(const co_rpdo_t *pdo)
Returns a pointer to the CANopen device of a Receive-PDO.
Definition: rpdo.c:323
static co_unsigned32_t co_rpdo_read_frame(co_rpdo_t *pdo, const struct can_msg *msg)
Parses a CAN frame received by a Receive-PDO service and updates the corresponding objects in the obj...
Definition: rpdo.c:777
int co_rpdo_sync(co_rpdo_t *pdo, co_unsigned8_t cnt)
Triggers the actuation of a received synchronous PDO.
Definition: rpdo.c:416
void co_rpdo_set_err(co_rpdo_t *pdo, co_rpdo_err_t *err, void *data)
Sets the error handling function of a Receive-PDO service.
Definition: rpdo.c:386
static co_unsigned32_t co_1400_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
The download indication function for (all sub-objects of) CANopen objects 1400..15FF (RPDO communicat...
Definition: rpdo.c:520
static int co_rpdo_init_timer_event(co_rpdo_t *pdo)
Initializes the CAN timer for deadline monitoring of a Receive-PDO service.
Definition: rpdo.c:472
static int co_rpdo_init_timer_swnd(co_rpdo_t *pdo)
Initializes the CAN timer for the synchronous time window of a Receive-PDO service.
Definition: rpdo.c:494
static co_unsigned32_t co_1600_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
The download indication function for (all sub-objects of) CANopen objects 1600..17FF (RPDO mapping pa...
Definition: rpdo.c:630
void co_rpdo_get_ind(const co_rpdo_t *pdo, co_rpdo_ind_t **pind, void **pdata)
Retrieves the indication function invoked when a Receive-PDO error occurs.
Definition: rpdo.c:355
can_net_t * co_rpdo_get_net(const co_rpdo_t *pdo)
Returns a pointer to the CAN network of a Receive-PDO.
Definition: rpdo.c:315
co_unsigned16_t co_rpdo_get_num(const co_rpdo_t *pdo)
Returns the PDO number of a Receive-PDO.
Definition: rpdo.c:331
static int co_rpdo_recv(const struct can_msg *msg, void *data)
The CAN receive callback function for a Receive-PDO service.
Definition: rpdo.c:713
static int co_rpdo_init_recv(co_rpdo_t *pdo)
Initializes the CAN frame receiver of a Receive-PDO service.
Definition: rpdo.c:442
void co_rpdo_set_ind(co_rpdo_t *pdo, co_rpdo_ind_t *ind, void *data)
Sets the indication function invoked when a Receive-PDO error occurs.
Definition: rpdo.c:366
const struct co_pdo_map_par * co_rpdo_get_map_par(const co_rpdo_t *pdo)
Returns a pointer to the PDO mapping parameter record of a Receive-PDO.
Definition: rpdo.c:347
const struct co_pdo_comm_par * co_rpdo_get_comm_par(const co_rpdo_t *pdo)
Returns a pointer to the PDO communication parameter record of a Receive-PDO.
Definition: rpdo.c:339
co_rpdo_t * co_rpdo_create(can_net_t *net, co_dev_t *dev, co_unsigned16_t num)
Creates a new CANopen Receive-PDO service.
Definition: rpdo.c:278
void co_rpdo_destroy(co_rpdo_t *rpdo)
Destroys a CANopen Receive-PDO service.
Definition: rpdo.c:305
This header file is part of the CANopen library; it contains the Receive-PDO declarations.
void co_rpdo_err_t(co_rpdo_t *pdo, co_unsigned16_t eec, co_unsigned8_t er, void *data)
The type of a CANopen Receive-PDO error handling function, invoked in case of a timeout or length mis...
Definition: rpdo.h:56
void co_rpdo_ind_t(co_rpdo_t *pdo, co_unsigned32_t ac, const void *ptr, size_t n, void *data)
The type of a CANopen Receive-PDO indication function, invoked when a PDO is received or an error occ...
Definition: rpdo.h:44
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:99
A CAN timer.
Definition: net.c:63
A CANopen device.
Definition: dev.c:38
A CANopen object.
Definition: obj.h:32
A CANopen Receive-PDO.
Definition: rpdo.c:40
void * ind_data
A pointer to user-specified data for ind.
Definition: rpdo.c:68
can_net_t * net
A pointer to a CAN network interface.
Definition: rpdo.c:42
struct co_sdo_req req
The CANopen SDO download request used for writing sub-objects.
Definition: rpdo.c:64
can_timer_t * timer_swnd
A pointer to the CAN timer for the synchronous time window.
Definition: rpdo.c:56
unsigned int sync
A flag indicating we're waiting for a SYNC object to process msg.
Definition: rpdo.c:58
unsigned int swnd
A flag indicating the synchronous time window has expired.
Definition: rpdo.c:60
can_timer_t * timer_event
A pointer to the CAN timer for deadline monitoring.
Definition: rpdo.c:54
co_unsigned16_t num
The PDO number.
Definition: rpdo.c:46
struct co_pdo_comm_par comm
The PDO communication parameter.
Definition: rpdo.c:48
co_dev_t * dev
A pointer to a CANopen device.
Definition: rpdo.c:44
can_recv_t * recv
A pointer to the CAN frame receiver.
Definition: rpdo.c:52
co_rpdo_ind_t * ind
A pointer to the indication function.
Definition: rpdo.c:66
void * err_data
A pointer to user-specified data for err.
Definition: rpdo.c:72
struct co_pdo_map_par map
The PDO mapping parameter.
Definition: rpdo.c:50
co_rpdo_err_t * err
A pointer to the error handling function.
Definition: rpdo.c:70
struct can_msg msg
A CAN frame waiting for a SYNC object to be processed.
Definition: rpdo.c:62
A CANopen sub-object.
Definition: obj.h:54
A CAN or CAN FD format frame.
Definition: msg.h:88
uint_least8_t data[CAN_MSG_MAX_LEN]
The frame payload (in case of a data frame).
Definition: msg.h:103
uint_least32_t id
The identifier (11 or 29 bits, depending on the CAN_FLAG_IDE flag).
Definition: msg.h:90
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
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 PDO communication parameter record.
Definition: pdo.h:43
co_unsigned16_t inhibit
Inhibit time.
Definition: pdo.h:51
co_unsigned16_t event
Event timer.
Definition: pdo.h:54
co_unsigned32_t cobid
COB-ID.
Definition: pdo.h:47
co_unsigned8_t trans
Transmission type.
Definition: pdo.h:49
A PDO mapping parameter record.
Definition: pdo.h:69
co_unsigned8_t n
Number of mapped objects in PDO.
Definition: pdo.h:71
co_unsigned32_t map[0x40]
An array of objects to be mapped.
Definition: pdo.h:73
A CANopen SDO upload/download request.
Definition: sdo.h:178
A time type with nanosecond resolution.
Definition: time.h:83
#define CO_DEFTYPE_UNSIGNED16
The data type (and object index) of a 16-bit unsigned integer.
Definition: type.h:47
#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:163
This header file is part of the CANopen library; it contains the CANopen value declarations.
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.
Definition: val.c:273