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 
53 struct __co_tpdo {
59  co_unsigned16_t num;
61  int stopped;
63  struct co_pdo_comm_par comm;
65  struct co_pdo_map_par map;
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;
85  struct co_sdo_req req;
89  void *data;
93  void *sample_data;
94 };
95 
101 static void co_tpdo_init_recv(co_tpdo_t *pdo);
102 
108 static void co_tpdo_init_timer_event(co_tpdo_t *pdo);
109 
114 static void co_tpdo_init_timer_swnd(co_tpdo_t *pdo);
115 
122 static co_unsigned32_t co_1800_dn_ind(
123  co_sub_t *sub, struct co_sdo_req *req, void *data);
124 
131 static co_unsigned32_t co_1a00_dn_ind(
132  co_sub_t *sub, struct co_sdo_req *req, void *data);
133 
139 static int co_tpdo_recv(const struct can_msg *msg, void *data);
140 
146 static int co_tpdo_timer_event(const struct timespec *tp, void *data);
147 
154 static int co_tpdo_timer_swnd(const struct timespec *tp, void *data);
155 
157 static int default_sample_ind(co_tpdo_t *pdo, void *data);
158 
168 static int co_tpdo_init_frame(co_tpdo_t *pdo, struct can_msg *msg);
169 
179 static int co_tpdo_send_frame(co_tpdo_t *pdo, const struct can_msg *msg);
180 
181 void *
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 
192 void
193 __co_tpdo_free(void *ptr)
194 {
195  free(ptr);
196 }
197 
198 struct __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  }
235  can_recv_set_func(pdo->recv, &co_tpdo_recv, pdo);
236 
237  pdo->timer_event = can_timer_create();
238  if (!pdo->timer_event) {
239  errc = get_errc();
240  goto error_create_timer_event;
241  }
243 
244  pdo->timer_swnd = can_timer_create();
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);
275 error_start:
277 error_create_timer_swnd:
279 error_create_timer_event:
280  can_recv_destroy(pdo->recv);
281 error_create_recv:
282 error_param:
283  set_errc(errc);
284  return NULL;
285 }
286 
287 void
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 
299  can_recv_destroy(pdo->recv);
300 }
301 
302 co_tpdo_t *
303 co_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 
322 error_init_pdo:
323  __co_tpdo_free(pdo);
324 error_alloc_pdo:
325  set_errc(errc);
326  return NULL;
327 }
328 
329 void
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 
339 int
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 
383  co_tpdo_init_recv(pdo);
385 
386  pdo->stopped = 0;
387 
388  return 0;
389 }
390 
391 void
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 
419 int
421 {
422  assert(pdo);
423 
424  return pdo->stopped;
425 }
426 
427 can_net_t *
429 {
430  assert(pdo);
431 
432  return pdo->net;
433 }
434 
435 co_dev_t *
437 {
438  assert(pdo);
439 
440  return pdo->dev;
441 }
442 
443 co_unsigned16_t
445 {
446  assert(pdo);
447 
448  return pdo->num;
449 }
450 
451 const struct co_pdo_comm_par *
453 {
454  assert(pdo);
455 
456  return &pdo->comm;
457 }
458 
459 const struct co_pdo_map_par *
461 {
462  assert(pdo);
463 
464  return &pdo->map;
465 }
466 
467 void
468 co_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 
478 void
479 co_tpdo_set_ind(co_tpdo_t *pdo, co_tpdo_ind_t *ind, void *data)
480 {
481  assert(pdo);
482 
483  pdo->ind = ind;
484  pdo->data = data;
485 }
486 
487 void
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 
499 void
501 {
502  assert(pdo);
503 
504  pdo->sample_ind = ind ? ind : &default_sample_ind;
505  pdo->sample_data = ind ? data : NULL;
506 }
507 
508 int
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 
564 int
565 co_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 
613 int
614 co_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)
635  ac = CO_SDO_AC_TIMEOUT;
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 
654 void
655 co_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 
665 int
666 co_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 
729 int
730 co_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 
801 static 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;
813  flags |= CAN_FLAG_IDE;
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 
824 static 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 
836 static 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 
855 static co_unsigned32_t
856 co_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 
908  co_tpdo_init_recv(pdo);
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 
933  co_tpdo_init_recv(pdo);
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 
986 static co_unsigned32_t
987 co_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 
1082 static int
1083 co_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 
1114 static int
1115 co_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 
1131 static int
1132 co_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 
1143 static int
1145 {
1146  (void)data;
1147 
1148  return co_tpdo_sample_res(pdo, 0);
1149 }
1150 
1151 static 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 
1181 static int
1182 co_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_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
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 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
void can_net_get_time(const can_net_t *net, struct timespec *tp)
Retrieves the current time of a CAN network interface.
Definition: net.c:196
void can_timer_set_func(can_timer_t *timer, can_timer_func_t *func, void *data)
Sets the callback function invoked when a CAN timer is triggered.
Definition: net.c:422
can_recv_t * can_recv_create(void)
Creates a new CAN frame receiver.
Definition: net.c:533
void can_recv_stop(can_recv_t *recv)
Stops a CAN frame receiver from processing frames and unregisters it with the network interface.
Definition: net.c:609
void can_recv_set_func(can_recv_t *recv, can_recv_func_t *func, void *data)
Sets the callback function used to process CAN frames with a receiver.
Definition: net.c:578
void can_recv_destroy(can_recv_t *recv)
Destroys a CAN frame receiver.
Definition: net.c:558
can_timer_t * can_timer_create(void)
Creates a new CAN timer.
Definition: net.c:376
void can_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
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_sub_t * co_sub_next(const co_sub_t *sub)
Finds the next sub-object in a CANopen object.
Definition: obj.c:542
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
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
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
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
static void co_tpdo_init_recv(co_tpdo_t *pdo)
Initializes the CAN frame receiver of a Transmit-PDO service.
Definition: tpdo.c:802
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
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
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
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
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
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
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
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
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.