1 /**
2  * CANopen Service Data Object - server protocol.
3  *
4  * @file        CO_SDO.h
5  * @ingroup     CO_SDO
6  * @author      Janez Paternoster
7  * @copyright   2004 - 2020 Janez Paternoster
8  *
9  * This file is part of CANopenNode, an opensource CANopen Stack.
10  * Project home page is <https://github.com/CANopenNode/CANopenNode>.
11  * For more information on CANopen see <http://www.can-cia.org/>.
12  *
13  * Licensed under the Apache License, Version 2.0 (the "License");
14  * you may not use this file except in compliance with the License.
15  * You may obtain a copy of the License at
16  *
17  *     http://www.apache.org/licenses/LICENSE-2.0
18  *
19  * Unless required by applicable law or agreed to in writing, software
20  * distributed under the License is distributed on an "AS IS" BASIS,
21  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22  * See the License for the specific language governing permissions and
23  * limitations under the License.
24  */
25 
26 
27 #ifndef CO_SDO_H
28 #define CO_SDO_H
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 /**
35  * @defgroup CO_SDO SDO server
36  * @ingroup CO_CANopen
37  * @{
38  *
39  * CANopen Service Data Object - server protocol.
40  *
41  * Service data objects (SDOs) allow the access to any entry of the CANopen
42  * Object dictionary. An SDO establishes a peer-to-peer communication channel
43  * between two devices. In addition, the SDO protocol enables to transfer any
44  * amount of data in a segmented way. Therefore the SDO protocol is mainly used
45  * in order to communicate configuration data.
46  *
47  * All CANopen devices must have implemented SDO server and first SDO server
48  * channel. Servers serves data from Object dictionary. Object dictionary
49  * is a collection of variables, arrays or records (structures), which can be
50  * used by the stack or by the application. This file (CO_SDO.h) implements
51  * SDO server.
52  *
53  * SDO client can be (optionally) implemented on one (or multiple, if multiple
54  * SDO channels are used) device in CANopen network. Usually this is master
55  * device and provides also some kind of user interface, so configuration of
56  * the network is possible. Code for the SDO client is in file CO_SDOmaster.h.
57  *
58  * SDO communication cycle is initiated by the client. Client can upload (read) data
59  * from device or can download (write) data to device. If data are less or equal
60  * of 4 bytes long, communication is finished by one server response (expedited
61  * transfer). If data are longer, they are split into multiple segments of
62  * request/response pairs (normal or segmented transfer). For longer data there
63  * is also a block transfer protocol, which transfers larger block of data in
64  * secure way with little protocol overhead. If error occurs during SDO transfer
65  * #CO_SDO_abortCode_t is send by client or server and transfer is terminated.
66  */
67 
68 
69 /**
70  * @defgroup CO_SDO_messageContents SDO message contents
71  *
72  * Excerpt from CiA DS301, V4.2.
73  *
74  * For CAN identifier see #CO_Default_CAN_ID_t
75  *
76  * Expedited transfer is used for transmission of up to 4 data bytes. It consists
77  * of one SDO request and one response. For longer variables is used segmented
78  * or block transfer.
79  *
80  * ####Initiate SDO download (client request)
81  *  - byte 0:       SDO command specifier. 8 bits: `0010nnes` (nn: if e=s=1,
82  *                  number of data bytes, that do *not* contain data; e=1 for
83  *                  expedited transfer; s=1 if data size is indicated).
84  *  - byte 1..2:    Object index.
85  *  - byte 3:       Object subIndex.
86  *  - byte 4..7:    Expedited data or data size if segmented transfer.
87  *
88  * ####Initiate SDO download (server response)
89  *  - byte 0:       SDO command specifier. 8 bits: `01100000`.
90  *  - byte 1..2:    Object index.
91  *  - byte 3:       Object subIndex.
92  *  - byte 4..7:    reserved.
93  *
94  * ####Download SDO segment (client request)
95  *  - byte 0:       SDO command specifier. 8 bits: `000tnnnc` (t: toggle bit set
96  *                  to 0 in first segment; nnn: number of data bytes, that do
97  *                  *not* contain data; c=1 if this is the last segment).
98  *  - byte 1..7:    Data segment.
99  *
100  * ####Download SDO segment (server response)
101  *  - byte 0:       SDO command specifier. 8 bits: `001t0000` (t: toggle bit set
102  *                  to 0 in first segment).
103  *  - byte 1..7:    Reserved.
104  *
105  * ####Initiate SDO upload (client request)
106  *  - byte 0:       SDO command specifier. 8 bits: `01000000`.
107  *  - byte 1..2:    Object index.
108  *  - byte 3:       Object subIndex.
109  *  - byte 4..7:    Reserved.
110  *
111  * ####Initiate SDO upload (server response)
112  *  - byte 0:       SDO command specifier. 8 bits: `0100nnes` (nn: if e=s=1,
113  *                  number of data bytes, that do *not* contain data; e=1 for
114  *                  expedited transfer; s=1 if data size is indicated).
115  *  - byte 1..2:    Object index.
116  *  - byte 3:       Object subIndex.
117  *  - byte 4..7:    reserved.
118  *
119  * ####Upload SDO segment (client request)
120  *  - byte 0:       SDO command specifier. 8 bits: `011t0000` (t: toggle bit set
121  *                  to 0 in first segment).
122  *  - byte 1..7:    Reserved.
123  *
124  * ####Upload SDO segment (server response)
125  *  - byte 0:       SDO command specifier. 8 bits: `000tnnnc` (t: toggle bit set
126  *                  to 0 in first segment; nnn: number of data bytes, that do
127  *                  *not* contain data; c=1 if this is the last segment).
128  *  - byte 1..7:    Data segment.
129  *
130  * ####Abort SDO transfer (client or server)
131  *  - byte 0:       SDO command specifier. 8 bits: `10000000`.
132  *  - byte 1..2:    Object index.
133  *  - byte 3:       Object subIndex.
134  *  - byte 4..7:    #CO_SDO_abortCode_t.
135  *
136  * ####Block transfer
137  *     See DS301 V4.2.
138  */
139 
140 
141 /**
142  * SDO abort codes.
143  *
144  * Send with Abort SDO transfer message.
145  *
146  * The abort codes not listed here are reserved.
147  */
148 typedef enum{
149     CO_SDO_AB_NONE                  = 0x00000000UL, /**< 0x00000000, No abort */
150     CO_SDO_AB_TOGGLE_BIT            = 0x05030000UL, /**< 0x05030000, Toggle bit not altered */
151     CO_SDO_AB_TIMEOUT               = 0x05040000UL, /**< 0x05040000, SDO protocol timed out */
152     CO_SDO_AB_CMD                   = 0x05040001UL, /**< 0x05040001, Command specifier not valid or unknown */
153     CO_SDO_AB_BLOCK_SIZE            = 0x05040002UL, /**< 0x05040002, Invalid block size in block mode */
154     CO_SDO_AB_SEQ_NUM               = 0x05040003UL, /**< 0x05040003, Invalid sequence number in block mode */
155     CO_SDO_AB_CRC                   = 0x05040004UL, /**< 0x05040004, CRC error (block mode only) */
156     CO_SDO_AB_OUT_OF_MEM            = 0x05040005UL, /**< 0x05040005, Out of memory */
157     CO_SDO_AB_UNSUPPORTED_ACCESS    = 0x06010000UL, /**< 0x06010000, Unsupported access to an object */
158     CO_SDO_AB_WRITEONLY             = 0x06010001UL, /**< 0x06010001, Attempt to read a write only object */
159     CO_SDO_AB_READONLY              = 0x06010002UL, /**< 0x06010002, Attempt to write a read only object */
160     CO_SDO_AB_NOT_EXIST             = 0x06020000UL, /**< 0x06020000, Object does not exist */
161     CO_SDO_AB_NO_MAP                = 0x06040041UL, /**< 0x06040041, Object cannot be mapped to the PDO */
162     CO_SDO_AB_MAP_LEN               = 0x06040042UL, /**< 0x06040042, Number and length of object to be mapped exceeds PDO length */
163     CO_SDO_AB_PRAM_INCOMPAT         = 0x06040043UL, /**< 0x06040043, General parameter incompatibility reasons */
164     CO_SDO_AB_DEVICE_INCOMPAT       = 0x06040047UL, /**< 0x06040047, General internal incompatibility in device */
165     CO_SDO_AB_HW                    = 0x06060000UL, /**< 0x06060000, Access failed due to hardware error */
166     CO_SDO_AB_TYPE_MISMATCH         = 0x06070010UL, /**< 0x06070010, Data type does not match, length of service parameter does not match */
167     CO_SDO_AB_DATA_LONG             = 0x06070012UL, /**< 0x06070012, Data type does not match, length of service parameter too high */
168     CO_SDO_AB_DATA_SHORT            = 0x06070013UL, /**< 0x06070013, Data type does not match, length of service parameter too short */
169     CO_SDO_AB_SUB_UNKNOWN           = 0x06090011UL, /**< 0x06090011, Sub index does not exist */
170     CO_SDO_AB_INVALID_VALUE         = 0x06090030UL, /**< 0x06090030, Invalid value for parameter (download only). */
171     CO_SDO_AB_VALUE_HIGH            = 0x06090031UL, /**< 0x06090031, Value range of parameter written too high */
172     CO_SDO_AB_VALUE_LOW             = 0x06090032UL, /**< 0x06090032, Value range of parameter written too low */
173     CO_SDO_AB_MAX_LESS_MIN          = 0x06090036UL, /**< 0x06090036, Maximum value is less than minimum value. */
174     CO_SDO_AB_NO_RESOURCE           = 0x060A0023UL, /**< 0x060A0023, Resource not available: SDO connection */
175     CO_SDO_AB_GENERAL               = 0x08000000UL, /**< 0x08000000, General error */
176     CO_SDO_AB_DATA_TRANSF           = 0x08000020UL, /**< 0x08000020, Data cannot be transferred or stored to application */
177     CO_SDO_AB_DATA_LOC_CTRL         = 0x08000021UL, /**< 0x08000021, Data cannot be transferred or stored to application because of local control */
178     CO_SDO_AB_DATA_DEV_STATE        = 0x08000022UL, /**< 0x08000022, Data cannot be transferred or stored to application because of present device state */
179     CO_SDO_AB_DATA_OD               = 0x08000023UL, /**< 0x08000023, Object dictionary not present or dynamic generation fails */
180     CO_SDO_AB_NO_DATA               = 0x08000024UL  /**< 0x08000024, No data available */
181 }CO_SDO_abortCode_t;
182 
183 
184 /**
185  * @defgroup CO_SDO_objectDictionary Object dictionary
186  *
187  * CANopen Object dictionary implementation in CANopenNode.
188  *
189  * CANopen Object dictionary is a collection of different data items, which can
190  * be used by the stack or by the application.
191  *
192  * Each Object dictionary entry is located under 16-bit index, as specified
193  * by the CANopen:
194  *  - 0x0001..0x025F: Data type definitions.
195  *  - 0x1000..0x1FFF: Communication profile area.
196  *  - 0x2000..0x5FFF: Manufacturer-specific profile area.
197  *  - 0x6000..0x9FFF: Standardized device profile area for eight logical devices.
198  *  - 0xA000..0xAFFF: Standardized network variable area.
199  *  - 0xB000..0xBFFF: Standardized system variable area.
200  *  - Other:          Reserved.
201  *
202  * If Object dictionary entry has complex data type (array or structure),
203  * then 8-bit subIndex specifies the sub-member of the entry. In that case
204  * subIndex 0x00 is encoded as uint8_t and specifies the highest available
205  * subIndex with that entry. Subindex 0xFF has special meaning in the standard
206  * and is not supported by CANopenNode.
207  *
208  * ####Object type of one Object dictionary entry
209  *  - NULL:         Not used by CANopenNode.
210  *  - DOMAIN:       Block of data of variable length. Data and length are
211  *                  under control of the application.
212  *  - DEFTYPE:      Definition of CANopen basic data type, for example
213  *                  INTEGER16.
214  *  - DEFSTRUCT:    Definition of complex data type - structure, which is
215  *                  used with RECORD.
216  *  - VAR:          Variable of CANopen basic data type. Subindex is 0.
217  *  - ARRAY:        Array of multiple variables of the same CANopen basic
218  *                  data type. Subindex 1..arrayLength specifies sub-member.
219  *  - RECORD:       Record or structure of multiple variables of different
220  *                  CANopen basic data type. Subindex specifies sub-member.
221  *
222  *
223  * ####Implementation in CANopenNode
224  * Object dictionary in CANopenNode is implemented in CO_OD.h and CO_OD.c files.
225  * These files are application specific and must be generated by Object
226  * dictionary editor (application is included by the stack).
227  *
228  * CO_OD.h and CO_OD.c files include:
229  *  - Structure definitions for records.
230  *  - Global declaration and initialization of all variables, arrays and records
231  *    mapped to Object dictionary. Variables are distributed in multiple objects,
232  *    depending on memory location. This eases storage to different memories in
233  *    microcontroller, like eeprom or flash.
234  *  - Constant array of multiple Object dictionary entries of type
235  *    CO_OD_entry_t. If object type is record, then entry includes additional
236  *    constant array with members of type CO_OD_entryRecord_t. Each OD entry
237  *    includes information: index, maxSubIndex, #CO_SDO_OD_attributes_t, data size and
238  *    pointer to variable.
239  *
240  *
241  * Function CO_SDO_init() initializes object CO_SDO_t, which includes SDO
242  * server and Object dictionary.
243  *
244  * Application doesn't need to know anything about the Object dictionary. It can
245  * use variables specified in CO_OD.h file directly. If it needs more control
246  * over the CANopen communication with the variables, it can configure additional
247  * functionality with function CO_OD_configure(). Additional functionality
248  * include: @ref CO_SDO_OD_function and #CO_SDO_OD_flags_t.
249  *
250  * Interface to Object dictionary is provided by following functions: CO_OD_find()
251  * finds OD entry by index, CO_OD_getLength() returns length of variable,
252  * CO_OD_getAttribute returns attribute and CO_OD_getDataPointer() returns pointer
253  * to data. These functions are used by SDO server and by PDO configuration. They
254  * can also be used to access the OD by index like this.
255  *
256  * \code{.c}
257  * index = CO_OD_find(CO->SDO[0], OD_H1001_ERR_REG);
258  * if (index == 0xffff) {
259  *     return;
260  * }
261  * length = CO_OD_getLength(CO->SDO[0], index, 1);
262  * if (length != sizeof(new_data)) {
263  *    return;
264  * }
265  *
266  * p = CO_OD_getDataPointer(CO->SDO[0], index, 1);
267  * if (p == NULL) {
268  *     return;
269  * }
270  * CO_LOCK_OD();
271  * *p = new_data;
272  * CO_UNLOCK_OD();
273  * \endcode
274  *
275  * Be aware that accessing the OD directly using CO_OD.h files is more CPU
276  * efficient as CO_OD_find() has to do a search everytime it is called.
277  *
278  */
279 
280 
281 /**
282  * @defgroup CO_SDO_OD_function Object Dictionary function
283  *
284  * Optional application specific function, which may manipulate data downloaded
285  * or uploaded via SDO.
286  *
287  * Object dictionary function is external function defined by application or
288  * by other stack files. It may be registered for specific Object dictionary
289  * entry (with specific index). If it is registered, it is called (through
290  * function pointer) from SDO server. It may verify and manipulate data during
291  * SDO transfer. Object dictionary function can be registered by function
292  * CO_OD_configure().
293  *
294  * ####SDO download (writing to Object dictionary)
295  *     After SDO client transfers data to the server, data are stored in internal
296  *     buffer. If data contains multibyte variable and processor is big endian,
297  *     then data bytes are swapped. Object dictionary function is called if
298  *     registered. Data may be verified and manipulated inside that function. After
299  *     function exits, data are copied to location as specified in CO_OD_entry_t.
300  *
301  * ####SDO upload (reading from Object dictionary)
302  *     Before start of SDO upload, data are read from Object dictionary into
303  *     internal buffer. If necessary, bytes are swapped.
304  *     Object dictionary function is called if registered. Data may be
305  *     manipulated inside that function. After function exits, data are
306  *     transferred via SDO server.
307  *
308  * ####Domain data type
309  *     If data type is domain, then length is not specified by Object dictionary.
310  *     In that case Object dictionary function must be used. In case of
311  *     download it must store the data in own location. In case of upload it must
312  *     write the data (maximum size is specified by length) into data buffer and
313  *     specify actual length. With domain data type it is possible to transfer
314  *     data, which are longer than #CO_SDO_BUFFER_SIZE. In that case
315  *     Object dictionary function is called multiple times between SDO transfer.
316  *
317  * ####Parameter to function:
318  *     ODF_arg     - Pointer to CO_ODF_arg_t object filled before function call.
319  *
320  * ####Return from function:
321  *  - 0: Data transfer is successful
322  *  - Different than 0: Failure. See #CO_SDO_abortCode_t.
323  */
324 
325 
326 /**
327  * SDO buffer size.
328  *
329  * Size of the internal SDO buffer.
330  *
331  * Size must be at least equal to size of largest variable in @ref CO_SDO_objectDictionary.
332  * If data type is domain, data length is not limited to SDO buffer size. If
333  * block transfer is implemented, value should be set to 889.
334  *
335  * Value can be in range from 7 to 889 bytes.
336  */
337     #ifndef CO_SDO_BUFFER_SIZE
338         #define CO_SDO_BUFFER_SIZE    32
339     #endif
340 
341 /**
342  * Size of fifo queue for SDO received messages.
343  *
344  * If block transfers are used size of fifo queue should be more that 1 message
345  * to avoid possible drops in consecutive SDO block upload transfers.
346  * To increase performance, value can be set to 1 if block transfers are not used
347  *
348  * Min value is 1.
349  */
350     #ifndef CO_SDO_RX_DATA_SIZE
351         #define CO_SDO_RX_DATA_SIZE   2
352     #endif
353 
354 /**
355  * Object Dictionary attributes. Bit masks for attribute in CO_OD_entry_t.
356  */
357 typedef enum{
358     CO_ODA_MEM_ROM          = 0x0001U,  /**< Variable is located in ROM memory */
359     CO_ODA_MEM_RAM          = 0x0002U,  /**< Variable is located in RAM memory */
360     CO_ODA_MEM_EEPROM       = 0x0003U,  /**< Variable is located in EEPROM memory */
361     CO_ODA_READABLE         = 0x0004U,  /**< SDO server may read from the variable */
362     CO_ODA_WRITEABLE        = 0x0008U,  /**< SDO server may write to the variable */
363     CO_ODA_RPDO_MAPABLE     = 0x0010U,  /**< Variable is mappable for RPDO */
364     CO_ODA_TPDO_MAPABLE     = 0x0020U,  /**< Variable is mappable for TPDO */
365     CO_ODA_TPDO_DETECT_COS  = 0x0040U,  /**< If variable is mapped to any PDO, then
366                                              PDO is automatically send, if variable
367                                              changes its value */
368     CO_ODA_MB_VALUE         = 0x0080U   /**< True when variable is a multibyte value */
369 }CO_SDO_OD_attributes_t;
370 
371 
372 /**
373  * Common DS301 object dictionary entries.
374  */
375 typedef enum{
376     OD_H1000_DEV_TYPE             = 0x1000U,/**< Device type */
377     OD_H1001_ERR_REG              = 0x1001U,/**< Error register */
378     OD_H1002_MANUF_STATUS_REG     = 0x1002U,/**< Manufacturer status register */
379     OD_H1003_PREDEF_ERR_FIELD     = 0x1003U,/**< Predefined error field */
380     OD_H1004_RSV                  = 0x1004U,/**< Reserved */
381     OD_H1005_COBID_SYNC           = 0x1005U,/**< Sync message cob-id */
382     OD_H1006_COMM_CYCL_PERIOD     = 0x1006U,/**< Communication cycle period */
383     OD_H1007_SYNC_WINDOW_LEN      = 0x1007U,/**< Sync windows length */
384     OD_H1008_MANUF_DEV_NAME       = 0x1008U,/**< Manufacturer device name */
385     OD_H1009_MANUF_HW_VERSION     = 0x1009U,/**< Manufacturer hardware version */
386     OD_H100A_MANUF_SW_VERSION     = 0x100AU,/**< Manufacturer software version */
387     OD_H100B_RSV                  = 0x100BU,/**< Reserved */
388     OD_H100C_GUARD_TIME           = 0x100CU,/**< Guard time */
389     OD_H100D_LIFETIME_FACTOR      = 0x100DU,/**< Life time factor */
390     OD_H100E_RSV                  = 0x100EU,/**< Reserved */
391     OD_H100F_RSV                  = 0x100FU,/**< Reserved */
392     OD_H1010_STORE_PARAM_FUNC     = 0x1010U,/**< Store parameter in persistent memory function */
393     OD_H1011_REST_PARAM_FUNC      = 0x1011U,/**< Restore default parameter function */
394     OD_H1012_COBID_TIME           = 0x1012U,/**< Timestamp message cob-id */
395     OD_H1013_HIGH_RES_TIMESTAMP   = 0x1013U,/**< High resolution timestamp */
396     OD_H1014_COBID_EMERGENCY      = 0x1014U,/**< Emergency message cob-id */
397     OD_H1015_INHIBIT_TIME_MSG     = 0x1015U,/**< Inhibit time message */
398     OD_H1016_CONSUMER_HB_TIME     = 0x1016U,/**< Consumer heartbeat time */
399     OD_H1017_PRODUCER_HB_TIME     = 0x1017U,/**< Producer heartbeat time */
400     OD_H1018_IDENTITY_OBJECT      = 0x1018U,/**< Identity object */
401     OD_H1019_SYNC_CNT_OVERFLOW    = 0x1019U,/**< Sync counter overflow value */
402     OD_H1020_VERIFY_CONFIG        = 0x1020U,/**< Verify configuration */
403     OD_H1021_STORE_EDS            = 0x1021U,/**< Store EDS */
404     OD_H1022_STORE_FORMAT         = 0x1022U,/**< Store format */
405     OD_H1023_OS_CMD               = 0x1023U,/**< OS command */
406     OD_H1024_OS_CMD_MODE          = 0x1024U,/**< OS command mode */
407     OD_H1025_OS_DBG_INTERFACE     = 0x1025U,/**< OS debug interface */
408     OD_H1026_OS_PROMPT            = 0x1026U,/**< OS prompt */
409     OD_H1027_MODULE_LIST          = 0x1027U,/**< Module list */
410     OD_H1028_EMCY_CONSUMER        = 0x1028U,/**< Emergency consumer object */
411     OD_H1029_ERR_BEHAVIOR         = 0x1029U,/**< Error behaviour */
412     OD_H1200_SDO_SERVER_PARAM     = 0x1200U,/**< SDO server parameters */
413     OD_H1280_SDO_CLIENT_PARAM     = 0x1280U,/**< SDO client parameters */
414     OD_H1400_RXPDO_1_PARAM        = 0x1400U,/**< RXPDO communication parameter */
415     OD_H1401_RXPDO_2_PARAM        = 0x1401U,/**< RXPDO communication parameter */
416     OD_H1402_RXPDO_3_PARAM        = 0x1402U,/**< RXPDO communication parameter */
417     OD_H1403_RXPDO_4_PARAM        = 0x1403U,/**< RXPDO communication parameter */
418     OD_H1600_RXPDO_1_MAPPING      = 0x1600U,/**< RXPDO mapping parameters */
419     OD_H1601_RXPDO_2_MAPPING      = 0x1601U,/**< RXPDO mapping parameters */
420     OD_H1602_RXPDO_3_MAPPING      = 0x1602U,/**< RXPDO mapping parameters */
421     OD_H1603_RXPDO_4_MAPPING      = 0x1603U,/**< RXPDO mapping parameters */
422     OD_H1800_TXPDO_1_PARAM        = 0x1800U,/**< TXPDO communication parameter */
423     OD_H1801_TXPDO_2_PARAM        = 0x1801U,/**< TXPDO communication parameter */
424     OD_H1802_TXPDO_3_PARAM        = 0x1802U,/**< TXPDO communication parameter */
425     OD_H1803_TXPDO_4_PARAM        = 0x1803U,/**< TXPDO communication parameter */
426     OD_H1A00_TXPDO_1_MAPPING      = 0x1A00U,/**< TXPDO mapping parameters */
427     OD_H1A01_TXPDO_2_MAPPING      = 0x1A01U,/**< TXPDO mapping parameters */
428     OD_H1A02_TXPDO_3_MAPPING      = 0x1A02U,/**< TXPDO mapping parameters */
429     OD_H1A03_TXPDO_4_MAPPING      = 0x1A03U /**< TXPDO mapping parameters */
430 }CO_ObjDicId_t;
431 
432 
433 /**
434  * Bit masks for flags associated with variable from @ref CO_SDO_objectDictionary.
435  *
436  * This additional functionality of any variable in @ref CO_SDO_objectDictionary can be
437  * enabled by function CO_OD_configure(). Location of the flag byte can be
438  * get from function CO_OD_getFlagsPointer().
439  */
440 typedef enum{
441     /** Variable was written by RPDO. Flag can be cleared by application */
442     CO_ODFL_RPDO_WRITTEN        = 0x01U,
443     /** Variable is mapped to TPDO */
444     CO_ODFL_TPDO_MAPPED         = 0x02U,
445     /** Change of state bit, initially copy of attribute from CO_OD_entry_t.
446     If set and variable is mapped to TPDO, TPDO will be automatically send,
447     if variable changed */
448     CO_ODFL_TPDO_COS_ENABLE     = 0x04U,
449     /** PDO send bit, can be set by application. If variable is mapped into
450     TPDO, TPDO will be send and bit will be cleared. */
451     CO_ODFL_TPDO_SEND           = 0x08U,
452     /** Variable was accessed by SDO download */
453     CO_ODFL_SDO_DOWNLOADED      = 0x10U,
454     /** Variable was accessed by SDO upload */
455     CO_ODFL_SDO_UPLOADED        = 0x20U,
456     /** Reserved */
457     CO_ODFL_BIT_6               = 0x40U,
458     /** Reserved */
459     CO_ODFL_BIT_7               = 0x80U
460 }CO_SDO_OD_flags_t;
461 
462 
463 /**
464  * Internal states of the SDO server state machine
465  */
466 typedef enum {
467     CO_SDO_ST_IDLE                   = 0x00U,
468     CO_SDO_ST_DOWNLOAD_INITIATE      = 0x11U,
469     CO_SDO_ST_DOWNLOAD_SEGMENTED     = 0x12U,
470     CO_SDO_ST_DOWNLOAD_BL_INITIATE   = 0x14U,
471     CO_SDO_ST_DOWNLOAD_BL_SUBBLOCK   = 0x15U,
472     CO_SDO_ST_DOWNLOAD_BL_SUB_RESP   = 0x16U,
473     CO_SDO_ST_DOWNLOAD_BL_SUB_RESP_2 = 0x17U,
474     CO_SDO_ST_DOWNLOAD_BL_END        = 0x18U,
475     CO_SDO_ST_UPLOAD_INITIATE        = 0x21U,
476     CO_SDO_ST_UPLOAD_SEGMENTED       = 0x22U,
477     CO_SDO_ST_UPLOAD_BL_INITIATE     = 0x24U,
478     CO_SDO_ST_UPLOAD_BL_INITIATE_2   = 0x25U,
479     CO_SDO_ST_UPLOAD_BL_SUBBLOCK     = 0x26U,
480     CO_SDO_ST_UPLOAD_BL_END          = 0x27U
481 } CO_SDO_state_t;
482 
483 
484 /**
485  * Object for one entry with specific index in @ref CO_SDO_objectDictionary.
486  */
487 typedef struct {
488     /** The index of Object from 0x1000 to 0xFFFF */
489     uint16_t            index;
490     /** Number of (sub-objects - 1). If Object Type is variable, then
491     maxSubIndex is 0, otherwise maxSubIndex is equal or greater than 1. */
492     uint8_t             maxSubIndex;
493     /** If Object Type is record, attribute is set to zero. Attribute for
494     each member is then set in special array with members of type
495     CO_OD_entryRecord_t. If Object Type is Array, attribute is common for
496     all array members. See #CO_SDO_OD_attributes_t. */
497     uint16_t            attribute;
498     /** If Object Type is Variable, length is the length of variable in bytes.
499     If Object Type is Array, length is the length of one array member.
500     If Object Type is Record, length is zero. Length for each member is
501     set in special array with members of type CO_OD_entryRecord_t.
502     If Object Type is Domain, length is zero. Length is specified
503     by application in @ref CO_SDO_OD_function. */
504     uint16_t            length;
505     /** If Object Type is Variable, pData is pointer to data.
506     If Object Type is Array, pData is pointer to data. Data doesn't
507     include Sub-Object 0.
508     If object type is Record, pData is pointer to special array
509     with members of type CO_OD_entryRecord_t.
510     If object type is Domain, pData is null. */
511     void               *pData;
512 }CO_OD_entry_t;
513 
514 
515 /**
516  * Object for record type entry in @ref CO_SDO_objectDictionary.
517  *
518  * See CO_OD_entry_t.
519  */
520 typedef struct{
521     /** See #CO_SDO_OD_attributes_t */
522     void               *pData;
523     /** Length of variable in bytes. If object type is Domain, length is zero */
524     uint16_t            attribute;
525     /** Pointer to data. If object type is Domain, pData is null */
526     uint16_t            length;
527 }CO_OD_entryRecord_t;
528 
529 
530 /**
531  * Object contains all information about the object being transferred by SDO server.
532  *
533  * Object is used as an argument to @ref CO_SDO_OD_function. It is also
534  * part of the CO_SDO_t object.
535  */
536 typedef struct{
537     /** Informative parameter. It may point to object, which is connected
538     with this OD entry. It can be used inside @ref CO_SDO_OD_function, ONLY
539     if it was registered by CO_OD_configure() function before. */
540     void               *object;
541     /** SDO data buffer contains data, which are exchanged in SDO transfer.
542     @ref CO_SDO_OD_function may verify or manipulate that data before (after)
543     they are written to (read from) Object dictionary. Data have the same
544     endianes as processor. Pointer must NOT be changed. (Data up to length
545     can be changed.) */
546     uint8_t            *data;
547     /** Pointer to location in object dictionary, where data are stored.
548     (informative reference to old data, read only). Data have the same
549     endianes as processor. If data type is Domain, this variable is null. */
550     const void         *ODdataStorage;
551     /** Length of data in the above buffer. Read only, except for domain. If
552     data type is domain see @ref CO_SDO_OD_function for special rules by upload. */
553     uint16_t            dataLength;
554     /** Attribute of object in Object dictionary (informative, must NOT be changed). */
555     uint16_t            attribute;
556     /** Pointer to the #CO_SDO_OD_flags_t byte. */
557     uint8_t            *pFlags;
558     /** Index of object in Object dictionary (informative, must NOT be changed). */
559     uint16_t            index;
560     /** Subindex of object in Object dictionary (informative, must NOT be changed). */
561     uint8_t             subIndex;
562     /** True, if SDO upload is in progress, false if SDO download is in progress. */
563     bool_t              reading;
564     /** Used by domain data type. Indicates the first segment. Variable is informative. */
565     bool_t              firstSegment;
566     /** Used by domain data type. If false by download, then application will
567     receive more segments during SDO communication cycle. If uploading,
568     application may set variable to false, so SDO server will call
569     @ref CO_SDO_OD_function again for filling the next data. */
570     bool_t              lastSegment;
571     /** Used by domain data type. By upload @ref CO_SDO_OD_function may write total
572     data length, so this information will be send in SDO upload initiate phase. It
573     is not necessary to specify this variable. By download this variable contains
574     total data size, if size is indicated in SDO download initiate phase */
575     uint32_t            dataLengthTotal;
576     /** Used by domain data type. In case of multiple segments, this indicates the offset
577     into the buffer this segment starts at. */
578     uint32_t            offset;
579 }CO_ODF_arg_t;
580 
581 
582 /**
583  * Object is used as array inside CO_SDO_t, parallel to @ref CO_SDO_objectDictionary.
584  *
585  * Object is generated by function CO_OD_configure(). It is then used as
586  * extension to Object dictionary entry at specific index.
587  */
588 typedef struct{
589     /** Pointer to @ref CO_SDO_OD_function */
590     CO_SDO_abortCode_t (*pODFunc)(CO_ODF_arg_t *ODF_arg);
591     /** Pointer to object, which will be passed to @ref CO_SDO_OD_function */
592     void               *object;
593     /** Pointer to #CO_SDO_OD_flags_t. If object type is array or record, this
594     variable points to array with length equal to number of subindexes. */
595     uint8_t            *flags;
596 }CO_OD_extension_t;
597 
598 
599 /**
600  * SDO server object.
601  */
602 typedef struct{
603     /** FIFO queue of the received message 8 data bytes each */
604     uint8_t             CANrxData[CO_SDO_RX_DATA_SIZE][8];
605     /** SDO data buffer of size #CO_SDO_BUFFER_SIZE. */
606     uint8_t             databuffer[CO_SDO_BUFFER_SIZE];
607     /** Internal flag indicates, that this object has own OD */
608     bool_t              ownOD;
609     /** Pointer to the @ref CO_SDO_objectDictionary (array) */
610     const CO_OD_entry_t *OD;
611     /** Size of the @ref CO_SDO_objectDictionary */
612     uint16_t            ODSize;
613     /** Pointer to array of CO_OD_extension_t objects. Size of the array is
614     equal to ODSize. */
615     CO_OD_extension_t  *ODExtensions;
616     /** Offset in buffer of next data segment being read/written */
617     uint16_t            bufferOffset;
618     /** Sequence number of OD entry as returned from CO_OD_find() */
619     uint16_t            entryNo;
620     /** CO_ODF_arg_t object with additional variables. Reference to this object
621     is passed to @ref CO_SDO_OD_function */
622     CO_ODF_arg_t        ODF_arg;
623     /** From CO_SDO_init() */
624     uint8_t             nodeId;
625     /** Current internal state of the SDO server state machine #CO_SDO_state_t */
626     CO_SDO_state_t      state;
627     /** Toggle bit in segmented transfer or block sequence in block transfer */
628     uint8_t             sequence;
629     /** Timeout timer for SDO communication */
630     uint16_t            timeoutTimer;
631     /** Number of segments per block with 1 <= blksize <= 127 */
632     uint8_t             blksize;
633     /** True, if CRC calculation by block transfer is enabled */
634     bool_t              crcEnabled;
635     /** Calculated CRC code */
636     uint16_t            crc;
637     /** Length of data in the last segment in block upload */
638     uint8_t             lastLen;
639     /** Indication timeout in sub-block transfer */
640     bool_t              timeoutSubblockDownolad;
641     /** Indication end of block transfer */
642     bool_t              endOfTransfer;
643     /** Variables indicates, if new SDO message received from CAN bus */
644     volatile void      *CANrxNew[CO_SDO_RX_DATA_SIZE];
645     /** Index of CANrxData for new received SDO message */
646     uint8_t             CANrxRcv;
647     /** Index of CANrxData SDO message to processed */
648     uint8_t             CANrxProc;
649     /** Number of new SDO messages in CANrxData to process */
650     uint8_t             CANrxSize;
651     /** From CO_SDO_initCallback() or NULL */
652     void              (*pFunctSignal)(void);
653     /** From CO_SDO_init() */
654     CO_CANmodule_t     *CANdevTx;
655     /** CAN transmit buffer inside CANdev for CAN tx message */
656     CO_CANtx_t         *CANtxBuff;
657 }CO_SDO_t;
658 
659 
660 /**
661  * Helper union for manipulating data bytes.
662  */
663 typedef union{
664     uint8_t  u8[8];  /**< 8 bytes */
665     uint16_t u16[4]; /**< 4 words */
666     uint32_t u32[2]; /**< 2 double words */
667 }CO_bytes_t;
668 
669 
670 /**
671  * Helper function like memcpy.
672  *
673  * Function copies n data bytes from source to destination.
674  *
675  * @param dest Destination location.
676  * @param src Source location.
677  * @param size Number of data bytes to be copied (max 0xFFFF).
678  */
679 void CO_memcpy(uint8_t dest[], const uint8_t src[], const uint16_t size);
680 
681 /**
682  * Helper function like memset.
683  *
684  * Function fills destination with char "c".
685  *
686  * @param dest Destination location.
687  * @param c set value.
688  * @param size Number of data bytes to be copied (max 0xFFFF).
689  */
690 void CO_memset(uint8_t dest[], uint8_t c, const uint16_t size);
691 
692 
693 /**
694  * Helper function returns uint16 from byte array.
695  *
696  * @param data Location of source data.
697  * @return Variable of type uint16_t.
698  */
699 uint16_t CO_getUint16(const uint8_t data[]);
700 
701 
702 /**
703  * Helper function returns uint32 from byte array.
704  *
705  * @param data Location of source data.
706  * @return Variable of type uint32_t.
707  */
708 uint32_t CO_getUint32(const uint8_t data[]);
709 
710 
711 /**
712  * Helper function writes uint16 to byte array.
713  *
714  * @param data Location of destination data.
715  * @param value Variable of type uint16_t to be written into data.
716  */
717 void CO_setUint16(uint8_t data[], const uint16_t value);
718 
719 
720 /**
721  * Helper function writes uint32 to byte array.
722  *
723  * @param data Location of destination data.
724  * @param value Variable of type uint32_t to be written into data.
725  */
726 void CO_setUint32(uint8_t data[], const uint32_t value);
727 
728 
729 /**
730  * Copy 2 data bytes from source to destination. Swap bytes if
731  * microcontroller is big-endian.
732  *
733  * @param dest Destination location.
734  * @param src Source location.
735  */
736 void CO_memcpySwap2(void* dest, const void* src);
737 
738 
739 /**
740  * Copy 4 data bytes from source to destination. Swap bytes if
741  * microcontroller is big-endian.
742  *
743  * @param dest Destination location.
744  * @param src Source location.
745  */
746 void CO_memcpySwap4(void* dest, const void* src);
747 
748 
749 /**
750  * Copy 8 data bytes from source to destination. Swap bytes if
751  * microcontroller is big-endian.
752  *
753  * @param dest Destination location.
754  * @param src Source location.
755  */
756 void CO_memcpySwap8(void* dest, const void* src);
757 
758 
759 /**
760  * Initialize SDO object.
761  *
762  * Function must be called in the communication reset section.
763  *
764  * @param SDO This object will be initialized.
765  * @param COB_IDClientToServer COB ID for client to server for this SDO object.
766  * @param COB_IDServerToClient COB ID for server to client for this SDO object.
767  * @param ObjDictIndex_SDOServerParameter Index in Object dictionary.
768  * @param parentSDO Pointer to SDO object, which contains object dictionary and
769  * its extension. For first (default) SDO object this argument must be NULL.
770  * If this argument is specified, then OD, ODSize and ODExtensions arguments
771  * are ignored.
772  * @param OD Pointer to @ref CO_SDO_objectDictionary array defined externally.
773  * @param ODSize Size of the above array.
774  * @param ODExtensions Pointer to the externally defined array of the same size
775  * as ODSize.
776  * @param nodeId CANopen Node ID of this device.
777  * @param CANdevRx CAN device for SDO server reception.
778  * @param CANdevRxIdx Index of receive buffer in the above CAN device.
779  * @param CANdevTx CAN device for SDO server transmission.
780  * @param CANdevTxIdx Index of transmit buffer in the above CAN device.
781  *
782  * @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
783  */
784 CO_ReturnError_t CO_SDO_init(
785         CO_SDO_t               *SDO,
786         uint32_t                COB_IDClientToServer,
787         uint32_t                COB_IDServerToClient,
788         uint16_t                ObjDictIndex_SDOServerParameter,
789         CO_SDO_t               *parentSDO,
790         const CO_OD_entry_t     OD[],
791         uint16_t                ODSize,
792         CO_OD_extension_t       ODExtensions[],
793         uint8_t                 nodeId,
794         CO_CANmodule_t         *CANdevRx,
795         uint16_t                CANdevRxIdx,
796         CO_CANmodule_t         *CANdevTx,
797         uint16_t                CANdevTxIdx);
798 
799 
800 /**
801  * Initialize SDOrx callback function.
802  *
803  * Function initializes optional callback function, which is called after new
804  * message is received from the CAN bus. Function may wake up external task,
805  * which processes mainline CANopen functions.
806  *
807  * @param SDO This object.
808  * @param pFunctSignal Pointer to the callback function. Not called if NULL.
809  */
810 void CO_SDO_initCallback(
811         CO_SDO_t               *SDO,
812         void                  (*pFunctSignal)(void));
813 
814 
815 /**
816  * Process SDO communication.
817  *
818  * Function must be called cyclically.
819  *
820  * @param SDO This object.
821  * @param NMTisPreOrOperational Different than zero, if #CO_NMT_internalState_t is
822  * NMT_PRE_OPERATIONAL or NMT_OPERATIONAL.
823  * @param timeDifference_ms Time difference from previous function call in [milliseconds].
824  * @param SDOtimeoutTime Timeout time for SDO communication in milliseconds.
825  * @param timerNext_ms Return value - info to OS - see CO_process().
826  *
827  * @return 0: SDO server is idle.
828  * @return 1: SDO server is in transfer state.
829  * @return -1: SDO abort just occurred.
830  */
831 int8_t CO_SDO_process(
832         CO_SDO_t               *SDO,
833         bool_t                  NMTisPreOrOperational,
834         uint16_t                timeDifference_ms,
835         uint16_t                SDOtimeoutTime,
836         uint16_t               *timerNext_ms);
837 
838 
839 /**
840  * Configure additional functionality to one @ref CO_SDO_objectDictionary entry.
841  *
842  * Additional functionality include: @ref CO_SDO_OD_function and
843  * #CO_SDO_OD_flags_t. It is optional feature and can be used on any object in
844  * Object dictionary. If OD entry does not exist, function returns silently.
845  *
846  * @param SDO This object.
847  * @param index Index of object in the Object dictionary.
848  * @param pODFunc Pointer to @ref CO_SDO_OD_function, specified by application.
849  * If NULL, @ref CO_SDO_OD_function will not be used on this object.
850  * @param object Pointer to object, which will be passed to @ref CO_SDO_OD_function.
851  * @param flags Pointer to array of #CO_SDO_OD_flags_t defined externally. If
852  * zero, #CO_SDO_OD_flags_t will not be used on this OD entry.
853  * @param flagsSize Size of the above array. It must be equal to number
854  * of sub-objects in object dictionary entry. Otherwise #CO_SDO_OD_flags_t will
855  * not be used on this OD entry.
856  */
857 void CO_OD_configure(
858         CO_SDO_t               *SDO,
859         uint16_t                index,
860         CO_SDO_abortCode_t    (*pODFunc)(CO_ODF_arg_t *ODF_arg),
861         void                   *object,
862         uint8_t                *flags,
863         uint8_t                 flagsSize);
864 
865 
866 /**
867  * Find object with specific index in Object dictionary.
868  *
869  * @param SDO This object.
870  * @param index Index of the object in Object dictionary.
871  *
872  * @return Sequence number of the @ref CO_SDO_objectDictionary entry, 0xFFFF if not found.
873  */
874 uint16_t CO_OD_find(CO_SDO_t *SDO, uint16_t index);
875 
876 
877 /**
878  * Get length of the given object with specific subIndex.
879  *
880  * @param SDO This object.
881  * @param entryNo Sequence number of OD entry as returned from CO_OD_find().
882  * @param subIndex Sub-index of the object in Object dictionary.
883  *
884  * @return Data length of the variable.
885  */
886 uint16_t CO_OD_getLength(CO_SDO_t *SDO, uint16_t entryNo, uint8_t subIndex);
887 
888 
889 /**
890  * Get attribute of the given object with specific subIndex. See #CO_SDO_OD_attributes_t.
891  *
892  * If Object Type is array and subIndex is zero, function always returns
893  * 'read-only' attribute. An exception to this rule is ID1003 (Error field).
894  * However, this is supposed to be only written by network.
895  *
896  * @param SDO This object.
897  * @param entryNo Sequence number of OD entry as returned from CO_OD_find().
898  * @param subIndex Sub-index of the object in Object dictionary.
899  *
900  * @return Attribute of the variable.
901  */
902 uint16_t CO_OD_getAttribute(CO_SDO_t *SDO, uint16_t entryNo, uint8_t subIndex);
903 
904 
905 /**
906  * Get pointer to data of the given object with specific subIndex.
907  *
908  * If Object Type is array and subIndex is zero, function returns pointer to
909  * object->maxSubIndex variable.
910  *
911  * @param SDO This object.
912  * @param entryNo Sequence number of OD entry as returned from CO_OD_find().
913  * @param subIndex Sub-index of the object in Object dictionary.
914  *
915  * @return Pointer to the variable in @ref CO_SDO_objectDictionary.
916  */
917 void* CO_OD_getDataPointer(CO_SDO_t *SDO, uint16_t entryNo, uint8_t subIndex);
918 
919 
920 /**
921  * Get pointer to the #CO_SDO_OD_flags_t byte of the given object with
922  * specific subIndex.
923  *
924  * @param SDO This object.
925  * @param entryNo Sequence number of OD entry as returned from CO_OD_find().
926  * @param subIndex Sub-index of the object in Object dictionary.
927  *
928  * @return Pointer to the #CO_SDO_OD_flags_t of the variable.
929  */
930 uint8_t* CO_OD_getFlagsPointer(CO_SDO_t *SDO, uint16_t entryNo, uint8_t subIndex);
931 
932 
933 /**
934  * Initialize SDO transfer.
935  *
936  * Find object in OD, verify, fill ODF_arg s.
937  *
938  * @param SDO This object.
939  * @param index Index of the object in Object dictionary.
940  * @param subIndex subIndex of the object in Object dictionary.
941  *
942  * @return 0 on success, otherwise #CO_SDO_abortCode_t.
943  */
944 uint32_t CO_SDO_initTransfer(CO_SDO_t *SDO, uint16_t index, uint8_t subIndex);
945 
946 
947 /**
948  * Read data from @ref CO_SDO_objectDictionary to internal buffer.
949  *
950  * ODF_arg s must be initialized before with CO_SDO_initTransfer().
951  * @ref CO_SDO_OD_function is called if configured.
952  *
953  * @param SDO This object.
954  * @param SDOBufferSize Total size of the SDO buffer.
955  *
956  * @return 0 on success, otherwise #CO_SDO_abortCode_t.
957  */
958 uint32_t CO_SDO_readOD(CO_SDO_t *SDO, uint16_t SDOBufferSize);
959 
960 
961 /**
962  * Write data from internal buffer to @ref CO_SDO_objectDictionary.
963  *
964  * ODF_arg s must be initialized before with CO_SDO_initTransfer().
965  * @ref CO_SDO_OD_function is called if configured.
966  *
967  * @param SDO This object.
968  * @param length Length of data (received from network) to write.
969  *
970  * @return 0 on success, otherwise #CO_SDO_abortCode_t.
971  */
972 uint32_t CO_SDO_writeOD(CO_SDO_t *SDO, uint16_t length);
973 
974 #ifdef __cplusplus
975 }
976 #endif /*__cplusplus*/
977 
978 /** @} */
979 #endif
980