-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathsdo.h
465 lines (420 loc) · 17.8 KB
/
sdo.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
/*
This file is part of CanFestival, a library implementing CanOpen Stack.
Copyright (C): Edouard TISSERANT and Francis DUPIN
See COPYING file for copyrights details.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/** @defgroup comobj Communication Objects
* @ingroup userapi
*/
/** @defgroup sdo Service Data Object (SDO)
* SDOs provide the access to entries in the CANopen Object Dictionary.
* An SDO is made up of at least two CAN messages with different identifiers.
* SDO s are always confirmed point-to-point communications services.
* @ingroup comobj
*/
#ifndef __sdo_h__
#define __sdo_h__
struct struct_s_transfer;
#include "CO_timer.h"
/* Block mode : Data consumer receive step
* - set to RXSTEP_STARTED when client receive initiate upload response
* - set to RXSTEP_END when last segment of a block received
*/
typedef enum {
RXSTEP_INIT, RXSTEP_STARTED, RXSTEP_END
}__attribute__ ((packed)) rxStep_t;
typedef void (*SDOCallback_t)(UNS8 nodeId);
/* The Transfer structure
Used to store the different segments of
- a SDO received before writing in the dictionary
- the reading of the dictionary to put on a SDO to transmit
WARNING : after a change in this structure check the macro s_transfer_Initializer in data.h
*/
struct struct_s_transfer {
UNS8 CliServNbr; /**< The index of the SDO client / server in our OD minus 0x1280 / 0x1200 */
UNS8 whoami; /**< Takes the values SDO_CLIENT or SDO_SERVER */
UNS8 state; /**< state of the transmission : Takes the values SDO_... */
UNS8 toggle;UNS32 abortCode; /**< Sent or received */
/**< index and subindex of the dictionary where to store */
/**< (for a received SDO) or to read (for a transmit SDO) */
UNS16 index;UNS8 subIndex;UNS32 count; /**< Number of data received or to be sent. */
UNS32 offset; /**< stack pointer of data[]
* Used only to tranfer part of a line to or from a SDO.
* offset is always pointing on the next free cell of data[].
* WARNING s_transfer.data is subject to ENDIANISATION
* (with respect to CANOPEN_BIG_ENDIAN)
*/
UNS8 data[SDO_MAX_LENGTH_TRANSFER];
#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
UNS8 *dynamicData;
UNS32 dynamicDataSize;
#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
UNS8 peerCRCsupport; /**< True if peer supports CRC */
UNS8 blksize; /**< Number of segments per block with 0 < blksize < 128 */
UNS8 ackseq; /**< sequence number of last segment that was received successfully */
UNS32 objsize; /**< Size in bytes of the object provided by data producer */
UNS8 lastblockoffset; /**< Value of offset before last block */
UNS8 seqno; /**< Last sequence number received OK or transmitted */
UNS8 endfield; /**< nbr of bytes in last segment of last block that do not contain data */
rxStep_t rxstep; /**< data consumer receive step - set to true when last segment of a block received */
UNS8 tmpData[8]; /**< temporary segment storage */
UNS8 dataType; /**< Defined in objdictdef.h Value is visible_string
* if it is a string, any other value if it is not a string,
* like 0. In fact, it is used only if client.
*/
TIMER_HANDLE timer; /**< Time counter to implement a timeout in milliseconds.
* It is automatically incremented whenever
* the line state is in SDO_DOWNLOAD_IN_PROGRESS or
* SDO_UPLOAD_IN_PROGRESS, and reseted to 0
* when the response SDO have been received.
*/
SDOCallback_t Callback; /**< The user callback func to be called at SDO transaction end */
};
typedef struct __attribute__ ((packed)) struct_s_transfer s_transfer;
#include "data.h"
/**
* @brief Reset of a SDO exchange on timeout.
* Send a SDO abort.
* @param *d Pointer on a CAN object data structure
* @param id
*/
void SDOTimeoutAlarm(UNS8 id);
/**
* @brief Reset all SDO buffers.
* @param *d Pointer on a CAN object data structure
*/
void resetSDO();
/**
* @brief Copy the data received from the SDO line transfer to the object dictionary.
* @param *d Pointer on a CAN object data structure
* @param line SDO line
* @return SDO error code if error. Else, returns 0.
*/
UNS32 SDOlineToObjdict(UNS8 line);
/**
* @brief Copy the data from the object dictionary to the SDO line for a network transfer.
* @param *d Pointer on a CAN object data structure
* @param line SDO line
* @return SDO error code if error. Else, returns 0.
*/
UNS32 objdictToSDOline(UNS8 line);
/**
* @brief Copy data from an existant line in the argument "* data"
* @param d Pointer on a CAN object data structure
* @param line SDO line
* @param nbBytes
* @param *data Pointer on the data
* @return 0xFF if error. Else, returns 0.
*/
UNS8 lineToSDO(UNS8 line, UNS32 nbBytes, UNS8 * data);
/**
* @brief Add data to an existant line
* @param d Pointer on a CAN object data structure
* @param line SDO line
* @param nbBytes
* @param *data Pointer on the data
* @return 0xFF if error. Else, returns 0.
*/
UNS8 SDOtoLine(UNS8 line, UNS32 nbBytes, UNS8 * data);
/**
* @brief Called when an internal SDO abort occurs.
* Release the line * Only if server *
* If client, the line must be released manually in the core application.
* The reason of that is to permit the program to read the transfers structure before its reset,
* because many informations are stored on it : index, subindex, data received or trasmited, ...
* In all cases, sends a SDO abort.
* @param *d Pointer on a CAN object data structure
* @param CliServNbr
* @param whoami
* @param index
* @param subIndex
* @param abortCode
* @return 0
*/
UNS8 failedSDO(UNS8 CliServNbr, UNS8 whoami, UNS16 index, UNS8 subIndex, UNS32 abortCode);
/**
* @brief Reset an unused line.
* @param *d Pointer on a CAN object data structure
* @param line SDO line
*/
void resetSDOline(UNS8 line);
/**
* @brief Initialize some fields of the structure.
* @param *d Pointer on a CAN object data structure
* @param line
* @param CliServNbr
* @param index
* @param subIndex
* @param state
* @return 0
*/
UNS8 initSDOline(UNS8 line, UNS8 CliServNbr, UNS16 index, UNS8 subIndex, UNS8 state);
/**
* @brief Search for an unused line in the transfers array
* to store a new SDO.
* ie a line which value of the field "state" is "SDO_RESET"
* An unused line have the field "state" at the value SDO_RESET
* @param *d Pointer on a CAN object data structure
* @param whoami Create the line for a SDO_SERVER or SDO_CLIENT.
* @param *line Pointer on a SDO line
* @return 0xFF if all the lines are on use. Else, return 0.
*/
UNS8 getSDOfreeLine(UNS8 whoami, UNS8 *line);
/**
* @brief Search for the line, in the transfers array, which contains the
* beginning of the reception of a fragmented SDO
* @param *d Pointer on a CAN object data structure
* @param CliServNbr Client or Server object involved
* @param whoami takes 2 values : look for a line opened as SDO_CLIENT or SDO_SERVER
* @param *line Pointer on a SDO line
* @return 0xFF if error. Else, return 0
*/
UNS8 getSDOlineOnUse(UNS8 CliServNbr, UNS8 whoami, UNS8 *line);
/**
* @brief Search for the line, in the transfers array, which contains the
* beginning of the reception of a fragmented SDO
*
* Because getSDOlineOnUse() does not return any line in state \c SDO_ABORTED_INTERNAL,
* this funtion is used to return them, too.
*
* @param *d Pointer on a CAN object data structure
* @param CliServNbr Client or Server object involved
* @param whoami takes 2 values : look for a line opened as SDO_CLIENT or SDO_SERVER
* @param *line Pointer on a SDO line
* @return 0xFF if error. Else, return 0
*/
UNS8 getSDOlineToClose(UNS8 CliServNbr, UNS8 whoami, UNS8 *line);
/**
* @brief Close a transmission.
* @param *d Pointer on a CAN object data structure
* @param CliServNbr Client or Server object involved
* @param whoami Line opened as SDO_CLIENT or SDO_SERVER
*/
UNS8 closeSDOtransfer(UNS8 CliServNbr, UNS8 whoami);
/**
* @brief Bytes in the line structure which must be transmited (or received)
* @param *d Pointer on a CAN object data structure
* @param line SDO line
* @param *nbBytes Pointer on nbBytes
* @return 0.
*/
UNS8 getSDOlineRestBytes(UNS8 line, UNS32 * nbBytes);
/**
* @brief Store in the line structure the nb of bytes which must be transmited (or received)
* @param *d Pointer on a CAN object data structure
* @param line SDO line
* @param nbBytes
* @return 0 if success, 0xFF if error.
*/
UNS8 setSDOlineRestBytes(UNS8 line, UNS32 nbBytes);
/**
* @brief Transmit a SDO frame on the bus bus_id
* @param *d Pointer on a CAN object data structure
* @param whoami Takes 2 values : SDO_CLIENT or SDO_SERVER
* @param CliServNbr Client or Server object involved
* @param data Array of the 8 bytes to transmit
* @return canSend(bus_id,&m) or 0xFF if error.
*/
UNS8 sendSDO(UNS8 whoami, UNS8 CliServNbr, UNS8 *pData);
/**
* @brief Transmit a SDO error to the client. The reasons may be :
* Read/Write to a undefined object
* Read/Write to a undefined subindex
* Read/write a not valid length object
* Write a read only object
* @param *d Pointer on a CAN object data structure
* @param whoami takes 2 values : SDO_CLIENT or SDO_SERVER
* @param CliServNbr
* @param index
* @param subIndex
* @param abortCode
* @return 0
*/
UNS8 sendSDOabort(UNS8 whoami, UNS8 CliServNbr, UNS16 index, UNS8 subIndex, UNS32 abortCode);
/**
* @brief Treat a SDO frame reception
* call the function sendSDO
* @param *d Pointer on a CAN object data structure
* @param *m Pointer on a CAN message structure
* @return code :
* - 0xFF if error
* - 0x80 if transfer aborted by the server
* - 0x0 ok
*/
UNS8 proceedSDO(Message *m);
/**
* @ingroup sdo
* @brief Used to send a SDO request frame to write the data at the index and subIndex indicated
* @param *d Pointer to a CAN object data structure
* @param nodeId Node Id of the slave
* @param index At index indicated
* @param subIndex At subIndex indicated
* @param count number of bytes to write in the dictionnary.
* @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value.
* @param *data Pointer to data
* @return
* - 0 is returned upon success.
* - 0xFE is returned when no sdo client to communicate with node.
* - 0xFF is returned when error occurs.
*/
UNS8 writeNetworkDict(UNS8 nodeId, UNS16 index,
UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, UNS8 useBlockMode);
/**
* @ingroup sdo
* @brief Used to send a SDO request frame to write in a distant node dictionnary.
* @details The function Callback which must be defined in the user code is called at the
* end of the exchange. (on succes or abort).
* @param *d Pointer to a CAN object data structure
* @param nodeId Node Id of the slave
* @param index At index indicated
* @param subIndex At subIndex indicated
* @param count number of bytes to write in the dictionnary.
* @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value.
* @param *data Pointer to data
* @param Callback Callback function
* @return
* - 0 is returned upon success.
* - 0xFE is returned when no sdo client to communicate with node.
* - 0xFF is returned when error occurs.
*/
UNS8 writeNetworkDictCallBack(UNS8 nodeId, UNS16 index,
UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 useBlockMode);
/**
* @ingroup sdo
* @brief Used to send a SDO request frame to write in a distant node dictionnary.
* @details The function Callback which must be defined in the user code is called at the
* end of the exchange. (on succes or abort). First free SDO client parameter is
* automatically initialized for specific node if not already defined.
* @param *d Pointer to a CAN object data structure
* @param nodeId Node Id of the slave
* @param index At index indicated
* @param subIndex At subIndex indicated
* @param count number of bytes to write in the dictionnary.
* @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value.
* @param *data Pointer to data
* @param Callback Callback function
* @param endianize When not 0, data is endianized into network byte order
* when 0, data is not endianized and copied in machine native
* endianness
* @return
* - 0 is returned upon success.
* - 0xFF is returned when error occurs.
*/
UNS8 writeNetworkDictCallBackAI(UNS8 nodeId, UNS16 index,
UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize, UNS8 useBlockMode);
/**
* @ingroup sdo
* @brief Used to send a SDO request frame to read.
* @param *d Pointer to a CAN object data structure
* @param nodeId Node Id of the slave
* @param index At index indicated
* @param subIndex At subIndex indicated
* @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value.
* @return
* - 0 is returned upon success.
* - 0xFE is returned when no sdo client to communicate with node.
* - 0xFF is returned when error occurs.
*/
UNS8 readNetworkDict(UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, UNS8 useBlockMode);
/**
* @ingroup sdo
* @brief Used to send a SDO request frame to read in a distant node dictionnary.
* @details The function Callback which must be defined in the user code is called at the
* end of the exchange. (on succes or abort).
* @param *d Pointer on a CAN object data structure
* @param nodeId Node Id of the slave
* @param index At index indicated
* @param subIndex At subIndex indicated
* @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value.
* @param Callback Callback function
* @return
* - 0 is returned upon success.
* - 0xFE is returned when no sdo client to communicate with node.
* - 0xFF is returned when error occurs.
*/
UNS8 readNetworkDictCallback(UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback, UNS8 useBlockMode);
/**
* @ingroup sdo
* @brief Used to send a SDO request frame to read in a distant node dictionnary.
* @details The function Callback which must be defined in the user code is called at the
* end of the exchange. (on succes or abort). First free SDO client parameter is
* automatically initialized for specific node if not already defined.
* @param *d Pointer on a CAN object data structure
* @param nodeId Node Id of the slave
* @param index At index indicated
* @param subIndex At subIndex indicated
* @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value.
* @param Callback Callback function
* @return
* - 0 is returned upon success.
* - 0xFF is returned when error occurs.
*/
UNS8 readNetworkDictCallbackAI(UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback, UNS8 useBlockMode);
/**
* @ingroup sdo
* @brief Use this function after calling readNetworkDict to get the result.
*
* @param *d Pointer to a CAN object data structure
* @param nodeId Node Id of the slave
* @param *data Pointer to the buffer to get the data
* @param *size Pointer to the size : MUST contain the size of the buffer before calling
* The function set it to the actual number of written bytes
* @param *abortCode Pointer to the abortcode. (0 = not available. Else : SDO abort code. (received if return SDO_ABORTED_RCV)
*
*
* @return
* - SDO_FINISHED // datas are available
* - SDO_ABORTED_RCV // Transfer failed (abort SDO received)
* - SDO_ABORTED_INTERNAL // Transfer failed (internal abort)
* - SDO_UPLOAD_IN_PROGRESS // Datas are not yet available
* - SDO_DOWNLOAD_IN_PROGRESS // Download is in progress
* - SDO_PROVIDED_BUFFER_TOO_SMALL //The value *size is not enough to store the received data
* \n\n
* example :
* @code
* UNS32 data;
* UNS8 size;
* readNetworkDict(0, 0x05, 0x1016, 1, 0) // get the data index 1016 subindex 1 of node 5
* while (getReadResultNetworkDict (0, 0x05, &data, &size) == SDO_UPLOAD_IN_PROGRESS);
* @endcode
*/
UNS8 getReadResultNetworkDict(UNS8 nodeId, void* data, UNS32 *size, UNS32 * abortCode);
/**
* @ingroup sdo
* @brief Use this function after calling writeNetworkDict function to get the result of the write.
* @details It is mandatory to call this function because it is releasing the line used for the transfer.
* @param *d Pointer to a CAN object data structure
* @param nodeId Node Id of the slave
* @param *abortCode Pointer to the abortcode
* - 0 = not available.
* - SDO abort code (received if return SDO_ABORTED_RCV)
*
* @return :
* - SDO_FINISHED // datas are available
* - SDO_ABORTED_RCV // Transfer failed (abort SDO received)
* - SDO_ABORTED_INTERNAL // Transfer failed (Internal abort)
* - SDO_DOWNLOAD_IN_PROGRESS // Datas are not yet available
* - SDO_UPLOAD_IN_PROGRESS // Upload in progress
* \n\n
* example :
* @code
* UNS32 data = 0x50;
* UNS8 size;
* UNS32 abortCode;
* writeNetworkDict(0, 0x05, 0x1016, 1, size, &data) // write the data index 1016 subindex 1 of node 5
* while (getWriteResultNetworkDict (0, 0x05, &abortCode) == SDO_DOWNLOAD_IN_PROGRESS);
* @endcode
*/
UNS8 getWriteResultNetworkDict(UNS8 nodeId, UNS32 * abortCode);
#endif