Lely core libraries 2.3.4
tpdo.c
Go to the documentation of this file.
1
33#include "co.h"
34
35#if !LELY_NO_CO_TPDO
36
37#include <lely/co/dev.h>
38#include <lely/co/obj.h>
39#include <lely/co/sdo.h>
40#include <lely/co/tpdo.h>
41#include <lely/co/val.h>
42#if !LELY_NO_CO_MPDO
43#include <lely/util/endian.h>
44#endif
45#include <lely/util/errnum.h>
46#include <lely/util/time.h>
47
48#include <assert.h>
49#include <stdlib.h>
50#include <string.h>
51
53struct __co_tpdo {
59 co_unsigned16_t num;
73 struct can_msg msg;
75 struct timespec inhibit;
77 unsigned int event : 1;
79 unsigned int swnd : 1;
81 co_unsigned8_t sync;
83 co_unsigned8_t cnt;
89 void *data;
94};
95
101static void co_tpdo_init_recv(co_tpdo_t *pdo);
102
108static void co_tpdo_init_timer_event(co_tpdo_t *pdo);
109
114static void co_tpdo_init_timer_swnd(co_tpdo_t *pdo);
115
122static co_unsigned32_t co_1800_dn_ind(
123 co_sub_t *sub, struct co_sdo_req *req, void *data);
124
131static co_unsigned32_t co_1a00_dn_ind(
132 co_sub_t *sub, struct co_sdo_req *req, void *data);
133
139static int co_tpdo_recv(const struct can_msg *msg, void *data);
140
146static int co_tpdo_timer_event(const struct timespec *tp, void *data);
147
154static int co_tpdo_timer_swnd(const struct timespec *tp, void *data);
155
157static int default_sample_ind(co_tpdo_t *pdo, void *data);
158
168static int co_tpdo_init_frame(co_tpdo_t *pdo, struct can_msg *msg);
169
179static int co_tpdo_send_frame(co_tpdo_t *pdo, const struct can_msg *msg);
180
181void *
182__co_tpdo_alloc(void)
183{
184 void *ptr = malloc(sizeof(struct __co_tpdo));
185#if !LELY_NO_ERRNO
186 if (!ptr)
187 set_errc(errno2c(errno));
188#endif
189 return ptr;
190}
191
192void
193__co_tpdo_free(void *ptr)
194{
195 free(ptr);
196}
197
198struct __co_tpdo *
199__co_tpdo_init(struct __co_tpdo *pdo, can_net_t *net, co_dev_t *dev,
200 co_unsigned16_t num)
201{
202 assert(pdo);
203 assert(net);
204 assert(dev);
205
206 int errc = 0;
207
208 if (!num || num > CO_NUM_PDOS) {
209 errc = errnum2c(ERRNUM_INVAL);
210 goto error_param;
211 }
212
213 // Find the PDO parameters in the object dictionary.
214 co_obj_t *obj_1800 = co_dev_find_obj(dev, 0x1800 + num - 1);
215 co_obj_t *obj_1a00 = co_dev_find_obj(dev, 0x1a00 + num - 1);
216 if (!obj_1800 || !obj_1a00) {
217 errc = errnum2c(ERRNUM_INVAL);
218 goto error_param;
219 }
220
221 pdo->net = net;
222 pdo->dev = dev;
223 pdo->num = num;
224
225 pdo->stopped = 1;
226
227 memset(&pdo->comm, 0, sizeof(pdo->comm));
228 memset(&pdo->map, 0, sizeof(pdo->map));
229
230 pdo->recv = can_recv_create();
231 if (!pdo->recv) {
232 errc = get_errc();
233 goto error_create_recv;
234 }
236
238 if (!pdo->timer_event) {
239 errc = get_errc();
240 goto error_create_timer_event;
241 }
243
245 if (!pdo->timer_swnd) {
246 errc = get_errc();
247 goto error_create_timer_swnd;
248 }
250
251 pdo->msg = (struct can_msg)CAN_MSG_INIT;
252
253 pdo->inhibit = (struct timespec){ 0, 0 };
254 pdo->event = 0;
255 pdo->swnd = 1;
256 pdo->sync = 0;
257 pdo->cnt = 0;
258
259 co_sdo_req_init(&pdo->req);
260
261 pdo->ind = NULL;
262 pdo->data = NULL;
263
265 pdo->sample_data = NULL;
266
267 if (co_tpdo_start(pdo) == -1) {
268 errc = get_errc();
269 goto error_start;
270 }
271
272 return pdo;
273
274 // co_tpdo_stop(pdo);
275error_start:
277error_create_timer_swnd:
279error_create_timer_event:
281error_create_recv:
282error_param:
283 set_errc(errc);
284 return NULL;
285}
286
287void
288__co_tpdo_fini(struct __co_tpdo *pdo)
289{
290 assert(pdo);
291 assert(pdo->num >= 1 && pdo->num <= CO_NUM_PDOS);
292
293 co_tpdo_stop(pdo);
294
295 co_sdo_req_fini(&pdo->req);
296
300}
301
302co_tpdo_t *
303co_tpdo_create(can_net_t *net, co_dev_t *dev, co_unsigned16_t num)
304{
305 trace("creating Transmit-PDO %d", num);
306
307 int errc = 0;
308
309 co_tpdo_t *pdo = __co_tpdo_alloc();
310 if (!pdo) {
311 errc = get_errc();
312 goto error_alloc_pdo;
313 }
314
315 if (!__co_tpdo_init(pdo, net, dev, num)) {
316 errc = get_errc();
317 goto error_init_pdo;
318 }
319
320 return pdo;
321
322error_init_pdo:
323 __co_tpdo_free(pdo);
324error_alloc_pdo:
325 set_errc(errc);
326 return NULL;
327}
328
329void
331{
332 if (tpdo) {
333 trace("destroying Transmit-PDO %d", tpdo->num);
334 __co_tpdo_fini(tpdo);
335 __co_tpdo_free(tpdo);
336 }
337}
338
339int
341{
342 assert(pdo);
343
344 if (!pdo->stopped)
345 return 0;
346
347 co_unsigned16_t idx_1800 = 0x1800 + pdo->num - 1;
348 co_obj_t *obj_1800 = co_dev_find_obj(pdo->dev, idx_1800);
349 assert(obj_1800);
350 // Copy the PDO communication parameters.
351 memset(&pdo->comm, 0, sizeof(pdo->comm));
352 pdo->comm.n = co_dev_get_val_u8(pdo->dev, idx_1800, 0);
353 pdo->comm.cobid = co_dev_get_val_u32(pdo->dev, idx_1800, 1);
354 pdo->comm.trans = co_dev_get_val_u8(pdo->dev, idx_1800, 2);
355 pdo->comm.inhibit = co_dev_get_val_u16(pdo->dev, idx_1800, 3);
356 pdo->comm.event = co_dev_get_val_u16(pdo->dev, idx_1800, 5);
357 pdo->comm.sync = co_dev_get_val_u8(pdo->dev, idx_1800, 6);
358 // Set the download indication functions PDO communication parameter
359 // record.
360 co_obj_set_dn_ind(obj_1800, &co_1800_dn_ind, pdo);
361
362 co_unsigned16_t idx_1a00 = 0x1a00 + pdo->num - 1;
363 co_obj_t *obj_1a00 = co_dev_find_obj(pdo->dev, idx_1a00);
364 assert(obj_1a00);
365 // Copy the PDO mapping parameter record.
366 memset(&pdo->map, 0, sizeof(pdo->map));
367 pdo->map.n = co_dev_get_val_u8(pdo->dev, idx_1a00, 0);
368 for (co_sub_t *sub = co_obj_first_sub(obj_1a00); sub;
369 sub = co_sub_next(sub)) {
370 co_unsigned8_t subidx = co_sub_get_subidx(sub);
371 if (subidx > 0 && subidx <= CO_PDO_NUM_MAPS)
372 pdo->map.map[subidx - 1] = co_sub_get_val_u32(sub);
373 }
374 // Set the download indication functions PDO mapping parameter record.
375 co_obj_set_dn_ind(obj_1a00, &co_1a00_dn_ind, pdo);
376
377 can_net_get_time(pdo->net, &pdo->inhibit);
378 pdo->event = 0;
379 pdo->swnd = 1;
380 pdo->sync = pdo->comm.sync;
381 pdo->cnt = 0;
382
385
386 pdo->stopped = 0;
387
388 return 0;
389}
390
391void
393{
394 assert(pdo);
395
396 if (pdo->stopped)
397 return;
398
401
402 can_recv_stop(pdo->recv);
403
404 // Remove the download indication functions PDO mapping parameter
405 // record.
406 co_obj_t *obj_1a00 = co_dev_find_obj(pdo->dev, 0x1a00 + pdo->num - 1);
407 assert(obj_1a00);
408 co_obj_set_dn_ind(obj_1a00, NULL, NULL);
409
410 // Remove the download indication functions PDO communication parameter
411 // record.
412 co_obj_t *obj_1800 = co_dev_find_obj(pdo->dev, 0x1800 + pdo->num - 1);
413 assert(obj_1800);
414 co_obj_set_dn_ind(obj_1800, NULL, NULL);
415
416 pdo->stopped = 1;
417}
418
419int
421{
422 assert(pdo);
423
424 return pdo->stopped;
425}
426
427can_net_t *
429{
430 assert(pdo);
431
432 return pdo->net;
433}
434
435co_dev_t *
437{
438 assert(pdo);
439
440 return pdo->dev;
441}
442
443co_unsigned16_t
445{
446 assert(pdo);
447
448 return pdo->num;
449}
450
451const struct co_pdo_comm_par *
453{
454 assert(pdo);
455
456 return &pdo->comm;
457}
458
459const struct co_pdo_map_par *
461{
462 assert(pdo);
463
464 return &pdo->map;
465}
466
467void
468co_tpdo_get_ind(const co_tpdo_t *pdo, co_tpdo_ind_t **pind, void **pdata)
469{
470 assert(pdo);
471
472 if (pind)
473 *pind = pdo->ind;
474 if (pdata)
475 *pdata = pdo->data;
476}
477
478void
480{
481 assert(pdo);
482
483 pdo->ind = ind;
484 pdo->data = data;
485}
486
487void
489 const co_tpdo_t *pdo, co_tpdo_sample_ind_t **pind, void **pdata)
490{
491 assert(pdo);
492
493 if (pind)
494 *pind = pdo->sample_ind;
495 if (pdata)
496 *pdata = pdo->sample_data;
497}
498
499void
501{
502 assert(pdo);
503
504 pdo->sample_ind = ind ? ind : &default_sample_ind;
505 pdo->sample_data = ind ? data : NULL;
506}
507
508int
510{
511 assert(pdo);
512
513 // Check whether the PDO exists and is valid.
514 if (pdo->comm.cobid & CO_PDO_COBID_VALID)
515 return 0;
516
517 // Check whether this is an MPDO.
518 if (pdo->map.n > 0x40)
519 return 0;
520
521 // See table 72 (Description of TPDO transmission type) in CiA 301.
522 switch (pdo->comm.trans) {
523 case 0x00: pdo->event = 1; break;
524 case 0xfd:
525 if (co_tpdo_init_frame(pdo, &pdo->msg) == -1)
526 return -1;
527 break;
528 case 0xfe:
529 case 0xff:
530 if (pdo->comm.inhibit) {
531 // Check whether the inhibit time has passed.
532 struct timespec now;
533 can_net_get_time(pdo->net, &now);
534 if (timespec_cmp(&now, &pdo->inhibit) < 0) {
536 return -1;
537 }
538 pdo->inhibit = now;
539 }
540
541 // In case of an event-driven TPDO, send the frame right away.
542 if (co_tpdo_init_frame(pdo, &pdo->msg) == -1)
543 return -1;
544 if (co_tpdo_send_frame(pdo, &pdo->msg) == -1)
545 return -1;
546
547 // Update the inhibit time if the PDO was transmitted successfully.
548 if (pdo->comm.inhibit)
549 // The inhibit time value is defined as a multiple of
550 // 100 microseconds.
552 &pdo->inhibit, pdo->comm.inhibit * 100);
553 break;
554 default:
555 // Ignore events if the transmission type is synchronous.
556 return 0;
557 }
558
560
561 return 0;
562}
563
564int
565co_tpdo_sync(co_tpdo_t *pdo, co_unsigned8_t cnt)
566{
567 assert(pdo);
568
569 if (cnt > 240) {
571 return -1;
572 }
573
574 // Check whether the PDO exists and is valid.
575 if (pdo->comm.cobid & CO_PDO_COBID_VALID)
576 return 0;
577
578 // Ignore SYNC objects if the transmission type is not synchronous.
579 // See table 72 (Description of TPDO transmission type) in CiA 301.
580 if (pdo->comm.trans > 0xf0 && pdo->comm.trans != 0xfc)
581 return 0;
582
583 // Wait for the SYNC counter to equal the SYNC start value.
584 if (pdo->sync && cnt) {
585 if (pdo->sync != cnt)
586 return 0;
587 pdo->sync = 0;
588 pdo->cnt = 0;
589 }
590
591 // Reset the time window for synchronous PDOs.
592 pdo->swnd = 0;
594
595 if (!pdo->comm.trans) {
596 // In case of a synchronous (acyclic) TPDO, do nothing unless an
597 // event occurred.
598 if (!pdo->event)
599 return 0;
600 pdo->event = 0;
601 } else if (pdo->comm.trans <= 0xf0) {
602 // In case of a synchronous (cyclic) TPDO, do nothing unless the
603 // n-th SYNC object has been received.
604 if (++pdo->cnt < pdo->comm.trans)
605 return 0;
606 pdo->cnt = 0;
607 }
608
609 assert(pdo->sample_ind);
610 return pdo->sample_ind(pdo, pdo->sample_data);
611}
612
613int
614co_tpdo_sample_res(co_tpdo_t *pdo, co_unsigned32_t ac)
615{
616 assert(pdo);
617
618 // Check whether the PDO exists and is valid.
619 if (pdo->comm.cobid & CO_PDO_COBID_VALID)
620 return 0;
621
622 // Ignore the sampling result if the transmission type is not
623 // synchronous or RTR-only. See table 72 (Description of TPDO
624 // transmission type) in CiA 301.
625 if (pdo->comm.trans > 0xf0 && pdo->comm.trans != 0xfc
626 && pdo->comm.trans != 0xfd)
627 return 0;
628
629 // Check whether this is an MPDO.
630 if (pdo->map.n > 0x40)
631 return 0;
632
633 // Check if the synchronous window expired.
634 if (!ac && pdo->comm.trans != 0xfd && pdo->swnd)
636
637 // Do not send a PDO in case of an error.
638 if (ac) {
639 if (pdo->ind)
640 pdo->ind(pdo, ac, NULL, 0, pdo->data);
641 return 0;
642 }
643
644 if (co_tpdo_init_frame(pdo, &pdo->msg) == -1)
645 return -1;
646
647 // In case of an RTR-only (synchronous) PDO, wait for the RTR.
648 if (pdo->comm.trans == 0xfc)
649 return 0;
650
651 return co_tpdo_send_frame(pdo, &pdo->msg);
652}
653
654void
655co_tpdo_get_next(const co_tpdo_t *pdo, struct timespec *tp)
656{
657 assert(pdo);
658
659 if (tp)
660 *tp = pdo->inhibit;
661}
662
663#if !LELY_NO_CO_MPDO
664
665int
666co_dam_mpdo_event(co_tpdo_t *pdo, co_unsigned8_t id, co_unsigned16_t idx,
667 co_unsigned8_t subidx, const co_unsigned8_t data[4])
668{
669 assert(pdo);
670 assert(data);
671 struct can_msg *msg = &pdo->msg;
672
673 // Check whether the PDO exists and is valid.
674 if (pdo->comm.cobid & CO_PDO_COBID_VALID)
675 return 0;
676
677 // Check whether the PDO is event-driven.
678 if (pdo->comm.trans < 0xfe)
679 return 0;
680
681 // Check whether this is a DAM-MPDO.
682 if (pdo->map.n != CO_PDO_MAP_DAM_MPDO)
683 return 0;
684
685 // Check wether the node-ID is valid (0 indicates all nodes).
686 if (id > CO_NUM_NODES)
687 return 0;
688
689 if (pdo->comm.inhibit) {
690 // Check whether the inhibit time has passed.
691 struct timespec now;
692 can_net_get_time(pdo->net, &now);
693 if (timespec_cmp(&now, &pdo->inhibit) < 0) {
695 return -1;
696 }
697 pdo->inhibit = now;
698 }
699
700 *msg = (struct can_msg)CAN_MSG_INIT;
701
702 msg->id = pdo->comm.cobid;
703 if (pdo->comm.cobid & CO_PDO_COBID_FRAME) {
704 msg->id &= CAN_MASK_EID;
705 msg->flags |= CAN_FLAG_IDE;
706 } else {
707 msg->id &= CAN_MASK_BID;
708 }
709
710 msg->len = CAN_MAX_LEN;
711 msg->data[0] = id | 0x80;
712 stle_u16(msg->data + 1, idx);
713 msg->data[3] = subidx;
714
715 memcpy(msg->data + 4, data, 4);
716
717 if (co_tpdo_send_frame(pdo, &pdo->msg) == -1)
718 return -1;
719
720 // Update the inhibit time if the PDO was transmitted successfully.
721 if (pdo->comm.inhibit)
722 // The inhibit time value is defined as a multiple of 100
723 // microseconds.
724 timespec_add_usec(&pdo->inhibit, pdo->comm.inhibit * 100);
725
726 return 0;
727}
728
729int
730co_sam_mpdo_event(co_tpdo_t *pdo, co_unsigned16_t idx, co_unsigned8_t subidx)
731{
732 assert(pdo);
733 struct can_msg *msg = &pdo->msg;
734
735 // Check whether the PDO exists and is valid.
736 if (pdo->comm.cobid & CO_PDO_COBID_VALID)
737 return 0;
738
739 // Check whether the PDO is event-driven.
740 if (pdo->comm.trans < 0xfe)
741 return 0;
742
743 // Check whether this is a SAM-MPDO.
744 if (pdo->map.n != CO_PDO_MAP_SAM_MPDO)
745 return 0;
746
747 // Check whether the node-ID is valid.
748 co_unsigned8_t id = co_dev_get_id(pdo->dev);
749 if (!id || id > CO_NUM_NODES)
750 return 0;
751
752 if (pdo->comm.inhibit) {
753 // Check whether the inhibit time has passed.
754 struct timespec now;
755 can_net_get_time(pdo->net, &now);
756 if (timespec_cmp(&now, &pdo->inhibit) < 0) {
758 return -1;
759 }
760 pdo->inhibit = now;
761 }
762
763 *msg = (struct can_msg)CAN_MSG_INIT;
764
765 msg->id = pdo->comm.cobid;
766 if (pdo->comm.cobid & CO_PDO_COBID_FRAME) {
767 msg->id &= CAN_MASK_EID;
768 msg->flags |= CAN_FLAG_IDE;
769 } else {
770 msg->id &= CAN_MASK_BID;
771 }
772
773 msg->len = CAN_MAX_LEN;
774 msg->data[0] = id;
775 stle_u16(msg->data + 1, idx);
776 msg->data[3] = subidx;
777
778 // Copy the value if the object exists and can be mapped to a SAM-MPDO.
779 co_unsigned32_t ac = co_sam_mpdo_up(
780 pdo->dev, idx, subidx, &pdo->req, msg->data + 4);
781 if (ac) {
782 if (pdo->ind)
783 pdo->ind(pdo, ac, NULL, 0, pdo->data);
784 return -1;
785 }
786
787 if (co_tpdo_send_frame(pdo, &pdo->msg) == -1)
788 return -1;
789
790 // Update the inhibit time if the PDO was transmitted successfully.
791 if (pdo->comm.inhibit)
792 // The inhibit time value is defined as a multiple of 100
793 // microseconds.
794 timespec_add_usec(&pdo->inhibit, pdo->comm.inhibit * 100);
795
796 return 0;
797}
798
799#endif // !LELY_NO_CO_MPDO
800
801static void
803{
804 assert(pdo);
805
806 if (!(pdo->comm.cobid & CO_PDO_COBID_VALID)
807 && !(pdo->comm.cobid & CO_PDO_COBID_RTR)) {
808 // Register the receiver under the specified CAN-ID.
809 uint_least32_t id = pdo->comm.cobid;
810 uint_least8_t flags = CAN_FLAG_RTR;
811 if (id & CO_PDO_COBID_FRAME) {
812 id &= CAN_MASK_EID;
814 } else {
815 id &= CAN_MASK_BID;
816 }
817 can_recv_start(pdo->recv, pdo->net, id, flags);
818 } else {
819 // Stop the receiver unless the TPDO is valid and allows RTR.
820 can_recv_stop(pdo->recv);
821 }
822}
823
824static void
826{
827 assert(pdo);
828
830 if (!(pdo->comm.cobid & CO_PDO_COBID_VALID) && pdo->comm.trans >= 0xfe
831 && pdo->comm.event)
832 // Reset the event timer.
833 can_timer_timeout(pdo->timer_event, pdo->net, pdo->comm.event);
834}
835
836static void
838{
839 assert(pdo);
840 assert(!(pdo->comm.cobid & CO_PDO_COBID_VALID));
841 assert(pdo->comm.trans <= 0xf0 || pdo->comm.trans == 0xfc);
842
844 // Ignore the synchronous window length unless the TPDO is valid and
845 // synchronous.
846 co_unsigned32_t swnd = co_dev_get_val_u32(pdo->dev, 0x1007, 0x00);
847 if (swnd) {
848 struct timespec start = { 0, 0 };
849 can_net_get_time(pdo->net, &start);
850 timespec_add_usec(&start, swnd);
851 can_timer_start(pdo->timer_swnd, pdo->net, &start, NULL);
852 }
853}
854
855static co_unsigned32_t
856co_1800_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
857{
858 assert(sub);
859 assert(req);
860 co_tpdo_t *pdo = data;
861 assert(pdo);
862 assert(co_obj_get_idx(co_sub_get_obj(sub)) == 0x1800 + pdo->num - 1);
863
864 co_unsigned16_t type = co_sub_get_type(sub);
865 assert(!co_type_is_array(type));
866
867 union co_val val;
868 co_unsigned32_t ac = 0;
869 if (co_sdo_req_dn_val(req, type, &val, &ac) == -1)
870 return ac;
871
872 switch (co_sub_get_subidx(sub)) {
873 case 0: return CO_SDO_AC_NO_WRITE;
874 case 1: {
875 assert(type == CO_DEFTYPE_UNSIGNED32);
876 co_unsigned32_t cobid = val.u32;
877 co_unsigned32_t cobid_old = co_sub_get_val_u32(sub);
878 if (cobid == cobid_old)
879 return 0;
880
881 // The CAN-ID cannot be changed when the PDO is and remains
882 // valid.
883 int valid = !(cobid & CO_PDO_COBID_VALID);
884 int valid_old = !(cobid_old & CO_PDO_COBID_VALID);
885 uint_least32_t canid = cobid & CAN_MASK_EID;
886 uint_least32_t canid_old = cobid_old & CAN_MASK_EID;
887 if (valid && valid_old && canid != canid_old)
888 return CO_SDO_AC_PARAM_VAL;
889
890 // A 29-bit CAN-ID is only valid if the frame bit is set.
891 if (!(cobid & CO_PDO_COBID_FRAME)
892 && (cobid & (CAN_MASK_EID ^ CAN_MASK_BID)))
893 return CO_SDO_AC_PARAM_VAL;
894
895 pdo->comm.cobid = cobid;
896
897 if (valid && !valid_old) {
898 can_net_get_time(pdo->net, &pdo->inhibit);
899 pdo->event = 0;
900 pdo->sync = pdo->comm.sync;
901 pdo->cnt = 0;
902 }
903
904 pdo->msg = (struct can_msg)CAN_MSG_INIT;
905 pdo->event = 0;
906 pdo->swnd = 1;
907
911 break;
912 }
913 case 2: {
914 // See table 72 (Description of TPDO transmission type) in CiA
915 // 301.
916 assert(type == CO_DEFTYPE_UNSIGNED8);
917 co_unsigned8_t trans = val.u8;
918 co_unsigned8_t trans_old = co_sub_get_val_u8(sub);
919 if (trans == trans_old)
920 return 0;
921
922 // Transmission types 0xF1..0xFB are reserved.
923 if (trans > 0xf0 && trans < 0xfc)
924 return CO_SDO_AC_PARAM_VAL;
925
926 // Check whether RTR is allowed on this PDO.
927 if ((trans == 0xfc || trans == 0xfd)
928 && (pdo->comm.cobid & CO_PDO_COBID_RTR))
929 return CO_SDO_AC_PARAM_VAL;
930
931 pdo->comm.trans = trans;
932
934 break;
935 }
936 case 3: {
937 assert(type == CO_DEFTYPE_UNSIGNED16);
938 co_unsigned16_t inhibit = val.u16;
939 co_unsigned16_t inhibit_old = co_sub_get_val_u16(sub);
940 if (inhibit == inhibit_old)
941 return 0;
942
943 // The inhibit time cannot be changed while the PDO exists and
944 // is valid.
945 if (!(pdo->comm.cobid & CO_PDO_COBID_VALID))
946 return CO_SDO_AC_PARAM_VAL;
947
948 pdo->comm.inhibit = inhibit;
949 break;
950 }
951 case 5: {
952 assert(type == CO_DEFTYPE_UNSIGNED16);
953 co_unsigned16_t event = val.u16;
954 co_unsigned16_t event_old = co_sub_get_val_u16(sub);
955 if (event == event_old)
956 return 0;
957
958 pdo->comm.event = event;
959
961 break;
962 }
963 case 6: {
964 assert(type == CO_DEFTYPE_UNSIGNED8);
965 co_unsigned8_t sync = val.u8;
966 co_unsigned8_t sync_old = co_sub_get_val_u8(sub);
967 if (sync == sync_old)
968 return 0;
969
970 // The SYNC start value cannot be changed while the PDO exists
971 // and is valid.
972 if (!(pdo->comm.cobid & CO_PDO_COBID_VALID))
973 return CO_SDO_AC_PARAM_VAL;
974
975 pdo->comm.sync = sync;
976 break;
977 }
978 default: return CO_SDO_AC_NO_SUB;
979 }
980
981 co_sub_dn(sub, &val);
982
983 return 0;
984}
985
986static co_unsigned32_t
987co_1a00_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
988{
989 assert(sub);
990 assert(req);
991 co_tpdo_t *pdo = data;
992 assert(pdo);
993 assert(co_obj_get_idx(co_sub_get_obj(sub)) == 0x1a00 + pdo->num - 1);
994
995 co_unsigned32_t ac = 0;
996
997 co_unsigned16_t type = co_sub_get_type(sub);
998 assert(!co_type_is_array(type));
999
1000 union co_val val;
1001 if (co_sdo_req_dn_val(req, type, &val, &ac) == -1)
1002 return ac;
1003
1004 int valid = !(pdo->comm.cobid & CO_PDO_COBID_VALID);
1005
1006 if (!co_sub_get_subidx(sub)) {
1007 assert(type == CO_DEFTYPE_UNSIGNED8);
1008 co_unsigned8_t n = val.u8;
1009 co_unsigned8_t n_old = co_sub_get_val_u8(sub);
1010 if (n == n_old)
1011 return 0;
1012
1013 // The PDO mapping cannot be changed when the PDO is valid.
1014 if (valid)
1015 return CO_SDO_AC_PARAM_VAL;
1016
1017 if (n <= CO_PDO_NUM_MAPS) {
1018 size_t bits = 0;
1019 for (size_t i = 1; i <= n; i++) {
1020 co_unsigned32_t map = pdo->map.map[i - 1];
1021 if (!map)
1022 continue;
1023
1024 // See figure 73 (Structure of TPDO mapping) in
1025 // CiA 301.
1026 co_unsigned16_t idx = (map >> 16) & 0xffff;
1027 co_unsigned8_t subidx = (map >> 8) & 0xff;
1028 co_unsigned8_t len = map & 0xff;
1029
1030 // Check the PDO length (in bits).
1031 if ((bits += len) > CAN_MAX_LEN * 8)
1032 return CO_SDO_AC_PDO_LEN;
1033
1034 // Check whether the sub-object exists and can
1035 // be mapped into a PDO.
1036 // clang-format off
1037 if ((ac = co_dev_chk_tpdo(
1038 pdo->dev, idx, subidx)))
1039 // clang-format on
1040 return ac;
1041 }
1042#if LELY_NO_CO_MPDO
1043 } else {
1044#else
1045 } else if (n != CO_PDO_MAP_SAM_MPDO
1046 && n != CO_PDO_MAP_DAM_MPDO) {
1047#endif
1048 return CO_SDO_AC_PARAM_VAL;
1049 }
1050
1051 pdo->map.n = n;
1052 } else {
1053 assert(type == CO_DEFTYPE_UNSIGNED32);
1054 co_unsigned32_t map = val.u32;
1055 co_unsigned32_t map_old = co_sub_get_val_u32(sub);
1056 if (map == map_old)
1057 return 0;
1058
1059 // The PDO mapping cannot be changed when the PDO is valid or
1060 // sub-index 0x00 is non-zero.
1061 if (valid || pdo->map.n)
1062 return CO_SDO_AC_PARAM_VAL;
1063
1064 if (map) {
1065 // See figure 73 (Structure of TPDO mapping) in CiA 301.
1066 co_unsigned16_t idx = (map >> 16) & 0xffff;
1067 co_unsigned8_t subidx = (map >> 8) & 0xff;
1068 // Check whether the sub-object exists and can be mapped
1069 // into a PDO.
1070 if ((ac = co_dev_chk_tpdo(pdo->dev, idx, subidx)))
1071 return ac;
1072 }
1073
1074 pdo->map.map[co_sub_get_subidx(sub) - 1] = map;
1075 }
1076
1077 co_sub_dn(sub, &val);
1078
1079 return 0;
1080}
1081
1082static int
1083co_tpdo_recv(const struct can_msg *msg, void *data)
1084{
1085 assert(msg);
1086 assert(msg->flags & CAN_FLAG_RTR);
1087 (void)msg;
1088 co_tpdo_t *pdo = data;
1089 assert(pdo);
1090
1091 // See table 72 (Description of TPDO transmission type) in CiA 301.
1092 switch (pdo->comm.trans) {
1093 case 0xfc: {
1094 uint_least32_t mask = (pdo->comm.cobid & CO_PDO_COBID_FRAME)
1095 ? CAN_MASK_EID
1096 : CAN_MASK_BID;
1097 // Ignore the RTR if no buffered CAN frame is available.
1098 if (pdo->msg.id != (pdo->comm.cobid & mask))
1099 break;
1100 co_tpdo_send_frame(pdo, &pdo->msg);
1101 break;
1102 }
1103 case 0xfd:
1104 // Start sampling.
1105 assert(pdo->sample_ind);
1106 pdo->sample_ind(pdo, pdo->sample_data);
1107 break;
1108 default: break;
1109 }
1110
1111 return 0;
1112}
1113
1114static int
1115co_tpdo_timer_event(const struct timespec *tp, void *data)
1116{
1117 (void)tp;
1118 co_tpdo_t *pdo = data;
1119 assert(pdo);
1120
1121 int errsv = get_errc();
1122 if (co_tpdo_event(pdo) == -1) {
1123 // Restart the event timer, even if we failed to send a PDO.
1125 set_errc(errsv);
1126 }
1127
1128 return 0;
1129}
1130
1131static int
1132co_tpdo_timer_swnd(const struct timespec *tp, void *data)
1133{
1134 (void)tp;
1135 co_tpdo_t *pdo = data;
1136 assert(pdo);
1137
1138 pdo->swnd = 1;
1139
1140 return 0;
1141}
1142
1143static int
1145{
1146 (void)data;
1147
1148 return co_tpdo_sample_res(pdo, 0);
1149}
1150
1151static int
1153{
1154 assert(pdo);
1155 assert(pdo->map.n <= 0x40);
1156 assert(msg);
1157
1158 *msg = (struct can_msg)CAN_MSG_INIT;
1159
1160 msg->id = pdo->comm.cobid;
1161 if (pdo->comm.cobid & CO_PDO_COBID_FRAME) {
1162 msg->id &= CAN_MASK_EID;
1163 msg->flags |= CAN_FLAG_IDE;
1164 } else {
1165 msg->id &= CAN_MASK_BID;
1166 }
1167
1168 size_t n = CAN_MAX_LEN;
1169 co_unsigned32_t ac = co_pdo_up(
1170 &pdo->map, pdo->dev, &pdo->req, msg->data, &n, 1);
1171 if (ac) {
1172 if (pdo->ind)
1173 pdo->ind(pdo, ac, NULL, 0, pdo->data);
1174 return -1;
1175 }
1176 msg->len = n;
1177
1178 return 0;
1179}
1180
1181static int
1182co_tpdo_send_frame(co_tpdo_t *pdo, const struct can_msg *msg)
1183{
1184 int result = can_net_send(pdo->net, msg);
1185 if (pdo->ind) {
1186 if (!result) {
1187 pdo->ind(pdo, 0, pdo->msg.data, pdo->msg.len,
1188 pdo->data);
1189 } else {
1190 pdo->ind(pdo, CO_SDO_AC_ERROR, NULL, 0, pdo->data);
1191 }
1192 }
1193 return result;
1194}
1195
1196#endif // !LELY_NO_CO_TPDO
@ 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_MAX_LEN
The maximum number of bytes in the payload of a CAN format frame.
Definition: msg.h:72
#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
co_unsigned8_t co_dev_get_id(const co_dev_t *dev)
Returns the node-ID of a CANopen device.
Definition: dev.c:197
#define CO_NUM_NODES
The maximum number of nodes in a CANopen network.
Definition: dev.h:56
This header file is part of the utilities library; it contains the byte order (endianness) function d...
void stle_u16(uint_least8_t dst[2], uint_least16_t x)
Stores a 16-bit unsigned integer in little-endian byte order.
Definition: endian.h:504
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_INVAL
Invalid argument.
Definition: errnum.h:132
@ ERRNUM_AGAIN
Resource unavailable, try again.
Definition: errnum.h:89
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
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Definition: errnum.h:424
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
void co_sdo_req_fini(struct co_sdo_req *req)
Finalizes a CANopen SDO upload/download request.
Definition: sdo.c:121
#define CO_SDO_AC_ERROR
SDO abort code: General error.
Definition: sdo.h:150
#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_TIMEOUT
SDO abort code: SDO protocol timed out.
Definition: sdo.h:66
#define CO_SDO_AC_NO_WRITE
SDO abort code: Attempt to write a read only object.
Definition: sdo.h:90
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_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:478
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_sub_t * co_obj_first_sub(const co_obj_t *obj)
Finds the first sub-object (with the lowest sub-index) in a CANopen object.
Definition: obj.c:249
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_sub_t * co_sub_next(const co_sub_t *sub)
Finds the next sub-object in a CANopen object.
Definition: obj.c:542
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
co_unsigned32_t co_pdo_up(const struct co_pdo_map_par *par, const co_dev_t *dev, struct co_sdo_req *req, uint_least8_t *buf, size_t *pn, int chk)
Reads mapped PDO values from the object dictionary through a local SDO upload request.
Definition: pdo.c:432
co_unsigned32_t co_sam_mpdo_up(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx, struct co_sdo_req *req, uint_least8_t buf[4])
Reads the value of the specified SAM-MPDO-mapped object from the local object dictionary through a lo...
Definition: pdo.c:483
#define CO_PDO_NUM_MAPS
The maximum number of mapped application objects in a single PDO.
Definition: pdo.h:34
co_unsigned32_t co_dev_chk_tpdo(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 Transmit-PDO.
Definition: pdo.c:130
#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:46
#define CO_PDO_COBID_VALID
The bit in the PDO COB-ID specifying whether the PDO exists and is valid.
Definition: pdo.h:37
#define CO_NUM_PDOS
The maximum number of Receive/Transmit-PDOs.
Definition: pdo.h:28
#define CO_PDO_MAP_DAM_MPDO
The value of sub-index 0 of the PDO mapping parameter record indicating a a destination address mode ...
Definition: pdo.h:58
#define CO_PDO_COBID_RTR
The bit in the PDO COB-ID specifying whether RTR is allowed.
Definition: pdo.h:40
#define CO_PDO_MAP_SAM_MPDO
The value of sub-index 0 of the PDO mapping parameter record indicating a a source address mode multi...
Definition: pdo.h:52
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....
This header file is part of the C11 and POSIX compatibility library; it includes <string....
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 Transmit-PDO.
Definition: tpdo.c:53
void * sample_data
A pointer to user-specified data for sample_ind.
Definition: tpdo.c:93
struct co_sdo_req req
The CANopen SDO upload request used for reading sub-objects.
Definition: tpdo.c:85
unsigned int swnd
A flag indicating the synchronous time window has expired.
Definition: tpdo.c:79
struct co_pdo_map_par map
The PDO mapping parameter.
Definition: tpdo.c:65
struct can_msg msg
A buffered CAN frame, used for RTR-only or event-driven TPDOs.
Definition: tpdo.c:73
can_recv_t * recv
A pointer to the CAN frame receiver.
Definition: tpdo.c:67
co_unsigned16_t num
The PDO number.
Definition: tpdo.c:59
struct co_pdo_comm_par comm
The PDO communication parameter.
Definition: tpdo.c:63
co_dev_t * dev
A pointer to a CANopen device.
Definition: tpdo.c:57
co_unsigned8_t sync
The SYNC start value.
Definition: tpdo.c:81
unsigned int event
A flag indicating the occurrence of an event.
Definition: tpdo.c:77
co_unsigned8_t cnt
The SYNC counter value.
Definition: tpdo.c:83
co_tpdo_ind_t * ind
A pointer to the indication function.
Definition: tpdo.c:87
can_net_t * net
A pointer to a CAN network interface.
Definition: tpdo.c:55
struct timespec inhibit
The time at which the next event-driven TPDO may be sent.
Definition: tpdo.c:75
void * data
A pointer to user-specified data for ind.
Definition: tpdo.c:89
int stopped
A flag specifying whether the Transmit-PDO service is stopped.
Definition: tpdo.c:61
co_tpdo_sample_ind_t * sample_ind
A pointer to the sampling indication function.
Definition: tpdo.c:91
can_timer_t * timer_event
A pointer to the CAN timer for events.
Definition: tpdo.c:69
can_timer_t * timer_swnd
A pointer to the CAN timer for the synchronous time window.
Definition: tpdo.c:71
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 PDO communication parameter record.
Definition: pdo.h:64
co_unsigned8_t sync
SYNC start value.
Definition: pdo.h:77
co_unsigned16_t inhibit
Inhibit time.
Definition: pdo.h:72
co_unsigned16_t event
Event timer.
Definition: pdo.h:75
co_unsigned32_t cobid
COB-ID.
Definition: pdo.h:68
co_unsigned8_t trans
Transmission type.
Definition: pdo.h:70
co_unsigned8_t n
Highest sub-index supported.
Definition: pdo.h:66
A PDO mapping parameter record.
Definition: pdo.h:90
co_unsigned8_t n
Number of mapped objects in PDO.
Definition: pdo.h:92
co_unsigned32_t map[CO_PDO_NUM_MAPS]
An array of objects to be mapped.
Definition: pdo.h:94
A CANopen SDO upload/download request.
Definition: sdo.h:181
int co_tpdo_is_stopped(const co_tpdo_t *pdo)
Retuns 1 if the specified Transmit-PDO service is stopped, and 0 if not.
Definition: tpdo.c:420
can_net_t * co_tpdo_get_net(const co_tpdo_t *pdo)
Returns a pointer to the CAN network of a Transmit-PDO.
Definition: tpdo.c:428
static void co_tpdo_init_recv(co_tpdo_t *pdo)
Initializes the CAN frame receiver of a Transmit-PDO service.
Definition: tpdo.c:802
void co_tpdo_set_sample_ind(co_tpdo_t *pdo, co_tpdo_sample_ind_t *ind, void *data)
Sets the indication function invoked when a Transmit-PDO starts sampling after the reception of a SYN...
Definition: tpdo.c:500
void co_tpdo_destroy(co_tpdo_t *tpdo)
Destroys a CANopen Transmit-PDO service.
Definition: tpdo.c:330
static co_unsigned32_t co_1800_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
The download indication function for (all sub-objects of) CANopen objects 1800..19FF (TPDO communicat...
Definition: tpdo.c:856
int co_tpdo_event(co_tpdo_t *pdo)
Triggers the transmission of an acyclic or event-driven PDO.
Definition: tpdo.c:509
void co_tpdo_get_sample_ind(const co_tpdo_t *pdo, co_tpdo_sample_ind_t **pind, void **pdata)
Retrieves the indication function invoked when a Transmit-PDO starts sampling after the reception of ...
Definition: tpdo.c:488
static void co_tpdo_init_timer_event(co_tpdo_t *pdo)
Initializes the CAN timer for events of a Transmit-PDO service.
Definition: tpdo.c:825
int co_sam_mpdo_event(co_tpdo_t *pdo, co_unsigned16_t idx, co_unsigned8_t subidx)
Triggers the transmission of a DAM-MPDO.
Definition: tpdo.c:730
static int co_tpdo_timer_swnd(const struct timespec *tp, void *data)
The CAN timer callback function for the synchronous time window of a Transmit-PDO service.
Definition: tpdo.c:1132
const struct co_pdo_map_par * co_tpdo_get_map_par(const co_tpdo_t *pdo)
Returns a pointer to the PDO mapping parameter record of a Transmit-PDO.
Definition: tpdo.c:460
int co_tpdo_sample_res(co_tpdo_t *pdo, co_unsigned32_t ac)
Indicates the result of the sampling step after the reception of a SYNC event.
Definition: tpdo.c:614
static int co_tpdo_timer_event(const struct timespec *tp, void *data)
The CAN timer callback function for events of a Transmit-PDO service.
Definition: tpdo.c:1115
const struct co_pdo_comm_par * co_tpdo_get_comm_par(const co_tpdo_t *pdo)
Returns a pointer to the PDO communication parameter record of a Transmit-PDO.
Definition: tpdo.c:452
co_tpdo_t * co_tpdo_create(can_net_t *net, co_dev_t *dev, co_unsigned16_t num)
Creates a new CANopen Transmit-PDO service.
Definition: tpdo.c:303
void co_tpdo_get_next(const co_tpdo_t *pdo, struct timespec *tp)
Retrieves the time at which the next event-driven TPDO may be sent.
Definition: tpdo.c:655
void co_tpdo_get_ind(const co_tpdo_t *pdo, co_tpdo_ind_t **pind, void **pdata)
Retrieves the indication function invoked when a Transmit-PDO is sent or an error occurs.
Definition: tpdo.c:468
static int co_tpdo_recv(const struct can_msg *msg, void *data)
The CAN receive callback function for a Transmit-PDO service.
Definition: tpdo.c:1083
int co_dam_mpdo_event(co_tpdo_t *pdo, co_unsigned8_t id, co_unsigned16_t idx, co_unsigned8_t subidx, const co_unsigned8_t data[4])
Triggers the transmission of a DAM-MPDO.
Definition: tpdo.c:666
void co_tpdo_set_ind(co_tpdo_t *pdo, co_tpdo_ind_t *ind, void *data)
Sets the indication function invoked when a Transmit-PDO is sent or an error occurs.
Definition: tpdo.c:479
int co_tpdo_start(co_tpdo_t *pdo)
Starts a Transmit-PDO service.
Definition: tpdo.c:340
static co_unsigned32_t co_1a00_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
The download indication function for (all sub-objects of) CANopen objects 1A00..1BFF (TPDO mapping pa...
Definition: tpdo.c:987
int co_tpdo_sync(co_tpdo_t *pdo, co_unsigned8_t cnt)
Triggers the transmission of a synchronous PDO.
Definition: tpdo.c:565
co_dev_t * co_tpdo_get_dev(const co_tpdo_t *pdo)
Returns a pointer to the CANopen device of a Transmit-PDO.
Definition: tpdo.c:436
static int default_sample_ind(co_tpdo_t *pdo, void *data)
The default sampling indication function.
Definition: tpdo.c:1144
void co_tpdo_stop(co_tpdo_t *pdo)
Stops a Transmit-PDO service.
Definition: tpdo.c:392
static int co_tpdo_init_frame(co_tpdo_t *pdo, struct can_msg *msg)
Initializes a CAN frame to be sent by a Transmit-PDO service.
Definition: tpdo.c:1152
co_unsigned16_t co_tpdo_get_num(const co_tpdo_t *pdo)
Returns the PDO number of a Transmit-PDO.
Definition: tpdo.c:444
static int co_tpdo_send_frame(co_tpdo_t *pdo, const struct can_msg *msg)
Sends a CAN frame from a Transmit-PDO service and invokes the indication function.
Definition: tpdo.c:1182
static void co_tpdo_init_timer_swnd(co_tpdo_t *pdo)
Initializes the CAN timer for the synchronous time window of a Transmit-PDO service.
Definition: tpdo.c:837
This header file is part of the CANopen library; it contains the Transmit-PDO declarations.
int co_tpdo_sample_ind_t(co_tpdo_t *pdo, void *data)
The type of a CANopen Transmit-PDO sampling indication function, invoked when the device starts sampl...
Definition: tpdo.h:60
void co_tpdo_ind_t(co_tpdo_t *pdo, co_unsigned32_t ac, const void *ptr, size_t n, void *data)
The type of a CANopen Transmit-PDO indication function, invoked when a PDO is sent or an error occurs...
Definition: tpdo.h:46
#define CO_DEFTYPE_UNSIGNED16
The data type (and object index) of a 16-bit unsigned integer.
Definition: type.h:47
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.
int timespec_cmp(const void *p1, const void *p2)
Compares two times.
Definition: time.h:251
void timespec_add_usec(struct timespec *tp, uint_least64_t usec)
Adds usec microseconds to the time at tp.
Definition: time.h:149
This header file is part of the CANopen library; it contains the CANopen value declarations.