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