Lely core libraries  1.9.2
pdo.c
Go to the documentation of this file.
1 
24 #include "co.h"
25 
26 #include <lely/can/msg.h>
27 #include <lely/co/dev.h>
28 #include <lely/co/obj.h>
29 #include <lely/co/pdo.h>
30 #include <lely/co/sdo.h>
31 #include <lely/util/endian.h>
32 
33 #include <assert.h>
34 
35 static co_unsigned32_t co_dev_cfg_pdo_comm(const co_dev_t *dev,
36  co_unsigned16_t idx, const struct co_pdo_comm_par *par);
37 
38 static co_unsigned32_t co_dev_cfg_pdo_map(const co_dev_t *dev,
39  co_unsigned16_t num, const struct co_pdo_map_par *par);
40 
41 co_unsigned32_t
42 co_dev_chk_rpdo(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
43 {
44  assert(dev);
45 
46  if (co_type_is_basic(idx) && !subidx) {
47  // If the object is a dummy entry, check if it is enabled.
48  if (__unlikely(!(co_dev_get_dummy(dev) & (1 << idx))))
49  return CO_SDO_AC_NO_OBJ;
50  } else {
51  co_obj_t *obj = co_dev_find_obj(dev, idx);
52  if (__unlikely(!obj))
53  return CO_SDO_AC_NO_OBJ;
54 
55  co_sub_t *sub = co_obj_find_sub(obj, subidx);
56  if (__unlikely(!sub))
57  return CO_SDO_AC_NO_SUB;
58 
59  unsigned int access = co_sub_get_access(sub);
60  if (__unlikely(!(access & CO_ACCESS_WRITE)))
61  return CO_SDO_AC_NO_WRITE;
62 
63  // clang-format off
65  || !(access & CO_ACCESS_RPDO)))
66  // clang-format on
67  return CO_SDO_AC_NO_PDO;
68  }
69 
70  return 0;
71 }
72 
73 co_unsigned32_t
74 co_dev_cfg_rpdo(const co_dev_t *dev, co_unsigned16_t num,
75  const struct co_pdo_comm_par *comm,
76  const struct co_pdo_map_par *map)
77 {
78  assert(comm);
79 
80  co_unsigned32_t ac = 0;
81 
82  struct co_pdo_comm_par par = *comm;
83  // Disable the RPDO service before configuring any parameters.
85  ac = co_dev_cfg_rpdo_comm(dev, num, &par);
86  if (__unlikely(ac))
87  return ac;
88 
89  ac = co_dev_cfg_rpdo_map(dev, num, map);
90  if (__unlikely(ac))
91  return ac;
92 
93  // Re-enable the RPDO service if necessary.
94  if (!(comm->cobid & CO_PDO_COBID_VALID))
95  ac = co_dev_cfg_rpdo_comm(dev, num, comm);
96  return ac;
97 }
98 
99 co_unsigned32_t
100 co_dev_cfg_rpdo_comm(const co_dev_t *dev, co_unsigned16_t num,
101  const struct co_pdo_comm_par *par)
102 {
103  if (__unlikely(!num || num > 512))
104  return CO_SDO_AC_NO_OBJ;
105 
106  return co_dev_cfg_pdo_comm(dev, 0x1400 + num - 1, par);
107 }
108 
109 co_unsigned32_t
110 co_dev_cfg_rpdo_map(const co_dev_t *dev, co_unsigned16_t num,
111  const struct co_pdo_map_par *par)
112 {
113  if (__unlikely(!num || num > 512))
114  return CO_SDO_AC_NO_OBJ;
115 
116  return co_dev_cfg_pdo_map(dev, 0x1600 + num - 1, par);
117 }
118 
119 co_unsigned32_t
120 co_dev_chk_tpdo(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
121 {
122  assert(dev);
123 
124  co_obj_t *obj = co_dev_find_obj(dev, idx);
125  if (__unlikely(!obj))
126  return CO_SDO_AC_NO_OBJ;
127 
128  co_sub_t *sub = co_obj_find_sub(obj, subidx);
129  if (__unlikely(!sub))
130  return CO_SDO_AC_NO_SUB;
131 
132  unsigned int access = co_sub_get_access(sub);
133  if (__unlikely(!(access & CO_ACCESS_READ)))
134  return CO_SDO_AC_NO_READ;
135 
136  // clang-format off
138  || !(access & CO_ACCESS_TPDO)))
139  // clang-format on
140  return CO_SDO_AC_NO_PDO;
141 
142  return 0;
143 }
144 
145 co_unsigned32_t
146 co_dev_cfg_tpdo(const co_dev_t *dev, co_unsigned16_t num,
147  const struct co_pdo_comm_par *comm,
148  const struct co_pdo_map_par *map)
149 {
150  assert(comm);
151 
152  co_unsigned32_t ac = 0;
153 
154  struct co_pdo_comm_par par = *comm;
155  // Disable the TPDO service before configuring any parameters.
156  par.cobid |= CO_PDO_COBID_VALID;
157  ac = co_dev_cfg_tpdo_comm(dev, num, &par);
158  if (__unlikely(ac))
159  return ac;
160 
161  ac = co_dev_cfg_tpdo_map(dev, num, map);
162  if (__unlikely(ac))
163  return ac;
164 
165  // Re-enable the TPDO service if necessary.
166  if (!(comm->cobid & CO_PDO_COBID_VALID))
167  ac = co_dev_cfg_tpdo_comm(dev, num, comm);
168  return ac;
169 }
170 
171 co_unsigned32_t
172 co_dev_cfg_tpdo_comm(const co_dev_t *dev, co_unsigned16_t num,
173  const struct co_pdo_comm_par *par)
174 {
175  if (__unlikely(!num || num > 512))
176  return CO_SDO_AC_NO_OBJ;
177 
178  return co_dev_cfg_pdo_comm(dev, 0x1800 + num - 1, par);
179 }
180 
181 co_unsigned32_t
182 co_dev_cfg_tpdo_map(const co_dev_t *dev, co_unsigned16_t num,
183  const struct co_pdo_map_par *par)
184 {
185  if (__unlikely(!num || num > 512))
186  return CO_SDO_AC_NO_OBJ;
187 
188  return co_dev_cfg_pdo_map(dev, 0x1a00 + num - 1, par);
189 }
190 
191 co_unsigned32_t
192 co_pdo_map(const struct co_pdo_map_par *par, const co_unsigned64_t *val,
193  co_unsigned8_t n, uint8_t *buf, size_t *pn)
194 {
195  assert(par);
196  assert(val);
197 
198  if (__unlikely(par->n > 0x40 || n != par->n))
199  return CO_SDO_AC_PDO_LEN;
200 
201  size_t offset = 0;
202  for (size_t i = 0; i < par->n; i++) {
203  co_unsigned8_t len = par->map[i] & 0xff;
204 
205  if (__unlikely(offset + len > CAN_MAX_LEN * 8))
206  return CO_SDO_AC_PDO_LEN;
207 
208  uint8_t tmp[sizeof(co_unsigned64_t)] = { 0 };
209  stle_u64(tmp, val[i]);
210  if (buf && pn && offset + len <= *pn * 8)
211  bcpyle(buf, offset, tmp, 0, len);
212 
213  offset += len;
214  }
215 
216  if (pn)
217  *pn = (offset + 7) / 8;
218 
219  return 0;
220 }
221 
222 co_unsigned32_t
223 co_pdo_unmap(const struct co_pdo_map_par *par, const uint8_t *buf, size_t n,
224  co_unsigned64_t *val, co_unsigned8_t *pn)
225 {
226  assert(par);
227  assert(buf);
228 
229  if (__unlikely(par->n > 0x40))
230  return CO_SDO_AC_PDO_LEN;
231 
232  size_t offset = 0;
233  for (size_t i = 0; i < par->n; i++) {
234  co_unsigned8_t len = par->map[i] & 0xff;
235 
236  if (__unlikely(offset + len > n * 8))
237  return CO_SDO_AC_PDO_LEN;
238 
239  uint8_t tmp[sizeof(co_unsigned64_t)] = { 0 };
240  bcpyle(tmp, 0, buf, offset, len);
241  if (val && pn && i < *pn)
242  val[i] = ldle_u64(tmp);
243 
244  offset += len;
245  }
246 
247  if (pn)
248  *pn = par->n;
249 
250  return 0;
251 }
252 
253 co_unsigned32_t
254 co_pdo_dn(const struct co_pdo_map_par *par, co_dev_t *dev,
255  struct co_sdo_req *req, const uint8_t *buf, size_t n)
256 {
257  assert(par);
258  assert(dev);
259  assert(req);
260  assert(buf);
261 
262  if (__unlikely(n > CAN_MAX_LEN))
263  return CO_SDO_AC_PDO_LEN;
264 
265  co_unsigned32_t ac = 0;
266 
267  size_t offset = 0;
268  for (size_t i = 0; i < MIN(par->n, 0x40u); i++) {
269  co_unsigned32_t map = par->map[i];
270  co_unsigned16_t idx = (map >> 16) & 0xffff;
271  co_unsigned8_t subidx = (map >> 8) & 0xff;
272  co_unsigned8_t len = map & 0xff;
273 
274  // Check the PDO length.
275  if (__unlikely(offset + len > n * 8))
276  return CO_SDO_AC_PDO_LEN;
277 
278  // Check whether the sub-object exists and can be mapped into a
279  // PDO (or is a valid dummy entry).
280  ac = co_dev_chk_rpdo(dev, idx, subidx);
281  if (__unlikely(ac))
282  return ac;
283 
284  co_sub_t *sub = co_dev_find_sub(dev, idx, subidx);
285  if (sub) {
286  // Copy the value and download it into the sub-object.
287  uint8_t tmp[CAN_MAX_LEN] = { 0 };
288  bcpyle(tmp, 0, buf, offset, len);
289  co_sdo_req_clear(req);
290  req->size = (len + 7) / 8;
291  req->buf = tmp;
292  req->nbyte = req->size;
293  ac = co_sub_dn_ind(sub, req);
294  if (__unlikely(ac))
295  return ac;
296  }
297 
298  offset += len;
299  }
300 
301  return ac;
302 }
303 
304 co_unsigned32_t
305 co_pdo_up(const struct co_pdo_map_par *par, const co_dev_t *dev,
306  struct co_sdo_req *req, uint8_t *buf, size_t *pn)
307 {
308  assert(par);
309  assert(dev);
310  assert(req);
311 
312  co_unsigned32_t ac = 0;
313 
314  size_t offset = 0;
315  for (size_t i = 0; i < MIN(par->n, 0x40u); i++) {
316  co_unsigned32_t map = par->map[i];
317  co_unsigned16_t idx = (map >> 16) & 0xffff;
318  co_unsigned8_t subidx = (map >> 8) & 0xff;
319  co_unsigned8_t len = map & 0xff;
320 
321  // Check the PDO length.
322  if (__unlikely(offset + len > CAN_MAX_LEN * 8))
323  return CO_SDO_AC_PDO_LEN;
324 
325  // Check whether the sub-object exists and can be mapped into a
326  // PDO.
327  ac = co_dev_chk_tpdo(dev, idx, subidx);
328  if (__unlikely(ac))
329  return ac;
330 
331  // Upload the value of the sub-object and copy the value.
332  co_sdo_req_clear(req);
333  ac = co_sub_up_ind(co_dev_find_sub(dev, idx, subidx), req);
334  if (__unlikely(ac))
335  return ac;
336  if (__unlikely(!co_sdo_req_first(req) || !co_sdo_req_last(req)))
337  return CO_SDO_AC_PDO_LEN;
338  if (buf && pn && offset + len <= *pn * 8)
339  bcpyle(buf, offset, req->buf, 0, len);
340 
341  offset += len;
342  }
343 
344  if (pn)
345  *pn = (offset + 7) / 8;
346 
347  return ac;
348 }
349 
350 static co_unsigned32_t
351 co_dev_cfg_pdo_comm(const co_dev_t *dev, co_unsigned16_t idx,
352  const struct co_pdo_comm_par *par)
353 {
354  assert(dev);
355  assert(par);
356 
357  co_unsigned32_t ac = 0;
358 
359  co_obj_t *obj = co_dev_find_obj(dev, idx);
360  if (__unlikely(!obj))
361  return CO_SDO_AC_NO_OBJ;
362 
363  // Check if all sub-objects are available.
364  co_unsigned8_t n = co_obj_get_val_u8(obj, 0x00);
365  if (__unlikely(par->n > n))
366  return CO_SDO_AC_NO_SUB;
367 
368  // Configure the COB-ID.
369  if (par->n >= 1 && !ac) {
370  co_sub_t *sub = co_obj_find_sub(obj, 0x01);
371  if (__unlikely(!sub))
372  return CO_SDO_AC_NO_SUB;
374  }
375 
376  // Configure the transmission type.
377  if (par->n >= 2 && !ac) {
378  co_sub_t *sub = co_obj_find_sub(obj, 0x02);
379  if (__unlikely(!sub))
380  return CO_SDO_AC_NO_SUB;
381  ac = co_sub_dn_ind_val(sub, CO_DEFTYPE_UNSIGNED8, &par->trans);
382  }
383 
384  // Configure the inhibit time.
385  if (par->n >= 3 && !ac) {
386  co_sub_t *sub = co_obj_find_sub(obj, 0x03);
387  if (__unlikely(!sub))
388  return CO_SDO_AC_NO_SUB;
389  ac = co_sub_dn_ind_val(
390  sub, CO_DEFTYPE_UNSIGNED16, &par->inhibit);
391  }
392 
393  // Configure the event timer.
394  if (par->n >= 5 && !ac) {
395  co_sub_t *sub = co_obj_find_sub(obj, 0x05);
396  if (__unlikely(!sub))
397  return CO_SDO_AC_NO_SUB;
399  }
400 
401  // Configure the SYNC start value.
402  if (par->n >= 6 && !ac) {
403  co_sub_t *sub = co_obj_find_sub(obj, 0x06);
404  if (__unlikely(!sub))
405  return CO_SDO_AC_NO_SUB;
406  ac = co_sub_dn_ind_val(sub, CO_DEFTYPE_UNSIGNED8, &par->sync);
407  }
408 
409  return ac;
410 }
411 
412 static co_unsigned32_t
413 co_dev_cfg_pdo_map(const co_dev_t *dev, co_unsigned16_t idx,
414  const struct co_pdo_map_par *par)
415 {
416  assert(dev);
417  assert(par);
418 
419  co_unsigned32_t ac = 0;
420 
421  co_obj_t *obj = co_dev_find_obj(dev, idx);
422  if (__unlikely(!obj))
423  return CO_SDO_AC_NO_OBJ;
424 
425  co_sub_t *sub_00 = co_obj_find_sub(obj, 0x00);
426  if (__unlikely(!sub_00))
427  return CO_SDO_AC_NO_SUB;
428  // Disable mapping by setting subindex 0x00 to zero.
429  ac = co_sub_dn_ind_val(
430  sub_00, CO_DEFTYPE_UNSIGNED8, &(co_unsigned8_t){ 0 });
431  if (__unlikely(ac))
432  return ac;
433 
434  // Copy the mapping parameters.
435  for (co_unsigned8_t i = 1; i <= par->n; i++) {
436  co_sub_t *sub = co_obj_find_sub(obj, i);
437  if (__unlikely(!sub))
438  return CO_SDO_AC_NO_SUB;
439  ac = co_sub_dn_ind_val(
440  sub, CO_DEFTYPE_UNSIGNED32, &par->map[i - 1]);
441  if (__unlikely(ac))
442  return ac;
443  }
444 
445  // Enable mapping.
446  return co_sub_dn_ind_val(sub_00, CO_DEFTYPE_UNSIGNED8, &par->n);
447 }
A CANopen SDO upload/download request.
Definition: sdo.h:178
A PDO mapping parameter record.
Definition: pdo.h:69
#define CO_SDO_AC_NO_READ
SDO abort code: Attempt to read a write only object.
Definition: sdo.h:87
co_unsigned8_t sync
SYNC start value.
Definition: pdo.h:56
co_unsigned32_t co_dev_cfg_rpdo_map(const co_dev_t *dev, co_unsigned16_t num, const struct co_pdo_map_par *par)
Configures the mapping parameters of a Receive-PDO service by updating CANopen object 1600 - 17FF (RP...
Definition: pdo.c:110
co_unsigned32_t co_pdo_dn(const struct co_pdo_map_par *par, co_dev_t *dev, struct co_sdo_req *req, const uint8_t *buf, size_t n)
Writes mapped PDO values to the object dictionary through a local SDO download request.
Definition: pdo.c:254
co_unsigned32_t co_sub_dn_ind_val(co_sub_t *sub, co_unsigned16_t type, const void *val)
Invokes the download indication function of a CANopen sub-object, registered with co_sub_set_dn_ind()...
Definition: obj.c:810
void stle_u64(void *ptr, uint_least64_t x)
Stores a 64-bit unsigned integer in little-endian byte order.
Definition: endian.h:588
co_unsigned32_t co_dev_get_dummy(const co_dev_t *dev)
Returns the data types supported by a CANopen device for mapping dummy entries in PDOs (one bit for e...
Definition: dev.c:513
size_t size
The total size (in bytes) of the value to be uploaded/downloaded.
Definition: sdo.h:184
A CANopen sub-object.
Definition: obj.h:54
#define CO_ACCESS_WRITE
The object can be written.
Definition: obj.h:60
uint_least64_t ldle_u64(const void *ptr)
Loads a 64-bit unsigned integer in little-endian byte order.
Definition: endian.h:595
void co_sdo_req_clear(struct co_sdo_req *req)
Clears a CANopen SDO upload/download request, including its buffer.
Definition: sdo.c:129
co_unsigned8_t n
Number of mapped objects in PDO.
Definition: pdo.h:71
co_unsigned32_t co_dev_cfg_tpdo(const co_dev_t *dev, co_unsigned16_t num, const struct co_pdo_comm_par *comm, const struct co_pdo_map_par *map)
Configures the communication and parameters of a Transmit-PDO service.
Definition: pdo.c:146
#define CO_ACCESS_TPDO
The object can be mapped to a TPDO.
Definition: obj.h:63
A PDO communication parameter record.
Definition: pdo.h:43
#define MIN(a, b)
Returns the minimum of a and b.
Definition: util.h:57
co_unsigned32_t cobid
COB-ID.
Definition: pdo.h:47
void bcpyle(void *dst, int dstbit, const void *src, int srcbit, size_t n)
Copies n bits from a source to a destination buffer.
Definition: endian.c:128
This header file is part of the CANopen library; it contains the Service Data Object (SDO) declaratio...
#define CO_ACCESS_RPDO
The object can be mapped to an RPDO.
Definition: obj.h:66
int co_sub_get_pdo_mapping(const co_sub_t *sub)
Returns 1 if it is possible to map the specified CANopen sub-object into a PDO, and 0 if not...
Definition: obj.c:706
unsigned int co_sub_get_access(const co_sub_t *sub)
Returns the access type of a CANopen sub-object.
Definition: obj.c:682
#define CO_ACCESS_READ
The object can be read.
Definition: obj.h:57
#define CO_DEFTYPE_UNSIGNED32
The data type (and object index) of a 32-bit unsigned integer.
Definition: type.h:50
co_unsigned16_t event
Event timer.
Definition: pdo.h:54
int co_sdo_req_first(const struct co_sdo_req *req)
Returns 1 if the specified request includes the first segment, and 0 otherwise.
Definition: sdo.h:340
co_unsigned32_t co_dev_chk_rpdo(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
Checks if the specified object is valid and can be mapped into a Receive-PDO.
Definition: pdo.c:42
co_unsigned32_t co_pdo_unmap(const struct co_pdo_map_par *par, const uint8_t *buf, size_t n, co_unsigned64_t *val, co_unsigned8_t *pn)
Unmaps a PDO into its constituent values.
Definition: pdo.c:223
#define CO_DEFTYPE_UNSIGNED16
The data type (and object index) of a 16-bit unsigned integer.
Definition: type.h:47
This header file is part of the utilities library; it contains the byte order (endianness) function d...
int co_type_is_basic(co_unsigned16_t type)
Returns 1 if the specified (static) data type is a basic type, and 0 if not.
Definition: type.c:28
This is the internal header file of the CANopen library.
co_unsigned32_t co_sub_up_ind(const co_sub_t *sub, struct co_sdo_req *req)
Invokes the upload indication function of a CANopen sub-object, registered with co_sub_set_up_ind().
Definition: obj.c:890
#define CO_PDO_COBID_VALID
The bit in the PDO COB-ID specifying whether the PDO exists and is valid.
Definition: pdo.h:28
co_unsigned8_t n
Highest sub-index supported.
Definition: pdo.h:45
This header file is part of the CAN library; it contains the CAN frame declarations.
#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
#define CO_DEFTYPE_UNSIGNED8
The data type (and object index) of an 8-bit unsigned integer.
Definition: type.h:44
co_unsigned32_t co_pdo_map(const struct co_pdo_map_par *par, const co_unsigned64_t *val, co_unsigned8_t n, uint8_t *buf, size_t *pn)
Maps values into a PDO.
Definition: pdo.c:192
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:120
co_unsigned32_t co_dev_cfg_rpdo_comm(const co_dev_t *dev, co_unsigned16_t num, const struct co_pdo_comm_par *par)
Configures the communication parameters of a Receive-PDO service by updating CANopen object 1400 - 15...
Definition: pdo.c:100
#define CO_SDO_AC_NO_WRITE
SDO abort code: Attempt to write a read only object.
Definition: sdo.h:90
#define __unlikely(x)
Indicates to the compiler that the expression is most-likely false.
Definition: features.h:286
co_unsigned32_t co_pdo_up(const struct co_pdo_map_par *par, const co_dev_t *dev, struct co_sdo_req *req, uint8_t *buf, size_t *pn)
Reads mapped PDO values from the object dictionary through a local SDO upload request.
Definition: pdo.c:305
A CANopen device.
Definition: dev.c:38
co_unsigned32_t co_dev_cfg_tpdo_comm(const co_dev_t *dev, co_unsigned16_t num, const struct co_pdo_comm_par *par)
Configures the communication parameters of a Transmit-PDO service by updating CANopen object 1800 - 1...
Definition: pdo.c:172
This header file is part of the CANopen library; it contains the device description declarations...
co_unsigned32_t co_dev_cfg_tpdo_map(const co_dev_t *dev, co_unsigned16_t num, const struct co_pdo_map_par *par)
Configures the mapping parameters of a Transmit-PDO service by updating CANopen object 1A00 - 1BFF (T...
Definition: pdo.c:182
#define CO_SDO_AC_NO_SUB
SDO abort code: Sub-index does not exist.
Definition: sdo.h:132
size_t nbyte
The number of bytes available at buf.
Definition: sdo.h:188
const void * buf
A pointer to the next bytes to be uploaded/downloaded.
Definition: sdo.h:186
co_unsigned32_t map[0x40]
An array of objects to be mapped.
Definition: pdo.h:73
co_obj_t * co_dev_find_obj(const co_dev_t *dev, co_unsigned16_t idx)
Finds an object in the object dictionary of a CANopen device.
Definition: dev.c:279
co_sub_t * co_obj_find_sub(const co_obj_t *obj, co_unsigned8_t subidx)
Finds a sub-object in a CANopen object.
Definition: obj.c:207
#define CAN_MAX_LEN
The maximum number of bytes in the payload of a CAN format frame.
Definition: msg.h:73
co_unsigned32_t co_sub_dn_ind(co_sub_t *sub, struct co_sdo_req *req)
Invokes the download indication function of a CANopen sub-object, registered with co_sub_set_dn_ind()...
Definition: obj.c:794
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...
co_unsigned8_t trans
Transmission type.
Definition: pdo.h:49
int co_sdo_req_last(const struct co_sdo_req *req)
Returns 1 if the specified request includes the last segment, and 0 otherwise.
Definition: sdo.h:346
co_unsigned32_t co_dev_cfg_rpdo(const co_dev_t *dev, co_unsigned16_t num, const struct co_pdo_comm_par *comm, const struct co_pdo_map_par *map)
Configures the communication and parameters of a Receive-PDO service.
Definition: pdo.c:74
#define CO_SDO_AC_NO_PDO
SDO abort code: Object cannot be mapped to the PDO.
Definition: sdo.h:96
co_sub_t * co_dev_find_sub(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
Finds a sub-object in the object dictionary of a CANopen device.
Definition: dev.c:290
#define CO_SDO_AC_NO_OBJ
SDO abort code: Object does not exist in the object dictionary.
Definition: sdo.h:93
This header file is part of the CANopen library; it contains the Process Data Object (PDO) declaratio...