Lely core libraries  2.2.5
tpdo.c
Go to the documentation of this file.
1 
24 #include "co.h"
25 
26 #ifndef LELY_NO_CO_TPDO
27 
28 #include <lely/co/dev.h>
29 #include <lely/co/obj.h>
30 #include <lely/co/sdo.h>
31 #include <lely/co/tpdo.h>
32 #include <lely/co/val.h>
33 #include <lely/util/errnum.h>
34 #include <lely/util/time.h>
35 
36 #include <assert.h>
37 #include <stdlib.h>
38 
40 struct __co_tpdo {
46  co_unsigned16_t num;
56  struct can_msg msg;
58  struct timespec inhibit;
60  unsigned int event : 1;
62  co_unsigned8_t sync;
64  co_unsigned8_t cnt;
66  struct co_sdo_req req;
70  void *data;
71 };
72 
80 static int co_tpdo_init_recv(co_tpdo_t *pdo);
81 
89 static int co_tpdo_init_timer_event(co_tpdo_t *pdo);
90 
97 static co_unsigned32_t co_1800_dn_ind(
98  co_sub_t *sub, struct co_sdo_req *req, void *data);
99 
106 static co_unsigned32_t co_1a00_dn_ind(
107  co_sub_t *sub, struct co_sdo_req *req, void *data);
108 
114 static int co_tpdo_recv(const struct can_msg *msg, void *data);
115 
121 static int co_tpdo_timer_event(const struct timespec *tp, void *data);
122 
132 static int co_tpdo_init_frame(co_tpdo_t *pdo, struct can_msg *msg);
133 
143 static int co_tpdo_send_frame(co_tpdo_t *pdo, const struct can_msg *msg);
144 
145 void *
146 __co_tpdo_alloc(void)
147 {
148  void *ptr = malloc(sizeof(struct __co_tpdo));
149  if (!ptr)
150  set_errc(errno2c(errno));
151  return ptr;
152 }
153 
154 void
155 __co_tpdo_free(void *ptr)
156 {
157  free(ptr);
158 }
159 
160 struct __co_tpdo *
161 __co_tpdo_init(struct __co_tpdo *pdo, can_net_t *net, co_dev_t *dev,
162  co_unsigned16_t num)
163 {
164  assert(pdo);
165  assert(net);
166  assert(dev);
167 
168  int errc = 0;
169 
170  if (!num || num > 512) {
171  errc = errnum2c(ERRNUM_INVAL);
172  goto error_param;
173  }
174 
175  // Find the PDO parameters in the object dictionary.
176  co_obj_t *obj_1800 = co_dev_find_obj(dev, 0x1800 + num - 1);
177  co_obj_t *obj_1a00 = co_dev_find_obj(dev, 0x1a00 + num - 1);
178  if (!obj_1800 || !obj_1a00) {
179  errc = errnum2c(ERRNUM_INVAL);
180  goto error_param;
181  }
182 
183  pdo->net = net;
184  pdo->dev = dev;
185  pdo->num = num;
186 
187  // Copy the PDO communication parameter record.
188  memset(&pdo->comm, 0, sizeof(pdo->comm));
189  memcpy(&pdo->comm, co_obj_addressof_val(obj_1800),
190  MIN(co_obj_sizeof_val(obj_1800), sizeof(pdo->comm)));
191 
192  // Copy the PDO mapping parameter record.
193  memset(&pdo->map, 0, sizeof(pdo->map));
194  memcpy(&pdo->map, co_obj_addressof_val(obj_1a00),
195  MIN(co_obj_sizeof_val(obj_1a00), sizeof(pdo->map)));
196 
197  pdo->recv = NULL;
198 
199  pdo->timer_event = NULL;
200 
201  pdo->msg = (struct can_msg)CAN_MSG_INIT;
202 
203  can_net_get_time(pdo->net, &pdo->inhibit);
204  pdo->event = 0;
205  pdo->sync = pdo->comm.sync;
206  pdo->cnt = 0;
207 
208  co_sdo_req_init(&pdo->req);
209 
210  pdo->ind = NULL;
211  pdo->data = NULL;
212 
213  // Set the download indication functions PDO communication parameter
214  // record.
215  co_obj_set_dn_ind(obj_1800, &co_1800_dn_ind, pdo);
216 
217  // Set the download indication functions PDO mapping parameter record.
218  co_obj_set_dn_ind(obj_1a00, &co_1a00_dn_ind, pdo);
219 
220  if (co_tpdo_init_recv(pdo) == -1) {
221  errc = get_errc();
222  goto error_init_recv;
223  }
224 
225  if (co_tpdo_init_timer_event(pdo) == -1) {
226  errc = get_errc();
227  goto error_init_timer_event;
228  }
229 
230  return pdo;
231 
232  // can_timer_destroy(pdo->timer_event);
233 error_init_timer_event:
234  can_recv_destroy(pdo->recv);
235 error_init_recv:
236  co_obj_set_dn_ind(obj_1a00, NULL, NULL);
237  co_obj_set_dn_ind(obj_1800, NULL, NULL);
238 error_param:
239  set_errc(errc);
240  return NULL;
241 }
242 
243 void
244 __co_tpdo_fini(struct __co_tpdo *pdo)
245 {
246  assert(pdo);
247  assert(pdo->num >= 1 && pdo->num <= 512);
248 
249  // Remove the download indication functions PDO mapping parameter
250  // record.
251  co_obj_t *obj_1a00 = co_dev_find_obj(pdo->dev, 0x1a00 + pdo->num - 1);
252  assert(obj_1a00);
253  co_obj_set_dn_ind(obj_1a00, NULL, NULL);
254 
255  // Remove the download indication functions PDO communication parameter
256  // record.
257  co_obj_t *obj_1800 = co_dev_find_obj(pdo->dev, 0x1800 + pdo->num - 1);
258  assert(obj_1800);
259  co_obj_set_dn_ind(obj_1800, NULL, NULL);
260 
261  co_sdo_req_fini(&pdo->req);
262 
264 
265  can_recv_destroy(pdo->recv);
266 }
267 
268 co_tpdo_t *
269 co_tpdo_create(can_net_t *net, co_dev_t *dev, co_unsigned16_t num)
270 {
271  trace("creating Transmit-PDO %d", num);
272 
273  int errc = 0;
274 
275  co_tpdo_t *pdo = __co_tpdo_alloc();
276  if (!pdo) {
277  errc = get_errc();
278  goto error_alloc_pdo;
279  }
280 
281  if (!__co_tpdo_init(pdo, net, dev, num)) {
282  errc = get_errc();
283  goto error_init_pdo;
284  }
285 
286  return pdo;
287 
288 error_init_pdo:
289  __co_tpdo_free(pdo);
290 error_alloc_pdo:
291  set_errc(errc);
292  return NULL;
293 }
294 
295 void
297 {
298  if (tpdo) {
299  trace("destroying Transmit-PDO %d", tpdo->num);
300  __co_tpdo_fini(tpdo);
301  __co_tpdo_free(tpdo);
302  }
303 }
304 
305 can_net_t *
307 {
308  assert(pdo);
309 
310  return pdo->net;
311 }
312 
313 co_dev_t *
315 {
316  assert(pdo);
317 
318  return pdo->dev;
319 }
320 
321 co_unsigned16_t
323 {
324  assert(pdo);
325 
326  return pdo->num;
327 }
328 
329 const struct co_pdo_comm_par *
331 {
332  assert(pdo);
333 
334  return &pdo->comm;
335 }
336 
337 const struct co_pdo_map_par *
339 {
340  assert(pdo);
341 
342  return &pdo->map;
343 }
344 
345 void
346 co_tpdo_get_ind(const co_tpdo_t *pdo, co_tpdo_ind_t **pind, void **pdata)
347 {
348  assert(pdo);
349 
350  if (pind)
351  *pind = pdo->ind;
352  if (pdata)
353  *pdata = pdo->data;
354 }
355 
356 void
358 {
359  assert(pdo);
360 
361  pdo->ind = ind;
362  pdo->data = data;
363 }
364 
365 int
367 {
368  assert(pdo);
369 
370  // Check whether the PDO exists and is valid.
371  if (pdo->comm.cobid & CO_PDO_COBID_VALID)
372  return 0;
373 
374  switch (pdo->comm.trans) {
375  case 0x00: pdo->event = 1; break;
376  case 0xfd:
377  if (co_tpdo_init_frame(pdo, &pdo->msg) == -1)
378  return -1;
379  break;
380  case 0xfe:
381  case 0xff:
382  if (pdo->comm.inhibit) {
383  // Check whether the inhibit time has passed.
384  struct timespec now;
385  can_net_get_time(pdo->net, &now);
386  if (timespec_cmp(&now, &pdo->inhibit) < 0) {
388  return -1;
389  }
390  pdo->inhibit = now;
391  }
392 
393  // In case of an event-driven TPDO, send the frame right away.
394  if (co_tpdo_init_frame(pdo, &pdo->msg) == -1)
395  return -1;
396  if (co_tpdo_send_frame(pdo, &pdo->msg) == -1)
397  return -1;
398 
399  if (pdo->comm.inhibit)
401  &pdo->inhibit, pdo->comm.inhibit * 100);
402  break;
403  default:
404  // Ignore events if the transmission type is synchronous.
405  return 0;
406  }
407 
408  return co_tpdo_init_timer_event(pdo);
409 }
410 
411 int
412 co_tpdo_sync(co_tpdo_t *pdo, co_unsigned8_t cnt)
413 {
414  assert(pdo);
415 
416  if (cnt > 240) {
418  return -1;
419  }
420 
421  // Check whether the PDO exists and is valid.
422  if (pdo->comm.cobid & CO_PDO_COBID_VALID)
423  return 0;
424 
425  // Ignore SYNC objects if the transmission type is not synchronous.
426  if (pdo->comm.trans > 0xf0 && pdo->comm.trans != 0xfc)
427  return 0;
428 
429  // Wait for the SYNC counter to equal the SYNC start value.
430  if (pdo->sync && cnt) {
431  if (pdo->sync != cnt)
432  return 0;
433  pdo->sync = 0;
434  pdo->cnt = 0;
435  }
436 
437  if (!pdo->comm.trans) {
438  // In case of a synchronous (acyclic) TPDO, do nothing unless an
439  // event occurred.
440  if (!pdo->event)
441  return 0;
442  pdo->event = 0;
443  } else if (pdo->comm.trans <= 0xf0) {
444  // In case of a synchronous (cyclic) TPDO, do nothing unless the
445  // n-th SYNC object has been received.
446  if (++pdo->cnt < pdo->comm.trans)
447  return 0;
448  pdo->cnt = 0;
449  }
450 
451  if (co_tpdo_init_frame(pdo, &pdo->msg) == -1)
452  return -1;
453 
454  // Send a synchronous TPDO right away.
455  if (pdo->comm.trans <= 0xf0 && co_tpdo_send_frame(pdo, &pdo->msg) == -1)
456  return -1;
457 
458  return 0;
459 }
460 
461 void
462 co_tpdo_get_next(const co_tpdo_t *pdo, struct timespec *tp)
463 {
464  assert(pdo);
465 
466  if (tp)
467  *tp = pdo->inhibit;
468 }
469 
470 static int
472 {
473  assert(pdo);
474 
475  if (!(pdo->comm.cobid & CO_PDO_COBID_VALID)
476  && !(pdo->comm.cobid & CO_PDO_COBID_RTR)) {
477  if (!pdo->recv) {
478  pdo->recv = can_recv_create();
479  if (!pdo->recv)
480  return -1;
481  can_recv_set_func(pdo->recv, &co_tpdo_recv, pdo);
482  }
483  // Register the receiver under the specified CAN-ID.
484  uint_least32_t id = pdo->comm.cobid;
485  uint_least8_t flags = CAN_FLAG_RTR;
486  if (id & CO_PDO_COBID_FRAME) {
487  id &= CAN_MASK_EID;
488  flags |= CAN_FLAG_IDE;
489  } else {
490  id &= CAN_MASK_BID;
491  }
492  can_recv_start(pdo->recv, pdo->net, id, flags);
493  } else if (pdo->recv) {
494  // Stop the receiver unless the TPDO is valid and allows RTR.
495  can_recv_destroy(pdo->recv);
496  pdo->recv = NULL;
497  }
498 
499  return 0;
500 }
501 
502 static int
504 {
505  assert(pdo);
506 
507  if (!(pdo->comm.cobid & CO_PDO_COBID_VALID) && pdo->comm.trans >= 0xfe
508  && pdo->comm.event) {
509  if (!pdo->timer_event) {
510  pdo->timer_event = can_timer_create();
511  if (!pdo->timer_event)
512  return -1;
514  &co_tpdo_timer_event, pdo);
515  }
516  // Reset the event timer.
517  can_timer_timeout(pdo->timer_event, pdo->net, pdo->comm.event);
518  } else if (pdo->timer_event) {
520  pdo->timer_event = NULL;
521  }
522 
523  return 0;
524 }
525 
526 static co_unsigned32_t
528 {
529  assert(sub);
530  assert(req);
531  co_tpdo_t *pdo = data;
532  assert(pdo);
533  assert(co_obj_get_idx(co_sub_get_obj(sub)) == 0x1800 + pdo->num - 1);
534 
535  co_unsigned32_t ac = 0;
536 
537  co_unsigned16_t type = co_sub_get_type(sub);
538  union co_val val;
539  if (co_sdo_req_dn_val(req, type, &val, &ac) == -1)
540  return ac;
541 
542  switch (co_sub_get_subidx(sub)) {
543  case 0: ac = CO_SDO_AC_NO_WRITE; goto error;
544  case 1: {
545  assert(type == CO_DEFTYPE_UNSIGNED32);
546  co_unsigned32_t cobid = val.u32;
547  co_unsigned32_t cobid_old = co_sub_get_val_u32(sub);
548  if (cobid == cobid_old)
549  goto error;
550 
551  // The CAN-ID cannot be changed when the PDO is and remains
552  // valid.
553  int valid = !(cobid & CO_PDO_COBID_VALID);
554  int valid_old = !(cobid_old & CO_PDO_COBID_VALID);
555  uint_least32_t canid = cobid & CAN_MASK_EID;
556  uint_least32_t canid_old = cobid_old & CAN_MASK_EID;
557  if (valid && valid_old && canid != canid_old) {
558  ac = CO_SDO_AC_PARAM_VAL;
559  goto error;
560  }
561 
562  // A 29-bit CAN-ID is only valid if the frame bit is set.
563  if (!(cobid & CO_PDO_COBID_FRAME)
564  && (cobid & (CAN_MASK_EID ^ CAN_MASK_BID))) {
565  ac = CO_SDO_AC_PARAM_VAL;
566  goto error;
567  }
568 
569  pdo->comm.cobid = cobid;
570 
571  if (valid && !valid_old) {
572  can_net_get_time(pdo->net, &pdo->inhibit);
573  pdo->event = 0;
574  pdo->sync = pdo->comm.sync;
575  pdo->cnt = 0;
576  }
577 
578  pdo->msg = (struct can_msg)CAN_MSG_INIT;
579  pdo->event = 0;
580 
581  co_tpdo_init_recv(pdo);
583  break;
584  }
585  case 2: {
586  assert(type == CO_DEFTYPE_UNSIGNED8);
587  co_unsigned8_t trans = val.u8;
588  co_unsigned8_t trans_old = co_sub_get_val_u8(sub);
589  if (trans == trans_old)
590  goto error;
591 
592  // Transmission types 0xF1..0xFB are reserved.
593  if (trans > 0xf0 && trans < 0xfc) {
594  ac = CO_SDO_AC_PARAM_VAL;
595  goto error;
596  }
597 
598  // Check whether RTR is allowed on this PDO.
599  if ((trans == 0xfc || trans == 0xfd)
600  && (pdo->comm.cobid & CO_PDO_COBID_RTR)) {
601  ac = CO_SDO_AC_PARAM_VAL;
602  goto error;
603  }
604 
605  pdo->comm.trans = trans;
606 
607  co_tpdo_init_recv(pdo);
608  break;
609  }
610  case 3: {
611  assert(type == CO_DEFTYPE_UNSIGNED16);
612  co_unsigned16_t inhibit = val.u16;
613  co_unsigned16_t inhibit_old = co_sub_get_val_u16(sub);
614  if (inhibit == inhibit_old)
615  goto error;
616 
617  // The inhibit time cannot be changed while the PDO exists and
618  // is valid.
619  if (!(pdo->comm.cobid & CO_PDO_COBID_VALID)) {
620  ac = CO_SDO_AC_PARAM_VAL;
621  goto error;
622  }
623 
624  pdo->comm.inhibit = inhibit;
625  break;
626  }
627  case 5: {
628  assert(type == CO_DEFTYPE_UNSIGNED16);
629  co_unsigned16_t event = val.u16;
630  co_unsigned16_t event_old = co_sub_get_val_u16(sub);
631  if (event == event_old)
632  goto error;
633 
634  pdo->comm.event = event;
635 
637  break;
638  }
639  case 6: {
640  assert(type == CO_DEFTYPE_UNSIGNED8);
641  co_unsigned8_t sync = val.u8;
642  co_unsigned8_t sync_old = co_sub_get_val_u8(sub);
643  if (sync == sync_old)
644  goto error;
645 
646  // The SYNC start value cannot be changed while the PDO exists
647  // and is valid.
648  if (!(pdo->comm.cobid & CO_PDO_COBID_VALID)) {
649  ac = CO_SDO_AC_PARAM_VAL;
650  goto error;
651  }
652 
653  pdo->comm.sync = sync;
654  break;
655  }
656  default: ac = CO_SDO_AC_NO_SUB; goto error;
657  }
658 
659  co_sub_dn(sub, &val);
660 error:
661  co_val_fini(type, &val);
662  return ac;
663 }
664 
665 static co_unsigned32_t
667 {
668  assert(sub);
669  assert(req);
670  co_tpdo_t *pdo = data;
671  assert(pdo);
672  assert(co_obj_get_idx(co_sub_get_obj(sub)) == 0x1a00 + pdo->num - 1);
673 
674  co_unsigned32_t ac = 0;
675 
676  co_unsigned16_t type = co_sub_get_type(sub);
677  union co_val val;
678  if (co_sdo_req_dn_val(req, type, &val, &ac) == -1)
679  return ac;
680 
681  int valid = !(pdo->comm.cobid & CO_PDO_COBID_VALID);
682 
683  if (!co_sub_get_subidx(sub)) {
684  assert(type == CO_DEFTYPE_UNSIGNED8);
685  co_unsigned8_t n = val.u8;
686  co_unsigned8_t n_old = co_sub_get_val_u8(sub);
687  if (n == n_old)
688  goto error;
689 
690  // The PDO mapping cannot be changed when the PDO is valid.
691  if (valid || n > 0x40) {
692  ac = CO_SDO_AC_PARAM_VAL;
693  goto error;
694  }
695 
696  size_t bits = 0;
697  for (size_t i = 1; i <= n; i++) {
698  co_unsigned32_t map = pdo->map.map[i - 1];
699  if (!map)
700  continue;
701 
702  co_unsigned16_t idx = (map >> 16) & 0xffff;
703  co_unsigned8_t subidx = (map >> 8) & 0xff;
704  co_unsigned8_t len = map & 0xff;
705 
706  // Check the PDO length.
707  if ((bits += len) > CAN_MAX_LEN * 8) {
708  ac = CO_SDO_AC_PDO_LEN;
709  goto error;
710  }
711 
712  // Check whether the sub-object exists and can be mapped
713  // into a PDO.
714  ac = co_dev_chk_tpdo(pdo->dev, idx, subidx);
715  if (ac)
716  goto error;
717  }
718 
719  pdo->map.n = n;
720  } else {
721  assert(type == CO_DEFTYPE_UNSIGNED32);
722  co_unsigned32_t map = val.u32;
723  co_unsigned32_t map_old = co_sub_get_val_u32(sub);
724  if (map == map_old)
725  goto error;
726 
727  // The PDO mapping cannot be changed when the PDO is valid or
728  // sub-index 0x00 is non-zero.
729  if (valid || pdo->map.n) {
730  ac = CO_SDO_AC_PARAM_VAL;
731  goto error;
732  }
733 
734  if (map) {
735  co_unsigned16_t idx = (map >> 16) & 0xffff;
736  co_unsigned8_t subidx = (map >> 8) & 0xff;
737  // Check whether the sub-object exists and can be mapped
738  // into a PDO.
739  ac = co_dev_chk_tpdo(pdo->dev, idx, subidx);
740  if (ac)
741  goto error;
742  }
743 
744  pdo->map.map[co_sub_get_subidx(sub) - 1] = map;
745  }
746 
747  co_sub_dn(sub, &val);
748 error:
749  co_val_fini(type, &val);
750  return ac;
751 }
752 
753 static int
754 co_tpdo_recv(const struct can_msg *msg, void *data)
755 {
756  assert(msg);
757  assert(msg->flags & CAN_FLAG_RTR);
758  (void)msg;
759  co_tpdo_t *pdo = data;
760  assert(pdo);
761 
762  switch (pdo->comm.trans) {
763  case 0xfc: {
764  uint_least32_t mask = (pdo->comm.cobid & CO_PDO_COBID_FRAME)
765  ? CAN_MASK_EID
766  : CAN_MASK_BID;
767  // Ignore the RTR if no buffered CAN frame is available.
768  if (pdo->msg.id != (pdo->comm.cobid & mask))
769  break;
770  co_tpdo_send_frame(pdo, &pdo->msg);
771  break;
772  }
773  case 0xfd:
774  if (!co_tpdo_init_frame(pdo, &pdo->msg))
775  co_tpdo_send_frame(pdo, &pdo->msg);
776  break;
777  default: break;
778  }
779 
780  return 0;
781 }
782 
783 static int
784 co_tpdo_timer_event(const struct timespec *tp, void *data)
785 {
786  (void)tp;
787  co_tpdo_t *pdo = data;
788  assert(pdo);
789 
790  co_tpdo_event(pdo);
791 
792  return 0;
793 }
794 
795 static int
797 {
798  assert(pdo);
799  assert(msg);
800 
801  *msg = (struct can_msg)CAN_MSG_INIT;
802  msg->id = pdo->comm.cobid;
803  if (pdo->comm.cobid & CO_PDO_COBID_FRAME) {
804  msg->id &= CAN_MASK_EID;
805  msg->flags |= CAN_FLAG_IDE;
806  } else {
807  msg->id &= CAN_MASK_BID;
808  }
809 
810  size_t n = CAN_MAX_LEN;
811  co_unsigned32_t ac = co_pdo_up(
812  &pdo->map, pdo->dev, &pdo->req, msg->data, &n);
813  if (ac) {
814  if (pdo->ind)
815  pdo->ind(pdo, ac, NULL, 0, pdo->data);
816  return -1;
817  }
818  msg->len = n;
819 
820  return 0;
821 }
822 
823 static int
825 {
826  int result = can_net_send(pdo->net, msg);
827  if (pdo->ind) {
828  if (!result) {
829  pdo->ind(pdo, 0, pdo->msg.data, pdo->msg.len,
830  pdo->data);
831  } else {
832  pdo->ind(pdo, CO_SDO_AC_ERROR, NULL, 0, pdo->data);
833  }
834  }
835  return result;
836 }
837 
838 #endif // !LELY_NO_CO_TPDO
A CANopen SDO upload/download request.
Definition: sdo.h:178
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:527
int co_tpdo_event(co_tpdo_t *pdo)
Triggers the transmission of an acyclic or event-driven PDO.
Definition: tpdo.c:366
A PDO mapping parameter record.
Definition: pdo.h:69
A CAN or CAN FD format frame.
Definition: msg.h:87
co_unsigned8_t sync
SYNC start value.
Definition: pdo.h:56
void co_tpdo_destroy(co_tpdo_t *tpdo)
Destroys a CANopen Transmit-PDO service.
Definition: tpdo.c:296
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:372
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:462
uint_least32_t id
The identifier (11 or 29 bits, depending on the CAN_FLAG_IDE flag).
Definition: msg.h:89
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:317
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:754
A CAN network interface.
Definition: net.c:37
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
#define CO_PDO_COBID_RTR
The bit in the PDO COB-ID specifying whether RTR is allowed.
Definition: pdo.h:31
A CANopen sub-object.
Definition: obj.h:54
This header file is part of the CANopen library; it contains the Transmit-PDO declarations.
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
co_tpdo_ind_t * ind
A pointer to the indication function.
Definition: tpdo.c:68
int errnum2c(errnum_t errnum)
Transforms a platform-independent error number to a native error code.
Definition: errnum.c:825
can_timer_t * timer_event
A pointer to the CAN timer for events.
Definition: tpdo.c:54
A CANopen Transmit-PDO.
Definition: tpdo.c:40
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Definition: errnum.h:375
co_unsigned8_t n
Number of mapped objects in PDO.
Definition: pdo.h:71
#define CO_SDO_AC_PARAM_VAL
SDO abort code: Invalid value for parameter (download only).
Definition: sdo.h:135
A union of the CANopen static data types.
Definition: val.h:163
can_recv_t * recv
A pointer to the CAN frame receiver.
Definition: tpdo.c:52
co_unsigned8_t sync
The SYNC start value.
Definition: tpdo.c:62
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:204
A PDO communication parameter record.
Definition: pdo.h:43
#define CO_SDO_AC_ERROR
SDO abort code: General error.
Definition: sdo.h:150
#define MIN(a, b)
Returns the minimum of a and b.
Definition: util.h:57
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:45
co_unsigned32_t cobid
COB-ID.
Definition: pdo.h:47
#define CAN_MASK_BID
The mask used to extract the 11-bit Base Identifier from a CAN frame.
Definition: msg.h:31
This header file is part of the CANopen library; it contains the Service Data Object (SDO) declaratio...
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 error occurs.
Definition: tpdo.c:357
This header file is part of the CANopen library; it contains the CANopen value declarations.
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:957
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:330
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
can_recv_t * can_recv_create(void)
Creates a new CAN frame receiver.
Definition: net.c:537
static int co_tpdo_init_recv(co_tpdo_t *pdo)
Initializes the CAN frame receiver of a Transmit-PDO service.
Definition: tpdo.c:471
void * data
A pointer to user-specified data for ind.
Definition: tpdo.c:70
#define CO_DEFTYPE_UNSIGNED32
The data type (and object index) of a 32-bit unsigned integer.
Definition: type.h:50
void timespec_add_usec(struct timespec *tp, uint_least64_t usec)
Adds usec microseconds to the time at tp.
Definition: time.h:143
uint_least8_t data[CAN_MSG_MAX_LEN]
The frame payload (in case of a data frame).
Definition: msg.h:102
co_unsigned16_t num
The PDO number.
Definition: tpdo.c:46
This header file is part of the utilities library; it contains the native and platform-independent er...
co_unsigned16_t event
Event timer.
Definition: pdo.h:54
This header file is part of the utilities library; it contains the time function declarations.
#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
struct co_pdo_comm_par comm
The PDO communication parameter.
Definition: tpdo.c:48
#define CO_DEFTYPE_UNSIGNED16
The data type (and object index) of a 16-bit unsigned integer.
Definition: type.h:47
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:338
void can_recv_destroy(can_recv_t *recv)
Destroys a CAN frame receiver.
Definition: net.c:562
can_net_t * net
A pointer to a CAN network interface.
Definition: tpdo.c:42
The Remote Transmission Request (RTR) flag (unavailable in CAN FD format frames). ...
Definition: msg.h:48
This is the internal header file of the CANopen library.
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 error occurs.
Definition: tpdo.c:346
#define CAN_MAX_LEN
The maximum number of bytes in the payload of a CAN format frame.
Definition: msg.h:72
#define CO_PDO_COBID_VALID
The bit in the PDO COB-ID specifying whether the PDO exists and is valid.
Definition: pdo.h:28
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function...
Definition: errnum.c:947
A CAN timer.
Definition: net.c:63
Resource unavailable, try again.
Definition: errnum.h:86
#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 can_timer_destroy(can_timer_t *timer)
Destroys a CAN timer.
Definition: net.c:407
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:954
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:314
#define CO_DEFTYPE_UNSIGNED8
The data type (and object index) of an 8-bit unsigned integer.
Definition: type.h:44
unsigned int event
A flag indicating the occurrence of an event.
Definition: tpdo.c:60
int co_tpdo_sync(co_tpdo_t *pdo, co_unsigned8_t cnt)
Triggers the transmission of a synchronous PDO.
Definition: tpdo.c:412
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:824
Invalid argument.
Definition: errnum.h:129
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:269
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition: errnum.c:43
#define CO_SDO_AC_NO_WRITE
SDO abort code: Attempt to write a read only object.
Definition: sdo.h:90
int timespec_cmp(const void *p1, const void *p2)
Compares two times.
Definition: time.h:228
A CANopen device.
Definition: dev.c:41
struct timespec inhibit
The time at which the next event-driven TPDO may be sent.
Definition: tpdo.c:58
co_unsigned8_t cnt
The SYNC counter value.
Definition: tpdo.c:64
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
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
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:520
The Identifier Extension (IDE) flag.
Definition: msg.h:43
can_timer_t * can_timer_create(void)
Creates a new CAN timer.
Definition: net.c:382
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:666
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.
Definition: val.c:275
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
struct co_pdo_map_par map
The PDO mapping parameter.
Definition: tpdo.c:50
#define CO_SDO_AC_NO_SUB
SDO abort code: Sub-index does not exist.
Definition: sdo.h:132
void co_sdo_req_init(struct co_sdo_req *req)
Initializes a CANopen SDO upload/download request.
Definition: sdo.c:109
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
This header file is part of the CANopen library; it contains the device description declarations...
co_dev_t * dev
A pointer to a CANopen device.
Definition: tpdo.c:44
co_unsigned32_t map[0x40]
An array of objects to be mapped.
Definition: pdo.h:73
co_unsigned8_t co_sub_get_subidx(const co_sub_t *sub)
Returns the sub-index of a CANopen sub-object.
Definition: obj.c:528
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib.h> and defines any missing functionality.
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:796
A CAN frame receiver.
Definition: net.c:99
void co_sdo_req_fini(struct co_sdo_req *req)
Finalizes a CANopen SDO upload/download request.
Definition: sdo.c:121
co_unsigned16_t co_sub_get_type(const co_sub_t *sub)
Returns the data type of a CANopen sub-object.
Definition: obj.c:570
co_unsigned16_t co_tpdo_get_num(const co_tpdo_t *pdo)
Returns the PDO number of a Transmit-PDO.
Definition: tpdo.c:322
struct can_msg msg
A buffered CAN frame, used for RTR-only or event-driven TPDOs.
Definition: tpdo.c:56
co_unsigned16_t co_obj_get_idx(const co_obj_t *obj)
Returns the index of a CANopen object.
Definition: obj.c:154
co_unsigned16_t inhibit
Inhibit time.
Definition: pdo.h:51
A CANopen object.
Definition: obj.h:32
This header file is part of the CANopen library; it contains the object dictionary declarations...
#define CAN_MSG_INIT
The static initializer for can_msg.
Definition: msg.h:113
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:117
struct co_sdo_req req
The CANopen SDO upload request used for reading sub-objects.
Definition: tpdo.c:66
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
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:288
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:784
co_unsigned8_t trans
Transmission type.
Definition: pdo.h:49
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)
Reads mapped PDO values from the object dictionary through a local SDO upload request.
Definition: pdo.c:308
void * co_obj_addressof_val(const co_obj_t *obj)
Returns the address of the value of a CANopen object.
Definition: obj.c:311
#define CAN_MASK_EID
The mask used to extract the 29-bit Extended Identifier from a CAN frame.
Definition: msg.h:34
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:306
static int co_tpdo_init_timer_event(co_tpdo_t *pdo)
Initializes the CAN timer for events of a Transmit-PDO service.
Definition: tpdo.c:503