1 /** 2 * CANopen Service Data Object - client protocol. 3 * 4 * @file CO_SDOmaster.h 5 * @ingroup CO_SDOmaster 6 * @author Janez Paternoster 7 * @author Matej Severkar 8 * @copyright 2004 - 2020 Janez Paternoster 9 * 10 * This file is part of CANopenNode, an opensource CANopen Stack. 11 * Project home page is <https://github.com/CANopenNode/CANopenNode>. 12 * For more information on CANopen see <http://www.can-cia.org/>. 13 * 14 * Licensed under the Apache License, Version 2.0 (the "License"); 15 * you may not use this file except in compliance with the License. 16 * You may obtain a copy of the License at 17 * 18 * http://www.apache.org/licenses/LICENSE-2.0 19 * 20 * Unless required by applicable law or agreed to in writing, software 21 * distributed under the License is distributed on an "AS IS" BASIS, 22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 * See the License for the specific language governing permissions and 24 * limitations under the License. 25 */ 26 27 28 #ifndef CO_SDO_CLIENT_H 29 #define CO_SDO_CLIENT_H 30 31 #ifdef __cplusplus 32 extern "C" { 33 #endif 34 35 /** 36 * @defgroup CO_SDOmaster SDO client 37 * @ingroup CO_CANopen 38 * @{ 39 * 40 * CANopen Service Data Object - client protocol. 41 * 42 * @see @ref CO_SDO 43 */ 44 45 46 /** 47 * Return values of SDO client functions. 48 */ 49 typedef enum{ 50 /** Transmit buffer is full. Waiting */ 51 CO_SDOcli_transmittBufferFull = 4, 52 /** Block download is in progress. Sending train of messages */ 53 CO_SDOcli_blockDownldInProgress = 3, 54 /** Block upload in progress. Receiving train of messages */ 55 CO_SDOcli_blockUploadInProgress = 2, 56 /** Waiting server response */ 57 CO_SDOcli_waitingServerResponse = 1, 58 /** Success, end of communication */ 59 CO_SDOcli_ok_communicationEnd = 0, 60 /** Error in arguments */ 61 CO_SDOcli_wrongArguments = -2, 62 /** Communication ended with client abort */ 63 CO_SDOcli_endedWithClientAbort = -9, 64 /** Communication ended with server abort */ 65 CO_SDOcli_endedWithServerAbort = -10, 66 /** Communication ended with timeout */ 67 CO_SDOcli_endedWithTimeout = -11 68 }CO_SDOclient_return_t; 69 70 71 /** 72 * SDO Client Parameter. The same as record from Object dictionary (index 0x1280+). 73 */ 74 typedef struct{ 75 /** Equal to 3 */ 76 uint8_t maxSubIndex; 77 /** Communication object identifier for client transmission. Meaning of the specific bits: 78 - Bit 0...10: 11-bit CAN identifier. 79 - Bit 11..30: reserved, set to 0. 80 - Bit 31: if 1, SDO client object is not used. */ 81 uint32_t COB_IDClientToServer; 82 /** Communication object identifier for message received from server. Meaning of the specific bits: 83 - Bit 0...10: 11-bit CAN identifier. 84 - Bit 11..30: reserved, set to 0. 85 - Bit 31: if 1, SDO client object is not used. */ 86 uint32_t COB_IDServerToClient; 87 /** Node-ID of the SDO server */ 88 uint8_t nodeIDOfTheSDOServer; 89 }CO_SDOclientPar_t; 90 91 92 /** 93 * SDO client object 94 */ 95 typedef struct{ 96 /** From CO_SDOclient_init() */ 97 CO_SDOclientPar_t *SDOClientPar; 98 /** From CO_SDOclient_init() */ 99 CO_SDO_t *SDO; 100 /** Internal state of the SDO client */ 101 uint8_t state; 102 /** Pointer to data buffer supplied by user */ 103 uint8_t *buffer; 104 /** By download application indicates data size in buffer. 105 By upload application indicates buffer size */ 106 uint32_t bufferSize; 107 /** Offset in buffer of next data segment being read/written */ 108 uint32_t bufferOffset; 109 /** Acknowledgement */ 110 uint32_t bufferOffsetACK; 111 /** data length to be uploaded in block transfer */ 112 uint32_t dataSize; 113 /** Data length transferred in block transfer */ 114 uint32_t dataSizeTransfered; 115 /** Timeout timer for SDO communication */ 116 uint16_t timeoutTimer; 117 /** Timeout timer for SDO block transfer */ 118 uint16_t timeoutTimerBLOCK; 119 /** Index of current object in Object Dictionary */ 120 uint16_t index; 121 /** Subindex of current object in Object Dictionary */ 122 uint8_t subIndex; 123 /** From CO_SDOclient_init() */ 124 CO_CANmodule_t *CANdevRx; 125 /** From CO_SDOclient_init() */ 126 uint16_t CANdevRxIdx; 127 /** Indicates, if new SDO message received from CAN bus. 128 It is not cleared, until received message is completely processed. */ 129 volatile void *CANrxNew; 130 /** 8 data bytes of the received message */ 131 uint8_t CANrxData[8]; 132 /** From CO_SDOclient_initCallback() or NULL */ 133 void (*pFunctSignal)(void); 134 /** From CO_SDOclient_init() */ 135 CO_CANmodule_t *CANdevTx; 136 /** CAN transmit buffer inside CANdevTx for CAN tx message */ 137 CO_CANtx_t *CANtxBuff; 138 /** From CO_SDOclient_init() */ 139 uint16_t CANdevTxIdx; 140 /** Toggle bit toggled with each subsequent in segmented transfer */ 141 uint8_t toggle; 142 /** Server threshold for switch back to segmented transfer, if data size is small. 143 Set in CO_SDOclient_init(). Can be changed by application. 0 Disables switching. */ 144 uint8_t pst; 145 /** Maximum number of segments in one block. Set in CO_SDOclient_init(). Can 146 be changed by application to 2 .. 127. */ 147 uint8_t block_size_max; 148 /** Last sector number */ 149 uint8_t block_seqno; 150 /** Block size in current transfer */ 151 uint8_t block_blksize; 152 /** Number of bytes in last segment that do not contain data */ 153 uint8_t block_noData; 154 /** Server CRC support in block transfer */ 155 uint8_t crcEnabled; 156 /** Previous value of the COB_IDClientToServer */ 157 uint32_t COB_IDClientToServerPrev; 158 /** Previous value of the COB_IDServerToClient */ 159 uint32_t COB_IDServerToClientPrev; 160 161 }CO_SDOclient_t; 162 163 164 /** 165 * Initialize SDO client object. 166 * 167 * Function must be called in the communication reset section. 168 * 169 * @param SDO_C This object will be initialized. 170 * @param SDO SDO server object. It is used in case, if client is accessing 171 * object dictionary from its own device. If NULL, it will be ignored. 172 * @param SDOClientPar Pointer to _SDO Client Parameter_ record from Object 173 * dictionary (index 0x1280+). Will be written. 174 * @param CANdevRx CAN device for SDO client reception. 175 * @param CANdevRxIdx Index of receive buffer in the above CAN device. 176 * @param CANdevTx CAN device for SDO client transmission. 177 * @param CANdevTxIdx Index of transmit buffer in the above CAN device. 178 * 179 * @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT. 180 */ 181 CO_ReturnError_t CO_SDOclient_init( 182 CO_SDOclient_t *SDO_C, 183 CO_SDO_t *SDO, 184 CO_SDOclientPar_t *SDOClientPar, 185 CO_CANmodule_t *CANdevRx, 186 uint16_t CANdevRxIdx, 187 CO_CANmodule_t *CANdevTx, 188 uint16_t CANdevTxIdx); 189 190 191 /** 192 * Initialize SDOclientRx callback function. 193 * 194 * Function initializes optional callback function, which is called after new 195 * message is received from the CAN bus. Function may wake up external task, 196 * which processes mainline CANopen functions. 197 * 198 * @param SDOclient This object. 199 * @param pFunctSignal Pointer to the callback function. Not called if NULL. 200 */ 201 void CO_SDOclient_initCallback( 202 CO_SDOclient_t *SDOclient, 203 void (*pFunctSignal)(void)); 204 205 206 /** 207 * Setup SDO client object. 208 * 209 * Function must be called before new SDO communication. If previous SDO 210 * communication was with the same node, function does not need to be called. 211 * 212 * @remark If configuring SDO client from network is required, this function 213 * should be set as callback for the corresponding SDO client parameter OD 214 * entry. 215 * 216 * @param SDO_C This object. 217 * @param COB_IDClientToServer See CO_SDOclientPar_t. If zero, then 218 * nodeIDOfTheSDOServer is used with default COB-ID. 219 * @param COB_IDServerToClient See CO_SDOclientPar_t. If zero, then 220 * nodeIDOfTheSDOServer is used with default COB-ID. 221 * @param nodeIDOfTheSDOServer Node-ID of the SDO server. If zero, SDO client 222 * object is not used. If it is the same as node-ID of this node, then data will 223 * be exchanged with this node (without CAN communication). 224 * 225 * @return #CO_SDOclient_return_t 226 */ 227 CO_SDOclient_return_t CO_SDOclient_setup( 228 CO_SDOclient_t *SDO_C, 229 uint32_t COB_IDClientToServer, 230 uint32_t COB_IDServerToClient, 231 uint8_t nodeIDOfTheSDOServer); 232 233 234 /** 235 * Initiate SDO download communication. 236 * 237 * Function initiates SDO download communication with server specified in 238 * CO_SDOclient_init() function. Data will be written to remote node. 239 * Function is non-blocking. 240 * 241 * @param SDO_C This object. 242 * @param index Index of object in object dictionary in remote node. 243 * @param subIndex Subindex of object in object dictionary in remote node. 244 * @param dataTx Pointer to data to be written. Data must be valid until end 245 * of communication. Note that data are aligned in little-endian 246 * format, because CANopen itself uses little-endian. Take care, 247 * when using processors with big-endian. 248 * @param dataSize Size of data in dataTx. 249 * @param blockEnable Try to initiate block transfer. 250 * 251 * @return #CO_SDOclient_return_t 252 */ 253 CO_SDOclient_return_t CO_SDOclientDownloadInitiate( 254 CO_SDOclient_t *SDO_C, 255 uint16_t index, 256 uint8_t subIndex, 257 uint8_t *dataTx, 258 uint32_t dataSize, 259 uint8_t blockEnable); 260 261 262 /** 263 * Process SDO download communication. 264 * 265 * Function must be called cyclically until it returns <=0. It Proceeds SDO 266 * download communication initiated with CO_SDOclientDownloadInitiate(). 267 * Function is non-blocking. 268 * 269 * @param SDO_C This object. 270 * @param timeDifference_ms Time difference from previous function call in [milliseconds]. 271 * @param SDOtimeoutTime Timeout time for SDO communication in milliseconds. 272 * @param pSDOabortCode Pointer to external variable written by this function 273 * in case of error in communication. 274 * 275 * @return #CO_SDOclient_return_t 276 */ 277 CO_SDOclient_return_t CO_SDOclientDownload( 278 CO_SDOclient_t *SDO_C, 279 uint16_t timeDifference_ms, 280 uint16_t SDOtimeoutTime, 281 uint32_t *pSDOabortCode); 282 283 284 /** 285 * Initiate SDO upload communication. 286 * 287 * Function initiates SDO upload communication with server specified in 288 * CO_SDOclient_init() function. Data will be read from remote node. 289 * Function is non-blocking. 290 * 291 * @param SDO_C This object. 292 * @param index Index of object in object dictionary in remote node. 293 * @param subIndex Subindex of object in object dictionary in remote node. 294 * @param dataRx Pointer to data buffer, into which received data will be written. 295 * Buffer must be valid until end of communication. Note that data are aligned 296 * in little-endian format, because CANopen itself uses 297 * little-endian. Take care, when using processors with big-endian. 298 * @param dataRxSize Size of dataRx. 299 * @param blockEnable Try to initiate block transfer. 300 * 301 * @return #CO_SDOclient_return_t 302 */ 303 CO_SDOclient_return_t CO_SDOclientUploadInitiate( 304 CO_SDOclient_t *SDO_C, 305 uint16_t index, 306 uint8_t subIndex, 307 uint8_t *dataRx, 308 uint32_t dataRxSize, 309 uint8_t blockEnable); 310 311 312 /** 313 * Process SDO upload communication. 314 * 315 * Function must be called cyclically until it returns <=0. It Proceeds SDO 316 * upload communication initiated with CO_SDOclientUploadInitiate(). 317 * Function is non-blocking. 318 * 319 * @param SDO_C This object. 320 * @param timeDifference_ms Time difference from previous function call in [milliseconds]. 321 * @param SDOtimeoutTime Timeout time for SDO communication in milliseconds. 322 * @param pDataSize pointer to external variable, where size of received 323 * data will be written. 324 * @param pSDOabortCode Pointer to external variable written by this function 325 * in case of error in communication. 326 * 327 * @return #CO_SDOclient_return_t 328 */ 329 CO_SDOclient_return_t CO_SDOclientUpload( 330 CO_SDOclient_t *SDO_C, 331 uint16_t timeDifference_ms, 332 uint16_t SDOtimeoutTime, 333 uint32_t *pDataSize, 334 uint32_t *pSDOabortCode); 335 336 337 /** 338 * Close SDO communication temporary. 339 * 340 * Function must be called after finish of each SDO client communication cycle. 341 * It disables reception of SDO client CAN messages. It is necessary, because 342 * CO_SDOclient_receive function may otherwise write into undefined SDO buffer. 343 */ 344 void CO_SDOclientClose(CO_SDOclient_t *SDO_C); 345 346 #ifdef __cplusplus 347 } 348 #endif /*__cplusplus*/ 349 350 /** @} */ 351 #endif 352