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